Version 0.8.6.0

 svn merge -r 28918:29152 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@29156 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index 4d98d9e..5d2879d 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -511,6 +511,9 @@
 
 \subsubsection{Changes Since Version 0.7}
 
+
+\ref{variables}: Final variables no longer introduce setters.
+
 \ref{new}: Instantiating subclasses of malbounded types is a dynamic error.
 
 \ref{leastUpperBounds}:  Extended LUBs to all types.
@@ -821,10 +824,13 @@
 
 If a variable declaration does not explicitly specify a type, the type of the declared variable(s) is  \DYNAMIC{}, the unknown type (\ref{typeDynamic}). 
 
-Static and instance variable declarations always induce implicit getters and setters.
+A variable is {\em mutable} if it is not final.
+Static and instance variable declarations always induce implicit getters. If the variable is mutable it also introduces an implicit setter.
 The scope into which the implicit getters and setters are introduced depends on the kind of variable declaration involved. 
 
-A library variable introduces a getter and a setter into the top level scope of the enclosing library. A static class variable introduces a static getter and a static setter into the immediately enclosing class. An instance variable introduces an instance getter and an instance setter into the immediately enclosing class. 
+A library variable introduces a getter into the top level scope of the enclosing library. A static class variable introduces a static getter into the immediately enclosing class. An instance variable introduces an instance getter into the immediately enclosing class. 
+
+A mutable library variable introduces a setter into the top level scope of the enclosing library. A mutable static class variable introduces a static setter into the immediately enclosing class. A mutable instance variable introduces an instance setter into the immediately enclosing class. 
 
 Local variables are added to the innermost enclosing scope.  They do not induce getters and setters.  A local variable may only be referenced at a source code location that is after its initializer, if any, is complete, or a compile-time error occurs.  The error may be reported either at the point where the premature reference occurs, or at the variable declaration.
 
@@ -909,24 +915,6 @@
 
 whose execution sets the value of $v$ to the incoming argument $x$.
 
-% A final variable introduces a setter that throws and causes a type warning
-
-A final or constant variable declaration  of the form \code{\FINAL{} $T$ $v$;}, \code{\FINAL{} $T$ $v$ = $e$;} or the form  \code{\CONST{} $T$ $v$ = $e$;}   always induces an implicit  setter function (\ref{setters}) with signature 
-
- \VOID{} \SET{} $v=(T$ $x)$
-
-whose execution causes a runtime exception. It is a static warning to invoke such a setter.
-
-A  final variable declaration  of the form \code{\FINAL{} $v$;},  \code{\FINAL{} $v$ = $e$;} or the form  \code{\CONST{} $v$ = $e$;}   always induces an implicit  setter function with signature 
-
-\SET{} $v=(x)$
-
-whose execution causes a runtime exception. It is a static warning to invoke such a setter. % maybe redundant with rules for assignment?
-
-\rationale{
-Creating a setter that may not be used may seem pointless, but it prevents situations where a setter from an enclosing scope might be accidentally accessed from a scope that defines an immutable variable.
-}
-
 
 \subsection{Evaluation of Implicit  Variable Getters}
 \label{evaluationOfImplicitVariableGetters}
@@ -3521,7 +3509,7 @@
  If $f_{id}$ is a local function, a library function, a library or static getter or a variable then $i$ is interpreted as a function expression invocation (\ref{functionExpressionInvocation}).
  \item
 Otherwise, if $f_{id}$ is a static method of the enclosing class $C$, $i$ is equivalent to $C.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$.
-\item Otherwise, if $i$ occurs inside a top level or static function (be it function, method, getter,  or setter) or variable initializer, evaluation of $i$ causes a \cd{NoSuchMethodError} to be thrown.
+\item Otherwise, $f_{id}$ is necessarily an instance method or getter of the enclosing class C, and i is equivalent to the ordinary method invocation $\THIS{}.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$.
 \end{itemize}
 
 %Otherwise, if there is an accessible (\ref{privacy}) static method named $id$ declared in a superclass $S$ of the immediately enclosing class $C$ then i is equivalent to the static method invocation $S.id(a_1, \ldots, a_n, x_{n+1}: a_{n+1}, \ldots, x_{n+k}: a_{n+k})$.  
@@ -3530,7 +3518,9 @@
 %Unqualified access to static methods of superclasses is inconsistent with the idea that static methods are not inherited. It is not particularly necessary and  may be restricted in future versions.
 %}
 
-Otherwise, $i$ is equivalent to $\THIS{}.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$.
+Otherwise, if $i$ occurs inside a top level or static function (be it function, method, getter,  or setter) or variable initializer, evaluation of $i$ causes a \cd{NoSuchMethodError} to be thrown.
+
+If $i$ does not occur inside a top level or static function, $i$ is equivalent to $\THIS{}.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$.
 
 
 
diff --git a/pkg/analyzer_experimental/bin/analyzer.dart b/pkg/analyzer_experimental/bin/analyzer.dart
index 6c96907..40e5a6d 100644
--- a/pkg/analyzer_experimental/bin/analyzer.dart
+++ b/pkg/analyzer_experimental/bin/analyzer.dart
@@ -19,8 +19,7 @@
 import 'package:analyzer_experimental/src/analyzer_impl.dart';
 import 'package:analyzer_experimental/src/error_formatter.dart';
 
-void main() {
-  var args = new Options().arguments;
+void main(args) {
   var options = CommandLineOptions.parse(args);
   if (options.shouldBatch) {
     BatchRunner.runAsBatch(args, (List<String> args) {
diff --git a/pkg/analyzer_experimental/bin/coverage.dart b/pkg/analyzer_experimental/bin/coverage.dart
index ed6d2f6..a4bb482 100644
--- a/pkg/analyzer_experimental/bin/coverage.dart
+++ b/pkg/analyzer_experimental/bin/coverage.dart
@@ -12,10 +12,10 @@
 import 'package:analyzer_experimental/src/services/runtime/coverage/coverage_impl.dart';
 
 
-main() {
+main(args) {
   ArgResults options;
   try {
-    options = _argParser.parse(new Options().arguments);
+    options = _argParser.parse(args);
   } on FormatException catch (e) {
     print(e.message);
     print('Run "coverage --help" to see available options.');
diff --git a/pkg/analyzer_experimental/bin/formatter.dart b/pkg/analyzer_experimental/bin/formatter.dart
index d52feec..ad5f4cd 100755
--- a/pkg/analyzer_experimental/bin/formatter.dart
+++ b/pkg/analyzer_experimental/bin/formatter.dart
@@ -26,8 +26,8 @@
 const followLinks = false;
 
 
-main() {
-  var options = argParser.parse(new Options().arguments);
+main(args) {
+  var options = argParser.parse(args);
   if (options['help']) {
     _printUsage();
     return;
diff --git a/pkg/analyzer_experimental/lib/options.dart b/pkg/analyzer_experimental/lib/options.dart
index 9b3ffac..32fc49a 100644
--- a/pkg/analyzer_experimental/lib/options.dart
+++ b/pkg/analyzer_experimental/lib/options.dart
@@ -58,13 +58,13 @@
    */
   CommandLineOptions._fromArgs(ArgResults args)
     : shouldBatch = args['batch'],
-      machineFormat = args['machine'],
+      machineFormat = args['machine'] || args['format'] == 'machine',
       displayVersion = args['version'],
       disableHints = args['no-hints'],
       ignoreUnrecognizedFlags = args['ignore-unrecognized-flags'],
       perf = args['perf'],
-      showPackageWarnings = args['show-package-warnings'],
-      showSdkWarnings = args['show-sdk-warnings'],
+      showPackageWarnings = args['show-package-warnings'] || args['package-warnings'],
+      showSdkWarnings = args['show-sdk-warnings'] || args['warnings'],
       warningsAreFatal = args['fatal-warnings'],
       dartSdkPath = args['dart-sdk'],
       packageRootPath = args['package-root'],
@@ -100,9 +100,12 @@
       ..addFlag('batch', abbr: 'b', help: 'Run in batch mode',
           defaultsTo: false, negatable: false)
       ..addOption('dart-sdk', help: 'The path to the Dart SDK')
-      ..addOption('package-root', help: 'The path to the package root')
+      ..addOption('package-root', abbr: 'p',
+          help: 'The path to the package root')
+      ..addOption('format',
+          help: 'Specifies the format in which errors are displayed')
       ..addFlag('machine',
-          help: 'Print errors in a format suitable for parsing',
+          help: 'Print errors in a format suitable for parsing (deprecated)',
           defaultsTo: false, negatable: false)
       ..addFlag('version', help: 'Print the analyzer version',
           defaultsTo: false, negatable: false)
@@ -113,13 +116,18 @@
           defaultsTo: false, negatable: false)
       ..addFlag('fatal-warnings', help: 'Treat non-type warnings as fatal',
           defaultsTo: false, negatable: false)
-      ..addFlag('show-package-warnings',
+      ..addFlag('package-warnings',
           help: 'Show warnings from package: imports',
           defaultsTo: false, negatable: false)
+      ..addFlag('show-package-warnings',
+          help: 'Show warnings from package: imports (deprecated)',
+          defaultsTo: false, negatable: false)
       ..addFlag('perf',
           help: 'Show performance statistics',
           defaultsTo: false, negatable: false)
-      ..addFlag('show-sdk-warnings', help: 'Show warnings from SDK imports',
+      ..addFlag('warnings', help: 'Show warnings from SDK imports',
+          defaultsTo: false, negatable: false)
+      ..addFlag('show-sdk-warnings', help: 'Show warnings from SDK imports (deprecated)',
           defaultsTo: false, negatable: false)
       ..addFlag('help', abbr: 'h', help: 'Display this help message',
           defaultsTo: false, negatable: false);
diff --git a/pkg/analyzer_experimental/test/options_test.dart b/pkg/analyzer_experimental/test/options_test.dart
index 67b8467..c4c9a34 100644
--- a/pkg/analyzer_experimental/test/options_test.dart
+++ b/pkg/analyzer_experimental/test/options_test.dart
@@ -5,23 +5,48 @@
 library options_test;
 
 import 'package:unittest/unittest.dart';
-//import 'package:analyzer_experimental/options.dart';
+import 'package:analyzer_experimental/options.dart';
 
 main() {
 
   group('AnalyzerOptions.parse()', () {
 
     test('defaults', () {
-//      CommandLineOptions options = CommandLineOptions.parse(['foo.dart']);
-//      expect(options, isNotNull);
-//      expect(options.shouldBatch, isFalse);
-//      expect(options.machineFormat, isFalse);
-//      expect(options.ignoreUnrecognizedFlags, isFalse);
-//      expect(options.showPackageWarnings, isFalse);
-//      expect(options.showSdkWarnings, isFalse);
-//      expect(options.warningsAreFatal, isFalse);
-//      expect(options.dartSdkPath, isNull);
-//      expect(options.sourceFiles, equals(['foo.dart']));
+      CommandLineOptions options = CommandLineOptions
+          .parse(['--dart-sdk', '.', 'foo.dart']);
+      expect(options, isNotNull);
+      expect(options.shouldBatch, isFalse);
+      expect(options.machineFormat, isFalse);
+      expect(options.ignoreUnrecognizedFlags, isFalse);
+      expect(options.showPackageWarnings, isFalse);
+      expect(options.showSdkWarnings, isFalse);
+      expect(options.warningsAreFatal, isFalse);
+      expect(options.dartSdkPath, isNotNull);
+      expect(options.sourceFiles, equals(['foo.dart']));
+    });
+
+    test('machine format', () {
+      CommandLineOptions options = CommandLineOptions
+          .parse(['--dart-sdk', '.', '--format=machine', 'foo.dart']);
+      expect(options.machineFormat, isTrue);
+    });
+
+    test('package root', () {
+      CommandLineOptions options = CommandLineOptions
+          .parse(['--dart-sdk', '.', '-p', 'bar', 'foo.dart']);
+      expect(options.packageRootPath, equals('bar'));
+    });
+    
+    test('package warnings', () {
+      CommandLineOptions options = CommandLineOptions
+          .parse(['--dart-sdk', '.', '--package-warnings', 'foo.dart']);
+      expect(options.showPackageWarnings, isTrue);
+    });
+    
+    test('sdk warnings', () {
+      CommandLineOptions options = CommandLineOptions
+          .parse(['--dart-sdk', '.', '--warnings', 'foo.dart']);
+      expect(options.showSdkWarnings, isTrue);
     });
 
 //    test('notice unrecognized flags', () {
diff --git a/pkg/barback/lib/src/asset_node.dart b/pkg/barback/lib/src/asset_node.dart
index da771cd..2372ba9 100644
--- a/pkg/barback/lib/src/asset_node.dart
+++ b/pkg/barback/lib/src/asset_node.dart
@@ -62,26 +62,30 @@
   final _stateChangeController =
       new StreamController<AssetState>.broadcast(sync: true);
 
-  /// Returns a Future that completes when the node's asset is available.
+  /// Calls [callback] when the node's asset is available.
   ///
-  /// If the asset is currently available, this completes synchronously to
-  /// ensure that the asset is still available in the [Future.then] callback.
+  /// If the asset is currently available, this calls [callback] synchronously
+  /// to ensure that the asset is still available.
   ///
-  /// If the asset is removed before becoming available, this will throw an
-  /// [AssetNotFoundException].
-  Future<Asset> get whenAvailable {
-    return _waitForState((state) => state.isAvailable || state.isRemoved)
-        .then((state) {
+  /// The return value of [callback] is piped to the returned Future. If the
+  /// asset is removed before becoming available, the returned future will throw
+  /// an [AssetNotFoundException].
+  Future whenAvailable(callback(Asset asset)) {
+    return _waitForState((state) => state.isAvailable || state.isRemoved,
+        (state) {
       if (state.isRemoved) throw new AssetNotFoundException(id);
-      return asset;
+      return callback(asset);
     });
   }
 
-  /// Returns a Future that completes when the node's asset is removed.
+  /// Calls [callback] when the node's asset is removed.
   ///
-  /// If the asset is already removed when this is called, it completes
+  /// If the asset is already removed when this is called, it calls [callback]
   /// synchronously.
-  Future get whenRemoved => _waitForState((state) => state.isRemoved);
+  ///
+  /// The return value of [callback] is piped to the returned Future.
+  Future whenRemoved(callback()) =>
+    _waitForState((state) => state.isRemoved, (_) => callback());
 
   /// Runs [callback] repeatedly until the node's asset has maintained the same
   /// value for the duration.
@@ -95,7 +99,7 @@
   /// If this asset is removed, this will throw an [AssetNotFoundException] as
   /// soon as [callback]'s Future is finished running.
   Future tryUntilStable(Future callback(Asset asset)) {
-    return whenAvailable.then((asset) {
+    return whenAvailable((asset) {
       var modifiedDuringCallback = false;
       var subscription;
       subscription = onStateChange.listen((_) {
@@ -114,13 +118,15 @@
     });
   }
 
-  /// Returns a Future that completes as soon as the node is in a state that
-  /// matches [test].
+  /// Calls [callback] as soon as the node is in a state that matches [test].
   ///
-  /// The Future completes synchronously if this is already in such a state.
-  Future<AssetState> _waitForState(bool test(AssetState state)) {
-    if (test(state)) return new Future.sync(() => state);
-    return onStateChange.firstWhere(test);
+  /// [callback] is called synchronously if this is already in such a state.
+  ///
+  /// The return value of [callback] is piped to the returned Future.
+  Future _waitForState(bool test(AssetState state),
+      callback(AssetState state)) {
+    if (test(state)) return new Future.sync(() => callback(state));
+    return onStateChange.firstWhere(test).then((_) => callback(state));
   }
 
   AssetNode._(this.id, this._transform, this._origin)
diff --git a/pkg/barback/lib/src/barback.dart b/pkg/barback/lib/src/barback.dart
index affc1b5..932077e 100644
--- a/pkg/barback/lib/src/barback.dart
+++ b/pkg/barback/lib/src/barback.dart
@@ -9,6 +9,7 @@
 import 'asset.dart';
 import 'asset_id.dart';
 import 'asset_set.dart';
+import 'barback_logger.dart';
 import 'build_result.dart';
 import 'errors.dart';
 import 'package_graph.dart';
diff --git a/pkg/barback/lib/src/file_pool.dart b/pkg/barback/lib/src/file_pool.dart
index 06192e7..7e95c68 100644
--- a/pkg/barback/lib/src/file_pool.dart
+++ b/pkg/barback/lib/src/file_pool.dart
@@ -9,6 +9,9 @@
 import 'dart:convert';
 import 'dart:io';
 
+import 'pool.dart';
+import 'utils.dart';
+
 /// Manages a pool of files that are opened for reading to cope with maximum
 /// file descriptor limits.
 ///
@@ -17,16 +20,27 @@
 /// again. If this doesn't succeed after a certain amount of time, the open
 /// will fail and the original "too many files" exception will be thrown.
 class FilePool {
-  /// [_FileReader]s whose last [listen] call failed and that are waiting for
-  /// another file to close so they can be retried.
-  final _pendingListens = new Queue<_FileReader>();
+  /// The underlying pool.
+  ///
+  /// The maximum number of allocated descriptors is based on empirical tests
+  /// that indicate that beyond 32, additional file reads don't provide
+  /// substantial additional throughput.
+  final Pool _pool = new Pool(32, timeout: new Duration(seconds: 60));
 
   /// Opens [file] for reading.
   ///
   /// When the returned stream is listened to, if there are too many files
   /// open, this will wait for a previously opened file to be closed and then
   /// try again.
-  Stream<List<int>> openRead(File file) => new _FileReader(this, file).stream;
+  Stream<List<int>> openRead(File file) {
+    return futureStream(_pool.checkOut().then((resource) {
+      return file.openRead().transform(new StreamTransformer.fromHandlers(
+          handleDone: (sink) {
+        sink.close();
+        resource.release();
+      }));
+    }));
+  }
 
   /// Reads [file] as a string using [encoding].
   ///
@@ -48,138 +62,4 @@
 
     return completer.future;
   }
-
-  /// Tries to re-listen to the next pending file reader if there are any.
-  void _retryPendingListen() {
-    if (_pendingListens.isEmpty) return;
-
-    var pending = _pendingListens.removeFirst();
-    pending._listen();
-  }
-}
-
-/// Wraps a raw file reading stream in a stream that handles "too many files"
-/// errors.
-///
-/// This also notifies the pool when the underlying file stream is closed so
-/// that it can try to open a waiting file.
-class _FileReader {
-  final FilePool _pool;
-  final File _file;
-
-  /// The underyling file stream.
-  Stream<List<int>> _fileStream;
-
-  /// The controller for the stream wrapper.
-  StreamController<List<int>> _controller;
-
-  /// The current subscription to the underlying file stream.
-  ///
-  /// This will only be non-null while the wrapped stream is being listened to.
-  StreamSubscription _subscription;
-
-  /// The timeout timer.
-  ///
-  /// If this timer fires before the listen is retried, it gives up and throws
-  /// the original error.
-  Timer _timer;
-
-  /// When a [listen] call has thrown a "too many files" error, this will be
-  /// the exception object.
-  Object _exception;
-
-  /// When a [listen] call has thrown a "too many files" error, this will be
-  /// the captured stack trace.
-  Object _stackTrace;
-
-  /// The wrapped stream that the file can be read from.
-  Stream<List<int>> get stream => _controller.stream;
-
-  _FileReader(this._pool, this._file) {
-    _controller = new StreamController<List<int>>(onListen: _listen,
-        onPause: () {
-      _subscription.pause();
-    }, onResume: () {
-      _subscription.resume();
-    }, onCancel: () {
-      if (_subscription != null) _subscription.cancel();
-      _subscription = null;
-    }, sync: true);
-  }
-
-  /// Starts listening to the underlying file stream.
-  void _listen() {
-    if (_timer != null) {
-      _timer.cancel();
-      _timer = null;
-    }
-
-    _exception = null;
-    _stackTrace = null;
-
-    _fileStream = _file.openRead();
-    _subscription = _fileStream.listen(_controller.add,
-        onError: _onError, onDone: _onDone, cancelOnError: true);
-  }
-
-  /// Handles an error from the underlying file stream.
-  ///
-  /// "Too many file" errors are caught so that we can retry later. Other
-  /// errors are passed to the wrapped stream and the underlying stream
-  /// subscription is canceled.
-  void _onError(Object exception, Object stackTrace) {
-    assert(_subscription != null);
-    assert(_exception == null);
-
-    // The subscription is canceled after an error.
-    _subscription = null;
-
-    // We only handle "Too many open files errors".
-    if (exception is! FileException || exception.osError.errorCode != 24) {
-      _controller.addError(exception, stackTrace);
-      return;
-    }
-
-    _exception = exception;
-    _stackTrace = stackTrace;
-
-    // We'll try to defer the listen in the hopes that another file will close
-    // and we can try. If that doesn't happen after a while, give up and just
-    // throw the original error.
-    // TODO(rnystrom): The point of this timer is to not get stuck forever in
-    // a deadlock scenario. But this can also erroneously fire if there is a
-    // large number of slow reads that do incrementally finish. A file may not
-    // move to the front of the queue in time even though it is making
-    // progress. A better solution is to have a single deadlock timer on the
-    // FilePool itself that starts when a pending listen is enqueued and checks
-    // to see if progress has been made when it fires.
-    _timer = new Timer(new Duration(seconds: 60), _onTimeout);
-
-    // Tell the pool that this file is waiting.
-    _pool._pendingListens.add(this);
-  }
-
-  /// Handles the underlying file stream finishing.
-  void _onDone() {
-    _subscription = null;
-
-    _controller.close();
-    _pool._retryPendingListen();
-  }
-
-  /// If this file failed to be read because there were too many open files and
-  /// no file was closed in time to retry, this handles giving up.
-  void _onTimeout() {
-    assert(_subscription == null);
-    assert(_exception != null);
-
-    // We failed to open in time, so just fail with the original error.
-    _pool._pendingListens.remove(this);
-    _controller.addError(_exception, _stackTrace);
-    _controller.close();
-
-    _timer = null;
-    _exception = null;
-    _stackTrace = null;
-  }
 }
diff --git a/pkg/barback/lib/src/group_runner.dart b/pkg/barback/lib/src/group_runner.dart
index 5551e47..dc7b4b4 100644
--- a/pkg/barback/lib/src/group_runner.dart
+++ b/pkg/barback/lib/src/group_runner.dart
@@ -85,7 +85,7 @@
     var newOutputs = _phases.last.availableOutputs
         .difference(_alreadyEmittedOutputs);
     for (var output in newOutputs) {
-      output.whenRemoved.then((_) => _alreadyEmittedOutputs.remove(output));
+      output.whenRemoved(() => _alreadyEmittedOutputs.remove(output));
     }
     _alreadyEmittedOutputs.addAll(newOutputs);
 
diff --git a/pkg/barback/lib/src/package_graph.dart b/pkg/barback/lib/src/package_graph.dart
index 68753f6..dcc3d7f 100644
--- a/pkg/barback/lib/src/package_graph.dart
+++ b/pkg/barback/lib/src/package_graph.dart
@@ -14,6 +14,7 @@
 import 'build_result.dart';
 import 'errors.dart';
 import 'package_provider.dart';
+import 'pool.dart';
 import 'transformer.dart';
 import 'utils.dart';
 
@@ -65,6 +66,13 @@
   /// [Future] returned by [getAllAssets].
   var _lastUnexpectedError;
 
+  // TODO(nweiz): Allow transformers to declare themselves as "lightweight" or
+  // "heavyweight" and adjust their restrictions appropriately. Simple
+  // transformers may be very efficient to run in parallel, whereas dart2js uses
+  // a lot of memory and should be run more sequentially.
+  /// A pool that controls how many transformers may be applied at once.
+  final Pool transformPool = new Pool(10);
+
   /// Creates a new [PackageGraph] that will transform assets in all packages
   /// made available by [provider].
   PackageGraph(this.provider, {BarbackLogger logger})
diff --git a/pkg/barback/lib/src/phase.dart b/pkg/barback/lib/src/phase.dart
index 20d6383..8680e60 100644
--- a/pkg/barback/lib/src/phase.dart
+++ b/pkg/barback/lib/src/phase.dart
@@ -151,7 +151,7 @@
     _inputOrigins.add(node.origin);
     var input = new PhaseInput(this, node, _transformers);
     _inputs[node.id] = input;
-    input.input.whenRemoved.then((_) {
+    input.input.whenRemoved(() {
       _inputOrigins.remove(node.origin);
       _inputs.remove(node.id);
       _forwarders.remove(node.id).remove();
@@ -281,13 +281,11 @@
       if (!input.isDirty) return new Future.value(new Set());
       return input.process().then(_handleOutputs);
     }));
-    outputFutures.addAll(_groups.values.map((input) {
-      if (!input.isDirty) return new Future.value(new Set());
-      return input.process().then(_handleOutputs);
+    outputFutures.addAll(_groups.values.map((group) {
+      if (!group.isDirty) return new Future.value(new Set());
+      return group.process().then(_handleOutputs);
     }));
 
-    // TODO(nweiz): handle pass-through.
-
     return Future.wait(outputFutures).then((_) {
       // Report collisions in a deterministic order.
       outputIds = outputIds.toList();
diff --git a/pkg/barback/lib/src/phase_input.dart b/pkg/barback/lib/src/phase_input.dart
index 1097022..1b96ee0 100644
--- a/pkg/barback/lib/src/phase_input.dart
+++ b/pkg/barback/lib/src/phase_input.dart
@@ -273,16 +273,27 @@
   }
 
   /// Processes the transforms for this input.
+  ///
+  /// Returns the set of newly-created asset nodes that transforms have emitted
+  /// for this input. The assets returned this way are guaranteed not to be
+  /// [AssetState.REMOVED].
   Future<Set<AssetNode>> process() {
-    if (_adjustTransformersFuture == null) return _processTransforms();
-    return _waitForInputs().then((_) => _processTransforms());
+    return _waitForTransformers(() => _processTransforms()).then((outputs) {
+      if (input.state.isRemoved) return new Set();
+      return outputs;
+    });
   }
 
-  Future _waitForInputs() {
-    // Return a synchronous future so we can be sure [_adjustTransformers] isn't
-    // called between now and when the Future completes.
-    if (_adjustTransformersFuture == null) return new Future.sync(() {});
-    return _adjustTransformersFuture.then((_) => _waitForInputs());
+  /// Runs [callback] once all the transformers are adjusted correctly and the
+  /// input is ready to be processed.
+  ///
+  /// If the transformers are already properly adjusted, [callback] is called
+  /// synchronously to ensure that [_adjustTransformers] isn't called before the
+  /// callback.
+  Future _waitForTransformers(callback()) {
+    if (_adjustTransformersFuture == null) return new Future.sync(callback);
+    return _adjustTransformersFuture.then(
+        (_) => _waitForTransformers(callback));
   }
 
   /// Applies all currently wired up and dirty transforms.
diff --git a/pkg/barback/lib/src/phase_output.dart b/pkg/barback/lib/src/phase_output.dart
index 31dcdd2..17a613f 100644
--- a/pkg/barback/lib/src/phase_output.dart
+++ b/pkg/barback/lib/src/phase_output.dart
@@ -30,7 +30,7 @@
 
   /// The asset node for this output.
   AssetNode get output => _outputForwarder.node;
-  AssetNodeForwarder _outputForwarder;
+  AssetForwarder _outputForwarder;
 
   /// A stream that emits an [AssetNode] each time this output starts forwarding
   /// a new asset.
@@ -82,7 +82,7 @@
 
   /// Watches [node] to adjust [_assets] and [output] when it's removed.
   void _watchAsset(AssetNode node) {
-    node.whenRemoved.then((_) {
+    node.whenRemoved(() {
       if (_assets.length == 1) {
         assert(_assets.single == node);
         _outputForwarder.close();
diff --git a/pkg/barback/lib/src/pool.dart b/pkg/barback/lib/src/pool.dart
new file mode 100644
index 0000000..8da8434
--- /dev/null
+++ b/pkg/barback/lib/src/pool.dart
@@ -0,0 +1,133 @@
+import 'dart:async';
+import 'dart:collection';
+
+import 'package:stack_trace/stack_trace.dart';
+
+/// Manages an abstract pool of resources with a limit on how many may be in use
+/// at once.
+///
+/// When a resource is needed, the user should call [checkOut]. When the
+/// returned future completes with a [PoolResource], the resource may be
+/// allocated. Once the resource has been released, the user should call
+/// [PoolResource.release]. The pool will ensure that only a certain number of
+/// [PoolResource]s may be checked out at once.
+class Pool {
+  /// Completers for checkouts beyond the first [_maxCheckedOutResources].
+  ///
+  /// When an item is released, the next element of [_pendingResources] will be
+  /// completed.
+  final _pendingResources = new Queue<Completer<PoolResource>>();
+
+  /// The maximum number of resources that may be checked out at once.
+  final int _maxCheckedOutResources;
+
+  /// The number of resources that are currently checked out.
+  int _checkedOutResources = 0;
+
+  /// The timeout timer.
+  ///
+  /// If [_timeout] isn't null, this timer is set as soon as the resource limit
+  /// is reached and is reset every time an resource is released or a new
+  /// resource is requested. If it fires, that indicates that the caller became
+  /// deadlocked, likely due to files waiting for additional files to be read
+  /// before they could be closed.
+  Timer _timer;
+
+  /// The amount of time to wait before timing out the pending resources.
+  Duration _timeout;
+
+  /// Creates a new pool with the given limit on how many resources may be
+  /// checked out at once.
+  ///
+  /// If [timeout] is passed, then if that much time passes without any activity
+  /// all pending [checkOut] futures will throw an exception. This is indented
+  /// to avoid deadlocks.
+  Pool(this._maxCheckedOutResources, {Duration timeout})
+      : _timeout = timeout;
+
+  /// Check out a [PoolResource].
+  ///
+  /// If the maximum number of resources is already checked out, this will delay
+  /// until one of them is released.
+  Future<PoolResource> checkOut() {
+    if (_checkedOutResources < _maxCheckedOutResources) {
+      _checkedOutResources++;
+      return new Future.value(new PoolResource._(this));
+    } else {
+      var completer = new Completer<PoolResource>();
+      _pendingResources.add(completer);
+      _heartbeat();
+      return completer.future;
+    }
+  }
+
+  /// Checks out a resource for the duration of [callback], which may return a
+  /// Future.
+  ///
+  /// The return value of [callback] is piped to the returned Future.
+  Future withResource(callback()) {
+    return checkOut().then((resource) =>
+        new Future.sync(callback).whenComplete(resource.release));
+  }
+
+  /// If there are any pending checkouts, this will fire the oldest one.
+  void _onResourceReleased() {
+    if (_pendingResources.isEmpty) {
+      _checkedOutResources--;
+      if (_timer != null) {
+        _timer.cancel();
+        _timer = null;
+      }
+      return;
+    }
+
+    _heartbeat();
+    var pending = _pendingResources.removeFirst();
+    pending.complete(new PoolResource._(this));
+  }
+
+  /// Indicates that some external action has occurred and the timer should be
+  /// restarted.
+  void _heartbeat() {
+    if (_timer != null) _timer.cancel();
+    if (_timeout == null) {
+      _timer = null;
+    } else {
+      _timer = new Timer(_timeout, _onTimeout);
+    }
+  }
+
+  /// Handles [_timer] timing out by causing all pending resource completers to
+  /// emit exceptions.
+  void _onTimeout() {
+    for (var completer in _pendingResources) {
+      completer.completeException("Pool deadlock: all resources have been "
+          "checked out for too long.", new Trace.current().vmTrace);
+    }
+    _pendingResources.clear();
+    _timer = null;
+  }
+}
+
+/// A member of a [Pool].
+///
+/// A [PoolResource] is a token that indicates that a resource is allocated.
+/// When the associated resource is released, the user should call [release].
+class PoolResource {
+  final Pool _pool;
+
+  /// Whether [this] has been released yet.
+  bool _released = false;
+
+  PoolResource._(this._pool);
+
+  /// Tells the parent [Pool] that the resource associated with this resource is
+  /// no longer allocated, and that a new [PoolResource] may be checked out.
+  void release() {
+    if (_released) {
+      throw new StateError("A PoolResource may only be released once.");
+    }
+    _released = true;
+    _pool._onResourceReleased();
+  }
+}
\ No newline at end of file
diff --git a/pkg/barback/lib/src/transform.dart b/pkg/barback/lib/src/transform.dart
index b9c2de0..fa1df82 100644
--- a/pkg/barback/lib/src/transform.dart
+++ b/pkg/barback/lib/src/transform.dart
@@ -7,10 +7,13 @@
 import 'dart:async';
 import 'dart:convert';
 
+import 'package:source_maps/span.dart';
+
 import 'asset.dart';
 import 'asset_id.dart';
 import 'asset_node.dart';
 import 'asset_set.dart';
+import 'barback_logger.dart';
 import 'errors.dart';
 import 'transform_logger.dart';
 import 'transform_node.dart';
diff --git a/pkg/barback/lib/src/transform_node.dart b/pkg/barback/lib/src/transform_node.dart
index 6df4315..aa77d72 100644
--- a/pkg/barback/lib/src/transform_node.dart
+++ b/pkg/barback/lib/src/transform_node.dart
@@ -6,6 +6,8 @@
 
 import 'dart:async';
 
+import 'package:source_maps/span.dart';
+
 import 'asset.dart';
 import 'asset_id.dart';
 import 'asset_node.dart';
@@ -125,7 +127,10 @@
     _inputSubscriptions.clear();
 
     _isDirty = false;
-    return transformer.apply(transform).catchError((error) {
+
+    return phase.cascade.graph.transformPool
+        .withResource(() => transformer.apply(transform))
+        .catchError((error) {
       // If the transform became dirty while processing, ignore any errors from
       // it.
       if (_isDirty) return;
@@ -160,7 +165,7 @@
 
       // If the asset node is found, wait until its contents are actually
       // available before we return them.
-      return node.whenAvailable.then((asset) {
+      return node.whenAvailable((asset) {
         _inputSubscriptions.putIfAbsent(node.id,
             () => node.onStateChange.listen((_) => _dirty()));
 
diff --git a/pkg/barback/lib/src/utils.dart b/pkg/barback/lib/src/utils.dart
index 22203b4..a925bec 100644
--- a/pkg/barback/lib/src/utils.dart
+++ b/pkg/barback/lib/src/utils.dart
@@ -5,6 +5,7 @@
 library barback.utils;
 
 import 'dart:async';
+import 'dart:io';
 
 /// A pair of values.
 class Pair<E, F> {
diff --git a/pkg/barback/test/package_graph/many_parallel_transformers_test.dart b/pkg/barback/test/package_graph/many_parallel_transformers_test.dart
new file mode 100644
index 0000000..389beb1
--- /dev/null
+++ b/pkg/barback/test/package_graph/many_parallel_transformers_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library barback.test.package_graph.transform_test;
+
+import 'package:barback/src/utils.dart';
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../utils.dart';
+
+main() {
+  initConfig();
+
+  test("handles many parallel transformers", () {
+    var files = new List.generate(100, (i) => "app|$i.txt");
+    var rewrite = new RewriteTransformer("txt", "out");
+    initGraph(files, {"app": [[rewrite]]});
+
+    // Pause and resume apply to simulate parallel long-running transformers.
+    rewrite.pauseApply();
+    updateSources(files);
+    schedule(pumpEventQueue);
+    rewrite.resumeApply();
+
+    for (var i = 0; i < 100; i++) {
+      expectAsset("app|$i.out", "$i.out");
+    }
+    buildShouldSucceed();
+
+    expect(rewrite.maxParallelRuns, completion(equals(10)));
+  });
+}
diff --git a/pkg/barback/test/package_graph/repetition_test.dart b/pkg/barback/test/package_graph/repetition_test.dart
new file mode 100644
index 0000000..cd98440
--- /dev/null
+++ b/pkg/barback/test/package_graph/repetition_test.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library barback.test.package_graph.transform_test;
+
+import 'package:barback/src/utils.dart';
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../utils.dart';
+
+main() {
+  initConfig();
+
+  test("updates sources many times", () {
+    initGraph(["app|foo.txt"], {
+      "app": [[new RewriteTransformer("txt", "out")]]
+    });
+
+    for (var i = 0; i < 1000; i++) {
+      updateSources(["app|foo.txt"]);
+    }
+
+    expectAsset("app|foo.out", "foo.out");
+    buildShouldSucceed();
+  });
+
+  test("updates and then removes sources many times", () {
+    initGraph(["app|foo.txt"], {
+      "app": [[new RewriteTransformer("txt", "out")]]
+    });
+
+    for (var i = 0; i < 1000; i++) {
+      updateSources(["app|foo.txt"]);
+      removeSources(["app|foo.txt"]);
+    }
+
+    expectNoAsset("app|foo.out");
+    expectNoAsset("app|foo.txt");
+    buildShouldSucceed();
+  });
+
+  test("updates transformers many times", () {
+    var rewrite = new RewriteTransformer("txt", "out");
+    initGraph(["app|foo.txt"], {"app": [[rewrite]]});
+    updateSources(["app|foo.txt"]);
+
+    for (var i = 0; i < 1; i++) {
+      updateTransformers("app", [[rewrite]]);
+    }
+
+    expectAsset("app|foo.out", "foo.out");
+    buildShouldSucceed();
+  });
+
+  test("updates and removes transformers many times", () {
+    var rewrite = new RewriteTransformer("txt", "out");
+    initGraph(["app|foo.txt"], {"app": [[rewrite]]});
+    updateSources(["app|foo.txt"]);
+
+    for (var i = 0; i < 1; i++) {
+      updateTransformers("app", [[rewrite]]);
+      updateTransformers("app", [[]]);
+    }
+
+    expectAsset("app|foo.txt", "foo");
+    expectNoAsset("app|foo.out");
+    buildShouldSucceed();
+  });
+}
diff --git a/pkg/barback/test/package_graph/transform_test.dart b/pkg/barback/test/package_graph/transform_test.dart
index 14aff9f..ae097a6 100644
--- a/pkg/barback/test/package_graph/transform_test.dart
+++ b/pkg/barback/test/package_graph/transform_test.dart
@@ -806,6 +806,30 @@
     buildShouldSucceed();
   });
 
+  test("one transformer takes a long time while the other finishes, then "
+      "the input is removed", () {
+    var rewrite1 = new RewriteTransformer("txt", "out1");
+    var rewrite2 = new RewriteTransformer("txt", "out2");
+    initGraph(["app|foo.txt"], {"app": [[rewrite1, rewrite2]]});
+
+    rewrite1.pauseApply();
+
+    updateSources(["app|foo.txt"]);
+
+    // Wait for rewrite1 to pause and rewrite2 to finish.
+    schedule(pumpEventQueue);
+
+    removeSources(["app|foo.txt"]);
+
+    // Make sure the removal is processed completely before we restart rewrite2.
+    schedule(pumpEventQueue);
+    rewrite1.resumeApply();
+
+    buildShouldSucceed();
+    expectNoAsset("app|foo.out1");
+    expectNoAsset("app|foo.out2");
+  });
+
   group("pass-through", () {
     test("passes an asset through a phase in which no transforms apply", () {
       initGraph([
diff --git a/pkg/barback/test/transformer/mock.dart b/pkg/barback/test/transformer/mock.dart
index 57d3f07..cfbb21a 100644
--- a/pkg/barback/test/transformer/mock.dart
+++ b/pkg/barback/test/transformer/mock.dart
@@ -27,6 +27,9 @@
   Future<int> get numRuns => schedule(() => _numRuns);
   var _numRuns = 0;
 
+  Future<int> get maxParallelRuns => schedule(() => _maxParallelRuns);
+  var _maxParallelRuns = 0;
+
   /// The number of currently running transforms.
   int _runningTransforms = 0;
 
@@ -176,6 +179,9 @@
     _numRuns++;
     if (_runningTransforms == 0) _started.complete();
     _runningTransforms++;
+    if (_runningTransforms > _maxParallelRuns) {
+      _maxParallelRuns = _runningTransforms;
+    }
     return newFuture(() => doApply(transform)).then((_) {
       if (_apply != null) return _apply.future;
     }).whenComplete(() {
diff --git a/pkg/browser/lib/interop.js b/pkg/browser/lib/interop.js
index 71af132..1caeb5a 100644
--- a/pkg/browser/lib/interop.js
+++ b/pkg/browser/lib/interop.js
@@ -457,7 +457,7 @@
       if (proxiedObjectTable.contains(id)) {
         return proxiedObjectTable.get(id);
       }
-      proxy = new DartObject(id, port);
+      var proxy = new DartObject(id, port);
       proxiedObjectTable.add(proxy, id);
       return proxy;
     }
diff --git a/pkg/collection_helpers/lib/algorithms.dart b/pkg/collection_helpers/lib/algorithms.dart
new file mode 100644
index 0000000..c5229b3
--- /dev/null
+++ b/pkg/collection_helpers/lib/algorithms.dart
@@ -0,0 +1,301 @@
+// 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.
+
+/**
+ * Operations on collections.
+ */
+library dart.collection_helper.algorithms;
+
+import "dart:math" show Random;
+
+/** Version of [binarySearch] optimized for comparable keys */
+int _comparableBinarySearch(List<Comparable> list, Comparable key) {
+  int min = 0;
+  int max = list.length;
+  while (min < max) {
+    int mid = min + ((max - min) >> 1);
+    var element = list[mid];
+    int comp = element.compareTo(key);
+    if (comp == 0) return mid;
+    if (comp < 0) {
+      min = mid + 1;
+    } else {
+      max = mid;
+    }
+  }
+  return -1;
+}
+
+/**
+ * Returns a position of the [key] in [sortedList], if it is there.
+ *
+ * If the list isn't sorted according to the [compare] function, the result
+ * is unpredictable.
+ *
+ * If [compare] is omitted, it defaults to calling [Comparable.compareTo] on
+ * the objects.
+ *
+ * Returns -1 if [key] is not in the list by default.
+ */
+int binarySearch(List sortedList, var key,
+                 { int compare(var a, var b) }) {
+  if (compare == null) {
+    return _comparableBinarySearch(sortedList, key);
+  }
+  int min = 0;
+  int max = sortedList.length;
+  while (min < max) {
+    int mid = min + ((max - min) >> 1);
+    var element = sortedList[mid];
+    int comp = compare(element, key);
+    if (comp == 0) return mid;
+    if (comp < 0) {
+      min = mid + 1;
+    } else {
+      max = mid;
+    }
+  }
+  return -1;
+}
+
+
+/**
+ * Shuffles a list randomly.
+ *
+ * A sub-range of a list can be shuffled by providing [start] and [end].
+ */
+void shuffle(List list, [int start = 0, int end = null]) {
+  Random random = new Random();
+  if (end == null) end = list.length;
+  int length = end - start;
+  while (length > 1) {
+    int pos = random.nextInt(length);
+    length--;
+    var tmp1 = list[start + pos];
+    list[start + pos] = list[start + length];
+    list[start + length] = tmp1;
+  }
+}
+
+
+/**
+ * Reverses a list, or a part of a list, in-place.
+ */
+void reverse(List list, [int start = 0, int end = null]) {
+  if (end == null) end = list.length;
+  _reverse(list, start, end);
+}
+
+// Internal helper function that assumes valid arguments.
+void _reverse(List list, int start, int end) {
+  for (int i = start, j = end - 1; i < j; i++, j--) {
+    var tmp = list[i];
+    list[i] = list[j];
+    list[j] = tmp;
+  }
+}
+
+/**
+ * Sort a list using insertion sort.
+ *
+ * Insertion sort is a simple sorting algorithm. For `n` elements it does on
+ * the order of `n * log(n)` comparisons but up to `n` squared moves. The
+ * sorting is performed in-place, without using extra memory.
+ *
+ * For short lists the many moves have less impact than the simple algorithm,
+ * and it is often the favored sorting algorithm for short lists.
+ *
+ * This insertion sort is stable: Equal elements end up in the same order
+ * as they started in.
+ */
+void insertionSort(List list,
+                   { int compare(a, b),
+                     int start: 0,
+                     int end: null }) {
+  // If the same method could have both positional and named optional
+  // parameters, this should be (list, [start, end], {compare}).
+  if (end == null) end = list.length;
+  if (compare == null) compare = Comparable.compare;
+  _insertionSort(list, compare, start, end, start + 1);
+}
+
+/**
+ * Internal helper function that assumes arguments correct.
+ *
+ * Assumes that the elements up to [sortedUntil] (not inclusive) are
+ * already sorted. The [sortedUntil] values should always be at least
+ * `start + 1`.
+ */
+void _insertionSort(List list, int compare(a, b), int start, int end,
+                    int sortedUntil) {
+  for (int pos = sortedUntil; pos < end; pos++) {
+    int min = start;
+    int max = pos;
+    var element = list[pos];
+    while (min < max) {
+      int mid = min + ((max - min) >> 1);
+      int comparison = compare(element, list[mid]);
+      if (comparison < 0) {
+        max = mid;
+      } else {
+        min = mid + 1;
+      }
+    }
+    list.setRange(min + 1, pos + 1, list, min);
+    list[min] = element;
+  }
+}
+
+/** Limit below which merge sort defaults to insertion sort. */
+const int _MERGE_SORT_LIMIT = 32;
+
+/**
+ * Sorts a list, or a range of a list, using the merge sort algorithm.
+ *
+ * Merge-sorting works by splitting the job into two parts, sorting each
+ * recursively, and then merging the two sorted parts.
+ *
+ * This takes on the order of `n * log(n)` comparisons and moves to sort
+ * `n` elements, but requires extra space of about the same size as the list
+ * being sorted.
+ *
+ * This merge sort is stable: Equal elements end up in the same order
+ * as they started in.
+ */
+void mergeSort(List list, {int start: 0, int end: null, int compare(a, b)}) {
+  if (end == null) end = list.length;
+  if (compare == null) compare = Comparable.compare;
+  int length = end - start;
+  if (length < 2) return;
+  if (length < _MERGE_SORT_LIMIT) {
+    _insertionSort(list, compare, start, end, start + 1);
+    return;
+  }
+  // Special case the first split instead of directly calling
+  // _mergeSort, because the _mergeSort requires its target to
+  // be different from its source, and it requires extra space
+  // of the same size as the list to sort.
+  // This split allows us to have only half as much extra space,
+  // and it ends up in the original place.
+  int middle = start + ((end - start) >> 1);
+  int firstLength = middle - start;
+  int secondLength = end - middle;
+  // secondLength is always the same as firstLength, or one greater.
+  List scratchSpace = new List(secondLength);
+  _mergeSort(list, compare, middle, end, scratchSpace, 0);
+  int firstTarget = end - firstLength;
+  _mergeSort(list, compare, start, middle, list, firstTarget);
+  _merge(compare,
+         list, firstTarget, end,
+         scratchSpace, 0, secondLength,
+         list, start);
+}
+
+/**
+ * Performs an insertion sort into a potentially different list than the
+ * one containing the original values.
+ *
+ * It will work in-place as well.
+ */
+void _movingInsertionSort(List list, int compare(a, b), int start, int end,
+                          List target, int targetOffset) {
+  int length = end - start;
+  if (length == 0) return;
+  target[targetOffset] = list[start];
+  for (int i = 1; i < length; i++) {
+    var element = list[start + i];
+    int min = targetOffset;
+    int max = targetOffset + i;
+    while (min < max) {
+      int mid = min + ((max - min) >> 1);
+      if (compare(element, target[mid]) < 0) {
+        max = mid;
+      } else {
+        min = mid + 1;
+      }
+    }
+    target.setRange(min + 1, targetOffset + i + 1,
+                    target, min);
+    target[min] = element;
+  }
+}
+
+/**
+ * Sorts [list] from [start] to [end] into [target] at [targetOffset].
+ *
+ * The `target` list must be able to contain the range from `start` to `end`
+ * after `targetOffset`.
+ *
+ * Allows target to be the same list as [list], as long as it's not
+ * overlapping the `start..end` range.
+ */
+void _mergeSort(List list, int compare(a, b), int start, int end,
+                List target, int targetOffset) {
+  int length = end - start;
+  if (length < _MERGE_SORT_LIMIT) {
+    _movingInsertionSort(list, compare, start, end, target, targetOffset);
+    return;
+  }
+  int middle = start + (length >> 1);
+  int firstLength = middle - start;
+  int secondLength = end - middle;
+  // Here secondLength >= firstLength (differs by at most one).
+  int targetMiddle = targetOffset + firstLength;
+  // Sort the second half into the end of the target area.
+  _mergeSort(list, compare, middle, end,
+             target, targetMiddle);
+  // Sort the first half into the end of the source area.
+  _mergeSort(list, compare, start, middle,
+             list, middle);
+  // Merge the two parts into the target area.
+  _merge(compare,
+         list, middle, middle + firstLength,
+         target, targetMiddle, targetMiddle + secondLength,
+         target, targetOffset);
+}
+
+/**
+ * Merges two lists into a target list.
+ *
+ * One of the input lists may be positioned at the end of the target
+ * list.
+ *
+ * For equal object, elements from [firstList] are always preferred.
+ * This allows the merge to be stable if the first list contains elements
+ * that started out earlier than the ones in [secondList]
+ */
+void _merge(int compare(a, b),
+            List firstList, int firstStart, int firstEnd,
+            List secondList, int secondStart, int secondEnd,
+            List target, int targetOffset) {
+  // No empty lists reaches here.
+  assert(firstStart < firstEnd);
+  assert(secondStart < secondEnd);
+  int cursor1 = firstStart;
+  int cursor2 = secondStart;
+  var firstElement = firstList[cursor1++];
+  var secondElement = secondList[cursor2++];
+  while (true) {
+    if (compare(firstElement, secondElement) <= 0) {
+      target[targetOffset++] = firstElement;
+      if (cursor1 == firstEnd) break;  // Flushing second list after loop.
+      firstElement = firstList[cursor1++];
+    } else {
+      target[targetOffset++] = secondElement;
+      if (cursor2 != secondEnd) {
+        secondElement = secondList[cursor2++];
+        continue;
+      }
+      // Second list empties first. Flushing first list here.
+      target[targetOffset++] = firstElement;
+      target.setRange(targetOffset, targetOffset + (firstEnd - cursor1),
+          firstList, cursor1);
+      return;
+    }
+  }
+  // First list empties first. Reached by break above.
+  target[targetOffset++] = secondElement;
+  target.setRange(targetOffset, targetOffset + (secondEnd - cursor2),
+      secondList, cursor2);
+}
diff --git a/pkg/collection_helpers/lib/all.dart b/pkg/collection_helpers/lib/all.dart
new file mode 100644
index 0000000..66571e9
--- /dev/null
+++ b/pkg/collection_helpers/lib/all.dart
@@ -0,0 +1,18 @@
+// 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.
+
+/**
+ * Exports all the individual parts of the collection-helper library.
+ *
+ * The sub-libraries of this package are:
+ * - `algorithms.dart`: Algorithms that work on lists (shuffle, binary search
+ *   and various sorting algorithms).
+ * - `wrappers.dart`: Wrapper classes that delegate to a collection object.
+ * - `equality.dart`: Different notions of equality of collections.
+ */
+library dart.collection_helper;
+
+export "algorithms.dart";
+export "wrappers.dart";
+export "equality.dart";
\ No newline at end of file
diff --git a/pkg/collection_helpers/lib/equality.dart b/pkg/collection_helpers/lib/equality.dart
new file mode 100644
index 0000000..c52d30f
--- /dev/null
+++ b/pkg/collection_helpers/lib/equality.dart
@@ -0,0 +1,419 @@
+// 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.
+
+/**
+ * Defines equality relations on collections.
+ */
+library dart.collection_helper.equality;
+
+import "dart:collection";
+
+const int _HASH_MASK = 0x7fffffff;
+
+/**
+ * A generic equality relation on objects.
+ */
+abstract class Equality<E> {
+  const factory Equality() = DefaultEquality;
+
+  /**
+   * Compare two elements for being equal.
+   *
+   * This should be a proper equality relation.
+   */
+  bool equals(E e1, E e2);
+
+  /**
+   * Get a hashcode of an element.
+   *
+   * The hashcode should be compatible with [equals], so that if
+   * `equals(a, b)` then `hash(a) == hash(b)`.
+   */
+  int hash(E e);
+
+  /**
+   * Test whether an object is a valid argument to [equals] and [hash].
+   *
+   * Some implementations may be restricted to only work on specific types
+   * of objects.
+   */
+  bool isValidKey(Object o);
+}
+
+/**
+ * Equality of objects that compares only the natural equality of the objects.
+ *
+ * This equality uses the objects' own [Object.==] and [Object.hashCode] for
+ * the equality.
+ */
+class DefaultEquality implements Equality {
+  const DefaultEquality();
+  bool equals(Object e1, Object e2) => e1 == e2;
+  int hash(Object e) => e.hashCode;
+  bool isValidKey(Object o) => true;
+}
+
+/**
+ * Equality of objects that compares only the identity of the objects.
+ */
+class IdentityEquality implements Equality {
+  const IdentityEquality();
+  bool equals(Object e1, Object e2) => identical(e1, e2);
+  int hash(Object e) => identityHashCode(e);
+  bool isValidKey(Object o) => true;
+}
+
+/**
+ * Equality on iterables.
+ *
+ * Two iterables are equal if they have the same elements in the same order.
+ */
+class IterableEquality<E> implements Equality<Iterable<E>> {
+  final Equality<E> _elementEquality;
+  const IterableEquality([Equality<E> elementEquality =
+                              const DefaultEquality()])
+      : _elementEquality = elementEquality;
+
+  bool equals(Iterable<E> elements1, Iterable<E> elements2) {
+    if (identical(elements1, elements2)) return true;
+    if (elements1 == null || elements2 == null) return false;
+    Iterator it1 = elements1.iterator;
+    Iterator it2 = elements2.iterator;
+    while (true) {
+      bool hasNext = it1.moveNext();
+      if (hasNext != it2.moveNext()) return false;
+      if (!hasNext) return true;
+      if (!_elementEquality.equals(it1.current, it2.current)) return false;
+    }
+  }
+
+  int hash(Iterable<E> elements) {
+    // Jenkins's one-at-a-time hash function.
+    int hash = 0;
+    for (E element in elements) {
+      int c = _elementEquality.hash(element);
+      hash = (hash + c) & _HASH_MASK;
+      hash = (hash + (hash << 10)) & _HASH_MASK;
+      hash ^= (hash >> 6);
+    }
+    hash = (hash + (hash << 3)) & _HASH_MASK;
+    hash ^= (hash >> 11);
+    hash = (hash + (hash << 15)) & _HASH_MASK;
+    return hash;
+  }
+
+  bool isValidKey(Object o) => o is Iterable<E>;
+}
+
+/**
+ * Equality on lists.
+ *
+ * Two lists are equal if they have the same length and their elements
+ * at each index are equal.
+ *
+ * This is effectively the same as [IterableEquality] except that it
+ * accesses elements by index instead of through iteration.
+ */
+class ListEquality<E> implements Equality<List<E>> {
+  final Equality<E> _elementEquality;
+  const ListEquality([Equality<E> elementEquality = const DefaultEquality()])
+      : _elementEquality = elementEquality;
+
+  bool equals(List<E> e1, List<E> e2) {
+    if (identical(e1, e2)) return true;
+    if (e1 == null || e2 == null) return false;
+    int length = e1.length;
+    if (length != e2.length) return false;
+    for (int i = 0; i < length; i++) {
+      if (!_elementEquality.equals(e1[i], e2[i])) return false;
+    }
+    return true;
+  }
+
+  int hash(List<E> e) {
+    // Jenkins's one-at-a-time hash function.
+    // This code is almost identical to the one in IterableEquality, except
+    // that it uses indexing instead of iterating to get the elements.
+    int hash = 0;
+    for (int i = 0; i < e.length; i++) {
+      int c = _elementEquality.hash(e[i]);
+      hash = (hash + c) & _HASH_MASK;
+      hash = (hash + (hash << 10)) & _HASH_MASK;
+      hash ^= (hash >> 6);
+    }
+    hash = (hash + (hash << 3)) & _HASH_MASK;
+    hash ^= (hash >> 11);
+    hash = (hash + (hash << 15)) & _HASH_MASK;
+    return hash;
+  }
+
+  bool isValidKey(Object o) => o is List<E>;
+}
+
+/**
+ * Equality of the elements of two iterables without considering order.
+ *
+ * Two iterables are considered equal if they have the same number of elements,
+ * and the elements of one set can be paired with the elements
+ * of the other iterable, so that each pair are equal.
+ */
+class UnorderedIterableEquality<E> implements Equality<Iterable<E>> {
+  final Equality<E> _elementEquality;
+
+  const UnorderedIterableEquality(
+      [Equality<E> elementEquality = const DefaultEquality()])
+      : _elementEquality = elementEquality;
+
+  bool equals(Iterable<E> e1, Iterable<E> e2) {
+    if (identical(e1, e2)) return true;
+    if (e1 == null || e2 == null) return false;
+    HashMap<E, int> counts = new HashMap(
+        equals: _elementEquality.equals,
+        hashCode: _elementEquality.hash,
+        isValidKey: _elementEquality.isValidKey);
+    int length = 0;
+    for (E e in e1) {
+      int count = counts[e];
+      if (count == null) count = 0;
+      counts[e] = count + 1;
+      length++;
+    }
+    for (E e in e2) {
+      int count = counts[e];
+      if (count == null || count == 0) return false;
+      counts[e] = count - 1;
+      length--;
+    }
+    return length == 0;
+  }
+
+  int hash(Iterable<E> e) {
+    int hash = 0;
+    for (E element in e) {
+      int c = _elementEquality.hash(element);
+      hash = (hash + c) & _HASH_MASK;
+    }
+    hash = (hash + (hash << 3)) & _HASH_MASK;
+    hash ^= (hash >> 11);
+    hash = (hash + (hash << 15)) & _HASH_MASK;
+    return hash;
+  }
+
+  bool isValidKey(Object o) => o is Iterable<E>;
+}
+
+/**
+ * Equality of sets.
+ *
+ * Two sets are considered equal if they have the same number of elements,
+ * and the elements of one set can be paired with the elements
+ * of the other set, so that each pair are equal.
+ *
+ * This equality behaves the same as [UnorderedIterableEquality] except that
+ * it expects sets instead of iterables as arguments.
+ */
+class SetEquality<E> extends UnorderedIterableEquality<E>
+                     implements Equality<Set<E>> {
+  const SetEquality(
+      [Equality<E> elementEquality = const DefaultEquality()])
+      : super(elementEquality);
+
+  bool equals(Set<E> e1, Set<E> e2) => super.equals(e1, e2);
+
+  int hash(Set<E> e) => super.hash(e);
+
+  bool isValidKey(Object o) => o is Set<E>;
+}
+
+/**
+ *  Internal class used by [MapEquality].
+ *
+ *  The class represents a map entry as a single object,
+ *  using a combined hashCode and equality of the key and value.
+ */
+class _MapEntry {
+  final MapEquality equality;
+  final key;
+  final value;
+  _MapEntry(this.equality, this.key, this.value);
+
+  int get hashCode =>
+      (3 * equality._keyEquality.hash(key) +
+       7 * equality._valueEquality.hash(value)) & _HASH_MASK;
+
+  bool operator==(Object other) {
+    if (other is! _MapEntry) return false;
+    _MapEntry otherEntry = other;
+    return equality._keyEquality.equals(key, otherEntry.key) &&
+           equality._valueEquality.equals(value, otherEntry.value);
+
+  }
+}
+
+/**
+ * Equality on maps.
+ *
+ * Two maps are equal if they have the same number of entries, and if the
+ * entries of the two maps are pairwise equal on both key and value.
+ */
+class MapEquality<K, V> implements Equality<Map<K, V>> {
+  final Equality<K> _keyEquality;
+  final Equality<V> _valueEquality;
+  const MapEquality({ Equality<K> keys : const DefaultEquality(),
+                      Equality<V> values : const DefaultEquality() })
+      : _keyEquality = keys, _valueEquality = values;
+
+  bool equals(Map<K, V> e1, Map<K, V> e2) {
+    if (identical(e1, e2)) return true;
+    if (e1 == null || e2 == null) return false;
+    int length = e1.length;
+    if (length != e2.length) return false;
+    Map<_MapEntry, int> equalElementCounts = new HashMap();
+    for (K key in e1.keys) {
+      _MapEntry entry = new _MapEntry(this, key, e1[key]);
+      int count = equalElementCounts[entry];
+      if (count == null) count = 0;
+      equalElementCounts[entry] = count + 1;
+    }
+    for (K key in e2.keys) {
+      _MapEntry entry = new _MapEntry(this, key, e2[key]);
+      int count = equalElementCounts[entry];
+      if (count == null || count == 0) return false;
+      equalElementCounts[entry] = count - 1;
+    }
+    return true;
+  }
+
+  int hash(Map<K, V> map) {
+    int hash = 0;
+    for (K key in map.keys) {
+      int keyHash = _keyEquality.hash(key);
+      int valueHash = _valueEquality.hash(map[key]);
+      hash = (hash + 3 * keyHash + 7 * valueHash) & _HASH_MASK;
+    }
+    hash = (hash + (hash << 3)) & _HASH_MASK;
+    hash ^= (hash >> 11);
+    hash = (hash + (hash << 15)) & _HASH_MASK;
+    return hash;
+  }
+
+  bool isValidKey(Object o) => o is Map<K, V>;
+}
+
+/**
+ * Combines several equalities into a single equality.
+ *
+ * Tries each equality in order, using [Equality.isValidKey], and returns
+ * the result of the first equality that applies to the argument or arguments.
+ *
+ * For `equals`, the first equality that matches the first argument is used,
+ * and if the second argument of `equals` is not valid for that equality,
+ * it returns false.
+ *
+ * Because the equalities are tried in order, they should generally work on
+ * disjoint types. Otherwise the multi-equality may give inconsistent results
+ * for `equals(e1, e2)` and `equals(e2, e1)`. This can happen if one equality
+ * considers only `e1` a valid key, and not `e2`, but an equality which is
+ * checked later, allows both.
+ */
+class MultiEquality<E> implements Equality<E> {
+  final Iterable<Equality<E>> _equalities;
+
+  const MultiEquality(Iterable<Equality<E>> equalities)
+      : _equalities = equalities;
+
+  bool equals(E e1, E e2) {
+    for (Equality<E> eq in _equalities) {
+      if (eq.isValidKey(e1)) return eq.isValidKey(e2) && eq.equals(e1, e2);
+    }
+    return false;
+  }
+
+  int hash(E e) {
+    for (Equality<E> eq in _equalities) {
+      if (eq.isValidKey(e)) return eq.hash(e);
+    }
+    return -1;
+  }
+
+  bool isValidKey(Object o) {
+    for (Equality<E> eq in _equalities) {
+      if (eq.isValidKey(o)) return true;
+    }
+    return false;
+  }
+}
+
+/**
+ * Deep equality on collections.
+ *
+ * Recognizes lists, sets, iterables and maps and compares their elements using
+ * deep equality as well.
+ *
+ * Non-iterable/map objects are compared using a configurable base equality.
+ *
+ * Works in one of two modes: ordered or unordered.
+ *
+ * In ordered mode, lists and iterables are required to have equal elements
+ * in the same order. In unordered mode, the order of elements in iterables
+ * and lists are not importan.
+ *
+ * A list is only equal to another list, likewise for sets and maps. All other
+ * iterables are compared as iterables only.
+ */
+class DeepCollectionEquality implements Equality {
+  final Equality _base;
+  final bool _unordered;
+  const DeepCollectionEquality([Equality base = const DefaultEquality()])
+      : _base = base, _unordered = false;
+
+  /**
+   * Creates a deep equality on collections where the order of lists and
+   * iterables are not considered important. That is, lists and iterables are
+   * treated as unordered iterables.
+   */
+  const DeepCollectionEquality.unordered(
+      [Equality base = const DefaultEquality()])
+      : _base = base, _unordered = true;
+
+  bool equals(e1, e2) {
+    if (e1 is Set) {
+      if (e2 is! Set) return false;
+      return new SetEquality(this).equals(e1, e2);
+    }
+    if (e1 is Map) {
+      if (e2 is! Map) return false;
+      return new MapEquality(keys: this, values: this).equals(e1, e2);
+    }
+    if (!_unordered) {
+      if (e1 is List) {
+        if (e2 is! List) return false;
+        return new ListEquality(this).equals(e1, e2);
+      }
+      if (e1 is Iterable) {
+        if (e2 is! Iterable) return false;
+        return new IterableEquality(this).equals(e1, e2);
+      }
+    } else if (e1 is Iterable) {
+      if (e2 is! Iterable) return false;
+      if (e1 is List != e2 is List) return false;
+      return new UnorderedIterableEquality(this).equals(e1, e2);
+    }
+    return _base.equals(e1, e2);
+  }
+
+  int hash(Object o) {
+    if (o is Set) return new SetEquality(this).hash(o);
+    if (o is Map) return new MapEquality(keys: this, values: this).hash(o);
+    if (!_unordered) {
+      if (o is List) return new ListEquality(this).hash(o);
+      if (o is Iterable) return new IterableEquality(this).hash(o);
+    } else if (o is Iterable) {
+      return new UnorderedIterableEquality(this).hash(o);
+    }
+    return _base.hash(o);
+  }
+
+  bool isValidKey(Object o) => o is Iterable || o is Map || _base.isValidKey(o);
+}
diff --git a/pkg/collection_helpers/lib/wrappers.dart b/pkg/collection_helpers/lib/wrappers.dart
new file mode 100644
index 0000000..36b9b03
--- /dev/null
+++ b/pkg/collection_helpers/lib/wrappers.dart
@@ -0,0 +1,322 @@
+// 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.
+
+/**
+ * Delegating wrappers for [Iterable], [List], [Set], [Queue] and [Map].
+ */
+library dart.collection_helper.wrappers;
+
+import "dart:collection";
+import "dart:math" show Random;
+
+/**
+ * Creates an [Iterable] that delegates all operations to a base iterable.
+ *
+ * This class can be used hide non-`Iterable` methods of an iterable object,
+ * or it can be extended to add extra functionality on top of an existing
+ * iterable object.
+ */
+class DelegatingIterable<E> implements Iterable<E> {
+  Iterable<E> _base;
+
+  /**
+   * Create a wrapper that forwards operations to [base].
+   */
+  DelegatingIterable(Iterable<E> base) : _base = base;
+
+  bool any(bool test(E element)) => _base.any(test);
+
+  bool contains(Object element) => _base.contains(element);
+
+  E elementAt(int index) => _base.elementAt(index);
+
+  bool every(bool test(E element)) => _base.every(test);
+
+  Iterable expand(Iterable f(E element)) => _base.expand(f);
+
+  E get first => _base.first;
+
+  E firstWhere(bool test(E element), {E orElse()}) =>
+      _base.firstWhere(test, orElse: orElse);
+
+  fold(initialValue, combine(previousValue, E element)) =>
+      _base.fold(initialValue, combine);
+
+  void forEach(void f(E element)) => _base.forEach(f);
+
+  bool get isEmpty => _base.isEmpty;
+
+  bool get isNotEmpty => _base.isNotEmpty;
+
+  Iterator<E> get iterator => _base.iterator;
+
+  String join([String separator = ""]) => _base.join(separator);
+
+  E get last => _base.last;
+
+  E lastWhere(bool test(E element), {E orElse()}) =>
+      _base.lastWhere(test, orElse: orElse);
+
+  int get length => _base.length;
+
+  Iterable map(f(E element)) => _base.map(f);
+
+  E reduce(E combine(E value, E element)) => _base.reduce(combine);
+
+  E get single => _base.single;
+
+  E singleWhere(bool test(E element)) => _base.singleWhere(test);
+
+  Iterable<E> skip(int n) => _base.skip(n);
+
+  Iterable<E> skipWhile(bool test(E value)) => _base.skipWhile(test);
+
+  Iterable<E> take(int n) => _base.take(n);
+
+  Iterable<E> takeWhile(bool test(E value)) => _base.takeWhile(test);
+
+  List<E> toList({bool growable: true}) => _base.toList(growable: growable);
+
+  Set<E> toSet() => _base.toSet();
+
+  Iterable<E> where(bool test(E element)) => _base.where(test);
+}
+
+
+/**
+ * Creates a [List] that delegates all operations to a base list.
+ *
+ * This class can be used hide non-`List` methods of a list object,
+ * or it can be extended to add extra functionality on top of an existing
+ * list object.
+ */
+class DelegatingList<E> extends DelegatingIterable<E> implements List<E> {
+  DelegatingList(List<E> base) : super(base);
+
+  List<E> get _listBase => _base;
+
+  E operator [](int index) => _listBase[index];
+
+  void operator []=(int index, E value) {
+    _listBase[index] = value;
+  }
+
+  void add(E value) {
+    _listBase.add(value);
+  }
+
+  void addAll(Iterable<E> iterable) {
+    _listBase.addAll(iterable);
+  }
+
+  Map<int, E> asMap() => _listBase.asMap();
+
+  void clear() {
+    _listBase.clear();
+  }
+
+  void fillRange(int start, int end, [E fillValue]) {
+    _listBase.fillRange(start, end, fillValue);
+  }
+
+  Iterable<E> getRange(int start, int end) => _listBase.getRange(start, end);
+
+  int indexOf(E element, [int start = 0]) => _listBase.indexOf(element, start);
+
+  void insert(int index, E element) {
+    _listBase.insert(index, element);
+  }
+
+  void insertAll(int index, Iterable<E> iterable) {
+    _listBase.insertAll(index, iterable);
+  }
+
+  int lastIndexOf(E element, [int start]) =>
+      _listBase.lastIndexOf(element, start);
+
+  void set length(int newLength) {
+    _listBase.length = newLength;
+  }
+
+  bool remove(Object value) => _listBase.remove(value);
+
+  E removeAt(int index) => _listBase.removeAt(index);
+
+  E removeLast() => _listBase.removeLast();
+
+  void removeRange(int start, int end) {
+    _listBase.removeRange(start, end);
+  }
+
+  void removeWhere(bool test(E element)) {
+    _listBase.removeWhere(test);
+  }
+
+  void replaceRange(int start, int end, Iterable<E> iterable) {
+    _listBase.replaceRange(start, end, iterable);
+  }
+
+  void retainWhere(bool test(E element)) {
+    _listBase.retainWhere(test);
+  }
+
+  Iterable<E> get reversed => _listBase.reversed;
+
+  void setAll(int index, Iterable<E> iterable) {
+    _listBase.setAll(index, iterable);
+  }
+
+  void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
+    _listBase.setRange(start, end, iterable, skipCount);
+  }
+
+  void shuffle([Random random]) {
+    _listBase.shuffle(random);
+  }
+
+  void sort([int compare(E a, E b)]) {
+    _listBase.sort(compare);
+  }
+
+  List<E> sublist(int start, [int end]) => _listBase.sublist(start, end);
+}
+
+
+/**
+ * Creates a [Set] that delegates all operations to a base set.
+ *
+ * This class can be used hide non-`Set` methods of a set object,
+ * or it can be extended to add extra functionality on top of an existing
+ * set object.
+ */
+class DelegatingSet<E> extends DelegatingIterable<E> implements Set<E> {
+  DelegatingSet(Set<E> base) : super(base);
+
+  Set<E> get _setBase => _base;
+
+  bool add(E value) => _setBase.add(value);
+
+  void addAll(Iterable<E> elements) {
+    _setBase.addAll(elements);
+  }
+
+  void clear() {
+    _setBase.clear();
+  }
+
+  bool containsAll(Iterable<Object> other) => _setBase.containsAll(other);
+
+  Set<E> difference(Set<E> other) => _setBase.difference(other);
+
+  Set<E> intersection(Set<Object> other) => _setBase.intersection(other);
+
+  E lookup(E element) => _setBase.lookup(element);
+
+  bool remove(Object value) => _setBase.remove(value);
+
+  void removeAll(Iterable<Object> elements) {
+    _setBase.removeAll(elements);
+  }
+
+  void removeWhere(bool test(E element)) {
+    _setBase.removeWhere(test);
+  }
+
+  void retainAll(Iterable<Object> elements) {
+    _setBase.retainAll(elements);
+  }
+
+  void retainWhere(bool test(E element)) {
+    _setBase.retainWhere(test);
+  }
+
+  Set<E> union(Set<E> other) => _setBase.union(other);
+}
+
+/**
+ * Creates a [Queue] that delegates all operations to a base queue.
+ *
+ * This class can be used hide non-`Queue` methods of a queue object,
+ * or it can be extended to add extra functionality on top of an existing
+ * queue object.
+ */
+class DelegatingQueue<E> extends DelegatingIterable<E> implements Queue<E> {
+  DelegatingQueue(Queue<E> queue) : super(queue);
+
+  Queue<E> get _baseQueue => _base;
+
+  void add(E value) {
+    _baseQueue.add(value);
+  }
+
+  void addAll(Iterable<E> iterable) {
+    _baseQueue.addAll(iterable);
+  }
+
+  void addFirst(E value) {
+    _baseQueue.addFirst(value);
+  }
+
+  void addLast(E value) {
+    _baseQueue.addLast(value);
+  }
+
+  void clear() {
+    _baseQueue.clear();
+  }
+
+  bool remove(Object object) => _baseQueue.remove(object);
+
+  E removeFirst() => _baseQueue.removeFirst();
+
+  E removeLast() => _baseQueue.removeLast();
+}
+
+/**
+ * Creates a [Map] that delegates all operations to a base map.
+ *
+ * This class can be used hide non-`Map` methods of an object that extends
+ * `Map`, or it can be extended to add extra functionality on top of an existing
+ * map object.
+ */
+class DelegatingMap<K, V> implements Map<K, V> {
+  Map<K, V> _base;
+  DelegatingMap(Map<K, V> base) : _base = base;
+
+  V operator [](Object key) => _base[key];
+
+  void operator []=(K key, V value) {
+    _base[key] = value;
+  }
+
+  void addAll(Map<K, V> other) {
+    _base.addAll(other);
+  }
+
+  void clear() {
+    _base.clear();
+  }
+
+  bool containsKey(Object key) => _base.containsKey(key);
+
+  bool containsValue(Object value) => _base.containsValue(value);
+
+  void forEach(void f(K key, V value)) {
+    _base.forEach(f);
+  }
+
+  bool get isEmpty => _base.isEmpty;
+
+  bool get isNotEmpty => _base.isNotEmpty;
+
+  Iterable<K> get keys => _base.keys;
+
+  int get length => _base.length;
+
+  V putIfAbsent(K key, V ifAbsent()) => _base.putIfAbsent(key, ifAbsent);
+
+  V remove(Object key) => _base.remove(key);
+
+  Iterable<V> get values => _base.values;
+}
diff --git a/pkg/collection_helpers/pubspec.yaml b/pkg/collection_helpers/pubspec.yaml
new file mode 100644
index 0000000..a0513ef
--- /dev/null
+++ b/pkg/collection_helpers/pubspec.yaml
@@ -0,0 +1,6 @@
+name: collection_helpers
+author: '"Dart Team <misc@dartlang.org>"'
+description: Utility functions and classes for working with collections.
+homepage: http://www.dartlang.org
+dev_dependencies:
+  unittest: any
diff --git a/pkg/collection_helpers/test/algorithms_test.dart b/pkg/collection_helpers/test/algorithms_test.dart
new file mode 100644
index 0000000..ff82fff
--- /dev/null
+++ b/pkg/collection_helpers/test/algorithms_test.dart
@@ -0,0 +1,271 @@
+// 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.
+
+/// Tests algorithm utilities.
+
+import "package:collection_helpers/all.dart";
+import "package:unittest/unittest.dart";
+import 'dart:math';
+
+void main() {
+  void testShuffle(List list) {
+    List copy = list.toList();
+    shuffle(list);
+    expect(new UnorderedIterableEquality().equals(list, copy), isTrue);
+  }
+
+  test("Shuffle 0", () {
+    testShuffle([]);
+  });
+  test("Shuffle 1", () {
+    testShuffle([1]);
+  });
+  test("Shuffle 3", () {
+    testShuffle([1, 2, 3]);
+  });
+  test("Shuffle 10", () {
+    testShuffle([1, 2, 3, 4, 5, 1, 3, 5, 7, 9]);
+  });
+  test("Shuffle shuffles", () {
+    List l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
+    List c = l.toList();
+    int count = 0;
+    do {
+      shuffle(l);
+      if (!const ListEquality().equals(c, l)) return;
+      // Odds of not changing the order should be one in ~ 16! ~= 2e+13.
+      // Repeat this 10 times, and the odds of accidentally shuffling to the
+      // same result every time is disappearingly tiny.
+      count++;
+      // If this happens even once, it's ok to report it.
+      print("Failed shuffle $count times");
+      if (count == 10) fail("Shuffle didn't change order.");
+    } while (true);
+  });
+  test("Shuffle sublist", (){
+    List l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
+    List c = l.toList();
+    shuffle(l, 4, 12);
+    expect(const IterableEquality().equals(l.getRange(0, 4),
+                                           c.getRange(0, 4)), isTrue);
+    expect(const IterableEquality().equals(l.getRange(12, 16),
+                                           c.getRange(12, 16)), isTrue);
+    expect(const UnorderedIterableEquality().equals(l.getRange(4, 12),
+                                                    c.getRange(4, 12)),
+           isTrue);
+
+  });
+
+  test("binsearch0", () {
+    expect(binarySearch([], 2), equals(-1));
+  });
+
+  test("binsearch1", () {
+    expect(binarySearch([5], 2), equals(-1));
+    expect(binarySearch([5], 5), equals(0));
+    expect(binarySearch([5], 7), equals(-1));
+  });
+
+  test("binsearch3", () {
+    expect(binarySearch([0, 5, 10], -1), equals(-1));
+    expect(binarySearch([0, 5, 10], 0), equals(0));
+    expect(binarySearch([0, 5, 10], 2), equals(-1));
+    expect(binarySearch([0, 5, 10], 5), equals(1));
+    expect(binarySearch([0, 5, 10], 7), equals(-1));
+    expect(binarySearch([0, 5, 10], 10), equals(2));
+    expect(binarySearch([0, 5, 10], 12), equals(-1));
+  });
+
+  test("binsearchCompare0", () {
+    expect(binarySearch([], new C(2), compare: compareC), equals(-1));
+  });
+
+  test("binsearchCompare1", () {
+    var l1 = [new C(5)];
+    expect(binarySearch(l1, new C(2), compare: compareC), equals(-1));
+    expect(binarySearch(l1, new C(5), compare: compareC), equals(0));
+    expect(binarySearch(l1, new C(7), compare: compareC), equals(-1));
+  });
+
+  test("binsearchCompare3", () {
+    var l3 = [new C(0), new C(5), new C(10)];
+    expect(binarySearch(l3, new C(-1), compare: compareC), equals(-1));
+    expect(binarySearch(l3, new C(0), compare: compareC), equals(0));
+    expect(binarySearch(l3, new C(2), compare: compareC), equals(-1));
+    expect(binarySearch(l3, new C(5), compare: compareC), equals(1));
+    expect(binarySearch(l3, new C(7), compare: compareC), equals(-1));
+    expect(binarySearch(l3, new C(10), compare: compareC), equals(2));
+    expect(binarySearch(l3, new C(12), compare: compareC), equals(-1));
+  });
+
+  test("insertionSortRandom", () {
+    Random random = new Random();
+    for (int i = 0; i < 25; i++) {
+      List list = new List(i);
+      for (int j = 0; j < i; j++) {
+        list[j] = random.nextInt(25);  // Expect some equal elements.
+      }
+      insertionSort(list);
+      for (int j = 1; j < i; j++) {
+        expect(list[j - 1], lessThanOrEqualTo(list[j]));
+      }
+    }
+  });
+
+  test("insertionSortSubRanges", () {
+    List l = [6, 5, 4, 3, 2, 1];
+    insertionSort(l, start: 2, end: 4);
+    expect(l, equals([6, 5, 3, 4, 2, 1]));
+    insertionSort(l, start: 1, end: 1);
+    expect(l, equals([6, 5, 3, 4, 2, 1]));
+    insertionSort(l, start: 4, end: 6);
+    expect(l, equals([6, 5, 3, 4, 1, 2]));
+    insertionSort(l, start: 0, end: 2);
+    expect(l, equals([5, 6, 3, 4, 1, 2]));
+    insertionSort(l, start: 0, end: 6);
+    expect(l, equals([1, 2, 3, 4, 5, 6]));
+  });
+
+  test("insertionSortSpecialCases", () {
+    List l = [6, 6, 6, 6, 6, 6];
+    insertionSort(l);
+    expect(l, equals([6, 6, 6, 6, 6, 6]));
+
+    l = [6, 6, 3, 3, 0, 0];
+    insertionSort(l);
+    expect(l, equals([0, 0, 3, 3, 6, 6]));
+  });
+
+  test("MergeSortRandom", () {
+    Random random = new Random();
+    for (int i = 0; i < 250; i += 1) {
+      List list = new List(i);
+      for (int j = 0; j < i; j++) {
+        list[j] = random.nextInt(i);  // Expect some equal elements.
+      }
+      mergeSort(list);
+      for (int j = 1; j < i; j++) {
+        expect(list[j - 1], lessThanOrEqualTo(list[j]));
+      }
+    }
+  });
+
+  test("MergeSortPreservesOrder", () {
+    Random random = new Random();
+    // Small case where only insertion call is called,
+    // larger case where the internal moving insertion sort is used
+    // larger cases with multiple splittings, numbers just around a power of 2.
+    for (int size in [8, 50, 511, 512, 513]) {
+      List list = new List(size);
+      // Class OC compares using id.
+      // With size elements with id's in the range 0..size/4, a number of
+      // collisions are guaranteed. These should be sorted so that the "order"
+      // part of the objects are still in order.
+      for (int i = 0; i < size; i++) {
+        list[i] = new OC(random.nextInt(size >> 2), i);
+      }
+      mergeSort(list);
+      OC prev = list[0];
+      for (int i = 1; i < size; i++) {
+        OC next = list[i];
+        expect(prev.id, lessThanOrEqualTo(next.id));
+        if (next.id == prev.id) {
+          expect(prev.order, lessThanOrEqualTo(next.order));
+        }
+        prev = next;
+      }
+      // Reverse compare on part of list.
+      List copy = list.toList();
+      int min = size >> 2;
+      int max = size - min;
+      mergeSort(list, start: min, end: max, compare: (a, b) => b.compareTo(a));
+      prev = list[min];
+      for (int i = min + 1; i < max; i++) {
+        OC next = list[i];
+        expect(prev.id, greaterThanOrEqualTo(next.id));
+        if (next.id == prev.id) {
+          expect(prev.order, lessThanOrEqualTo(next.order));
+        }
+        prev = next;
+      }
+      // Equals on OC objects is identity, so this means the parts before min,
+      // and the parts after max, didn't change at all.
+      expect(list.sublist(0, min), equals(copy.sublist(0, min)));
+      expect(list.sublist(max), equals(copy.sublist(max)));
+    }
+  });
+
+  test("MergeSortSpecialCases", () {
+    for (int size in [511, 512, 513]) {
+      // All equal.
+      List list = new List(size);
+      for (int i = 0; i < size; i++) {
+        list[i] = new OC(0, i);
+      }
+      mergeSort(list);
+      for (int i = 0; i < size; i++) {
+        expect(list[i].order, equals(i));
+      }
+      // All but one equal, first.
+      list[0] = new OC(1, 0);
+      for (int i = 1; i < size; i++) {
+        list[i] = new OC(0, i);
+      }
+      mergeSort(list);
+      for (int i = 0; i < size - 1; i++) {
+        expect(list[i].order, equals(i + 1));
+      }
+      expect(list[size - 1].order, equals(0));
+
+      // All but one equal, last.
+      for (int i = 0; i < size - 1; i++) {
+        list[i] = new OC(0, i);
+      }
+      list[size - 1] = new OC(-1, size - 1);
+      mergeSort(list);
+      expect(list[0].order, equals(size - 1));
+      for (int i = 1; i < size; i++) {
+        expect(list[i].order, equals(i - 1));
+      }
+
+      // Reversed.
+      for (int i = 0; i < size; i++) {
+        list[i] = new OC(size - 1 - i, i);
+      }
+      mergeSort(list);
+      for (int i = 0; i < size; i++) {
+        expect(list[i].id, equals(i));
+        expect(list[i].order, equals(size - 1 - i));
+      }
+    }
+  });
+
+  test("Reverse", () {
+    List l = [6, 5, 4, 3, 2, 1];
+    reverse(l, 2, 4);
+    expect(l, equals([6, 5, 3, 4, 2, 1]));
+    reverse(l, 1, 1);
+    expect(l, equals([6, 5, 3, 4, 2, 1]));
+    reverse(l, 4, 6);
+    expect(l, equals([6, 5, 3, 4, 1, 2]));
+    reverse(l, 0, 2);
+    expect(l, equals([5, 6, 3, 4, 1, 2]));
+    reverse(l, 0, 6);
+    expect(l, equals([2, 1, 4, 3, 6, 5]));
+  });
+}
+
+class C {
+  final int id;
+  C(this.id);
+}
+int compareC(C one, C other) => one.id - other.id;
+
+class OC implements Comparable<OC> {
+  final int id;
+  final int order;
+  OC(this.id, this.order);
+  int compareTo(OC other) => id - other.id;
+  String toString() => "OC[$id,$order]";
+}
\ No newline at end of file
diff --git a/pkg/collection_helpers/test/equality_test.dart b/pkg/collection_helpers/test/equality_test.dart
new file mode 100644
index 0000000..00a1505
--- /dev/null
+++ b/pkg/collection_helpers/test/equality_test.dart
@@ -0,0 +1,164 @@
+// 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.
+
+// Tests equality utilities.
+
+import "dart:collection";
+import "package:collection_helpers/all.dart";
+import "package:unittest/unittest.dart";
+
+main() {
+  test("IterableEquality - List", () {
+    var l1 = [1, 2, 3, 4, 5];
+    var l2 = [1.0, 2.0, 3.0, 4.0, 5.0];
+    expect(const IterableEquality().equals(l1, l2), isTrue);
+    Equality iterId = const IterableEquality(const IdentityEquality());
+    expect(iterId.equals(l1, l2), isFalse);  /// 01: ok
+  });
+
+  test("IterableEquality - LinkedSet", () {
+    var l1 = new LinkedHashSet.from([1, 2, 3, 4, 5]);
+    var l2 = new LinkedHashSet.from([1.0, 2.0, 3.0, 4.0, 5.0]);
+    expect(const IterableEquality().equals(l1, l2), isTrue);
+    Equality iterId = const IterableEquality(const IdentityEquality());
+    expect(iterId.equals(l1, l2), isFalse);  /// 02: ok
+  });
+
+  test("ListEquality", () {
+    var l1 = [1, 2, 3, 4, 5];
+    var l2 = [1.0, 2.0, 3.0, 4.0, 5.0];
+    expect(const ListEquality().equals(l1, l2),
+           isTrue);
+    Equality listId = const ListEquality(const IdentityEquality());
+    expect(listId.equals(l1, l2), isFalse);  /// 03: ok
+  });
+
+  test("ListInequality length", () {
+    var l1 = [1, 2, 3, 4, 5];
+    var l2 = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
+    expect(const ListEquality().equals(l1, l2),
+           isFalse);
+    expect(const ListEquality(const IdentityEquality()).equals(l1, l2),
+           isFalse);
+  });
+
+  test("ListInequality value", () {
+    var l1 = [1, 2, 3, 4, 5];
+    var l2 = [1.0, 2.0, 3.0, 4.0, 6.0];
+    expect(const ListEquality().equals(l1, l2),
+           isFalse);
+    expect(const ListEquality(const IdentityEquality()).equals(l1, l2),
+           isFalse);
+  });
+
+  test("UnorderedIterableEquality", () {
+    var l1 = [1, 2, 3, 4, 5];
+    var l2 = [1.0, 3.0, 5.0, 4.0, 2.0];
+    expect(const UnorderedIterableEquality().equals(l1, l2),
+           isTrue);
+    Equality uniterId =
+        const UnorderedIterableEquality(const IdentityEquality());
+    expect(uniterId.equals(l1, l2), isFalse);  /// 04: ok
+  });
+
+  test("UnorderedIterableInequality length", () {
+    var l1 = [1, 2, 3, 4, 5];
+    var l2 = [1.0, 3.0, 5.0, 4.0, 2.0, 1.0];
+    expect(const UnorderedIterableEquality().equals(l1, l2),
+           isFalse);
+    expect(const UnorderedIterableEquality(const IdentityEquality())
+               .equals(l1, l2),
+           isFalse);
+  });
+
+  test("UnorderedIterableInequality values", () {
+    var l1 = [1, 2, 3, 4, 5];
+    var l2 = [1.0, 3.0, 5.0, 4.0, 6.0];
+    expect(const UnorderedIterableEquality().equals(l1, l2),
+           isFalse);
+    expect(const UnorderedIterableEquality(const IdentityEquality())
+               .equals(l1, l2),
+           isFalse);
+  });
+
+  test("SetEquality", () {
+    var l1 = new HashSet.from([1, 2, 3, 4, 5]);
+    var l2 = new LinkedHashSet.from([1.0, 3.0, 5.0, 4.0, 2.0]);
+    expect(const SetEquality().equals(l1, l2),
+           isTrue);
+    Equality setId = const SetEquality(const IdentityEquality());
+    expect(setId.equals(l1, l2), isFalse);  /// 05: ok
+  });
+
+  test("SetInequality length", () {
+    var l1 = new HashSet.from([1, 2, 3, 4, 5]);
+    var l2 = new LinkedHashSet.from([1.0, 3.0, 5.0, 4.0, 2.0, 6.0]);
+    expect(const SetEquality().equals(l1, l2),
+           isFalse);
+    expect(const SetEquality(const IdentityEquality()).equals(l1, l2),
+           isFalse);
+  });
+
+  test("SetInequality value", () {
+    var l1 = new HashSet.from([1, 2, 3, 4, 5]);
+    var l2 = new LinkedHashSet.from([1.0, 3.0, 5.0, 4.0, 6.0]);
+    expect(const SetEquality().equals(l1, l2),
+           isFalse);
+    expect(const SetEquality(const IdentityEquality()).equals(l1, l2),
+           isFalse);
+  });
+
+  var map1a = {"x": [1, 2, 3], "y": [true, false, null]};
+  var map1b = {"x": [4.0, 5.0, 6.0], "y": [false, true, null]};
+  var map2a = {"x": [3.0, 2.0, 1.0], "y": [false, true, null]};
+  var map2b = {"x": [6, 5, 4], "y": [null, false, true]};
+  var l1 = [map1a, map1b];
+  var l2 = [map2a, map2b];
+  var s1 = new Set.from(l1);
+  var s2 = new Set.from([map2b, map2a]);
+
+  test("RecursiveEquality", () {
+    const unordered = const UnorderedIterableEquality();
+    expect(unordered.equals(map1a["x"], map2a["x"]),
+        isTrue);
+    expect(unordered.equals(map1a["y"], map2a["y"]),
+        isTrue);
+    expect(unordered.equals(map1b["x"], map2b["x"]),
+        isTrue);
+    expect(unordered.equals(map1b["y"], map2b["y"]),
+        isTrue);
+    const mapval = const MapEquality(values: unordered);
+    expect(
+        mapval.equals(map1a, map2a),
+        isTrue);
+    expect(mapval.equals(map1b, map2b),
+        isTrue);
+    const listmapval = const ListEquality(mapval);
+    expect(listmapval.equals(l1, l2),
+        isTrue);
+    const setmapval = const SetEquality(mapval);
+    expect(setmapval.equals(s1, s2),
+        isTrue);
+  });
+
+  test("DeepEquality", () {
+    var colleq = const DeepCollectionEquality.unordered();
+    expect(colleq.equals(map1a["x"], map2a["x"]),
+        isTrue);
+    expect(colleq.equals(map1a["y"], map2a["y"]),
+        isTrue);
+    expect(colleq.equals(map1b["x"], map2b["x"]),
+        isTrue);
+    expect(colleq.equals(map1b["y"], map2b["y"]),
+        isTrue);
+    expect(colleq.equals(map1a, map2a),
+        isTrue);
+    expect(colleq.equals(map1b, map2b),
+        isTrue);
+    expect(colleq.equals(l1, l2),
+        isTrue);
+    expect(colleq.equals(s1, s2),
+        isTrue);
+  });
+}
diff --git a/pkg/collection_helpers/test/wrapper_test.dart b/pkg/collection_helpers/test/wrapper_test.dart
new file mode 100644
index 0000000..3c3da3c
--- /dev/null
+++ b/pkg/collection_helpers/test/wrapper_test.dart
@@ -0,0 +1,255 @@
+// 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.
+
+/// Tests wrapper utilities.
+
+import "dart:collection";
+import "package:collection_helpers/all.dart";
+import "package:unittest/unittest.dart";
+
+// Test that any member access/call on the wrapper object is equal to
+// an expected access on the wrapped object.
+// This is implemented by capturing accesses using noSuchMethod and comparing
+// them to expected accesses captured previously.
+
+// Compare two Invocations for having equal type and arguments.
+void testInvocations(Invocation i1, Invocation i2) {
+  String name = "${i1.memberName}";
+  expect(i1.isGetter, equals(i2.isGetter), reason: name);
+  expect(i1.isSetter, equals(i2.isSetter), reason: name);
+  expect(i1.memberName, equals(i2.memberName), reason: name);
+  expect(i1.positionalArguments, equals(i2.positionalArguments), reason: name);
+  expect(i1.namedArguments, equals(i2.namedArguments), reason: name);
+}
+
+/**
+ * Utility class to record a member access and a member access on a wrapped
+ * object, and compare them for equality.
+ */
+abstract class Expector {
+  getWrappedObject(action(Invocation i));
+  // Hack to test assignment ([]=) because it doesn't return the result
+  // of the member call. Instead use (expect..[4]=5).equal[4]=5  where
+  // you would normally use expect[4].equals[4] for non-assignments.
+  var equals;
+
+  noSuchMethod(Invocation m) => new _Equals(equals = getWrappedObject((m2) {
+    testInvocations(m, m2);
+  }));
+}
+
+// An object with a field called "equals", only introduced into the
+// flow to allow writing expect.xxx.equals.xxx.
+class _Equals {
+  final equals;
+  _Equals(this.equals);
+}
+
+// Parameterization of noSuchMethod.
+class NSM {
+  Function _action;
+  NSM(this._action);
+  noSuchMethod(Invocation i) => _action(i);
+}
+
+// LikeNSM, but has types Iterable, Set and List to allow it as
+// argument to DelegatingIterable/Set/List.
+class IterableNSM extends NSM implements Iterable, Set, List, Queue {
+  IterableNSM(action(Invocation i)) : super(action);
+  noSuchMethod(Invocation i) => super.noSuchMethod(i);  // Silence warnings
+}
+
+// Expector that wraps in DelegatingIterable.
+class IterableExpector extends Expector {
+  getWrappedObject(void action(Invocation i)) {
+    return new DelegatingIterable(new IterableNSM(action));
+  }
+}
+
+// Expector that wraps in DelegatingList.
+class ListExpector extends Expector {
+  getWrappedObject(void action(Invocation i)) {
+    return new DelegatingList(new IterableNSM(action));
+  }
+}
+
+// Expector that wraps in DelegatingSet.
+class SetExpector extends Expector {
+  getWrappedObject(void action(Invocation i)) {
+    return new DelegatingSet(new IterableNSM(action));
+  }
+}
+
+// Expector that wraps in DelegatingSet.
+class QueueExpector extends Expector {
+  getWrappedObject(void action(Invocation i)) {
+    return new DelegatingQueue(new IterableNSM(action));
+  }
+}
+
+// Like NSM but implements Map to allow as argument for DelegatingMap.
+class MapNSM extends NSM implements Map {
+  MapNSM(action(Invocation i)) : super(action);
+  noSuchMethod(Invocation i) => super.noSuchMethod(i);
+}
+
+// Expector that wraps in DelegatingMap.
+class MapExpector extends Expector {
+  getWrappedObject(void action(Invocation i)) {
+    return new DelegatingMap(new MapNSM(action));
+  }
+}
+
+// Utility values to use as arguments in calls.
+func0() {}
+func1(x) {}
+func2(x, y) {}
+var val = new Object();
+
+void main() {
+  testIterable(var expect) {
+    expect.any(func1).equals.any(func1);
+    expect.contains(val).equals.contains(val);
+    expect.elementAt(0).equals.elementAt(0);
+    expect.every(func1).equals.every(func1);
+    expect.expand(func1).equals.expand(func1);
+    expect.first.equals.first;
+    // Default values of the Iterable interface will be added in the
+    // second call to firstWhere, so we must record them in our
+    // expectation (which doesn't have the interface implementat or
+    // its default values).
+    expect.firstWhere(func1, orElse: null).equals.firstWhere(func1);
+    expect.firstWhere(func1, orElse: func0).equals.
+           firstWhere(func1, orElse: func0);
+    expect.fold(null, func2).equals.fold(null, func2);
+    expect.forEach(func1).equals.forEach(func1);
+    expect.isEmpty.equals.isEmpty;
+    expect.isNotEmpty.equals.isNotEmpty;
+    expect.iterator.equals.iterator;
+    expect.join('').equals.join();
+    expect.join("X").equals.join("X");
+    expect.last.equals.last;
+    expect.lastWhere(func1, orElse: null).equals.lastWhere(func1);
+    expect.lastWhere(func1, orElse: func0).equals.
+           lastWhere(func1, orElse: func0);
+    expect.length.equals.length;
+    expect.map(func1).equals.map(func1);
+    expect.reduce(func2).equals.reduce(func2);
+    expect.single.equals.single;
+    expect.singleWhere(func1).equals.singleWhere(func1);
+    expect.skip(5).equals.skip(5);
+    expect.skipWhile(func1).equals.skipWhile(func1);
+    expect.take(5).equals.take(5);
+    expect.takeWhile(func1).equals.takeWhile(func1);
+    expect.toList(growable: true).equals.toList();
+    expect.toList(growable: true).equals.toList(growable: true);
+    expect.toList(growable: false).equals.toList(growable: false);
+    expect.toSet().equals.toSet();
+    expect.where(func1).equals.where(func1);
+  }
+
+  void testList(var expect) {
+    testIterable(expect);
+
+    expect[4].equals[4];
+    (expect..[4] = 5).equals[4] = 5;
+
+    expect.add(val).equals.add(val);
+    expect.addAll([val]).equals.addAll([val]);
+    expect.asMap().equals.asMap();
+    expect.clear().equals.clear();
+    expect.fillRange(4, 5, null).equals.fillRange(4, 5);
+    expect.fillRange(4, 5, val).equals.fillRange(4, 5, val);
+    expect.getRange(4, 5).equals.getRange(4, 5);
+    expect.indexOf(val, 0).equals.indexOf(val);
+    expect.indexOf(val, 4).equals.indexOf(val, 4);
+    expect.insert(4, val).equals.insert(4, val);
+    expect.insertAll(4, [val]).equals.insertAll(4, [val]);
+    expect.lastIndexOf(val, null).equals.lastIndexOf(val);
+    expect.lastIndexOf(val, 4).equals.lastIndexOf(val, 4);
+    (expect..length = 4).equals.length = 4;
+    expect.remove(val).equals.remove(val);
+    expect.removeAt(4).equals.removeAt(4);
+    expect.removeLast().equals.removeLast();
+    expect.removeRange(4, 5).equals.removeRange(4, 5);
+    expect.removeWhere(func1).equals.removeWhere(func1);
+    expect.replaceRange(4, 5, [val]).equals.replaceRange(4, 5, [val]);
+    expect.retainWhere(func1).equals.retainWhere(func1);
+    expect.reversed.equals.reversed;
+    expect.setAll(4, [val]).equals.setAll(4, [val]);
+    expect.setRange(4, 5, [val], 0).equals.setRange(4, 5, [val]);
+    expect.setRange(4, 5, [val], 3).equals.setRange(4, 5, [val], 3);
+    expect.sort(null).equals.sort();
+    expect.sort(func2).equals.sort(func2);
+    expect.sublist(4, null).equals.sublist(4);
+    expect.sublist(4, 5).equals.sublist(4, 5);
+  }
+
+  void testSet(var expect) {
+    testIterable(expect);
+    Set set = new Set();
+    expect.add(val).equals.add(val);
+    expect.addAll([val]).equals.addAll([val]);
+    expect.clear().equals.clear();
+    expect.containsAll([val]).equals.containsAll([val]);
+    expect.difference(set).equals.difference(set);
+    expect.intersection(set).equals.intersection(set);
+    expect.remove(val).equals.remove(val);
+    expect.removeAll([val]).equals.removeAll([val]);
+    expect.removeWhere(func1).equals.removeWhere(func1);
+    expect.retainAll([val]).equals.retainAll([val]);
+    expect.retainWhere(func1).equals.retainWhere(func1);
+    expect.union(set).equals.union(set);
+  }
+
+  void testQueue(var expect) {
+    testIterable(expect);
+    expect.add(val).equals.add(val);
+    expect.addAll([val]).equals.addAll([val]);
+    expect.addFirst(val).equals.addFirst(val);
+    expect.addLast(val).equals.addLast(val);
+    expect.clear().equals.clear();
+    expect.remove(val).equals.remove(val);
+    expect.removeFirst().equals.removeFirst();
+    expect.removeLast().equals.removeLast();
+  }
+
+  void testMap(var expect) {
+    Map map = new Map();
+    expect[val].equals[val];
+    (expect..[val] = val).equals[val] = val;
+    expect.addAll(map).equals.addAll(map);
+    expect.clear().equals.clear();
+    expect.containsKey(val).equals.containsKey(val);
+    expect.containsValue(val).equals.containsValue(val);
+    expect.forEach(func2).equals.forEach(func2);
+    expect.isEmpty.equals.isEmpty;
+    expect.isNotEmpty.equals.isNotEmpty;
+    expect.keys.equals.keys;
+    expect.length.equals.length;
+    expect.putIfAbsent(val, func0).equals.putIfAbsent(val, func0);
+    expect.remove(val).equals.remove(val);
+    expect.values.equals.values;
+  }
+
+  test("Iterable", () {
+    testIterable(new IterableExpector());
+  });
+
+  test("List", () {
+    testList(new ListExpector());
+  });
+
+  test("Set", () {
+    testSet(new SetExpector());
+  });
+
+  test("Queue", () {
+    testQueue(new QueueExpector());
+  });
+
+  test("Map", () {
+    testMap(new MapExpector());
+  });
+}
diff --git a/pkg/custom_element/lib/custom-elements.debug.js b/pkg/custom_element/lib/custom-elements.debug.js
index 07e9380..510dc2c 100644
--- a/pkg/custom_element/lib/custom-elements.debug.js
+++ b/pkg/custom_element/lib/custom-elements.debug.js
@@ -1063,7 +1063,7 @@
     // force our .constructor to be our actual constructor
     definition.prototype.constructor = definition.ctor;
     // if initial parsing is complete
-    if (scope.ready) {
+    if (scope.ready || scope.performedInitialDocumentUpgrade) {
       // upgrade any pre-existing nodes of this type
       scope.upgradeAll(document);
     }
@@ -1385,6 +1385,7 @@
   CustomElements.parser.parse(document);
   // one more pass before register is 'live'
   CustomElements.upgradeDocument(document);
+  CustomElements.performedInitialDocumentUpgrade = true;
   // choose async
   var async = window.Platform && Platform.endOfMicrotask ?
     Platform.endOfMicrotask :
diff --git a/pkg/custom_element/lib/custom-elements.min.js b/pkg/custom_element/lib/custom-elements.min.js
index e56b846..5ed2b0d 100644
--- a/pkg/custom_element/lib/custom-elements.min.js
+++ b/pkg/custom_element/lib/custom-elements.min.js
@@ -25,4 +25,4 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-window.CustomElements={flags:{}};var SideTable;if("undefined"!=typeof WeakMap&&navigator.userAgent.indexOf("Firefox/")<0?SideTable=WeakMap:function(){var a=Object.defineProperty,b=Date.now()%1e9;SideTable=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")},SideTable.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}}}(),function(a){function b(a){u.push(a),t||(t=!0,q(d))}function c(a){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(a)||a}function d(){t=!1;var a=u;u=[],a.sort(function(a,b){return a.uid_-b.uid_});var b=!1;a.forEach(function(a){var c=a.takeRecords();e(a),c.length&&(a.callback_(c,a),b=!0)}),b&&d()}function e(a){a.nodes_.forEach(function(b){var c=p.get(b);c&&c.forEach(function(b){b.observer===a&&b.removeTransientObservers()})})}function f(a,b){for(var c=a;c;c=c.parentNode){var d=p.get(c);if(d)for(var e=0;e<d.length;e++){var f=d[e],g=f.options;if(c===a||g.subtree){var h=b(g);h&&f.enqueue(h)}}}}function g(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++v}function h(a,b){this.type=a,this.target=b,this.addedNodes=[],this.removedNodes=[],this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function i(a){var b=new h(a.type,a.target);return b.addedNodes=a.addedNodes.slice(),b.removedNodes=a.removedNodes.slice(),b.previousSibling=a.previousSibling,b.nextSibling=a.nextSibling,b.attributeName=a.attributeName,b.attributeNamespace=a.attributeNamespace,b.oldValue=a.oldValue,b}function j(a,b){return w=new h(a,b)}function k(a){return x?x:(x=i(w),x.oldValue=a,x)}function l(){w=x=void 0}function m(a){return a===x||a===w}function n(a,b){return a===b?a:x&&m(a)?x:null}function o(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var p=new SideTable,q=window.msSetImmediate;if(!q){var r=[],s=String(Math.random());window.addEventListener("message",function(a){if(a.data===s){var b=r;r=[],b.forEach(function(a){a()})}}),q=function(a){r.push(a),window.postMessage(s,"*")}}var t=!1,u=[],v=0;g.prototype={observe:function(a,b){if(a=c(a),!b.childList&&!b.attributes&&!b.characterData||b.attributeOldValue&&!b.attributes||b.attributeFilter&&b.attributeFilter.length&&!b.attributes||b.characterDataOldValue&&!b.characterData)throw new SyntaxError;var d=p.get(a);d||p.set(a,d=[]);for(var e,f=0;f<d.length;f++)if(d[f].observer===this){e=d[f],e.removeListeners(),e.options=b;break}e||(e=new o(this,a,b),d.push(e),this.nodes_.push(a)),e.addListeners()},disconnect:function(){this.nodes_.forEach(function(a){for(var b=p.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){d.removeListeners(),b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}};var w,x;o.prototype={enqueue:function(a){var c=this.observer.records_,d=c.length;if(c.length>0){var e=c[d-1],f=n(e,a);if(f)return c[d-1]=f,void 0}else b(this.observer);c[d]=a},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(a){var b=this.options;b.attributes&&a.addEventListener("DOMAttrModified",this,!0),b.characterData&&a.addEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.addEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(a){var b=this.options;b.attributes&&a.removeEventListener("DOMAttrModified",this,!0),b.characterData&&a.removeEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.removeEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(a){if(a!==this.target){this.addListeners_(a),this.transientObservedNodes.push(a);var b=p.get(a);b||p.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[],a.forEach(function(a){this.removeListeners_(a);for(var b=p.get(a),c=0;c<b.length;c++)if(b[c]===this){b.splice(c,1);break}},this)},handleEvent:function(a){switch(a.stopImmediatePropagation(),a.type){case"DOMAttrModified":var b=a.attrName,c=a.relatedNode.namespaceURI,d=a.target,e=new j("attributes",d);e.attributeName=b,e.attributeNamespace=c;var g=a.attrChange===MutationEvent.ADDITION?null:a.prevValue;f(d,function(a){return!a.attributes||a.attributeFilter&&a.attributeFilter.length&&-1===a.attributeFilter.indexOf(b)&&-1===a.attributeFilter.indexOf(c)?void 0:a.attributeOldValue?k(g):e});break;case"DOMCharacterDataModified":var d=a.target,e=j("characterData",d),g=a.prevValue;f(d,function(a){return a.characterData?a.characterDataOldValue?k(g):e:void 0});break;case"DOMNodeRemoved":this.addTransientObserver(a.target);case"DOMNodeInserted":var h,i,d=a.relatedNode,m=a.target;"DOMNodeInserted"===a.type?(h=[m],i=[]):(h=[],i=[m]);var n=m.previousSibling,o=m.nextSibling,e=j("childList",d);e.addedNodes=h,e.removedNodes=i,e.previousSibling=n,e.nextSibling=o,f(d,function(a){return a.childList?e:void 0})}l()}},a.JsMutationObserver=g}(this),!window.MutationObserver&&(window.MutationObserver=window.WebKitMutationObserver||window.JsMutationObserver,!MutationObserver))throw new Error("no mutation observer support");!function(a){function b(a,c,d){var e=a.firstElementChild;if(!e)for(e=a.firstChild;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.nextSibling;for(;e;)c(e,d)!==!0&&b(e,c,d),e=e.nextElementSibling;return null}function c(a,b){for(var c=a.shadowRoot;c;)d(c,b),c=c.olderShadowRoot}function d(a,d){b(a,function(a){return d(a)?!0:(c(a,d),void 0)}),c(a,d)}function e(a){return h(a)?(i(a),!0):(l(a),void 0)}function f(a){d(a,function(a){return e(a)?!0:void 0})}function g(a){return e(a)||f(a)}function h(b){if(!b.__upgraded__&&b.nodeType===Node.ELEMENT_NODE){var c=b.getAttribute("is")||b.localName,d=a.registry[c];if(d)return y.dom&&console.group("upgrade:",b.localName),a.upgrade(b),y.dom&&console.groupEnd(),!0}}function i(a){l(a),p(a)&&d(a,function(a){l(a)})}function j(a){if(B.push(a),!A){A=!0;var b=window.Platform&&window.Platform.endOfMicrotask||setTimeout;b(k)}}function k(){A=!1;for(var a,b=B,c=0,d=b.length;d>c&&(a=b[c]);c++)a();B=[]}function l(a){z?j(function(){m(a)}):m(a)}function m(a){(a.enteredViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.group("inserted:",a.localName),p(a)&&(a.__inserted=(a.__inserted||0)+1,a.__inserted<1&&(a.__inserted=1),a.__inserted>1?y.dom&&console.warn("inserted:",a.localName,"insert/remove count:",a.__inserted):a.enteredViewCallback&&(y.dom&&console.log("inserted:",a.localName),a.enteredViewCallback())),y.dom&&console.groupEnd())}function n(a){o(a),d(a,function(a){o(a)})}function o(a){z?j(function(){_removed(a)}):_removed(a)}function o(a){(a.leftViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.log("removed:",a.localName),p(a)||(a.__inserted=(a.__inserted||0)-1,a.__inserted>0&&(a.__inserted=0),a.__inserted<0?y.dom&&console.warn("removed:",a.localName,"insert/remove count:",a.__inserted):a.leftViewCallback&&a.leftViewCallback()))}function p(a){for(var b=a,c=window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(document)||document;b;){if(b==c)return!0;b=b.parentNode||b.host}}function q(a){if(a.shadowRoot&&!a.shadowRoot.__watched){y.dom&&console.log("watching shadow-root for: ",a.localName);for(var b=a.shadowRoot;b;)r(b),b=b.olderShadowRoot}}function r(a){a.__watched||(v(a),a.__watched=!0)}function s(a){switch(a.localName){case"style":case"script":case"template":case void 0:return!0}}function t(a){if(y.dom){var b=a[0];if(b&&"childList"===b.type&&b.addedNodes&&b.addedNodes){for(var c=b.addedNodes[0];c&&c!==document&&!c.host;)c=c.parentNode;var d=c&&(c.URL||c._URL||c.host&&c.host.localName)||"";d=d.split("/?").shift().split("/").pop()}console.group("mutations (%d) [%s]",a.length,d||"")}a.forEach(function(a){"childList"===a.type&&(D(a.addedNodes,function(a){s(a)||g(a)}),D(a.removedNodes,function(a){s(a)||n(a)}))}),y.dom&&console.groupEnd()}function u(){t(C.takeRecords()),k()}function v(a){C.observe(a,{childList:!0,subtree:!0})}function w(a){v(a)}function x(a){y.dom&&console.group("upgradeDocument: ",(a.URL||a._URL||"").split("/").pop()),g(a),y.dom&&console.groupEnd()}var y=window.logFlags||{},z=!window.MutationObserver||window.MutationObserver===window.JsMutationObserver;a.hasPolyfillMutations=z;var A=!1,B=[],C=new MutationObserver(t),D=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.watchShadow=q,a.upgradeAll=g,a.upgradeSubtree=f,a.observeDocument=w,a.upgradeDocument=x,a.takeRecords=u}(window.CustomElements),function(a){function b(b,f){var g=f||{};if(!b)throw new Error("document.register: first argument `name` must not be empty");if(b.indexOf("-")<0)throw new Error("document.register: first argument ('name') must contain a dash ('-'). Argument provided was '"+String(b)+"'.");if(g.name=b,!g.prototype)throw new Error("Options missing required prototype property");return g.lifecycle=g.lifecycle||{},g.ancestry=c(g.extends),d(g),e(g),k(g.prototype),m(b,g),g.ctor=n(g),g.ctor.prototype=g.prototype,g.prototype.constructor=g.ctor,a.ready&&a.upgradeAll(document),g.ctor}function c(a){var b=v[a];return b?c(b.extends).concat([b]):[]}function d(a){for(var b,c=a.extends,d=0;b=a.ancestry[d];d++)c=b.is&&b.tag;a.tag=c||a.name,c&&(a.is=a.name)}function e(a){if(!Object.__proto__){var b=HTMLElement.prototype;if(a.is){var c=document.createElement(a.tag);b=Object.getPrototypeOf(c)}for(var d,e=a.prototype;e&&e!==b;){var d=Object.getPrototypeOf(e);e.__proto__=d,e=d}}a.native=b}function f(a){return g(w(a.tag),a)}function g(b,c){return c.is&&b.setAttribute("is",c.is),h(b,c),b.__upgraded__=!0,a.upgradeSubtree(b),j(b),b}function h(a,b){Object.__proto__?a.__proto__=b.prototype:(i(a,b.prototype,b.native),a.__proto__=b.prototype)}function i(a,b,c){for(var d={},e=b;e!==c&&e!==HTMLUnknownElement.prototype;){for(var f,g=Object.getOwnPropertyNames(e),h=0;f=g[h];h++)d[f]||(Object.defineProperty(a,f,Object.getOwnPropertyDescriptor(e,f)),d[f]=1);e=Object.getPrototypeOf(e)}}function j(a){a.createdCallback&&a.createdCallback()}function k(a){var b=a.setAttribute;a.setAttribute=function(a,c){l.call(this,a,c,b)};var c=a.removeAttribute;a.removeAttribute=function(a){l.call(this,a,null,c)}}function l(a,b,c){var d=this.getAttribute(a);c.apply(this,arguments),this.attributeChangedCallback&&this.getAttribute(a)!==d&&this.attributeChangedCallback(a,d,b)}function m(a,b){if(v[a])throw new Error("Cannot register a tag more than once");v[a]=b}function n(a){return function(){return f(a)}}function o(a,b){var c=v[b||a];if(c){if(a==c.tag&&b==c.is)return new c.ctor;if(!b&&!c.is)return new c.ctor}if(b){var d=o(a);return d.setAttribute("is",b),d}var d=w(a);return a.indexOf("-")>=0&&h(d,HTMLElement),d}function p(a){if(!a.__upgraded__&&a.nodeType===Node.ELEMENT_NODE){var b=a.getAttribute("is"),c=v[b||a.localName];if(c){if(b&&c.tag==a.localName)return g(a,c);if(!b&&!c.extends)return g(a,c)}}}function q(b){var c=x.call(this,b);return a.upgradeAll(c),c}a||(a=window.CustomElements={flags:{}});var r=a.flags,s=Boolean(document.register),t=!r.register&&s;if(t){var u=function(){};a.registry={},a.upgradeElement=u,a.watchShadow=u,a.upgrade=u,a.upgradeAll=u,a.upgradeSubtree=u,a.observeDocument=u,a.upgradeDocument=u,a.takeRecords=u}else{var v={},w=document.createElement.bind(document),x=Node.prototype.cloneNode;document.register=b,document.createElement=o,Node.prototype.cloneNode=q,a.registry=v,a.upgrade=p}a.hasNative=s,a.useNative=t}(window.CustomElements),function(){function a(a){return"link"===a.localName&&a.getAttribute("rel")===b}var b=window.HTMLImports?HTMLImports.IMPORT_LINK_TYPE:"none",c={selectors:["link[rel="+b+"]"],map:{link:"parseLink"},parse:function(a){if(!a.__parsed){a.__parsed=!0;var b=a.querySelectorAll(c.selectors);d(b,function(a){c[c.map[a.localName]](a)}),CustomElements.upgradeDocument(a),CustomElements.observeDocument(a)}},parseLink:function(b){a(b)&&this.parseImport(b)},parseImport:function(a){a.content&&c.parse(a.content)}},d=Array.prototype.forEach.call.bind(Array.prototype.forEach);CustomElements.parser=c}(),function(){function a(){CustomElements.parser.parse(document),CustomElements.upgradeDocument(document);var a=window.Platform&&Platform.endOfMicrotask?Platform.endOfMicrotask:setTimeout;a(function(){CustomElements.ready=!0,CustomElements.readyTime=Date.now(),window.HTMLImports&&(CustomElements.elapsed=CustomElements.readyTime-HTMLImports.readyTime),document.body.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0}))})}if("function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a){var b=document.createEvent("HTMLEvents");return b.initEvent(a,!0,!0),b}),"complete"===document.readyState)a();else{var b=window.HTMLImports?"HTMLImportsLoaded":"loading"==document.readyState?"DOMContentLoaded":"load";window.addEventListener(b,a)}}(),function(){function a(){}if(HTMLElement.prototype.createShadowRoot){var b=HTMLElement.prototype.createShadowRoot;HTMLElement.prototype.createShadowRoot=function(){var a=b.call(this);return a.host=this,a}}if(window.ShadowDOMPolyfill){CustomElements.watchShadow=a,CustomElements.watchAllShadows=a;var c=["upgradeAll","upgradeSubtree","observeDocument","upgradeDocument"],d={};c.forEach(function(a){d[a]=CustomElements[a]}),c.forEach(function(a){CustomElements[a]=function(b){return d[a](ShadowDOMPolyfill.wrapIfNeeded(b))}})}}();
+window.CustomElements={flags:{}};var SideTable;if("undefined"!=typeof WeakMap&&navigator.userAgent.indexOf("Firefox/")<0?SideTable=WeakMap:function(){var a=Object.defineProperty,b=Date.now()%1e9;SideTable=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")},SideTable.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}}}(),function(a){function b(a){u.push(a),t||(t=!0,q(d))}function c(a){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(a)||a}function d(){t=!1;var a=u;u=[],a.sort(function(a,b){return a.uid_-b.uid_});var b=!1;a.forEach(function(a){var c=a.takeRecords();e(a),c.length&&(a.callback_(c,a),b=!0)}),b&&d()}function e(a){a.nodes_.forEach(function(b){var c=p.get(b);c&&c.forEach(function(b){b.observer===a&&b.removeTransientObservers()})})}function f(a,b){for(var c=a;c;c=c.parentNode){var d=p.get(c);if(d)for(var e=0;e<d.length;e++){var f=d[e],g=f.options;if(c===a||g.subtree){var h=b(g);h&&f.enqueue(h)}}}}function g(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++v}function h(a,b){this.type=a,this.target=b,this.addedNodes=[],this.removedNodes=[],this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function i(a){var b=new h(a.type,a.target);return b.addedNodes=a.addedNodes.slice(),b.removedNodes=a.removedNodes.slice(),b.previousSibling=a.previousSibling,b.nextSibling=a.nextSibling,b.attributeName=a.attributeName,b.attributeNamespace=a.attributeNamespace,b.oldValue=a.oldValue,b}function j(a,b){return w=new h(a,b)}function k(a){return x?x:(x=i(w),x.oldValue=a,x)}function l(){w=x=void 0}function m(a){return a===x||a===w}function n(a,b){return a===b?a:x&&m(a)?x:null}function o(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var p=new SideTable,q=window.msSetImmediate;if(!q){var r=[],s=String(Math.random());window.addEventListener("message",function(a){if(a.data===s){var b=r;r=[],b.forEach(function(a){a()})}}),q=function(a){r.push(a),window.postMessage(s,"*")}}var t=!1,u=[],v=0;g.prototype={observe:function(a,b){if(a=c(a),!b.childList&&!b.attributes&&!b.characterData||b.attributeOldValue&&!b.attributes||b.attributeFilter&&b.attributeFilter.length&&!b.attributes||b.characterDataOldValue&&!b.characterData)throw new SyntaxError;var d=p.get(a);d||p.set(a,d=[]);for(var e,f=0;f<d.length;f++)if(d[f].observer===this){e=d[f],e.removeListeners(),e.options=b;break}e||(e=new o(this,a,b),d.push(e),this.nodes_.push(a)),e.addListeners()},disconnect:function(){this.nodes_.forEach(function(a){for(var b=p.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){d.removeListeners(),b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}};var w,x;o.prototype={enqueue:function(a){var c=this.observer.records_,d=c.length;if(c.length>0){var e=c[d-1],f=n(e,a);if(f)return c[d-1]=f,void 0}else b(this.observer);c[d]=a},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(a){var b=this.options;b.attributes&&a.addEventListener("DOMAttrModified",this,!0),b.characterData&&a.addEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.addEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(a){var b=this.options;b.attributes&&a.removeEventListener("DOMAttrModified",this,!0),b.characterData&&a.removeEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.removeEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(a){if(a!==this.target){this.addListeners_(a),this.transientObservedNodes.push(a);var b=p.get(a);b||p.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[],a.forEach(function(a){this.removeListeners_(a);for(var b=p.get(a),c=0;c<b.length;c++)if(b[c]===this){b.splice(c,1);break}},this)},handleEvent:function(a){switch(a.stopImmediatePropagation(),a.type){case"DOMAttrModified":var b=a.attrName,c=a.relatedNode.namespaceURI,d=a.target,e=new j("attributes",d);e.attributeName=b,e.attributeNamespace=c;var g=a.attrChange===MutationEvent.ADDITION?null:a.prevValue;f(d,function(a){return!a.attributes||a.attributeFilter&&a.attributeFilter.length&&-1===a.attributeFilter.indexOf(b)&&-1===a.attributeFilter.indexOf(c)?void 0:a.attributeOldValue?k(g):e});break;case"DOMCharacterDataModified":var d=a.target,e=j("characterData",d),g=a.prevValue;f(d,function(a){return a.characterData?a.characterDataOldValue?k(g):e:void 0});break;case"DOMNodeRemoved":this.addTransientObserver(a.target);case"DOMNodeInserted":var h,i,d=a.relatedNode,m=a.target;"DOMNodeInserted"===a.type?(h=[m],i=[]):(h=[],i=[m]);var n=m.previousSibling,o=m.nextSibling,e=j("childList",d);e.addedNodes=h,e.removedNodes=i,e.previousSibling=n,e.nextSibling=o,f(d,function(a){return a.childList?e:void 0})}l()}},a.JsMutationObserver=g}(this),!window.MutationObserver&&(window.MutationObserver=window.WebKitMutationObserver||window.JsMutationObserver,!MutationObserver))throw new Error("no mutation observer support");!function(a){function b(a,c,d){var e=a.firstElementChild;if(!e)for(e=a.firstChild;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.nextSibling;for(;e;)c(e,d)!==!0&&b(e,c,d),e=e.nextElementSibling;return null}function c(a,b){for(var c=a.shadowRoot;c;)d(c,b),c=c.olderShadowRoot}function d(a,d){b(a,function(a){return d(a)?!0:(c(a,d),void 0)}),c(a,d)}function e(a){return h(a)?(i(a),!0):(l(a),void 0)}function f(a){d(a,function(a){return e(a)?!0:void 0})}function g(a){return e(a)||f(a)}function h(b){if(!b.__upgraded__&&b.nodeType===Node.ELEMENT_NODE){var c=b.getAttribute("is")||b.localName,d=a.registry[c];if(d)return y.dom&&console.group("upgrade:",b.localName),a.upgrade(b),y.dom&&console.groupEnd(),!0}}function i(a){l(a),p(a)&&d(a,function(a){l(a)})}function j(a){if(B.push(a),!A){A=!0;var b=window.Platform&&window.Platform.endOfMicrotask||setTimeout;b(k)}}function k(){A=!1;for(var a,b=B,c=0,d=b.length;d>c&&(a=b[c]);c++)a();B=[]}function l(a){z?j(function(){m(a)}):m(a)}function m(a){(a.enteredViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.group("inserted:",a.localName),p(a)&&(a.__inserted=(a.__inserted||0)+1,a.__inserted<1&&(a.__inserted=1),a.__inserted>1?y.dom&&console.warn("inserted:",a.localName,"insert/remove count:",a.__inserted):a.enteredViewCallback&&(y.dom&&console.log("inserted:",a.localName),a.enteredViewCallback())),y.dom&&console.groupEnd())}function n(a){o(a),d(a,function(a){o(a)})}function o(a){z?j(function(){_removed(a)}):_removed(a)}function o(a){(a.leftViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.log("removed:",a.localName),p(a)||(a.__inserted=(a.__inserted||0)-1,a.__inserted>0&&(a.__inserted=0),a.__inserted<0?y.dom&&console.warn("removed:",a.localName,"insert/remove count:",a.__inserted):a.leftViewCallback&&a.leftViewCallback()))}function p(a){for(var b=a,c=window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(document)||document;b;){if(b==c)return!0;b=b.parentNode||b.host}}function q(a){if(a.shadowRoot&&!a.shadowRoot.__watched){y.dom&&console.log("watching shadow-root for: ",a.localName);for(var b=a.shadowRoot;b;)r(b),b=b.olderShadowRoot}}function r(a){a.__watched||(v(a),a.__watched=!0)}function s(a){switch(a.localName){case"style":case"script":case"template":case void 0:return!0}}function t(a){if(y.dom){var b=a[0];if(b&&"childList"===b.type&&b.addedNodes&&b.addedNodes){for(var c=b.addedNodes[0];c&&c!==document&&!c.host;)c=c.parentNode;var d=c&&(c.URL||c._URL||c.host&&c.host.localName)||"";d=d.split("/?").shift().split("/").pop()}console.group("mutations (%d) [%s]",a.length,d||"")}a.forEach(function(a){"childList"===a.type&&(D(a.addedNodes,function(a){s(a)||g(a)}),D(a.removedNodes,function(a){s(a)||n(a)}))}),y.dom&&console.groupEnd()}function u(){t(C.takeRecords()),k()}function v(a){C.observe(a,{childList:!0,subtree:!0})}function w(a){v(a)}function x(a){y.dom&&console.group("upgradeDocument: ",(a.URL||a._URL||"").split("/").pop()),g(a),y.dom&&console.groupEnd()}var y=window.logFlags||{},z=!window.MutationObserver||window.MutationObserver===window.JsMutationObserver;a.hasPolyfillMutations=z;var A=!1,B=[],C=new MutationObserver(t),D=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.watchShadow=q,a.upgradeAll=g,a.upgradeSubtree=f,a.observeDocument=w,a.upgradeDocument=x,a.takeRecords=u}(window.CustomElements),function(a){function b(b,f){var g=f||{};if(!b)throw new Error("document.register: first argument `name` must not be empty");if(b.indexOf("-")<0)throw new Error("document.register: first argument ('name') must contain a dash ('-'). Argument provided was '"+String(b)+"'.");if(g.name=b,!g.prototype)throw new Error("Options missing required prototype property");return g.lifecycle=g.lifecycle||{},g.ancestry=c(g.extends),d(g),e(g),k(g.prototype),m(b,g),g.ctor=n(g),g.ctor.prototype=g.prototype,g.prototype.constructor=g.ctor,(a.ready||a.performedInitialDocumentUpgrade)&&a.upgradeAll(document),g.ctor}function c(a){var b=v[a];return b?c(b.extends).concat([b]):[]}function d(a){for(var b,c=a.extends,d=0;b=a.ancestry[d];d++)c=b.is&&b.tag;a.tag=c||a.name,c&&(a.is=a.name)}function e(a){if(!Object.__proto__){var b=HTMLElement.prototype;if(a.is){var c=document.createElement(a.tag);b=Object.getPrototypeOf(c)}for(var d,e=a.prototype;e&&e!==b;){var d=Object.getPrototypeOf(e);e.__proto__=d,e=d}}a.native=b}function f(a){return g(w(a.tag),a)}function g(b,c){return c.is&&b.setAttribute("is",c.is),h(b,c),b.__upgraded__=!0,a.upgradeSubtree(b),j(b),b}function h(a,b){Object.__proto__?a.__proto__=b.prototype:(i(a,b.prototype,b.native),a.__proto__=b.prototype)}function i(a,b,c){for(var d={},e=b;e!==c&&e!==HTMLUnknownElement.prototype;){for(var f,g=Object.getOwnPropertyNames(e),h=0;f=g[h];h++)d[f]||(Object.defineProperty(a,f,Object.getOwnPropertyDescriptor(e,f)),d[f]=1);e=Object.getPrototypeOf(e)}}function j(a){a.createdCallback&&a.createdCallback()}function k(a){var b=a.setAttribute;a.setAttribute=function(a,c){l.call(this,a,c,b)};var c=a.removeAttribute;a.removeAttribute=function(a){l.call(this,a,null,c)}}function l(a,b,c){var d=this.getAttribute(a);c.apply(this,arguments),this.attributeChangedCallback&&this.getAttribute(a)!==d&&this.attributeChangedCallback(a,d,b)}function m(a,b){if(v[a])throw new Error("Cannot register a tag more than once");v[a]=b}function n(a){return function(){return f(a)}}function o(a,b){var c=v[b||a];if(c){if(a==c.tag&&b==c.is)return new c.ctor;if(!b&&!c.is)return new c.ctor}if(b){var d=o(a);return d.setAttribute("is",b),d}var d=w(a);return a.indexOf("-")>=0&&h(d,HTMLElement),d}function p(a){if(!a.__upgraded__&&a.nodeType===Node.ELEMENT_NODE){var b=a.getAttribute("is"),c=v[b||a.localName];if(c){if(b&&c.tag==a.localName)return g(a,c);if(!b&&!c.extends)return g(a,c)}}}function q(b){var c=x.call(this,b);return a.upgradeAll(c),c}a||(a=window.CustomElements={flags:{}});var r=a.flags,s=Boolean(document.register),t=!r.register&&s;if(t){var u=function(){};a.registry={},a.upgradeElement=u,a.watchShadow=u,a.upgrade=u,a.upgradeAll=u,a.upgradeSubtree=u,a.observeDocument=u,a.upgradeDocument=u,a.takeRecords=u}else{var v={},w=document.createElement.bind(document),x=Node.prototype.cloneNode;document.register=b,document.createElement=o,Node.prototype.cloneNode=q,a.registry=v,a.upgrade=p}a.hasNative=s,a.useNative=t}(window.CustomElements),function(){function a(a){return"link"===a.localName&&a.getAttribute("rel")===b}var b=window.HTMLImports?HTMLImports.IMPORT_LINK_TYPE:"none",c={selectors:["link[rel="+b+"]"],map:{link:"parseLink"},parse:function(a){if(!a.__parsed){a.__parsed=!0;var b=a.querySelectorAll(c.selectors);d(b,function(a){c[c.map[a.localName]](a)}),CustomElements.upgradeDocument(a),CustomElements.observeDocument(a)}},parseLink:function(b){a(b)&&this.parseImport(b)},parseImport:function(a){a.content&&c.parse(a.content)}},d=Array.prototype.forEach.call.bind(Array.prototype.forEach);CustomElements.parser=c}(),function(){function a(){CustomElements.parser.parse(document),CustomElements.upgradeDocument(document),CustomElements.performedInitialDocumentUpgrade=!0;var a=window.Platform&&Platform.endOfMicrotask?Platform.endOfMicrotask:setTimeout;a(function(){CustomElements.ready=!0,CustomElements.readyTime=Date.now(),window.HTMLImports&&(CustomElements.elapsed=CustomElements.readyTime-HTMLImports.readyTime),document.body.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0}))})}if("function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a){var b=document.createEvent("HTMLEvents");return b.initEvent(a,!0,!0),b}),"complete"===document.readyState)a();else{var b=window.HTMLImports?"HTMLImportsLoaded":"loading"==document.readyState?"DOMContentLoaded":"load";window.addEventListener(b,a)}}(),function(){function a(){}if(HTMLElement.prototype.createShadowRoot){var b=HTMLElement.prototype.createShadowRoot;HTMLElement.prototype.createShadowRoot=function(){var a=b.call(this);return a.host=this,a}}if(window.ShadowDOMPolyfill){CustomElements.watchShadow=a,CustomElements.watchAllShadows=a;var c=["upgradeAll","upgradeSubtree","observeDocument","upgradeDocument"],d={};c.forEach(function(a){d[a]=CustomElements[a]}),c.forEach(function(a){CustomElements[a]=function(b){return d[a](ShadowDOMPolyfill.wrapIfNeeded(b))}})}}();
diff --git a/pkg/custom_element/lib/custom_element.dart b/pkg/custom_element/lib/custom_element.dart
index 5ea5ca0..acabe00 100644
--- a/pkg/custom_element/lib/custom_element.dart
+++ b/pkg/custom_element/lib/custom_element.dart
@@ -19,100 +19,19 @@
 
 import 'dart:async';
 import 'dart:html';
-import 'package:mdv/mdv.dart' as mdv;
 import 'package:meta/meta.dart';
 import 'src/custom_tag_name.dart';
 
-part 'src/attribute_map.dart';
-
-// TODO(jmesserly): replace with a real custom element polyfill.
-// This is just something temporary.
 /**
- * *Warning*: this implementation is a work in progress. It only implements
- * the specification partially.
+ * *Deprecated* -- do not use. Extend [HtmlElement] and use
+ * [document.register] instead. If running on a browser without native
+ * document.register, you can add the polyfill script to your page:
  *
- * Registers a custom HTML element with [localName] and the associated
- * constructor. This will ensure the element is detected and
+ *     <script src="packages/custom_element/custom-elements.debug.js"></script>
  *
- * See the specification at:
- * <https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html>
+ * You can also use "custom-elements.min.js" for the minified version.
  */
-void registerCustomElement(String localName, CustomElement create()) {
-  if (_customElements == null) {
-    _customElements = {};
-    mdv.instanceCreated.add(initCustomElements);
-    // TODO(jmesserly): use MutationObserver to watch for inserts?
-  }
-
-  if (!isCustomTag(localName)) {
-    throw new ArgumentError('$localName is not a valid custom element name, '
-        'it should have at least one dash and not be a reserved name.');
-  }
-
-  if (_customElements.containsKey(localName)) {
-    throw new ArgumentError('custom element $localName already registered.');
-  }
-
-  // TODO(jmesserly): validate this is a valid tag name, not a selector.
-  _customElements[localName] = create;
-
-  // Initialize elements already on the page.
-  for (var query in [localName, '[is=$localName]']) {
-    for (var element in document.queryAll(query)) {
-      _initCustomElement(element, create);
-    }
-  }
-}
-
-/**
- * Creates a new element and returns it. If the [localName] has been registered
- * with [registerCustomElement], it will create the custom element.
- *
- * This is similar to `new Element.tag` in Dart and `document.createElement`
- * in JavaScript.
- *
- * *Warning*: this API is temporary until [dart:html] supports custom elements.
- */
-Element createElement(String localName) =>
-    initCustomElements(new Element.tag(localName));
-
-/**
- * Similar to `new Element.html`, but automatically creates registed custom
- * elements.
- * *Warning*: this API is temporary until [dart:html] supports custom elements.
- */
-Element createElementFromHtml(String html) =>
-    initCustomElements(new Element.html(html));
-
-/**
- * Initialize any registered custom elements recursively in the [node] tree.
- * For convenience this returns the [node] instance.
- *
- * *Warning*: this API is temporary until [dart:html] supports custom elements.
- */
-Node initCustomElements(Node node) {
-  for (var c = node.firstChild; c != null; c = c.nextNode) {
-    initCustomElements(c);
-  }
-  if (node is Element) {
-    var ctor = _customElements[(node as Element).localName];
-    if (ctor == null) {
-      var attr = (node as Element).attributes['is'];
-      if (attr != null) ctor = _customElements[attr];
-    }
-    if (ctor != null) _initCustomElement(node, ctor);
-  }
-  return node;
-}
-
-/**
- * The base class for all Dart web components. In addition to the [Element]
- * interface, it also provides lifecycle methods:
- * - [created]
- * - [inserted]
- * - [attributeChanged]
- * - [removed]
- */
+// This is only used by Dart Web UI.
 class CustomElement implements Element {
   /** The web component element wrapped by this class. */
   Element _host;
@@ -610,47 +529,3 @@
     throw new UnsupportedError('onMouseWheel is not supported');
   }
 }
-
-
-Map<String, Function> _customElements;
-
-void _initCustomElement(Element node, CustomElement ctor()) {
-  CustomElement element = ctor();
-  element.host = node;
-
-  // TODO(jmesserly): replace lifecycle stuff with a proper polyfill.
-  element.created();
-
-  _registerLifecycleInsert(element);
-}
-
-void _registerLifecycleInsert(CustomElement element) {
-  scheduleMicrotask(() {
-    // TODO(jmesserly): bottom up or top down insert?
-    var node = element.host;
-
-    // TODO(jmesserly): need a better check to see if the node has been removed.
-    if (node.parentNode == null) return;
-
-    _registerLifecycleRemove(element);
-    element.inserted();
-  });
-}
-
-void _registerLifecycleRemove(CustomElement element) {
-  // TODO(jmesserly): need fallback or polyfill for MutationObserver.
-  if (!MutationObserver.supported) return;
-
-  new MutationObserver((records, observer) {
-    var node = element.host;
-    for (var record in records) {
-      for (var removed in record.removedNodes) {
-        if (identical(node, removed)) {
-          observer.disconnect();
-          element.removed();
-          return;
-        }
-      }
-    }
-  }).observe(element.parentNode, childList: true);
-}
diff --git a/pkg/custom_element/lib/polyfill.dart b/pkg/custom_element/lib/polyfill.dart
new file mode 100644
index 0000000..413d7d6
--- /dev/null
+++ b/pkg/custom_element/lib/polyfill.dart
@@ -0,0 +1,63 @@
+// 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 APIs for interacting with the JavaScript Custom Elements polyfill. */
+library custom_element.polyfill;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:js' as js;
+
+/**
+ * A future that completes once all custom elements in the initial HTML page
+ * have been upgraded.
+ *
+ * This is needed because the native implementation can update the elements
+ * while parsing the HTML document, but the custom element polyfill cannot,
+ * so it completes this future once all elements are upgraded.
+ */
+Future customElementsReady = () {
+  if (_isReady) return new Future.value();
+
+  // Not upgraded. Wait for the polyfill to fire the WebComponentsReady event.
+  // Note: we listen on document (not on document.body) to allow this polyfill
+  // to be loaded in the HEAD element.
+  return document.on['WebComponentsReady'].first;
+}();
+
+// Return true if we are using the polyfill and upgrade is complete, or if we
+// have native document.register and therefore the browser took care of it.
+// Otherwise return false, including the case where we can't find the polyfill.
+bool get _isReady {
+  // If we don't have dart:js, assume things are ready
+  if (js.context == null) return true;
+
+  var customElements = js.context['CustomElements'];
+  if (customElements == null) {
+    // Return true if native document.register, otherwise false.
+    // (Maybe the polyfill isn't loaded yet. Wait for it.)
+    return document.supportsRegister;
+  }
+
+  return customElements['ready'] == true;
+}
+
+/**
+ * Loads `custom-elements.debug.js` or `custom-elements.min.js` by adding the
+ * script tag to the page. Returns a future that completes when custom elements
+ * are ready (equivalent to [customElementsReady]).
+ *
+ * Normally you should add this to your HTML file
+ * (the Polymer package will do this automatically), but loading dynamically
+ * can be useful for scenarios such as tests.
+ */
+Future loadCustomElementPolyfill() {
+  if (!document.supportsRegister && !js.context.hasProperty('CustomElements')) {
+    var script = new ScriptElement()
+        ..src = '/packages/custom_element/custom-elements.debug.js';
+    document.head.append(script);
+    return document.on['WebComponentsReady'].first;
+  }
+  return new Future.value();
+}
diff --git a/pkg/custom_element/lib/src/attribute_map.dart b/pkg/custom_element/lib/src/attribute_map.dart
deleted file mode 100644
index 8af62c3..0000000
--- a/pkg/custom_element/lib/src/attribute_map.dart
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of custom_element;
-
-/**
- * Represents an attribute map of model values. If any items are added,
- * removed, or replaced, then observers that are listening to [changes]
- * will be notified.
- */
-class _AttributeMap implements Map<String, String> {
-  final CustomElement _element;
-  final Map<String, String> _map;
-
-  /** Creates an attribute map wrapping the host attributes. */
-  _AttributeMap(CustomElement element)
-      : _element = element, _map = element.host.attributes;
-
-  // Forward all read methods:
-  Iterable<String> get keys => _map.keys;
-  Iterable<String> get values => _map.values;
-  int get length =>_map.length;
-  bool get isEmpty => _map.isEmpty;
-  bool get isNotEmpty => _map.isNotEmpty;
-  bool containsValue(Object value) => _map.containsValue(value);
-  bool containsKey(Object key) => _map.containsKey(key);
-  String operator [](Object key) => _map[key];
-  void forEach(void f(String key, String value)) => _map.forEach(f);
-  String toString() => _map.toString();
-
-  // Override the write methods and ensure attributeChanged is called:
-  void operator []=(String key, String value) {
-    int len = _map.length;
-    String oldValue = _map[key];
-    _map[key] = value;
-    if (len != _map.length || !identical(oldValue, value)) {
-      _element.attributeChanged(key, oldValue);
-    }
-  }
-
-  void addAll(Map<String, String> other) {
-    other.forEach((String key, String value) { this[key] = value; });
-  }
-
-  String putIfAbsent(String key, String ifAbsent()) {
-    int len = _map.length;
-    String result = _map.putIfAbsent(key, ifAbsent);
-    if (len != _map.length) {
-      _element.attributeChanged(key, null);
-    }
-    return result;
-  }
-
-  String remove(Object key) {
-    int len = _map.length;
-    String result =  _map.remove(key);
-    if (len != _map.length) {
-      _element.attributeChanged(key, result);
-    }
-    return result;
-  }
-
-  void clear() {
-    int len = _map.length;
-    if (len > 0) {
-      _map.forEach((key, value) {
-        _element.attributeChanged(key, value);
-      });
-    }
-    _map.clear();
-  }
-
-  /**
-   * This is not a [Map] method. We use it to implement "set attributes", which
-   * is a global replace operation. Rather than [clear] followed by [addAll],
-   * we try to be a bit smarter.
-   */
-  void _replaceAll(Map<String, String> other) {
-    for (var key in keys) {
-      if (!other.containsKey(key)) remove(key);
-    }
-    addAll(other);
-  }
-}
diff --git a/pkg/custom_element/pubspec.yaml b/pkg/custom_element/pubspec.yaml
index e52b080..b4b268b 100644
--- a/pkg/custom_element/pubspec.yaml
+++ b/pkg/custom_element/pubspec.yaml
@@ -8,7 +8,5 @@
 dependencies:
   meta: any
   mutation_observer: any
-  # TODO(jmesserly): fix this, we should not depend on MDV.
-  mdv: any
 dev_dependencies:
   unittest: any
diff --git a/pkg/custom_element/test/custom_element_test.dart b/pkg/custom_element/test/custom_element_test.dart
deleted file mode 100644
index 3094518..0000000
--- a/pkg/custom_element/test/custom_element_test.dart
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library custom_element.test.custom_element_test;
-
-import 'dart:async';
-import 'dart:html';
-import 'package:custom_element/custom_element.dart';
-import 'package:unittest/html_config.dart';
-import 'package:unittest/unittest.dart';
-
-main() {
-  useHtmlConfiguration();
-
-  setUp(() {
-    // Load the MutationObserver polyfill if needed.
-    if (!MutationObserver.supported) {
-      var script = new ScriptElement()
-          ..src =  '/packages/mutation_observer/mutation_observer.js';
-      document.head.append(script);
-      return script.onLoad.first;
-    }
-  });
-
-  test('register creates the element and calls lifecycle methods', () {
-    // Add element to the page.
-    var element = new Element.html('<fancy-button>foo bar</fancy-button>',
-        treeSanitizer: new NullTreeSanitizer());
-    document.body.nodes.add(element);
-
-    var xtag = null;
-    registerCustomElement('fancy-button', () => xtag = new FancyButton());
-    expect(xtag, isNotNull, reason: 'FancyButton was created');
-    expect(element.xtag, xtag, reason: 'xtag pointer should be set');
-    expect(xtag.host, element, reason: 'host pointer should be set');
-    expect(xtag.lifecycle, ['created']);
-    return new Future(() {
-      expect(xtag.lifecycle, ['created', 'inserted']);
-      element.remove();
-      // TODO(jmesserly): the extra future here is to give IE9 time to deliver
-      // its event. This seems wrong. We'll probably need some cooperation
-      // between Dart and the polyfill to coordinate the microtask event loop.
-      return new Future(() => new Future(() {
-        expect(xtag.lifecycle, ['created', 'inserted', 'removed']);
-      }));
-    });
-  });
-
-  test('create a component in code', () {
-    var element = createElement('super-button');
-    expect(element.xtag, element, reason: 'element not registered');
-
-    var xtag = null;
-    registerCustomElement('super-button', () => xtag = new FancyButton());
-
-    element = createElement('super-button');
-    expect(xtag, isNotNull, reason: 'FancyButton was created');
-    expect(element.xtag, xtag, reason: 'xtag pointer should be set');
-    expect(xtag.host, element, reason: 'host pointer should be set');
-    expect(xtag.lifecycle, ['created']);
-    return new Future(() {
-      expect(xtag.lifecycle, ['created'], reason: 'not inserted into document');
-
-      document.body.nodes.add(element);
-      return new Future(() {
-        expect(xtag.lifecycle, ['created'],
-            reason: 'mutation observer not implemented yet');
-
-        element.remove();
-        return new Future(() {
-          expect(xtag.lifecycle, ['created'],
-              reason: 'mutation observer not implemented yet');
-        });
-      });
-    });
-  });
-}
-
-class FancyButton extends CustomElement {
-  final lifecycle = [];
-  created() {
-    super.created();
-    lifecycle.add('created');
-  }
-  inserted() {
-    super.inserted();
-    lifecycle.add('inserted');
-  }
-  removed() {
-    super.removed();
-    lifecycle.add('removed');
-  }
-}
-
-/**
- * Sanitizer which does nothing.
- */
-class NullTreeSanitizer implements NodeTreeSanitizer {
-  void sanitizeTree(Node node) {}
-}
diff --git a/pkg/fixnum/lib/src/int32.dart b/pkg/fixnum/lib/src/int32.dart
index c013f91..d700040 100644
--- a/pkg/fixnum/lib/src/int32.dart
+++ b/pkg/fixnum/lib/src/int32.dart
@@ -71,7 +71,7 @@
       int c = s.codeUnitAt(i);
       int digit = _decodeDigit(c);
       if (digit < 0 || digit >= radix) {
-        throw new Exception("Non-radix code unit: $c");
+        throw new FormatException("Non-radix code unit: $c");
       }
       x = (x * radix) + digit;
     }
diff --git a/pkg/fixnum/lib/src/int64.dart b/pkg/fixnum/lib/src/int64.dart
index f12631c..192b11f 100644
--- a/pkg/fixnum/lib/src/int64.dart
+++ b/pkg/fixnum/lib/src/int64.dart
@@ -81,7 +81,7 @@
       int c = s.codeUnitAt(i);
       int digit = Int32._decodeDigit(c);
       if (digit < 0 || digit >= radix) {
-        throw new Exception("Non-radix char code: $c");
+        throw new FormatException("Non-radix char code: $c");
       }
 
       // [radix] and [digit] are at most 6 bits, component is 22, so we can
diff --git a/pkg/fixnum/test/int_32_test.dart b/pkg/fixnum/test/int_32_test.dart
index e34f714..8ce7824 100644
--- a/pkg/fixnum/test/int_32_test.dart
+++ b/pkg/fixnum/test/int_32_test.dart
@@ -304,6 +304,33 @@
     });
   });
 
+  group("parse", () {
+    test("base 10", () {
+      checkInt(int x) {
+        expect(Int32.parseRadix('$x', 10), new Int32(x));
+      }
+      checkInt(0);
+      checkInt(1);
+      checkInt(1000);
+      checkInt(12345678);
+      checkInt(2147483647);
+      checkInt(2147483648);
+      checkInt(4294967295);
+      checkInt(4294967296);
+      expect(() => Int32.parseRadix('xyzzy', -1), throwsArgumentError);
+      expect(() => Int32.parseRadix('plugh', 10),
+          throwsA(new isInstanceOf<FormatException>()));
+    });
+
+    test("parseRadix", () {
+      check(String s, int r, String x) {
+        expect(Int32.parseRadix(s, r).toString(), x);
+      }
+      check('deadbeef', 16, '-559038737');
+      check('95', 12, '113');
+    });
+  });
+
   group("string representation", () {
     test("toString", () {
       expect(new Int32(0).toString(), "0");
diff --git a/pkg/fixnum/test/int_64_test.dart b/pkg/fixnum/test/int_64_test.dart
index 891b8e7..a392182 100644
--- a/pkg/fixnum/test/int_64_test.dart
+++ b/pkg/fixnum/test/int_64_test.dart
@@ -658,6 +658,9 @@
       checkInt(4294967296);
       checkInt(-4294967295);
       checkInt(-4294967296);
+      expect(() => Int64.parseRadix('xyzzy', -1), throwsArgumentError);
+      expect(() => Int64.parseRadix('plugh', 10),
+          throwsA(new isInstanceOf<FormatException>()));
     });
 
     test("parseRadix", () {
diff --git a/pkg/http_server/README.md b/pkg/http_server/README.md
new file mode 100644
index 0000000..8653f9f
--- /dev/null
+++ b/pkg/http_server/README.md
@@ -0,0 +1,44 @@
+Library of HTTP server classes.
+
+This package contains a set of high-level classes that, together with
+HttpServer, makes is easy to provide content through HTTP servers.
+
+## Virtual Directory
+
+The VirtualDirectory class makes it possible to easy serve static content from
+the drive. It supports:
+
+ *  Range-based request, making it possible to pause/resume downloads and stream
+    videos.
+ *  If-Modified-Since based caching.
+ *  Automatic GZip-compression of content.
+ *  Ability to follow links within, either throughout the system or in a jailed
+    root.
+ *  Optional directory listing.
+
+ The following example shows how to set up a Virtual Directory of a given path
+
+    var virtualDirectory = new VirtualDirectory('/var/www/');
+    virtualDirectory.serve(new HttpServer('0.0.0.0', 8080));
+
+See [VirtualDirectory](
+http://api.dartlang.org/docs/http_server/VirtualDirectory.html)
+for more info about how to customize the class.
+
+## Virtual Host
+
+The VirtualHost class makes it possible to serve multiple hosts on the same
+address, by using the `Host` field of the incoming requests. It also provides
+the ability to work on wildcards for sub-domains.
+
+    var virtualHost = new VirtualHost(server);
+    // Filter out on a specific host
+    var stream1 = virtualServer.addHost('static.myserver.com');
+    // Wildcard for any other sub-domains.
+    var stream2 = virtualServer.addHost('*.myserver.com');
+    // Requets not matching any hosts.
+    var stream3 = virtualServer.unhandled;
+
+See [VirtualHost](
+http://api.dartlang.org/docs/http_server/VirtualHost.html)
+for more information.
diff --git a/pkg/http_server/lib/src/http_body.dart b/pkg/http_server/lib/src/http_body.dart
index f05d5b2..6eb4d31 100644
--- a/pkg/http_server/lib/src/http_body.dart
+++ b/pkg/http_server/lib/src/http_body.dart
@@ -15,7 +15,7 @@
  *
  * The following content types are recognized:
  *
- *     text/\*
+ *     text/ *
  *     application/json
  *     application/x-www-form-urlencoded
  *     multipart/form-data
@@ -141,12 +141,6 @@
  */
 abstract class HttpBody {
   /**
-   * The content type e.g. application/json, application/octet-stream,
-   * application/x-www-form-urlencoded, text/plain.
-   */
-  ContentType get contentType;
-
-  /**
    * A high-level type value, that reflects how the body was parsed, e.g.
    * "text", "binary" and "json".
    */
@@ -166,22 +160,8 @@
  */
 abstract class HttpClientResponseBody extends HttpBody {
   /**
-   * Returns the status code.
-   */
-  int get statusCode;
-
-  /**
-   * Returns the reason phrase associated with the status code.
-   */
-  String get reasonPhrase;
-
-  /**
-   * Returns the response headers.
-   */
-  HttpHeaders get headers;
-
-  /**
-   * The [HttpClientResponse] of the HTTP body.
+   * The [HttpClientResponse] from which the [HttpClientResponseBody] was
+   * created.
    */
   HttpClientResponse get response;
 }
@@ -189,29 +169,17 @@
 
 /**
  * The [HttpBody] of a [HttpRequest] will be of type [HttpRequestBody]. It
- * contains the fields used to read all request header information and
- * responding to the client.
+ * provides access to the request, for reading all request header information
+ * and responding to the client.
  */
 abstract class HttpRequestBody extends HttpBody {
   /**
-   * Returns the method for the request.
+   * The [HttpRequest] from which the [HttpRequestBody] was created.
+   *
+   * Note that the [HttpRequest] is already drained at this point, so the
+   * `Stream` methods cannot be used.
    */
-  String get method;
-
-  /**
-   * Returns the URI for the request.
-   */
-  Uri get uri;
-
-  /**
-   * Returns the request headers.
-   */
-  HttpHeaders get headers;
-
-  /**
-   * The [HttpResponse] used for responding to the client.
-   */
-  HttpResponse get response;
+  HttpRequest get request;
 }
 
 
diff --git a/pkg/http_server/lib/src/http_body_impl.dart b/pkg/http_server/lib/src/http_body_impl.dart
index 8e9c6d5..81c7ede 100644
--- a/pkg/http_server/lib/src/http_body_impl.dart
+++ b/pkg/http_server/lib/src/http_body_impl.dart
@@ -64,9 +64,7 @@
     Future<HttpBody> asBinary() {
       return stream
           .fold(new BytesBuilder(), (builder, data) => builder..add(data))
-          .then((builder) => new _HttpBody(contentType,
-                                           "binary",
-                                           builder.takeBytes()));
+          .then((builder) => new _HttpBody("binary", builder.takeBytes()));
     }
 
     Future<HttpBody> asText(Encoding defaultEncoding) {
@@ -77,9 +75,7 @@
       return stream
           .transform(encoding.decoder)
           .fold(new StringBuffer(), (buffer, data) => buffer..write(data))
-          .then((buffer) => new _HttpBody(contentType,
-                                          "text",
-                                          buffer.toString()));
+          .then((buffer) => new _HttpBody("text", buffer.toString()));
     }
 
     Future<HttpBody> asFormData() {
@@ -117,7 +113,7 @@
             for (var part in parts) {
               map[part[0]] = part[1];  // Override existing entries.
             }
-            return new _HttpBody(contentType, 'form', map);
+            return new _HttpBody('form', map);
           });
     }
 
@@ -133,9 +129,7 @@
         switch (contentType.subType) {
           case "json":
             return asText(UTF8)
-                .then((body) => new _HttpBody(contentType,
-                                              "json",
-                                              JSON.decode(body.body)));
+                .then((body) => new _HttpBody("json", JSON.decode(body.body)));
 
           case "x-www-form-urlencoded":
             return asText(ASCII)
@@ -146,7 +140,7 @@
                   for (var key in map.keys) {
                     result[key] = map[key];
                   }
-                  return new _HttpBody(contentType, "form", result);
+                  return new _HttpBody("form", result);
                 });
 
           default:
@@ -180,40 +174,23 @@
 }
 
 class _HttpBody implements HttpBody {
-  final ContentType contentType;
   final String type;
   final dynamic body;
 
-  _HttpBody(ContentType this.contentType,
-            String this.type,
-            dynamic this.body);
+  _HttpBody(this.type, this.body);
 }
 
 class _HttpRequestBody extends _HttpBody implements HttpRequestBody {
-  final String method;
-  final Uri uri;
-  final HttpHeaders headers;
-  final HttpResponse response;
+  final HttpRequest request;
 
-  _HttpRequestBody(HttpRequest request, HttpBody body)
-      : super(body.contentType, body.type, body.body),
-        method = request.method,
-        uri = request.uri,
-        headers = request.headers,
-        response = request.response;
+  _HttpRequestBody(this.request, HttpBody body)
+      : super(body.type, body.body);
 }
 
 class _HttpClientResponseBody
     extends _HttpBody implements HttpClientResponseBody {
   final HttpClientResponse response;
 
-  _HttpClientResponseBody(HttpClientResponse response, HttpBody body)
-      : super(body.contentType, body.type, body.body),
-        this.response = response;
-
-  int get statusCode => response.statusCode;
-
-  String get reasonPhrase => response.reasonPhrase;
-
-  HttpHeaders get headers => response.headers;
+  _HttpClientResponseBody(this.response, HttpBody body)
+      : super(body.type, body.body);
 }
diff --git a/pkg/http_server/lib/src/virtual_directory.dart b/pkg/http_server/lib/src/virtual_directory.dart
index 42b0c026..4b38466 100644
--- a/pkg/http_server/lib/src/virtual_directory.dart
+++ b/pkg/http_server/lib/src/virtual_directory.dart
@@ -11,7 +11,7 @@
  * The [VirtualDirectory] providing secure handling of request uris and
  * file-system links, correct mime-types and custom error pages.
  */
-abstract class VirtualDirectory {
+class VirtualDirectory {
   final String root;
 
   /**
@@ -26,6 +26,17 @@
    */
   bool followLinks = true;
 
+  /**
+   * Set or get if the [VirtualDirectory] should jail the root. When the root is
+   * not jailed, links can be followed to outside the [root] directory.
+   */
+  bool jailRoot = true;
+
+  final RegExp _invalidPathRegExp = new RegExp("[\\\/\x00]");
+
+  Function _errorCallback;
+  Function _dirCallback;
+
   /*
    * Create a new [VirtualDirectory] for serving static file content of
    * the path [root].
@@ -33,49 +44,18 @@
    * The [root] is not required to exist. If the [root] doesn't exist at time of
    * a request, a 404 is generated.
    */
-  factory VirtualDirectory(String root) => new _VirtualDirectory(root);
+  VirtualDirectory(this.root);
 
   /**
    * Serve a [Stream] of [HttpRequest]s, in this [VirtualDirectory].
    */
-  void serve(Stream<HttpRequest> requests);
-
-  /**
-   * Serve a single [HttpRequest], in this [VirtualDirectory].
-   */
-  void serveRequest(HttpRequest request);
-
-  /**
-   * Set the [callback] to override the default directory listing. The
-   * [callback] will be called with the [Directory] to be listed and the
-   * [HttpRequest].
-   */
-  void setDirectoryHandler(void callback(Directory dir, HttpRequest request));
-
-  /**
-   * Set the [callback] to override the error page handler. When [callback] is
-   * invoked, the `statusCode` property of the response is set.
-   */
-  void setErrorPageHandler(void callback(HttpRequest request));
-}
-
-class _VirtualDirectory implements VirtualDirectory {
-  final String root;
-
-  bool allowDirectoryListing = false;
-  bool followLinks = true;
-
-  final RegExp _invalidPathRegExp = new RegExp("[\\\/\x00]");
-
-  Function _errorCallback;
-  Function _dirCallback;
-
-  _VirtualDirectory(this.root);
-
   void serve(Stream<HttpRequest> requests) {
     requests.listen(serveRequest);
   }
 
+  /**
+   * Serve a single [HttpRequest], in this [VirtualDirectory].
+   */
   void serveRequest(HttpRequest request) {
     _locateResource('.', request.uri.pathSegments.iterator..moveNext())
         .then((entity) {
@@ -93,18 +73,30 @@
         });
   }
 
-  void setDirectoryHandler(void callback(Directory dir, HttpRequest request)) {
+  /**
+   * Set the [callback] to override the default directory listing. The
+   * [callback] will be called with the [Directory] to be listed and the
+   * [HttpRequest].
+   */
+  void set directoryHandler(void callback(Directory dir, HttpRequest request)) {
     _dirCallback = callback;
   }
 
-  void setErrorPageHandler(void callback(HttpRequest request)) {
+  /**
+   * Set the [callback] to override the error page handler. When [callback] is
+   * invoked, the `statusCode` property of the response is set.
+   */
+  void set errorPageHandler(void callback(HttpRequest request)) {
     _errorCallback = callback;
   }
 
   Future<FileSystemEntity> _locateResource(String path,
                                            Iterator<String> segments) {
+    // Don't allow navigating up paths.
+    if (segments.current == "..") return new Future.value(null);
     path = normalize(path);
-    if (split(path).first == "..") return new Future.value(null);
+    // If we jail to root, the relative path can never go up.
+    if (jailRoot && split(path).first == "..") return new Future.value(null);
     String fullPath() => join(root, path);
     return FileSystemEntity.type(fullPath(), followLinks: false)
         .then((type) {
@@ -132,9 +124,14 @@
                 return new Link(fullPath()).target()
                     .then((target) {
                       String targetPath = normalize(target);
-                      if (isAbsolute(targetPath)) return null;
-                      targetPath = join(dirname(path), targetPath);
-                      return _locateResource(targetPath, segments);
+                      if (isAbsolute(targetPath)) {
+                        // If we jail to root, the path can never be absolute.
+                        if (jailRoot) return null;
+                        return _locateResource(targetPath, segments);
+                      } else {
+                        targetPath = join(dirname(path), targetPath);
+                        return _locateResource(targetPath, segments);
+                      }
                     });
               }
               break;
diff --git a/pkg/http_server/pubspec.yaml b/pkg/http_server/pubspec.yaml
index 3112d77..7292837 100644
--- a/pkg/http_server/pubspec.yaml
+++ b/pkg/http_server/pubspec.yaml
@@ -2,6 +2,7 @@
 author: Dart Team <misc@dartlang.org>
 description: Library of HTTP server classes.
 homepage: http://www.dartlang.org
+documentation: http://api.dartlang.org/docs/pkg/http_server
 dependencies:
   mime: any
 dev_dependencies:
diff --git a/pkg/http_server/test/http_body_test.dart b/pkg/http_server/test/http_body_test.dart
index 150f1e5..bae4e1b 100644
--- a/pkg/http_server/test/http_body_test.dart
+++ b/pkg/http_server/test/http_body_test.dart
@@ -94,22 +94,24 @@
             expect(body.type, equals(type));
             switch (type) {
               case "text":
-                expect(body.contentType.mimeType, equals("text/plain"));
+                expect(body.request.headers.contentType.mimeType,
+                       equals("text/plain"));
                 expect(body.body, equals(expectedBody));
                 break;
 
               case "json":
-                expect(body.contentType.mimeType, equals("application/json"));
+                expect(body.request.headers.contentType.mimeType,
+                       equals("application/json"));
                 expect(body.body, equals(expectedBody));
                 break;
 
               case "binary":
-                expect(body.contentType, isNull);
+                expect(body.request.headers.contentType, isNull);
                 expect(body.body, equals(expectedBody));
                 break;
 
               case "form":
-                var mimeType = body.contentType.mimeType;
+                var mimeType = body.request.headers.contentType.mimeType;
                 expect(mimeType,
                        anyOf(equals('multipart/form-data'),
                              equals('application/x-www-form-urlencoded')));
@@ -134,7 +136,7 @@
               default:
                 throw "bad body type";
             }
-            body.response.close();
+            body.request.response.close();
           }, onError: (error) {
             if (!shouldFail) throw error;
           });
@@ -153,7 +155,9 @@
             if (shouldFail) {
               expect(response.statusCode, equals(HttpStatus.BAD_REQUEST));
             }
-            response.fold(null, (x, y) {});
+            return response.drain();
+          })
+          .then((_) {
             client.close();
             server.close();
           });
diff --git a/pkg/http_server/test/virtual_directory_test.dart b/pkg/http_server/test/virtual_directory_test.dart
index 9d38e68..a368c73 100644
--- a/pkg/http_server/test/virtual_directory_test.dart
+++ b/pkg/http_server/test/virtual_directory_test.dart
@@ -211,12 +211,12 @@
           var dir = Directory.systemTemp.createTempSync('http_server_virtual_');
           var virDir = new VirtualDirectory(dir.path);
           virDir.allowDirectoryListing = true;
-          virDir.setDirectoryHandler((dir2, request) {
+          virDir.directoryHandler = (dir2, request) {
             expect(dir2, isNotNull);
             expect(FileSystemEntity.identicalSync(dir.path, dir2.path), isTrue);
             request.response.write('My handler ${request.uri.path}');
             request.response.close();
-          });
+          };
 
           virDir.serve(server);
 
@@ -278,7 +278,7 @@
               var dir =
                   Directory.systemTemp.createTempSync('http_server_virtual_');
               var file = new File('${dir.path}/file')..createSync();
-              var link = new Link('${dir.path}/dir3')
+              var link = new Link('${dir.path}/file2')
                   ..createSync('${dir.path}/file');
               var virDir = new VirtualDirectory(dir.path);
               virDir.followLinks = true;
@@ -287,7 +287,7 @@
 
               return new HttpClient().get('localhost',
                                           server.port,
-                                          '/dir3/file')
+                                          '/file2')
                   .then((request) => request.close())
                   .then((response) => response.drain().then(
                       (_) => response.statusCode))
@@ -302,11 +302,11 @@
             expect(HttpServer.bind('localhost', 0).then((server) {
               var dir =
                   Directory.systemTemp.createTempSync('http_server_virtual_');
-              var name = basename(dir.path);
+              var dir2 = new Directory('${dir.path}/dir')..createSync();
               var file = new File('${dir.path}/file')..createSync();
-              var link = new Link('${dir.path}/dir3')
-                  ..createSync('../$name/file');
-              var virDir = new VirtualDirectory(dir.path);
+              var link = new Link('${dir2.path}/file')
+                  ..createSync('../file');
+              var virDir = new VirtualDirectory(dir2.path);
               virDir.followLinks = true;
 
               virDir.serve(server);
@@ -347,6 +347,63 @@
           }), completion(equals(HttpStatus.NOT_FOUND)));
         });
       });
+
+      group('follow-links', () {
+        test('no-root-jail', () {
+          test('absolute-link', () {
+            expect(HttpServer.bind('localhost', 0).then((server) {
+              var dir =
+                  Directory.systemTemp.createTempSync('http_server_virtual_');
+              var file = new File('${dir.path}/file')..createSync();
+              var link = new Link('${dir.path}/file2')
+                  ..createSync('${dir.path}/file');
+              var virDir = new VirtualDirectory(dir.path);
+              virDir.followLinks = true;
+              virDir.jailRoot = false;
+
+              virDir.serve(server);
+
+              return new HttpClient().get('localhost',
+                                          server.port,
+                                          '/file2')
+                  .then((request) => request.close())
+                  .then((response) => response.drain().then(
+                      (_) => response.statusCode))
+                  .whenComplete(() {
+                    server.close();
+                    dir.deleteSync(recursive: true);
+                  });
+            }), completion(equals(HttpStatus.OK)));
+          });
+
+          test('relative-parent-link', () {
+            expect(HttpServer.bind('localhost', 0).then((server) {
+              var dir =
+                  Directory.systemTemp.createTempSync('http_server_virtual_');
+              var dir2 = new Directory('${dir.path}/dir')..createSync();
+              var file = new File('${dir.path}/file')..createSync();
+              var link = new Link('${dir2.path}/file')
+                  ..createSync('../file');
+              var virDir = new VirtualDirectory(dir2.path);
+              virDir.followLinks = true;
+              virDir.jailRoot = false;
+
+              virDir.serve(server);
+
+              return new HttpClient().get('localhost',
+                                          server.port,
+                                          '/file')
+                  .then((request) => request.close())
+                  .then((response) => response.drain().then(
+                      (_) => response.statusCode))
+                  .whenComplete(() {
+                    server.close();
+                    dir.deleteSync(recursive: true);
+                  });
+            }), completion(equals(HttpStatus.OK)));
+          });
+        });
+      });
     }
   });
 
@@ -469,11 +526,11 @@
         var virDir = new VirtualDirectory(dir.path);
         dir.deleteSync();
 
-        virDir.setErrorPageHandler((request) {
+        virDir.errorPageHandler = (request) {
           request.response.write('my-page ');
           request.response.write(request.response.statusCode);
           request.response.close();
-        });
+        };
         virDir.serve(server);
 
         return getAsString(server.port, '/')
diff --git a/pkg/mdv/lib/mdv.dart b/pkg/mdv/lib/mdv.dart
deleted file mode 100644
index 6e90a77..0000000
--- a/pkg/mdv/lib/mdv.dart
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// TODO(jmesserly): more commentary here.
-/**
- * Template and node binding for HTML elements.
- *
- * This library provides access to the Polymer project's
- * [Template Binding](http://www.polymer-project.org/platform/template.html) and
- * [Node.bind()](http://www.polymer-project.org/platform/node_bind.html) APIs.
- * Find more information at the
- * [Polymer.dart homepage](https://www.dartlang.org/polymer-dart/).
- */
-library mdv;
-
-import 'dart:async';
-import 'dart:collection';
-import 'dart:html';
-import 'package:observe/observe.dart';
-
-import 'src/list_diff.dart' show calculateSplices, ListChangeDelta;
-
-part 'src/element.dart';
-part 'src/input_bindings.dart';
-part 'src/input_element.dart';
-part 'src/node.dart';
-part 'src/select_element.dart';
-part 'src/template.dart';
-part 'src/template_iterator.dart';
-part 'src/text.dart';
-part 'src/text_area_element.dart';
-
-/** Initialize the Model-Driven Views polyfill. */
-void initialize() {
-  TemplateElement.mdvPackage = _mdv;
-}
-
-
-typedef DocumentFragmentCreated(DocumentFragment fragment);
-
-// TODO(jmesserly): ideally this would be a stream, but they don't allow
-// reentrancy.
-Set<DocumentFragmentCreated> _instanceCreated;
-
-/**
- * *Warning*: This is an implementation helper for Model-Driven Views and
- * should not be used in your code.
- *
- * This event is fired whenever a template is instantiated via
- * [Element.createInstance].
- */
-// TODO(rafaelw): This is a hack, and is neccesary for the polyfill
-// because custom elements are not upgraded during clone()
-// TODO(jmesserly): polymer removed this in:
-// https://github.com/Polymer/platform/commit/344ffeaae475babb529403f6608588a0fc73f4e7
-Set<DocumentFragmentCreated> get instanceCreated {
-  if (_instanceCreated == null) {
-    _instanceCreated = new Set<DocumentFragmentCreated>();
-  }
-  return _instanceCreated;
-}
-
-
-// TODO(jmesserly): investigate if expandos give us enough performance.
-
-// The expando for storing our MDV wrappers.
-//
-// In general, we need state associated with the nodes. Rather than having a
-// bunch of individual expandos, we keep one per node.
-//
-// Aside from the potentially helping performance, it also keeps things simpler
-// if we decide to integrate MDV into the DOM later, and means less code needs
-// to worry about expandos.
-final Expando _mdvExpando = new Expando('mdv');
-
-_mdv(node) {
-  var wrapper = _mdvExpando[node];
-  if (wrapper != null) return wrapper;
-
-  if (node is InputElement) {
-    wrapper = new _InputElementExtension(node);
-  } else if (node is SelectElement) {
-    wrapper = new _SelectElementExtension(node);
-  } else if (node is TextAreaElement) {
-    wrapper = new _TextAreaElementExtension(node);
-  } else if (node is Element) {
-    if (node.isTemplate) {
-      wrapper = new _TemplateExtension(node);
-    } else {
-      wrapper = new _ElementExtension(node);
-    }
-  } else if (node is Text) {
-    wrapper = new _TextExtension(node);
-  } else if (node is Node) {
-    wrapper = new _NodeExtension(node);
-  } else {
-    // TODO(jmesserly): this happens for things like CompoundBinding.
-    wrapper = node;
-  }
-
-  _mdvExpando[node] = wrapper;
-  return wrapper;
-}
diff --git a/pkg/mdv/lib/src/node.dart b/pkg/mdv/lib/src/node.dart
deleted file mode 100644
index cf36831..0000000
--- a/pkg/mdv/lib/src/node.dart
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of mdv;
-
-/** Extensions to the [Node] API. */
-class _NodeExtension {
-  final Node node;
-  Map<String, NodeBinding> _bindings;
-
-  _NodeExtension(this.node);
-
-  NodeBinding createBinding(String name, model, String path) => null;
-
-  /**
-   * Binds the attribute [name] to the [path] of the [model].
-   * Path is a String of accessors such as `foo.bar.baz`.
-   */
-  NodeBinding bind(String name, model, String path) {
-    var binding = bindings[name];
-    if (binding != null) binding.close();
-
-    // Note: dispatch through the xtag so a custom element can override it.
-    binding = (node is Element ? (node as Element).xtag : node)
-        .createBinding(name, model, path);
-
-    bindings[name] = binding;
-    if (binding == null) {
-      window.console.error('Unhandled binding to Node: '
-          '$this $name $model $path');
-    }
-    return binding;
-  }
-
-  /** Unbinds the attribute [name]. */
-  void unbind(String name) {
-    if (_bindings == null) return;
-    var binding = bindings.remove(name);
-    if (binding != null) binding.close();
-  }
-
-  /** Unbinds all bound attributes. */
-  void unbindAll() {
-    if (_bindings == null) return;
-    for (var binding in bindings.values) {
-      if (binding != null) binding.close();
-    }
-    _bindings = null;
-  }
-
-  // TODO(jmesserly): we should return a read-only wrapper here.
-  Map<String, NodeBinding> get bindings {
-    if (_bindings == null) _bindings = new LinkedHashMap<String, NodeBinding>();
-    return _bindings;
-  }
-
-  TemplateInstance _templateInstance;
-
-  /** Gets the template instance that instantiated this node, if any. */
-  TemplateInstance get templateInstance =>
-      _templateInstance != null ? _templateInstance :
-      (node.parent != null ? node.parent.templateInstance : null);
-}
-
-/** A data binding on a [Node]. See [Node.bindings] and [Node.bind]. */
-abstract class NodeBinding {
-  Node _node;
-  var _model;
-  PathObserver _observer;
-  StreamSubscription _pathSub;
-
-  /** The property of [node] which will be data bound. */
-  final String property;
-
-  /** The property of [node] which will be data bound. */
-  final String path;
-
-  /** The node that has [property] which will be data bound. */
-  Node get node => _node;
-
-  /**
-   * The bound data model.
-   */
-  get model => _model;
-
-  /** True if this binding has been [closed]. */
-  bool get closed => _observer == null;
-
-  /** The value at the [path] on [model]. */
-  get value => _observer.value;
-
-  set value(newValue) {
-    _observer.value = newValue;
-  }
-
-  NodeBinding(this._node, this.property, this._model, this.path) {
-    // Create the path observer
-    _observer = new PathObserver(model, path);
-    _observePath();
-  }
-
-  void _observePath() {
-    _pathSub = _observer.bindSync(boundValueChanged);
-  }
-
-  /** Called when [value] changes to update the [node]. */
-  // TODO(jmesserly): the impl in MDV uses mirrors to set the property,
-  // but that isn't used except for specific known fields like "textContent",
-  // so I'm overridding this in the subclasses instead.
-  void boundValueChanged(newValue);
-
-  /** Called to sanitize the value before it is assigned into the property. */
-  sanitizeBoundValue(value) => value == null ? '' : '$value';
-
-  /**
-   * Called by [Node.unbind] to close this binding and unobserve the [path].
-   *
-   * This can be overridden in subclasses, but they must call `super.close()`
-   * to free associated resources. They must also check [closed] and return
-   * immediately if already closed.
-   */
-  void close() {
-    if (closed) return;
-
-    if (_pathSub != null) _pathSub.cancel();
-    _pathSub = null;
-    _observer = null;
-    _node = null;
-    _model = null;
-  }
-}
diff --git a/pkg/mdv/lib/src/template.dart b/pkg/mdv/lib/src/template.dart
deleted file mode 100644
index d2fb47e..0000000
--- a/pkg/mdv/lib/src/template.dart
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of mdv;
-
-/** Extensions to [Element]s that behave as templates. */
-class _TemplateExtension extends _ElementExtension {
-  var _model;
-  BindingDelegate _bindingDelegate;
-  _TemplateIterator _templateIterator;
-  bool _scheduled = false;
-
-  _TemplateExtension(Element node) : super(node);
-
-  Element get node => super.node;
-
-  NodeBinding createBinding(String name, model, String path) {
-    switch (name) {
-      case 'bind':
-      case 'repeat':
-      case 'if':
-        if (_templateIterator == null) {
-          _templateIterator = new _TemplateIterator(node);
-        }
-        // TODO(jmesserly): why do we do this here and nowhere else?
-        if (path == null) path = '';
-        return new _TemplateBinding(node, name, model, path);
-      default:
-        return super.createBinding(name, model, path);
-    }
-  }
-
-  /**
-   * Creates an instance of the template.
-   */
-  DocumentFragment createInstance(model, BindingDelegate delegate) {
-    var template = node.ref;
-    if (template == null) template = node;
-
-    var instance = _createDeepCloneAndDecorateTemplates(
-        template.ref.content, delegate);
-
-    if (_instanceCreated != null) {
-      for (var callback in _instanceCreated) callback(instance);
-    }
-
-    _addBindings(instance, model, delegate);
-    _addTemplateInstanceRecord(instance, model);
-    return instance;
-  }
-
-  /**
-   * The data model which is inherited through the tree.
-   */
-  get model => _model;
-
-  void set model(value) {
-    _model = value;
-    _ensureSetModelScheduled();
-  }
-
-  /**
-   * The binding delegate which is inherited through the tree. It can be used
-   * to configure custom syntax for `{{bindings}}` inside this template.
-   */
-  BindingDelegate get bindingDelegate => _bindingDelegate;
-
-  void set bindingDelegate(BindingDelegate value) {
-    _bindingDelegate = value;
-    _ensureSetModelScheduled();
-  }
-
-  _ensureSetModelScheduled() {
-    if (_scheduled) return;
-    _scheduled = true;
-    scheduleMicrotask(_setModel);
-  }
-
-  void _setModel() {
-    _scheduled = false;
-    _addBindings(node, _model, _bindingDelegate);
-  }
-}
-
-class _TemplateBinding extends NodeBinding {
-  // TODO(jmesserly): MDV uses TemplateIterator as the node, see:
-  // https://github.com/Polymer/mdv/issues/127
-  _TemplateBinding(node, name, model, path)
-      : super(node, name, model, path) {
-    _mdv(node)._templateIterator.inputs.bind(property, model, path);
-  }
-
-  // These are no-ops because we don't use the underlying PathObserver.
-  void _observePath() {}
-  void boundValueChanged(newValue) {}
-
-  void close() {
-    if (closed) return;
-    var templateIterator = _mdv(node)._templateIterator;
-    if (templateIterator != null) templateIterator.inputs.unbind(property);
-    super.close();
-  }
-}
diff --git a/pkg/mdv/pubspec.yaml b/pkg/mdv/pubspec.yaml
deleted file mode 100644
index 937a8cc..0000000
--- a/pkg/mdv/pubspec.yaml
+++ /dev/null
@@ -1,14 +0,0 @@
-name: mdv
-author: Web UI Team <web-ui-dev@dartlang.org>
-description: >
-  Model-Driven-Views (MDV) extends HTML and the DOM APIs to support a sensible
-  separation between the UI (DOM) of a document or application and its
-  underlying data (model).
-  Updates to the model are reflected in the DOM and user input into the DOM is
-  immediately assigned to the model.
-homepage: https://www.dartlang.org/polymer-dart/
-dependencies:
-  logging: any
-  observe: any
-dev_dependencies:
-  unittest: any
diff --git a/pkg/mdv/test/analyzer_test.dart b/pkg/mdv/test/analyzer_test.dart
deleted file mode 100644
index 68f5e85..0000000
--- a/pkg/mdv/test/analyzer_test.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library mdv.test.analyzer_test;
-
-import 'package:mdv/mdv.dart';
-
-// @static-clean
-
-// This test ensures MDV compiles without errors.
-void main() {}
diff --git a/pkg/mdv/test/mdv_test_utils.dart b/pkg/mdv/test/mdv_test_utils.dart
deleted file mode 100644
index 7f76506..0000000
--- a/pkg/mdv/test/mdv_test_utils.dart
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library observe_utils;
-
-import 'dart:html';
-import 'package:observe/observe.dart';
-import 'package:unittest/unittest.dart';
-
-import 'package:observe/src/microtask.dart';
-export 'package:observe/src/microtask.dart';
-
-final bool parserHasNativeTemplate = () {
-  var div = new DivElement()..innerHtml = '<table><template>';
-  return div.firstChild.firstChild != null &&
-      div.firstChild.firstChild.tagName == 'TEMPLATE';
-}();
-
-recursivelySetTemplateModel(element, model, [delegate]) {
-  for (var node in element.queryAll('*')) {
-    if (node.isTemplate) {
-      node.bindingDelegate = delegate;
-      node.model = model;
-    }
-  }
-}
-
-dispatchEvent(type, target) {
-  target.dispatchEvent(new Event(type, cancelable: false));
-}
-
-class FooBarModel extends Observable {
-  @observable var foo;
-  @observable var bar;
-
-  FooBarModel([this.foo, this.bar]);
-}
-
-@reflectable
-class FooBarNotifyModel extends ChangeNotifier implements FooBarModel {
-  var _foo;
-  var _bar;
-
-  FooBarNotifyModel([this._foo, this._bar]);
-
-  get foo => _foo;
-  set foo(value) {
-    _foo = notifyPropertyChange(#foo, _foo, value);
-  }
-
-  get bar => _bar;
-  set bar(value) {
-    _bar = notifyPropertyChange(#bar, _bar, value);
-  }
-}
-
-observeTest(name, testCase) => test(name, wrapMicrotask(testCase));
-
-solo_observeTest(name, testCase) => solo_test(name, wrapMicrotask(testCase));
diff --git a/pkg/observe/lib/src/dirty_check.dart b/pkg/observe/lib/src/dirty_check.dart
index 386ad60..8ab8c30 100644
--- a/pkg/observe/lib/src/dirty_check.dart
+++ b/pkg/observe/lib/src/dirty_check.dart
@@ -9,10 +9,11 @@
  *
  * It can collect all observed objects, which can be used to trigger predictable
  * delivery of all pending changes in a test, including objects allocated
- * internally to another library, such as those in `package:mdv`.
+ * internally to another library, such as those in `package:template_binding`.
  */
 library observe.src.dirty_check;
 
+import 'dart:async';
 import 'package:logging/logging.dart';
 import 'package:observe/observe.dart' show Observable;
 
@@ -84,9 +85,58 @@
 
 const MAX_DIRTY_CHECK_CYCLES = 1000;
 
-
 /**
  * Log for messages produced at runtime by this library. Logging can be
  * configured by accessing Logger.root from the logging library.
  */
 final Logger _logger = new Logger('Observable.dirtyCheck');
+
+/**
+ * Creates a [ZoneSpecification] to set up automatic dirty checking after each
+ * batch of async operations. This ensures that change notifications are always
+ * delivered. Typically used via [dirtyCheckZone].
+ */
+ZoneSpecification dirtyCheckZoneSpec() {
+  bool pending = false;
+
+  enqueueDirtyCheck(ZoneDelegate parent, Zone zone) {
+    // Only schedule one dirty check per microtask.
+    if (pending) return;
+
+    pending = true;
+    parent.scheduleMicrotask(zone, () {
+      pending = false;
+      Observable.dirtyCheck();
+    });
+  }
+
+  wrapCallback(Zone self, ZoneDelegate parent, Zone zone, f()) {
+    // TODO(jmesserly): why does this happen?
+    if (f == null) return f;
+    return () {
+      enqueueDirtyCheck(parent, zone);
+      return f();
+    };
+  }
+
+  wrapUnaryCallback(Zone self, ZoneDelegate parent, Zone zone, f(x)) {
+    // TODO(jmesserly): why does this happen?
+    if (f == null) return f;
+    return (x) {
+      enqueueDirtyCheck(parent, zone);
+      return f(x);
+    };
+  }
+
+  return new ZoneSpecification(
+      registerCallback: wrapCallback,
+      registerUnaryCallback: wrapUnaryCallback);
+}
+
+/**
+ * Forks a [Zone] off the current one that does dirty-checking automatically
+ * after each batch of async operations. Equivalent to:
+ *
+ *     Zone.current.fork(specification: dirtyCheckZoneSpec());
+ */
+Zone dirtyCheckZone() => Zone.current.fork(specification: dirtyCheckZoneSpec());
diff --git a/pkg/observe/lib/transform.dart b/pkg/observe/lib/transform.dart
index 3e0aac2..d8396b9 100644
--- a/pkg/observe/lib/transform.dart
+++ b/pkg/observe/lib/transform.dart
@@ -135,19 +135,20 @@
   // report a warning later below. Because we don't have type analysis (only
   // syntactic understanding of the code), we only report warnings that are
   // known to be true.
-  var declaresObservable = false;
+  var explicitObservable = false;
+  var implicitObservable = false;
   if (cls.extendsClause != null) {
     var id = _getSimpleIdentifier(cls.extendsClause.superclass.name);
     if (id.name == 'Observable') {
       code.edit(id.offset, id.end, 'ChangeNotifier');
-      declaresObservable = true;
+      explicitObservable = true;
     } else if (id.name == 'ChangeNotifier') {
-      declaresObservable = true;
+      explicitObservable = true;
     } else if (id.name != 'HtmlElement' && id.name != 'CustomElement'
         && id.name != 'Object') {
       // TODO(sigmund): this is conservative, consider using type-resolution to
       // improve this check.
-      declaresObservable = true;
+      implicitObservable = true;
     }
   }
 
@@ -156,25 +157,27 @@
       var id = _getSimpleIdentifier(type.name);
       if (id.name == 'Observable') {
         code.edit(id.offset, id.end, 'ChangeNotifier');
-        declaresObservable = true;
+        explicitObservable = true;
         break;
       } else if (id.name == 'ChangeNotifier') {
-        declaresObservable = true;
+        explicitObservable = true;
         break;
       } else {
         // TODO(sigmund): this is conservative, consider using type-resolution
         // to improve this check.
-        declaresObservable = true;
+        implicitObservable = true;
       }
     }
   }
 
-  if (!declaresObservable && cls.implementsClause != null) {
+  if (cls.implementsClause != null) {
     // TODO(sigmund): consider adding type-resolution to give a more precise
     // answer.
-    declaresObservable = true;
+    implicitObservable = true;
   }
 
+  var declaresObservable = explicitObservable || implicitObservable;
+
   // Track fields that were transformed.
   var instanceFields = new Set<String>();
   var getters = new List<String>();
@@ -223,6 +226,8 @@
   // If nothing was @observable, bail.
   if (instanceFields.length == 0) return;
 
+  if (!explicitObservable) _mixinObservable(cls, code);
+
   // Fix initializers, because they aren't allowed to call the setter.
   for (var member in cls.members) {
     if (member is ConstructorDeclaration) {
@@ -231,6 +236,23 @@
   }
 }
 
+/** Adds "with ChangeNotifier" and associated implementation. */
+void _mixinObservable(ClassDeclaration cls, TextEditTransaction code) {
+  // Note: we need to be careful to put the with clause after extends, but
+  // before implements clause.
+  if (cls.withClause != null) {
+    var pos = cls.withClause.end;
+    code.edit(pos, pos, ', ChangeNotifier');
+  } else if (cls.extendsClause != null) {
+    var pos = cls.extendsClause.end;
+    code.edit(pos, pos, ' with ChangeNotifier ');
+  } else {
+    var params = cls.typeParameters;
+    var pos =  params != null ? params.end : cls.name.end;
+    code.edit(pos, pos, ' extends ChangeNotifier ');
+  }
+}
+
 SimpleIdentifier _getSimpleIdentifier(Identifier id) =>
     id is PrefixedIdentifier ? (id as PrefixedIdentifier).identifier : id;
 
diff --git a/pkg/observe/test/transform_test.dart b/pkg/observe/test/transform_test.dart
index 73720cc..064ac87 100644
--- a/pkg/observe/test/transform_test.dart
+++ b/pkg/observe/test/transform_test.dart
@@ -36,6 +36,26 @@
         'extends Base with Mixin, ChangeNotifier implements I1, I2');
   });
 
+  group('adds "with ChangeNotifier" given', () {
+    _testClause('', 'extends ChangeNotifier');
+    _testClause('extends Base', 'extends Base with ChangeNotifier');
+    _testClause('extends Base<T>', 'extends Base<T> with ChangeNotifier');
+    _testClause('extends Base with Mixin',
+        'extends Base with Mixin, ChangeNotifier');
+    _testClause('extends Base with Mixin<T>',
+        'extends Base with Mixin<T>, ChangeNotifier');
+    _testClause('extends Base with Mixin, Mixin2',
+        'extends Base with Mixin, Mixin2, ChangeNotifier');
+    _testClause('implements Interface',
+        'extends ChangeNotifier implements Interface');
+    _testClause('implements Interface<T>',
+        'extends ChangeNotifier implements Interface<T>');
+    _testClause('extends Base implements Interface',
+        'extends Base with ChangeNotifier implements Interface');
+    _testClause('extends Base with Mixin implements I1, I2',
+        'extends Base with Mixin, ChangeNotifier implements I1, I2');
+  });
+
   group('fixes contructor calls ', () {
     _testInitializers('this.a', '(a) : __\$a = a');
     _testInitializers('{this.a}', '({a}) : __\$a = a');
diff --git a/pkg/pkg.gyp b/pkg/pkg.gyp
index f74e040..9e37d4d 100644
--- a/pkg/pkg.gyp
+++ b/pkg/pkg.gyp
@@ -17,6 +17,8 @@
                 '"third_party"])',
             '<!@(["python", "../tools/list_pkg_directories.py", '
                 '"../third_party/pkg"])',
+            '<!@(["python", "../tools/list_pkg_directories.py", '
+                '"../pkg/polymer/example/"])',
           ],
           'outputs': [
             '<(SHARED_INTERMEDIATE_DIR)/packages.stamp',
diff --git a/pkg/pkg.status b/pkg/pkg.status
index bc9917b..65ca59d 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -24,9 +24,12 @@
 
 [ $compiler == dart2js ]
 analyzer_experimental/test/generated/ast_test: RuntimeError #Issue 12341
-
-[ $compiler == dart2js && $runtime == drt ]
-polymer/test/prop_attr_reflection_test: Fail # Issue 14048
+collection_helpers/test/equality_test/01: Fail # Issue 1533
+collection_helpers/test/equality_test/02: Fail # Issue 1533
+collection_helpers/test/equality_test/03: Fail # Issue 1533
+collection_helpers/test/equality_test/04: Fail # Issue 1533
+collection_helpers/test/equality_test/05: Fail # Issue 1533
+collection_helpers/test/equality_test/none: Pass, Fail # Issue 14348
 
 [ $compiler == dart2js && $checked && $runtime == ie9 ]
 crypto/test/base64_test: Timeout # Issue 12486
@@ -41,13 +44,19 @@
 polymer/example: Skip # Uses dart:html
 polymer/test/attr_deserialize_test: Skip # uses dart:html
 polymer/test/attr_mustache_test: Skip #uses dart:html
+polymer/test/bind_test: Skip # uses dart:html
+polymer/test/bind_mdv_test: Skip # uses dart:html
+polymer/test/custom_event_test: Skip # uses dart:html
 polymer/test/event_path_test: Skip #uses dart:html
 polymer/test/events_test: Skip #uses dart:html
 polymer/test/instance_attrs_test: Skip #uses dart:html
 polymer/test/prop_attr_bind_reflection_test: Skip #uses dart:html
 polymer/test/prop_attr_reflection_test: Skip #uses dart:html
 polymer/test/publish_attributes_test: Skip #uses dart:html
+polymer/test/register_test: Skip #uses dart:html
 polymer/test/take_attributes_test: Skip #uses dart:html
+polymer/test/template_distribute_dynamic_test: Skip #uses dart:html
+polymer/test/unbind_test: Skip # uses dart:html
 
 [$compiler == dart2dart]
 *: Skip
@@ -66,13 +75,6 @@
 mime/test/mime_multipart_transformer_test: Skip # No typed_data on IE9.
 polymer/test/instance_attrs_test: Pass, Fail # Issue 14167
 
-[ $system == windows && $runtime == ff ]
-polymer/test/events_test: Pass, Fail # Issue 14167
-polymer/test/prop_attr_bind_reflection_test: Pass, Fail # Issue 14167
-polymer/test/prop_attr_reflection_test: Pass, Fail # Issue 14167
-polymer/test/take_attributes_test: Pass, Fail # Issue 14167
-polymer/test/attr_mustache_test: Pass, Fail # Issue 14167
-
 [ $runtime == safari ]
 fixnum/test/int_64_test: Pass, Fail # Bug in JSC.
 crypto/test/hmac_sha1_test: Pass, Fail # Issue 11407.
@@ -83,27 +85,24 @@
 polymer_expressions/test/globals_test: Fail # Issue 13890
 
 [ $runtime == ie9 || $runtime == ie10 ]
+polymer/example/canonicalization/test/canonicalization_deploy_test: Pass, Timeout
+polymer/example/canonicalization/test/canonicalization_test: Fail, Timeout, OK # tests development only behavior
 polymer/test/attr_deserialize_test: Fail, Timeout # Issue 12865, 13197, 13260
 polymer/test/attr_mustache_test: Fail, Timeout # Issue 12865, 13197, 13260
+polymer/test/bind_test: Fail, Timeout # Issue 12865, 13197, 13260
+polymer/test/bind_mdv_test: Fail, Timeout # Issue 12865, 13197, 13260
+polymer/test/custom_event_test: Fail, Timeout # Issue 12865, 13197, 13260
 polymer/test/event_path_test: Fail, Timeout # Issue 12865, 13197, 13260
 polymer/test/events_test: Fail, Timeout # Issue 12865, 13197, 13260
 polymer/test/prop_attr_reflection_test: Fail, Timeout # Issue 12865, 13197, 13260
 polymer/test/prop_attr_bind_reflection_test: Fail, Timeout # Issue 12865, 13197, 13260
 polymer/test/publish_attributes_test: Fail, Timeout # Issue 12865, 13197, 13260
+polymer/test/register_test: Pass, Fail, Timeout # Issue 12865, 13197, 13260
 polymer/test/take_attributes_test: Fail, Timeout # Issue 12865, 13197, 13260
+polymer/test/template_distribute_dynamic_test: Fail, Timeout # Issue 12865, 13197, 13260
+polymer/test/unbind_test: Fail, Timeout # Issue 12865, 13197, 13260
 polymer_expressions/test/globals_test: Fail # Issue 13890
 
-[ $system == windows && ($runtime == chrome || $runtime == ff) ]
-polymer/test/attr_deserialize_test: Pass, Timeout # Issue 13260
-polymer/test/attr_mustache_test: Pass, Timeout # Issue 13260
-polymer/test/event_path_test: Pass, Timeout # Issue 13260
-polymer/test/events_test: Pass, Timeout # Issue 13260
-polymer/test/instance_attrs_test: Pass, Timeout # Issue 13260
-polymer/test/prop_attr_reflection_test: Pass, Timeout # Issue 13260
-polymer/test/prop_attr_bind_reflection_test: Pass, Timeout # Issue 13260
-polymer/test/publish_attributes_test: Pass, Timeout # Issue 13260
-polymer/test/take_attributes_test: Pass, Timeout # Issue 13260
-
 # Skip browser-specific tests on VM
 [ $runtime == vm ]
 path/test/browser_test: Fail, OK # Uses dart:html
@@ -122,6 +121,11 @@
 # them in the analyzer.
 unittest/test/mock_regexp_negative_test: Skip
 unittest/test/mock_stepwise_negative_test: Skip
+collection_helpers/test/equality_test/none: Fail # TODO(lrn): Figure out if it's an error.
+polymer/example/canonicalization: Skip
+
+[ $compiler == dart2js && $runtime == none]
+polymer/example/canonicalization: Skip
 
 [ $compiler == dart2js && $csp ]
 unittest/test/mirror_matchers_test: Skip # Issue 12151
@@ -140,11 +144,15 @@
 crypto/test/sha256_test: Slow, Pass
 crypto/test/sha1_test: Slow, Pass
 polymer/example/component: Fail # Issue 13198
+polymer/example/canonicalization/test/canonicalization_test: Fail, OK # tests development only behavior
 
 [ $compiler == dart2js && $runtime == chromeOnAndroid ]
 docgen/test/single_library_test: Fail # TODO(kasperl): Please triage.
 intl/test/date_time_format_http_request_test: Fail # TODO(kasperl): Please triage.
 
+[ $compiler == none && $runtime == vm && $system == windows ]
+http_server/test/http_body_test: Pass, Fail # Issue 14381
+
 [ $browser ]
 analyzer_experimental/test/error_test: Fail, Timeout, OK # Uses dart:io.
 analyzer_experimental/test/generated/element_test: Fail, OK # Uses dart:io.
@@ -250,12 +258,15 @@
 unittest/test/unittest_test_returning_future_using_runasync_test: Fail # 13921
 unittest/test/unittest_testcases_immutable_test: Fail # 13921
 unittest/test/unitttest_group_name_test: Fail # 13921
+template_binding/test/template_element_test: Pass, Fail # Flaky, 14330
+polymer/test/custom_event_test: Pass, Crash # 14360
 
+polymer/example/canonicalization/test/canonicalization_deploy_test: Fail, OK # tests deploy only behavior
 
 # Skip tests on the VM if the package depends on dart:html
 [ $runtime == vm ]
 custom_element: Skip
-mdv: Skip
+template_binding: Skip
 mutation_observer: Skip
 polymer_expressions/test/syntax_test: Skip
 polymer_expressions/test/globals_test: Skip
@@ -273,19 +284,13 @@
 [ $runtime == vm ]
 intl/test/message_extraction/message_extraction_test: Pass, Fail # Issue 12930
 
-[ $compiler == none && $runtime == vm ]
-observe/test/observe_test: Pass, Fail # Issue 13543
-
-[ $compiler == none && $runtime == vm && $checked ]
-intl/test/message_extraction/failed_extraction_test: Pass, Fail # Issue 13543
-
 [ $compiler == none && $runtime == dartium ]
 source_maps/test/parser_test: Pass, Timeout # Issue 13719: Please triage this failure.
 
 [ $compiler == dartanalyzer ]
 # pkg issue 13944; Missing inherited members: 'ListChangeRecord.addedCount' and 'ListChangeRecord.removedCount'
 custom_element/test/analyzer_test: fail
-mdv/test/analyzer_test: fail
+template_binding/test/analyzer_test: fail
 observe/test/observe_test: fail
 
 # pkg issue 13945; Missing inherited member 'Trace.frames'
@@ -294,11 +299,8 @@
 [ $compiler == dart2analyzer ]
 # pkg issue 13944; Missing inherited members: 'ListChangeRecord.addedCount' and 'ListChangeRecord.removedCount'
 custom_element/test/analyzer_test: fail
-mdv/test/analyzer_test: fail
+template_binding/test/analyzer_test: fail
 observe/test/observe_test: fail
 
 # pkg issue 13945; Missing inherited member 'Trace.frames'
 observe/test/observe_test: fail
-
-[ $compiler == none && ( $runtime == dartium || $runtime == drt ) ]
-polymer/test/prop_attr_reflection_test: fail # Issue 14036
diff --git a/pkg/polymer/example/canonicalization/lib/a.dart b/pkg/polymer/example/canonicalization/lib/a.dart
new file mode 100644
index 0000000..78426db
--- /dev/null
+++ b/pkg/polymer/example/canonicalization/lib/a.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library canonicalization.a;
+
+import 'package:polymer/polymer.dart';
+import 'package:canonicalization/c.dart';
+import 'd.dart';
+
+int a = 0;
+@initMethod _init() {
+  a++;
+  c++;
+  d++;
+}
diff --git a/pkg/polymer/example/canonicalization/lib/a.html b/pkg/polymer/example/canonicalization/lib/a.html
new file mode 100644
index 0000000..c359e83
--- /dev/null
+++ b/pkg/polymer/example/canonicalization/lib/a.html
@@ -0,0 +1,6 @@
+<!--
+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.
+-->
+<script type='application/dart' src='a.dart'></script>
diff --git a/pkg/polymer/example/canonicalization/lib/b.dart b/pkg/polymer/example/canonicalization/lib/b.dart
new file mode 100644
index 0000000..0a3a29d
--- /dev/null
+++ b/pkg/polymer/example/canonicalization/lib/b.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library canonicalization.b;
+
+import 'package:polymer/polymer.dart';
+import 'package:canonicalization/c.dart';
+import 'd.dart';
+
+int b = 0;
+@initMethod _init() {
+  b++;
+  c++;
+  d++;
+}
diff --git a/pkg/polymer/example/canonicalization/lib/b.html b/pkg/polymer/example/canonicalization/lib/b.html
new file mode 100644
index 0000000..2a42437
--- /dev/null
+++ b/pkg/polymer/example/canonicalization/lib/b.html
@@ -0,0 +1,6 @@
+<!--
+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.
+-->
+<script type='application/dart' src='b.dart'></script>
diff --git a/pkg/polymer/example/canonicalization/lib/c.dart b/pkg/polymer/example/canonicalization/lib/c.dart
new file mode 100644
index 0000000..362f3e3
--- /dev/null
+++ b/pkg/polymer/example/canonicalization/lib/c.dart
@@ -0,0 +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 canonicalization.c;
+
+int c = 0;
diff --git a/pkg/polymer/example/canonicalization/lib/d.dart b/pkg/polymer/example/canonicalization/lib/d.dart
new file mode 100644
index 0000000..7d2a58e
--- /dev/null
+++ b/pkg/polymer/example/canonicalization/lib/d.dart
@@ -0,0 +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 canonicalization.d;
+
+int d = 0;
diff --git a/pkg/polymer/example/canonicalization/pubspec.yaml b/pkg/polymer/example/canonicalization/pubspec.yaml
new file mode 100644
index 0000000..80a7923
--- /dev/null
+++ b/pkg/polymer/example/canonicalization/pubspec.yaml
@@ -0,0 +1,6 @@
+name: canonicalization
+dependencies:
+  polymer:
+    path: ../../
+dev_dependencies:
+  unittest: any
diff --git a/pkg/polymer/example/canonicalization/test/canonicalization_deploy_test.dart b/pkg/polymer/example/canonicalization/test/canonicalization_deploy_test.dart
new file mode 100644
index 0000000..61dde5c
--- /dev/null
+++ b/pkg/polymer/example/canonicalization/test/canonicalization_deploy_test.dart
@@ -0,0 +1,39 @@
+// 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.
+
+/** Tests how canonicalization works when using the deployed app. */
+library canonicalization.deploy_test;
+
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+import 'package:polymer/polymer.dart';
+
+import 'package:canonicalization/a.dart';
+import 'packages/canonicalization/b.dart';
+import 'package:canonicalization/c.dart';
+import 'package:canonicalization/d.dart' as d1;
+import 'packages/canonicalization/d.dart' as d2;
+
+main() {
+  initPolymer();
+  useHtmlConfiguration();
+
+  setUp(() => Polymer.onReady);
+
+  test('canonicalization', () {
+    // "package:" urls work the same during development and deployment
+    expect(a, 1, reason:
+      'deploy picks the "package:" url as the canonical url for script tags.');
+
+    // relative urls do not. true, we shouldn't be using 'packages/' above, so
+    // that's ok.
+    expect(b, 0, reason:
+      'deploy picks the "package:" url as the canonical url for script tags.');
+    expect(c, 2, reason: 'c was always imported with "package:" urls.');
+    expect(d1.d, 2, reason: 'both a and b are loaded using package: urls');
+
+    // same here
+    expect(d2.d, 0, reason: 'both a and b are loaded using package: urls');
+  });
+}
diff --git a/pkg/polymer/example/canonicalization/test/canonicalization_deploy_test.html b/pkg/polymer/example/canonicalization/test/canonicalization_deploy_test.html
new file mode 100644
index 0000000..2f346f4
--- /dev/null
+++ b/pkg/polymer/example/canonicalization/test/canonicalization_deploy_test.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+for details. All rights reserved. Use of this source code is governed by a
+BSD-style license that can be found in the LICENSE file.
+-->
+<html>
+<!--polymer-test: this comment is needed for test_suite.dart-->
+  <head>
+    <title>Tests canonicalization at deployment time</title>
+    <link rel="import" href="packages/canonicalization/a.html">
+    <link rel="import" href="packages/canonicalization/b.html">
+    <script src="packages/unittest/test_controller.js"></script>
+  </head>
+  <body>
+    <script type="application/dart" src="canonicalization_deploy_test.dart"></script>
+  </body>
+</html>
diff --git a/pkg/polymer/example/canonicalization/test/canonicalization_test.dart b/pkg/polymer/example/canonicalization/test/canonicalization_test.dart
new file mode 100644
index 0000000..a2c54c2
--- /dev/null
+++ b/pkg/polymer/example/canonicalization/test/canonicalization_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/** Tests how canonicalization works during development. */
+library canonicalization.dev_test;
+
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+import 'package:polymer/polymer.dart';
+
+import 'package:canonicalization/a.dart';
+import 'packages/canonicalization/b.dart';
+import 'package:canonicalization/c.dart';
+import 'package:canonicalization/d.dart' as d1;
+import 'packages/canonicalization/d.dart' as d2;
+
+main() {
+  initPolymer();
+  useHtmlConfiguration();
+
+  setUp(() => Polymer.onReady);
+
+  test('canonicalization', () {
+    expect(a, 1, reason:
+      'initPolymer picks the "package:" url as the canonical url for script '
+      'tags whose library is also loaded with a "package:" url.');
+    expect(b, 1, reason:
+      'initPolymer does nothing with script tags where the program doesn\'t '
+      'use a "package:" urls matching the same library.');
+    expect(c, 2, reason: 'c was always imported with "package:" urls.');
+    expect(d1.d, 1, reason: 'this matches the import from a');
+    expect(d2.d, 1, reason: 'this matches the import from b');
+  });
+}
diff --git a/pkg/polymer/example/canonicalization/test/canonicalization_test.html b/pkg/polymer/example/canonicalization/test/canonicalization_test.html
new file mode 100644
index 0000000..fd9c8d9
--- /dev/null
+++ b/pkg/polymer/example/canonicalization/test/canonicalization_test.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+for details. All rights reserved. Use of this source code is governed by a
+BSD-style license that can be found in the LICENSE file.
+-->
+<html>
+<!--polymer-test: this comment is needed for test_suite.dart-->
+  <head>
+    <title>Tests canonicalization during the development cycle</title>
+    <link rel="import" href="packages/canonicalization/a.html">
+    <link rel="import" href="packages/canonicalization/b.html">
+    <script src="packages/unittest/test_controller.js"></script>
+  </head>
+  <body>
+    <script type="application/dart" src="canonicalization_test.dart"></script>
+  </body>
+</html>
diff --git a/pkg/polymer/example/component/news/test/news_index_test.dart b/pkg/polymer/example/component/news/test/news_index_test.dart
index e705c99..034894b 100644
--- a/pkg/polymer/example/component/news/test/news_index_test.dart
+++ b/pkg/polymer/example/component/news/test/news_index_test.dart
@@ -10,7 +10,8 @@
 /**
  * This test runs the news example and checks the state of the initial page.
  */
-@initMethod _main() {
+main() {
+  initPolymer();
   useHtmlConfiguration();
 
   extractLinks(nodes) => nodes.where((n) => n is Element)
@@ -21,8 +22,7 @@
     final items = listComp.queryAll('li');
     expect(items.length, 6);
     expect(extractLinks(items), ['1', '2', '3', '4', '4', '5']);
-    expect(listComp.xtag is Polymer, true,
-        reason: 'x-news should be created');
+    expect(listComp is Polymer, true, reason: 'x-news should be created');
 
     final contents = listComp.shadowRoot.queryAll('content');
     expect(contents.length, 2, reason: 'news has 2 content tags');
diff --git a/pkg/polymer/example/component/news/test/news_index_test.html b/pkg/polymer/example/component/news/test/news_index_test.html
index 8e5dbfd..1666751 100644
--- a/pkg/polymer/example/component/news/test/news_index_test.html
+++ b/pkg/polymer/example/component/news/test/news_index_test.html
@@ -5,6 +5,7 @@
 -->
 <html>
 <head>
+  <!--polymer-test: this comment is needed for test_suite.dart-->
   <title>Simple Web Components Example</title>
   <link rel="import" href="../web/news-component.html">
   <script src="packages/unittest/test_controller.js"></script>
@@ -20,6 +21,5 @@
     <li class="breaking"><a href="//example.com/stories/5">Horrible story</a></li>
 </ul>
 <script type="application/dart" src="news_index_test.dart"></script>
-<script type="application/dart" src="packages/polymer/init.dart"></script>
 </body>
 </html>
diff --git a/pkg/polymer/lib/builder.dart b/pkg/polymer/lib/builder.dart
index 590155a..11f401b 100644
--- a/pkg/polymer/lib/builder.dart
+++ b/pkg/polymer/lib/builder.dart
@@ -86,6 +86,8 @@
 
 import 'src/build/linter.dart';
 import 'src/build/runner.dart';
+import 'src/build/common.dart';
+
 import 'transformer.dart';
 
 
@@ -142,7 +144,7 @@
     String currentPackage, Map<String, String> packageDirs}) {
   if (options == null) options = _options;
   if (currentPackage == null) currentPackage = readCurrentPackageFromPubspec();
-  var linterOptions = new TransformOptions(currentPackage, entryPoints);
+  var linterOptions = new TransformOptions(entryPoints: entryPoints);
   var formatter = options.machineFormat ? jsonFormatter : consoleFormatter;
   var linter = new Linter(linterOptions, formatter);
   return runBarback(new BarbackOptions([[linter]], null,
@@ -198,8 +200,14 @@
     String currentPackage, Map<String, String> packageDirs}) {
   if (options == null) options = _options;
   if (currentPackage == null) currentPackage = readCurrentPackageFromPubspec();
+
+  var transformOptions = new TransformOptions(
+      entryPoints: entryPoints,
+      directlyIncludeJS: options.directlyIncludeJS,
+      contentSecurityPolicy: options.contentSecurityPolicy);
+
   var barbackOptions = new BarbackOptions(
-      createDeployPhases(new TransformOptions(currentPackage, entryPoints)),
+      new PolymerTransformerGroup(transformOptions).phases,
       options.outDir, currentPackage: currentPackage,
       packageDirs: packageDirs);
   return runBarback(barbackOptions)
@@ -233,8 +241,18 @@
   /** Location where to generate output files. */
   final String outDir;
 
+  /** True to use the CSP-compliant JS file. */
+  final bool contentSecurityPolicy;
+
+  /**
+   * True to include the JS script tag directly, without the
+   * "packages/browser/dart.js" trampoline.
+   */
+  final bool directlyIncludeJS;
+
   CommandLineOptions(this.changedFiles, this.removedFiles, this.clean,
-      this.full, this.machineFormat, this.forceDeploy, this.outDir);
+      this.full, this.machineFormat, this.forceDeploy, this.outDir,
+      this.directlyIncludeJS, this.contentSecurityPolicy);
 }
 
 /** Options parsed directly from the command line arguments. */
@@ -251,6 +269,10 @@
  *   * `--machine`: produce output that can be parsed by tools, such as the Dart
  *     Editor.
  *   * `--deploy`: force deploy.
+ *   * `--no-js`: deploy replaces *.dart scripts with *.dart.js. You can turn
+ *     this feature off with --no-js, which leaves "packages/browser/dart.js".
+ *   * `--csp`: replaces *.dart with *.dart.precompiled.js to comply with
+ *     Content Security Policy restrictions.
  *   * `--help`: print documentation for each option and exit.
  *
  * Currently not all the flags are used by [lint] or [deploy] above, but they
@@ -277,16 +299,36 @@
         help: 'Whether to force deploying.')
     ..addOption('out', abbr: 'o', help: 'Directory to generate files into.',
         defaultsTo: 'out')
+    ..addFlag('js', help:
+        'deploy replaces *.dart scripts with *.dart.js. This flag \n'
+        'leaves "packages/browser/dart.js" to do the replacement at runtime.',
+        defaultsTo: true)
+    ..addFlag('csp', help:
+        'replaces *.dart with *.dart.precompiled.js to comply with \n'
+        'Content Security Policy restrictions.')
     ..addFlag('help', abbr: 'h',
         negatable: false, help: 'Displays this help and exit.');
-  var res = parser.parse(args == null ? new Options().arguments : args);
-  if (res['help']) {
-    print('A build script that invokes the polymer linter and deploy tools.');
+
+  showUsage() {
     print('Usage: dart build.dart [options]');
     print('\nThese are valid options expected by build.dart:');
     print(parser.getUsage());
+  }
+
+  var res;
+  try {
+    res = parser.parse(args == null ? new Options().arguments : args);
+  } on FormatException catch (e) {
+    print(e.message);
+    showUsage();
+    exit(1);
+  }
+  if (res['help']) {
+    print('A build script that invokes the polymer linter and deploy tools.');
+    showUsage();
     exit(0);
   }
   return new CommandLineOptions(res['changed'], res['removed'], res['clean'],
-      res['full'], res['machine'], res['deploy'], res['out']);
+      res['full'], res['machine'], res['deploy'], res['out'], res['js'],
+      res['csp']);
 }
diff --git a/pkg/polymer/lib/deploy.dart b/pkg/polymer/lib/deploy.dart
index 8445ac8..13ed25c 100644
--- a/pkg/polymer/lib/deploy.dart
+++ b/pkg/polymer/lib/deploy.dart
@@ -27,6 +27,7 @@
 
 import 'package:args/args.dart';
 import 'package:path/path.dart' as path;
+import 'src/build/common.dart' show TransformOptions;
 import 'src/build/runner.dart';
 import 'transformer.dart';
 
@@ -36,9 +37,16 @@
 
   var test = args['test'];
   var outDir = args['out'];
-  var options = (test == null)
-    ? new BarbackOptions(createDeployPhases(new TransformOptions()), outDir)
-    : _createTestOptions(test, outDir);
+
+  var options;
+  if (test == null) {
+    var transformOps = new TransformOptions(
+        directlyIncludeJS: args['js'],
+        contentSecurityPolicy: args['csp']);
+    options = new BarbackOptions(createDeployPhases(transformOps), outDir);
+  } else {
+    options = _createTestOptions(test, outDir, args['js'], args['csp']);
+  }
   if (options == null) exit(1);
 
   print('polymer/deploy.dart: creating a deploy target for '
@@ -49,7 +57,10 @@
       .catchError(_reportErrorAndExit);
 }
 
-BarbackOptions _createTestOptions(String testFile, String outDir) {
+createDeployPhases(options) => new PolymerTransformerGroup(options).phases;
+
+BarbackOptions _createTestOptions(String testFile, String outDir,
+    bool directlyIncludeJS, bool contentSecurityPolicy) {
   var testDir = path.normalize(path.dirname(testFile));
 
   // A test must be allowed to import things in the package.
@@ -61,12 +72,15 @@
         'your package root directory or a subdirectory.');
     return null;
   }
+  var packageName = readCurrentPackageFromPubspec(pubspecDir);
 
   var phases = createDeployPhases(new TransformOptions(
-        '_test', [path.relative(testFile, from: pubspecDir)]));
+      entryPoints: [path.relative(testFile, from: pubspecDir)],
+      directlyIncludeJS: directlyIncludeJS,
+      contentSecurityPolicy: contentSecurityPolicy));
   return new BarbackOptions(phases, outDir,
-      currentPackage: '_test',
-      packageDirs: {'_test' : pubspecDir},
+      currentPackage: packageName,
+      packageDirs: {packageName : pubspecDir},
       transformTests: true);
 }
 
@@ -95,7 +109,14 @@
           defaultsTo: 'out')
       ..addOption('test', help: 'Deploy the test at the given path.\n'
           'Note: currently this will deploy all tests in its directory,\n'
-          'but it will eventually deploy only the specified test.');
+          'but it will eventually deploy only the specified test.')
+      ..addFlag('js', help:
+          'deploy replaces *.dart scripts with *.dart.js. This flag \n'
+          'leaves "packages/browser/dart.js" to do the replacement at runtime.',
+          defaultsTo: true)
+      ..addFlag('csp', help:
+          'replaces *.dart with *.dart.precompiled.js to comply with \n'
+          'Content Security Policy restrictions.');
   try {
     var results = parser.parse(arguments);
     if (results['help']) {
diff --git a/pkg/polymer/lib/job.dart b/pkg/polymer/lib/job.dart
index 677784a..e8a4fa6 100644
--- a/pkg/polymer/lib/job.dart
+++ b/pkg/polymer/lib/job.dart
@@ -28,6 +28,7 @@
 // TODO(jmesserly): it isn't clear to me what is supposed to be public API here.
 // Or what name we should use. "Job" is awfully generic.
 // (The type itself is not exported in Polymer.)
+// Remove this type in favor of Timer?
 class Job {
   Function _callback;
   Timer _timer;
diff --git a/pkg/polymer/lib/platform.dart b/pkg/polymer/lib/platform.dart
index f6c475a..ea26eb0 100644
--- a/pkg/polymer/lib/platform.dart
+++ b/pkg/polymer/lib/platform.dart
@@ -14,11 +14,9 @@
 import 'dart:async' show Completer;
 import 'dart:html' show Text, MutationObserver;
 import 'dart:collection' show Queue;
-import 'package:observe/src/microtask.dart' show performMicrotaskCheckpoint;
+import 'package:observe/observe.dart';
 
-void flush() {
-  endOfMicrotask(performMicrotaskCheckpoint);
-}
+void flush() => endOfMicrotask(Observable.dirtyCheck);
 
 int _iterations = 0;
 final Queue _callbacks = new Queue();
diff --git a/pkg/polymer/lib/polymer.dart b/pkg/polymer/lib/polymer.dart
index 62bec7c..a195ed8 100644
--- a/pkg/polymer/lib/polymer.dart
+++ b/pkg/polymer/lib/polymer.dart
@@ -49,15 +49,15 @@
     override: const ['polymer', 'polymer.deserialize'])
 import 'dart:mirrors';
 
+import 'package:custom_element/polyfill.dart' show customElementsReady;
 import 'package:logging/logging.dart' show Logger, Level;
-import 'package:mdv/mdv.dart' as mdv;
-import 'package:mdv/mdv.dart' show NodeBinding;
 import 'package:meta/meta.dart' show deprecated;
 import 'package:observe/observe.dart';
-import 'package:observe/src/microtask.dart';
+import 'package:observe/src/dirty_check.dart' show dirtyCheckZone;
 import 'package:path/path.dart' as path;
 import 'package:polymer_expressions/polymer_expressions.dart'
     show PolymerExpressions;
+import 'package:template_binding/template_binding.dart';
 
 import 'deserialize.dart' as deserialize;
 import 'job.dart';
@@ -66,7 +66,6 @@
 
 export 'package:observe/observe.dart';
 export 'package:observe/html.dart';
-export 'package:observe/src/microtask.dart';
 
 part 'src/boot.dart';
 part 'src/declaration.dart';
diff --git a/pkg/polymer/lib/src/build/common.dart b/pkg/polymer/lib/src/build/common.dart
index fc2acf5..743b80b 100644
--- a/pkg/polymer/lib/src/build/common.dart
+++ b/pkg/polymer/lib/src/build/common.dart
@@ -36,10 +36,34 @@
 
 /** Additional options used by polymer transformers */
 class TransformOptions {
-  String currentPackage;
-  List<String> entryPoints;
+  /**
+   * List of entrypoints paths. The paths are relative to the package root and
+   * are represented using posix style, which matches the representation used in
+   * asset ids in barback. If null, anything under 'web/' or 'test/' is
+   * considered an entry point.
+   */
+  final List<String> entryPoints;
 
-  TransformOptions([this.currentPackage, entryPoints])
+  /**
+   * True to enable Content Security Policy.
+   * This means the HTML page will include *.dart.precompiled.js
+   *
+   * This flag has no effect unless [directlyIncludeJS] is enabled.
+   */
+  final bool contentSecurityPolicy;
+
+  /**
+   * True to include the compiled JavaScript directly from the HTML page.
+   * If enabled this will remove "packages/browser/dart.js" and replace
+   * `type="application/dart"` scripts with equivalent *.dart.js files.
+   *
+   * If [contentSecurityPolicy] enabled, this will reference files
+   * named *.dart.precompiled.js.
+   */
+  final bool directlyIncludeJS;
+
+  TransformOptions({entryPoints, this.contentSecurityPolicy: false,
+      this.directlyIncludeJS: true})
       : entryPoints = entryPoints == null ? null
           : entryPoints.map(_systemToAssetPath).toList();
 
@@ -48,11 +72,11 @@
     if (id.extension != '.html') return false;
 
     // Note: [id.path] is a relative path from the root of a package.
-    if (currentPackage == null || entryPoints == null) {
+    if (entryPoints == null) {
       return id.path.startsWith('web/') || id.path.startsWith('test/');
     }
 
-    return id.package == currentPackage && entryPoints.contains(id.path);
+    return entryPoints.contains(id.path);
   }
 }
 
@@ -71,11 +95,12 @@
 
   Future<Document> readAsHtml(AssetId id, Transform transform) {
     var primaryId = transform.primaryInput.id;
-    var url = (id.package == primaryId.package) ? id.path
+    bool samePackage = id.package == primaryId.package;
+    var url = samePackage ? id.path
         : assetUrlFor(id, primaryId, transform.logger, allowAssetUrl: true);
     return transform.readInputAsString(id).then((content) {
       return _parseHtml(content, url, transform.logger,
-        checkDocType: options.isHtmlEntryPoint(id));
+        checkDocType: samePackage && options.isHtmlEntryPoint(id));
     });
   }
 
diff --git a/pkg/polymer/lib/src/build/import_inliner.dart b/pkg/polymer/lib/src/build/import_inliner.dart
index 98924f0..387e36d 100644
--- a/pkg/polymer/lib/src/build/import_inliner.dart
+++ b/pkg/polymer/lib/src/build/import_inliner.dart
@@ -6,14 +6,25 @@
 library polymer.src.build.import_inliner;
 
 import 'dart:async';
+import 'dart:convert';
 
 import 'package:barback/barback.dart';
 import 'package:path/path.dart' as path;
 import 'package:html5lib/dom.dart' show Document, Node, DocumentFragment;
 import 'package:html5lib/dom_parsing.dart' show TreeVisitor;
+
+import 'code_extractor.dart'; // import just for documentation.
 import 'common.dart';
 
-/** Recursively inlines the contents of HTML imports. */
+/**
+ * Recursively inlines the contents of HTML imports. Produces as output a single
+ * HTML file that inlines the polymer-element definitions, and a text file that
+ * contains, in order, the URIs to each library that sourced in a script tag.
+ *
+ * This transformer assumes that all script tags point to external files. To
+ * support script tags with inlined code, use this transformer after running
+ * [InlineCodeExtractor] on an earlier phase.
+ */
 // TODO(sigmund): currently we just inline polymer-element and script tags, we
 // need to make sure we match semantics of html-imports for other tags too.
 // (see dartbug.com/12613).
@@ -27,6 +38,7 @@
       new Future.value(options.isHtmlEntryPoint(input.id));
 
   Future apply(Transform transform) {
+    var logger = transform.logger;
     var seen = new Set<AssetId>();
     var elements = [];
     var id = transform.primaryInput.id;
@@ -34,8 +46,11 @@
     return readPrimaryAsHtml(transform).then((document) {
       var future = _visitImports(document, id, transform, seen, elements);
       return future.then((importsFound) {
+        // We produce a secondary asset with extra information for later phases.
+        var secondaryId = id.addExtension('.scriptUrls');
         if (!importsFound) {
           transform.addOutput(transform.primaryInput);
+          transform.addOutput(new Asset.fromString(secondaryId, '[]'));
           return;
         }
 
@@ -44,11 +59,49 @@
             tag.remove();
           }
         }
-        var fragment = new DocumentFragment()..nodes.addAll(elements);
+
+        // Split Dart script tags from all the other elements. Now that Dartium
+        // only allows a single script tag per page, we can't inline script
+        // tags. Instead, we collect the urls of each script tag so we import
+        // them directly from the Dart bootstrap code.
+        var scripts = [];
+        var rest = [];
+        for (var e in elements) {
+          if (e.tagName == 'script' &&
+              e.attributes['type'] == 'application/dart') {
+            scripts.add(e);
+          } else if (e.tagName == 'polymer-element') {
+            rest.add(e);
+            var script = e.query('script');
+            if (script != null &&
+                script.attributes['type'] == 'application/dart') {
+              script.remove();
+              scripts.add(script);
+            }
+          } else {
+            rest.add(e);
+          }
+        }
+
+        var fragment = new DocumentFragment()..nodes.addAll(rest);
         document.body.insertBefore(fragment,
             //TODO(jmesserly): add Node.firstChild to html5lib
             document.body.nodes.length == 0 ? null : document.body.nodes[0]);
         transform.addOutput(new Asset.fromString(id, document.outerHtml));
+
+        var scriptIds = [];
+        for (var script in scripts) {
+          var src = script.attributes['src'];
+          if (src == null) {
+            logger.warning('unexpected script without a src url. The '
+              'ImportInliner transformer should run after running the '
+              'InlineCodeExtractor', script.sourceSpan);
+            continue;
+          }
+          scriptIds.add(resolve(id, src, logger, script.sourceSpan));
+        }
+        transform.addOutput(new Asset.fromString(secondaryId,
+            JSON.encode(scriptIds, toEncodable: (id) => id.serialize())));
       });
     });
   }
diff --git a/pkg/polymer/lib/src/build/linter.dart b/pkg/polymer/lib/src/build/linter.dart
index bf95215..1227160 100644
--- a/pkg/polymer/lib/src/build/linter.dart
+++ b/pkg/polymer/lib/src/build/linter.dart
@@ -221,7 +221,7 @@
   TransformLogger _logger;
   bool _inPolymerElement = false;
   bool _dartJSSeen = false;
-  bool _initSeen = false;
+  bool _dartTagSeen = false;
   bool _isEntrypoint;
   Map<String, _ElementSummary> _elements;
 
@@ -251,7 +251,7 @@
   void run(Document doc) {
     visit(doc);
 
-    if (_isEntrypoint && !_initSeen) {
+    if (_isEntrypoint && !_dartTagSeen) {
       _logger.error(USE_INIT_DART, span: doc.body.sourceSpan);
     } 
 
@@ -266,9 +266,9 @@
     var rel = node.attributes['rel'];
     if (rel != 'import' && rel != 'stylesheet') return;
 
-    if (rel == 'import' && _initSeen) {
+    if (rel == 'import' && _dartTagSeen) {
       _logger.warning(
-          "Move HTML imports above the 'polymer/init.dart' script tag",
+          "Move HTML imports above your Dart script tag.",
           span: node.sourceSpan);
     }
 
@@ -347,6 +347,7 @@
    */
   void _validateScriptElement(Element node) {
     var scriptType = node.attributes['type'];
+    var isDart = scriptType == 'application/dart';
     var src = node.attributes['src'];
 
     if (scriptType == null) {
@@ -359,11 +360,12 @@
             'be treated as JavaScript. Did you forget type="application/dart"?',
             span: node.sourceSpan);
       }
-      if (src != null && src.endsWith('.dart')) {
-        _logger.warning('script tag with .dart source file but no type will '
-            'be treated as JavaScript. Did you forget type="application/dart"?',
-            span: node.sourceSpan);
+    } else if (isDart) {
+      if (_dartTagSeen) {
+        _logger.warning('Only one "application/dart" script tag per document '
+            'is allowed.', span: node.sourceSpan);
       }
+      _dartTagSeen = true;
     }
 
     if (src == null) return;
@@ -378,21 +380,17 @@
       return;
     }
 
-    if (src == 'packages/polymer/init.dart') {
-      _initSeen = true;
-      if (scriptType != 'application/dart') {
-        _logger.warning('wrong script type, expected type="application/dart".',
-            span: node.sourceSpan);
-      }
+    if (src.endsWith('.dart') && !isDart) {
+      _logger.warning('Wrong script type, expected type="application/dart".',
+          span: node.sourceSpan);
       return;
     }
 
-    if (scriptType != 'application/dart') return;
-
-    if (!src.endsWith('.dart')) {
+    if (!src.endsWith('.dart') && isDart) {
       _logger.warning('"application/dart" scripts should '
           'use the .dart file extension.',
           span: node.sourceSpan);
+      return;
     }
 
     if (node.innerHtml.trim() != '') {
@@ -544,9 +542,11 @@
 const String _NO_COLOR = '\u001b[0m';
 
 const String USE_INIT_DART = 
-    'To run a polymer applications, make sure to include '
+    'To run a polymer applications, you need to call "initPolymer". You can '
+    'either include a generic script tag that does this for you:'
     '\'<script type="application/dart" src="packages/polymer/init.dart">'
-    '</script>\' in your page, after all HTML imports.';
+    '</script>\' or add your own script tag and call that function. '
+    'Make sure the script tag is placed after all HTML imports.';
 
 const String USE_DART_JS =
     'To run a polymer applications in Dartium, make sure to include'
diff --git a/pkg/polymer/lib/src/build/polyfill_injector.dart b/pkg/polymer/lib/src/build/polyfill_injector.dart
index 3bf7e7a..f978613 100644
--- a/pkg/polymer/lib/src/build/polyfill_injector.dart
+++ b/pkg/polymer/lib/src/build/polyfill_injector.dart
@@ -20,6 +20,9 @@
  * are included. For example, this transformer will ensure that there is a
  * script tag that loads the shadow_dom polyfill and interop.js (used for the
  * css shimming).
+ *
+ * This step also replaces "packages/browser/dart.js" and the Dart script tag
+ * with a script tag that loads the dart2js compiled code directly.
  */
 class PolyfillInjector extends Transformer with PolymerTransformer {
   final TransformOptions options;
@@ -35,7 +38,8 @@
       bool shadowDomFound = false;
       bool jsInteropFound = false;
       bool customElementFound = false;
-      bool dartScriptTags = false;
+      Element dartJs;
+      final dartScripts = <Element>[];
 
       for (var tag in document.queryAll('script')) {
         var src = tag.attributes['src'];
@@ -47,22 +51,48 @@
             shadowDomFound = true;
           } else if (_customElementJS.hasMatch(last)) {
             customElementFound = true;
+          } else if (last == 'dart.js') {
+            dartJs = tag;
           }
         }
 
         if (tag.attributes['type'] == 'application/dart') {
-          dartScriptTags = true;
+          dartScripts.add(tag);
         }
       }
 
-      if (!dartScriptTags) {
+      if (dartScripts.isEmpty) {
         // This HTML has no Dart code, there is nothing to do here.
         transform.addOutput(transform.primaryInput);
         return;
       }
 
+      // TODO(jmesserly): ideally we would generate an HTML that loads
+      // dart2dart too. But for now dart2dart is not a supported deployment
+      // target, so just inline the JS script. This has the nice side effect of
+      // fixing our tests: even if content_shell supports Dart VM, we'll still
+      // test the compiled JS code.
+      if (options.directlyIncludeJS) {
+        // If using CSP add the "precompiled" extension
+        final csp = options.contentSecurityPolicy ? '.precompiled' : '';
+
+        // Replace all other Dart script tags with JavaScript versions.
+        for (var script in dartScripts) {
+          final src = script.attributes['src'];
+          if (src.endsWith('.dart')) {
+            script.attributes.remove('type');
+            script.attributes['src'] = '$src$csp.js';
+          }
+        }
+        // Remove "packages/browser/dart.js"
+        if (dartJs != null) dartJs.remove();
+      } else if (dartJs == null) {
+        document.body.nodes.add(parseFragment(
+              '<script src="packages/browser/dart.js"></script>'));
+      }
+
       _addScript(urlSegment) {
-        document.body.nodes.insert(0, parseFragment(
+        document.head.nodes.insert(0, parseFragment(
               '<script src="packages/$urlSegment"></script>\n'));
       }
 
@@ -72,7 +102,7 @@
         _addScript('custom_element/custom-elements.debug.js');
       }
 
-      // This polyfill needs to be the first one on the body
+      // This polyfill needs to be the first one on the head
       // TODO(jmesserly): this is .debug to workaround issue 13046.
       if (!shadowDomFound) _addScript('shadow_dom/shadow_dom.debug.js');
 
diff --git a/pkg/polymer/lib/src/build/runner.dart b/pkg/polymer/lib/src/build/runner.dart
index c00a7b7..e486fdf 100644
--- a/pkg/polymer/lib/src/build/runner.dart
+++ b/pkg/polymer/lib/src/build/runner.dart
@@ -65,8 +65,9 @@
 }
 
 /** Extract the current package from the pubspec.yaml file. */
-String readCurrentPackageFromPubspec() {
-  var pubspec = new File('pubspec.yaml');
+String readCurrentPackageFromPubspec([String dir]) {
+  var pubspec = new File(
+      dir == null ? 'pubspec.yaml' : path.join(dir, 'pubspec.yaml'));
   if (!pubspec.existsSync()) {
     print('error: pubspec.yaml file not found, please run this script from '
         'your package root directory.');
@@ -105,9 +106,10 @@
 final Set<String> _polymerPackageDependencies = [
     'analyzer_experimental', 'args', 'barback', 'browser', 'csslib',
     'custom_element', 'fancy_syntax', 'html5lib', 'html_import', 'js',
-    'logging', 'mdv', 'meta', 'mutation_observer', 'observe', 'path'
+    'logging', 'meta', 'mutation_observer', 'observe', 'path'
     'polymer_expressions', 'serialization', 'shadow_dom', 'source_maps',
-    'stack_trace', 'unittest', 'unmodifiable_collection', 'yaml'].toSet();
+    'stack_trace', 'template_binding', 'unittest', 'unmodifiable_collection',
+    'yaml'].toSet();
 
 /** Return the relative path of each file under [subDir] in [package]. */
 Iterable<String> _listPackageDir(String package, String subDir,
diff --git a/pkg/polymer/lib/src/build/script_compactor.dart b/pkg/polymer/lib/src/build/script_compactor.dart
index 7ac2b2a..01885f7 100644
--- a/pkg/polymer/lib/src/build/script_compactor.dart
+++ b/pkg/polymer/lib/src/build/script_compactor.dart
@@ -6,6 +6,7 @@
 library polymer.src.build.script_compactor;
 
 import 'dart:async';
+import 'dart:convert';
 
 import 'package:barback/barback.dart';
 import 'package:html5lib/parser.dart' show parseFragment;
@@ -24,8 +25,7 @@
  *
  * Internally, this transformer will convert each script tag into an import
  * statement to a library, and then uses `initPolymer` (see polymer.dart)  to
- * invoke the main method on each of these libraries and register any polymer
- * elements annotated with `@CustomTag`.
+ * process `@initMethod` and `@CustomTag` annotations in those libraries.
  */
 class ScriptCompactor extends Transformer with PolymerTransformer {
   final TransformOptions options;
@@ -38,70 +38,70 @@
 
   Future apply(Transform transform) {
     var id = transform.primaryInput.id;
+    var secondaryId = id.addExtension('.scriptUrls');
     var logger = transform.logger;
     return readPrimaryAsHtml(transform).then((document) {
-      var libraries = [];
-      bool changed = false;
-      var dartLoaderTag = null;
-      for (var tag in document.queryAll('script')) {
-        var src = tag.attributes['src'];
-        if (src != null) {
-          if (src == 'packages/polymer/boot.js' ||
-              src == 'packages/polymer/init.dart') {
+      return transform.readInputAsString(secondaryId).then((libraryIds) {
+        var libraries = JSON.decode(libraryIds).map(
+          (data) => new AssetId.deserialize(data)).toList();
+        var mainLibraryId;
+        var mainScriptTag;
+        bool changed = false;
+
+        for (var tag in document.queryAll('script')) {
+          var src = tag.attributes['src'];
+          if (src == 'packages/polymer/boot.js') {
             tag.remove();
             continue;
           }
-          var last = src.split('/').last;
-          if (last == 'dart.js') {
-            dartLoaderTag = tag;
+          if (tag.attributes['type'] != 'application/dart') continue;
+          if (src == null) {
+            logger.warning('unexpected script without a src url. The '
+              'ScriptCompactor transformer should run after running the '
+              'InlineCodeExtractor', span: tag.sourceSpan);
+            continue;
           }
+          if (mainLibraryId != null) {
+            logger.warning('unexpected script. Only one Dart script tag '
+              'per document is allowed.', span: tag.sourceSpan);
+            tag.remove();
+            continue;
+          }
+          mainLibraryId = resolve(id, src, logger, tag.sourceSpan);
+          mainScriptTag = tag;
         }
-        if (tag.attributes['type'] != 'application/dart') continue;
-        tag.remove();
-        changed = true;
-        if (src == null) {
-          logger.warning('unexpected script without a src url. The '
-            'ScriptCompactor transformer should run after running the '
-            'InlineCodeExtractor', tag.sourceSpan);
-          continue;
+
+        if (mainScriptTag == null) {
+          // We didn't find any main library, nothing to do.
+          transform.addOutput(transform.primaryInput);
+          return;
         }
-        var libraryId = resolve(id, src, logger, tag.sourceSpan);
 
-        // TODO(sigmund): should we detect/remove duplicates?
-        if (libraryId == null) continue;
-        libraries.add(libraryId);
-      }
+        var bootstrapId = id.addExtension('_bootstrap.dart');
+        mainScriptTag.attributes['src'] = 
+            path.url.basename(bootstrapId.path);
 
-      if (!changed) {
-        transform.addOutput(transform.primaryInput);
-        return;
-      }
+        libraries.add(mainLibraryId);
+        var urls = libraries.map((id) => assetUrlFor(id, bootstrapId, logger))
+            .where((url) => url != null).toList();
+        var buffer = new StringBuffer()..writeln(MAIN_HEADER);
+        int i = 0;
+        for (; i < urls.length; i++) {
+          buffer.writeln("import '${urls[i]}' as i$i;");
+        }
 
-      var bootstrapId = id.addExtension('_bootstrap.dart');
-      var filename = path.url.basename(bootstrapId.path);
+        buffer..write('\n')
+            ..writeln('void main() {')
+            ..writeln('  configureForDeployment([')
+            ..writeAll(urls.map((url) => "      '$url',\n"))
+            ..writeln('    ]);')
+            ..writeln('  i${i - 1}.main();')
+            ..writeln('}');
 
-      var bootstrapScript = parseFragment(
-            '<script type="application/dart" src="$filename"></script>');
-      if (dartLoaderTag == null) {
-        document.body.nodes.add(bootstrapScript);
-        document.body.nodes.add(parseFragment(
-            '<script src="packages/browser/dart.js"></script>'));
-      } else {
-        dartLoaderTag.parent.insertBefore(bootstrapScript, dartLoaderTag);
-      }
-
-      var urls = libraries.map((id) => assetUrlFor(id, bootstrapId, logger))
-          .where((url) => url != null).toList();
-      var buffer = new StringBuffer()..writeln(MAIN_HEADER);
-      for (int i = 0; i < urls.length; i++) {
-        buffer.writeln("import '${urls[i]}' as i$i;");
-      }
-      buffer..write(_mainPrefix)
-          ..writeAll(urls.map((url) => "      '$url',\n"))
-          ..write(_mainSuffix);
-
-      transform.addOutput(new Asset.fromString(bootstrapId, buffer.toString()));
-      transform.addOutput(new Asset.fromString(id, document.outerHtml));
+        transform.addOutput(new Asset.fromString(
+              bootstrapId, buffer.toString()));
+        transform.addOutput(new Asset.fromString(id, document.outerHtml));
+      });
     });
   }
 }
@@ -111,14 +111,3 @@
 
 import 'package:polymer/polymer.dart';
 """;
-
-const _mainPrefix = """
-
-void main() {
-  initPolymer([
-""";
-
-const _mainSuffix = """
-    ]);
-}
-""";
diff --git a/pkg/polymer/lib/src/declaration.dart b/pkg/polymer/lib/src/declaration.dart
index f776fb5..22c2e86 100644
--- a/pkg/polymer/lib/src/declaration.dart
+++ b/pkg/polymer/lib/src/declaration.dart
@@ -68,8 +68,8 @@
   List<Element> get styles => _styles;
 
   DocumentFragment get templateContent {
-    final template = this.query('template');
-    return template != null ? template.content : null;
+    final template = this.querySelector('template');
+    return template != null ? templateBind(template).content : null;
   }
 
   /** Maps event names and their associated method in the element class. */
@@ -169,10 +169,10 @@
     // TODO(jmesserly): resolvePath not ported, see first comment in this class.
 
     // under ShadowDOMPolyfill, transforms to approximate missing CSS features
-    _shimShadowDomStyling(templateContent, name);
+    _shimShadowDomStyling(templateContent, name, extendee);
 
     // register our custom element
-    registerType(name, extendsTag: extendee);
+    registerType(name);
 
     // NOTE: skip in Dart because we don't have mutable global scope.
     // reference constructor in a global named by 'constructor' attribute
@@ -234,11 +234,14 @@
 
   }
 
-  void registerType(String name, {String extendsTag}) {
-    // native element must be specified in extends
-    var nativeExtends = (extendsTag != null && !extendsTag.contains('-')) ?
-        extendsTag : null;
-    document.register(name, type, extendsTag: nativeExtends);
+  void registerType(String name) {
+    var baseTag;
+    var decl = this;
+    while (decl != null) {
+      baseTag = decl.attributes['extends'];
+      decl = decl.superDeclaration;
+    }
+    document.register(name, type, extendsTag: baseTag);
   }
 
   void publishAttributes(ClassMirror cls, PolymerDeclaration superDecl) {
@@ -333,8 +336,8 @@
   }
 
   void accumulateTemplatedEvents(Element node, Set<String> events) {
-    if (node.localName == 'template' && node.content != null) {
-      accumulateChildEvents(node.content, events);
+    if (node.localName == 'template') {
+      accumulateChildEvents(templateBind(node).content, events);
     }
   }
 
@@ -479,7 +482,7 @@
       if (method.isStatic || !method.isRegularMethod) continue;
 
       String name = MirrorSystem.getName(method.simpleName);
-      if (name.endsWith('Changed')) {
+      if (name.endsWith(_OBSERVE_SUFFIX) && name != 'attributeChanged') {
         if (_observe == null) _observe = {};
         name = name.substring(0, name.length - 7);
         _observe[name] = method.simpleName;
@@ -585,31 +588,16 @@
 /**
  * Using Polymer's platform/src/ShadowCSS.js passing the style tag's content.
  */
-void _shimShadowDomStyling(DocumentFragment template, String localName) {
+void _shimShadowDomStyling(DocumentFragment template, String name,
+    String extendee) {
   if (js.context == null || template == null) return;
+  if (js.context.hasProperty('ShadowDOMPolyfill')) return;
 
   var platform = js.context['Platform'];
   if (platform == null) return;
-
-  var style = template.query('style');
-  if (style == null) return;
-
   var shadowCss = platform['ShadowCSS'];
   if (shadowCss == null) return;
-
-  // TODO(terry): Remove calls to shimShadowDOMStyling2 and replace with
-  //              shimShadowDOMStyling when we support unwrapping dart:html
-  //              Element to a JS DOM node.
-  var shimShadowDOMStyling2 = shadowCss['shimShadowDOMStyling2'];
-  if (shimShadowDOMStyling2 == null) return;
-
-  var scopedCSS = shimShadowDOMStyling2.apply([style.text, localName],
-      thisArg: shadowCss);
-
-  // TODO(terry): Remove when shimShadowDOMStyling is called we don't need to
-  //              replace original CSS with scoped CSS shimShadowDOMStyling
-  //              does that.
-  style.text = scopedCSS;
+  shadowCss.callMethod('shimStyling', [template, name, extendee]);
 }
 
 const _STYLE_SELECTOR = 'style';
@@ -638,7 +626,7 @@
 
 String _cssTextFromSheet(Element sheet) {
   if (sheet == null || js.context == null) return '';
-  var resource = new JsObject.fromBrowserObject(sheet)['__resource'];
+  var resource = new js.JsObject.fromBrowserObject(sheet)['__resource'];
   return resource != null ? resource : '';
 }
 
diff --git a/pkg/polymer/lib/src/instance.dart b/pkg/polymer/lib/src/instance.dart
index 0dfefed..815c6bd 100644
--- a/pkg/polymer/lib/src/instance.dart
+++ b/pkg/polymer/lib/src/instance.dart
@@ -25,7 +25,7 @@
  * The mixin class for Polymer elements. It provides convenience features on top
  * of the custom elements web standard.
  */
-abstract class Polymer implements Element {
+abstract class Polymer implements Element, Observable, NodeBindExtension {
   // Fully ported from revision:
   // https://github.com/Polymer/polymer/blob/4dc481c11505991a7c43228d3797d28f21267779
   //
@@ -39,7 +39,6 @@
   // Not yet ported:
   //   src/instance/style.js -- blocked on ShadowCSS.shimPolyfillDirectives
 
-
   // TODO(jmesserly): should this really be public?
   /** Regular expression that matches data-bindings. */
   static final bindPattern = new RegExp(r'\{\{([^{}]*)}}');
@@ -128,12 +127,8 @@
   Job job(Job job, void callback(), Duration wait) =>
       runJob(job, callback, wait);
 
-  // TODO(jmesserly): I am not sure if we should have the
-  // created/createdCallback distinction. See post here:
-  // https://groups.google.com/d/msg/polymer-dev/W0ZUpU5caIM/v5itFnvnehEJ
-  // Same issue with inserted and removed.
   void polymerCreated() {
-    if (this.document.window != null || alwaysPrepare ||
+    if (this.ownerDocument.window != null || alwaysPrepare ||
         _preparingElements > 0) {
       prepareElement();
     }
@@ -187,9 +182,8 @@
   void parseDeclaration(Element elementElement) {
     var root = shadowFromTemplate(fetchTemplate(elementElement));
 
-    // Dart note: this is extra code compared to Polymer to support
-    // the getShadowRoot method.
-    if (root == null) return;
+    // Dart note: the following code is to support the getShadowRoot method.
+    if (root is! ShadowRoot) return;
 
     var name = elementElement.attributes['name'];
     if (name == null) return;
@@ -202,7 +196,19 @@
   Element fetchTemplate(Element elementElement) =>
       elementElement.query('template');
 
-  /** Utility function that creates a shadow root from a `<template>`. */
+  /**
+   * Utility function that creates a shadow root from a `<template>`.
+   *
+   * The base implementation will return a [ShadowRoot], but you can replace it
+   * with your own code and skip ShadowRoot creation. In that case, you should
+   * return `null`.
+   *
+   * In your overridden method, you can use [instanceTemplate] to stamp the
+   * template and initialize data binding, and [shadowRootReady] to intialize
+   * other Polymer features like event handlers. It is fine to call
+   * shadowRootReady with a node something other than a ShadowRoot; for example,
+   * with this Node.
+   */
   ShadowRoot shadowFromTemplate(Element template) {
     if (template == null) return null;
     // cache elder shadow root (if any)
@@ -230,7 +236,7 @@
     return root;
   }
 
-  void shadowRootReady(ShadowRoot root, Element template) {
+  void shadowRootReady(Node root, Element template) {
     // locate nodes with id and store references to them in this.$ hash
     marshalNodeReferences(root);
     // add local events of interest...
@@ -241,9 +247,9 @@
   }
 
   /** Locate nodes with id and store references to them in [$] hash. */
-  void marshalNodeReferences(ShadowRoot root) {
+  void marshalNodeReferences(Node root) {
     if (root == null) return;
-    for (var n in root.queryAll('[id]')) {
+    for (var n in (root as dynamic).queryAll('[id]')) {
       $[n.id] = n;
     }
   }
@@ -329,15 +335,12 @@
   Object deserializeValue(String value, Object defaultValue, TypeMirror type) =>
       deserialize.deserializeValue(value, defaultValue, type);
 
-  String serializeValue(Object value, TypeMirror inferredType) {
+  String serializeValue(Object value) {
     if (value == null) return null;
 
-    final type = inferredType.qualifiedName;
-    if (type == #dart.core.bool) {
+    if (value is bool) {
       return _toBoolean(value) ? '' : null;
-    } else if (type == #dart.core.String
-        || type == #dart.core.int
-        || type == #dart.core.double) {
+    } else if (value is String || value is int || value is double) {
       return '$value';
     }
     return null;
@@ -349,9 +352,7 @@
     // try to intelligently serialize property value
     // TODO(jmesserly): cache symbol?
     final propValue = self.getField(new Symbol(name)).reflectee;
-    final property = _declaration._publish[name];
-    var inferredType = _inferPropertyType(propValue, property);
-    final serializedValue = serializeValue(propValue, inferredType);
+    final serializedValue = serializeValue(propValue);
     // boolean properties must reflect as boolean attributes
     if (serializedValue != null) {
       attributes[name] = serializedValue;
@@ -360,7 +361,7 @@
       // refine the attr reflection system to achieve this; pica, for example,
       // relies on having inferredType object properties not removed as
       // attrs.
-    } else if (inferredType.qualifiedName == #dart.core.bool) {
+    } else if (propValue is bool) {
       attributes.remove(name);
     }
   }
@@ -369,7 +370,7 @@
    * Creates the document fragment to use for each instance of the custom
    * element, given the `<template>` node. By default this is equivalent to:
    *
-   *     template.createInstance(this, polymerSyntax);
+   *     templateBind(template).createInstance(this, polymerSyntax);
    *
    * Where polymerSyntax is a singleton `PolymerExpressions` instance from the
    * [polymer_expressions](https://pub.dartlang.org/packages/polymer_expressions)
@@ -379,7 +380,10 @@
    * template, for example to use a different data-binding syntax.
    */
   DocumentFragment instanceTemplate(Element template) =>
-      template.createInstance(this, _polymerSyntax);
+      templateBind(template).createInstance(this, _polymerSyntax);
+
+  NodeBinding createBinding(String name, model, String path) =>
+      nodeBindFallback(this).createBinding(name, model, path);
 
   NodeBinding bind(String name, model, String path) {
     // note: binding is a prepare signal. This allows us to be sure that any
@@ -399,13 +403,15 @@
       reflectPropertyToAttribute(MirrorSystem.getName(property.simpleName));
       return bindings[name] = observer;
     } else {
-      // Cannot call super.bind because of
-      // https://code.google.com/p/dart/issues/detail?id=13156
-      // https://code.google.com/p/dart/issues/detail?id=12456
-      return TemplateElement.mdvPackage(this).bind(name, model, path);
+      // Cannot call super.bind because template_binding is its own package
+      return nodeBindFallback(this).bind(name, model, path);
     }
   }
 
+  Map<String, NodeBinding> get bindings => nodeBindFallback(this).bindings;
+
+  void unbind(String name) => nodeBindFallback(this).unbind(name);
+
   void asyncUnbindAll() {
     if (_unbound == true) return;
     _unbindLog.fine('[$localName] asyncUnbindAll');
@@ -416,10 +422,7 @@
     if (_unbound == true) return;
 
     unbindAllProperties();
-    // Cannot call super.bind because of
-    // https://code.google.com/p/dart/issues/detail?id=13156
-    // https://code.google.com/p/dart/issues/detail?id=12456
-    TemplateElement.mdvPackage(this).unbindAll();
+    nodeBindFallback(this).unbindAll();
 
     _unbindNodeTree(shadowRoot);
     // TODO(sjmiles): must also unbind inherited shadow roots
@@ -449,7 +452,7 @@
   }
 
   static void _unbindNodeTree(Node node) {
-    _forNodeTree(node, (node) => node.unbindAll());
+    _forNodeTree(node, (node) => nodeBind(node).unbindAll());
   }
 
   static void _forNodeTree(Node node, void callback(Node node)) {
@@ -517,15 +520,13 @@
   }
 
   void observeProperty(String name, Symbol method) {
-    final self = reflect(this);
-    _observe(name, (value, old) => self.invoke(method, [old]));
+    _observe(name, (value, old) => _invoke(method, [old]));
   }
 
   void observeBoth(String name, Symbol methodName) {
-    final self = reflect(this);
     _observe(name, (value, old) {
       reflectPropertyToAttribute(name);
-      self.invoke(methodName, [old]);
+      _invoke(methodName, [old]);
     });
   }
 
@@ -597,7 +598,7 @@
   }
 
   /** Attach event listeners inside a shadow [root]. */
-  void addInstanceListeners(ShadowRoot root, Element template) {
+  void addInstanceListeners(Node root, Element template) {
     var templateDelegates = _declaration._templateDelegates;
     if (templateDelegates == null) return;
     var events = templateDelegates[template];
@@ -654,10 +655,15 @@
     bool log = _eventsLog.isLoggable(Level.FINE);
     if (log) _eventsLog.fine('>>> [$localName]: dispatch $methodName');
 
-    // TODO(sigmund): consider making event listeners list all arguments
-    // explicitly. Unless VM mirrors are optimized first, this reflectClass call
-    // will be expensive once custom elements extend directly from Element (see
-    // dartbug.com/11108).
+    _invoke(methodName, args);
+
+    if (log) _eventsLog.info('<<< [$localName]: dispatch $methodName');
+  }
+
+  InstanceMirror _invoke(Symbol methodName, List args) {
+    // TODO(sigmund): consider making callbacks list all arguments
+    // explicitly. Unless VM mirrors are optimized first, this will be expensive
+    // once custom elements extend directly from Element (see issue 11108).
     var self = reflect(this);
     var method = self.type.methods[methodName];
     if (method != null) {
@@ -667,12 +673,7 @@
       // them appart from named arguments (see http://dartbug.com/11334)
       args.length = method.parameters.where((p) => !p.isOptional).length;
     }
-    self.invoke(methodName, args);
-
-    if (log) _eventsLog.fine('<<< [$localName]: dispatch $methodName');
-
-    // TODO(jmesserly): workaround for HTML events not supporting zones.
-    performMicrotaskCheckpoint();
+    return self.invoke(methodName, args);
   }
 
   void instanceEventListener(Event event) {
@@ -922,12 +923,25 @@
       type.qualifiedName == #dynamic) {
     // Attempt to infer field type from the default value.
     if (value != null) {
-      type = reflect(value).type;
+      Type t = _getCoreType(value);
+      if (t != null) return reflectClass(t);
+      return reflect(value).type;
     }
   }
   return type;
 }
 
+Type _getCoreType(Object value) {
+  if (value == null) return Null;
+  if (value is int) return int;
+  // Avoid "is double" to prevent warning that it won't work in dart2js.
+  if (value is num) return double;
+  if (value is bool) return bool;
+  if (value is String) return String;
+  if (value is DateTime) return DateTime;
+  return null;
+}
+
 final Logger _observeLog = new Logger('polymer.observe');
 final Logger _eventsLog = new Logger('polymer.events');
 final Logger _unbindLog = new Logger('polymer.unbind');
diff --git a/pkg/polymer/lib/src/loader.dart b/pkg/polymer/lib/src/loader.dart
index c2e2f55..9681a93 100644
--- a/pkg/polymer/lib/src/loader.dart
+++ b/pkg/polymer/lib/src/loader.dart
@@ -32,42 +32,82 @@
  * The urls in [libraries] can be absolute or relative to
  * `currentMirrorSystem().isolate.rootLibrary.uri`.
  */
-void initPolymer([List<String> libraries]) {
-  runMicrotask(() {
-    // DOM events don't yet go through microtasks, so we catch those here.
-    new Timer.periodic(new Duration(milliseconds: 125),
-        (_) => performMicrotaskCheckpoint());
-
-    preventFlashOfUnstyledContent();
-
-    // TODO(jmesserly): mdv should use initMdv instead of mdv.initialize.
-    mdv.initialize();
-    document.register(PolymerDeclaration._TAG, PolymerDeclaration);
-
-    // Note: we synchronously load all libraries because the script invoking
-    // this is run after all HTML imports are resolved.
-    if (libraries == null) {
-      libraries = _discoverScripts(document, window.location.href);
-    }
-    _loadLibraries(libraries);
-  });
+void initPolymer() {
+  if (_useDirtyChecking) {
+    dirtyCheckZone().run(_initPolymerOptimized);
+  } else {
+    _initPolymerOptimized();
+  }
 }
 
-void _loadLibraries(libraries) {
-  for (var lib in libraries) {
-    _loadLibrary(lib);
+/**
+ * Same as [initPolymer], but runs the version that is optimized for deployment
+ * to the internet. The biggest difference is it omits the [Zone] that
+ * automatically invokes [Observable.dirtyCheck], and the list of libraries must
+ * be supplied instead of being dynamically searched for at runtime.
+ */
+// TODO(jmesserly): change the Polymer build step to call this directly.
+void _initPolymerOptimized() {
+  preventFlashOfUnstyledContent();
+
+  document.register(PolymerDeclaration._TAG, PolymerDeclaration);
+
+  _loadLibraries();
+}
+
+/**
+ * Configures [initPolymer] making it optimized for deployment to the internet.
+ * With this setup the list of libraries to initialize is supplied instead of
+ * being dynamically searched for at runtime. Additionally, after this method is
+ * called, [initPolymer] omits the [Zone] that automatically invokes
+ * [Observable.dirtyCheck].
+ */
+void configureForDeployment(List<String> libraries) {
+  _librariesToLoad = libraries;
+  _useDirtyChecking = false;
+}
+
+/**
+ * Libraries that will be initialized. For each library, the intialization
+ * registers any type tagged with a [CustomTag] annotation and calls any
+ * top-level method annotated with [initMethod]. The value of this field is
+ * assigned programatically by the code generated from the polymer deploy
+ * scripts. During development, the libraries are inferred by crawling HTML
+ * imports and searching for script tags.
+ */
+List<String> _librariesToLoad =
+    _discoverScripts(document, window.location.href);
+bool _useDirtyChecking = true;
+
+void _loadLibraries() {
+  for (var lib in _librariesToLoad) {
+    try {
+      _loadLibrary(lib);
+    } catch (e, s) {
+      // Deliver errors async, so if a single library fails it doesn't prevent
+      // other things from loading.
+      new Completer().completeError(e, s);
+    }
   }
-  Polymer._ready.complete();
+
+  customElementsReady.then((_) => Polymer._ready.complete());
 }
 
 /**
  * Walks the HTML import structure to discover all script tags that are
- * implicitly loaded.
+ * implicitly loaded. This code is only used in Dartium and should only be
+ * called after all HTML imports are resolved. Polymer ensures this by asking
+ * users to put their Dart script tags after all HTML imports (this is checked
+ * by the linter, and Dartium will otherwise show an error message).
  */
 List<String> _discoverScripts(Document doc, String baseUri,
     [Set<Document> seen, List<String> scripts]) {
   if (seen == null) seen = new Set<Document>();
   if (scripts == null) scripts = <String>[];
+  if (doc == null) {
+    print('warning: $baseUri not found.');
+    return;
+  }
   if (seen.contains(doc)) return scripts;
   seen.add(doc);
 
@@ -100,6 +140,9 @@
 // root library (see dartbug.com/12612)
 final _rootUri = currentMirrorSystem().isolate.rootLibrary.uri;
 
+final String _packageRoot =
+    '${path.dirname(Uri.parse(window.location.href).path)}/packages/';
+
 /** Regex that matches urls used to represent inlined scripts. */
 final RegExp _inlineScriptRegExp = new RegExp('\(.*\.html.*\):\([0-9]\+\)');
 
@@ -156,6 +199,13 @@
     if (list != null && pos >= 0 && pos < list.length && list[pos] != null) {
       lib = _libs[list[pos]];
     }
+  } else if (uri.path.startsWith(_packageRoot)) {
+    var packageUri =
+        Uri.parse('package:${uri.path.substring(_packageRoot.length)}');
+    lib = _libs[packageUri];
+    if (lib == null) {
+      lib = _libs[uri];
+    }
   } else {
     lib = _libs[uri];
   }
diff --git a/pkg/polymer/lib/transformer.dart b/pkg/polymer/lib/transformer.dart
index a0e4902..4d132cf 100644
--- a/pkg/polymer/lib/transformer.dart
+++ b/pkg/polymer/lib/transformer.dart
@@ -2,9 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/** Transfomers used for pub-serve and pub-deploy. */
-// TODO(sigmund): move into a plugin directory when pub supports it.
-library polymer.src.transform;
+/** Transfomer used for pub-serve and pub-deploy. */
+library polymer.transformer;
 
 import 'package:barback/barback.dart';
 import 'package:observe/transform.dart';
@@ -14,14 +13,51 @@
 import 'src/build/polyfill_injector.dart';
 import 'src/build/common.dart';
 
-export 'src/build/code_extractor.dart';
-export 'src/build/import_inliner.dart';
-export 'src/build/script_compactor.dart';
-export 'src/build/polyfill_injector.dart';
-export 'src/build/common.dart' show TransformOptions;
+/**
+ * The Polymer transformer, which internally runs several phases that will:
+ *   * Extract inlined script tags into their separate files
+ *   * Apply the observable transformer on every Dart script.
+ *   * Inline imported html files
+ *   * Combine scripts from multiple files into a single script tag
+ *   * Inject extra polyfills needed to run on all browsers.
+ *
+ * At the end of these phases, this tranformer produces a single entrypoint HTML
+ * file with a single Dart script that can later be compiled with dart2js.
+ */
+class PolymerTransformerGroup implements TransformerGroup {
+  final Iterable<Iterable> phases;
 
-/** Creates phases to deploy a polymer application. */
-List<List<Transformer>> createDeployPhases(TransformOptions options) {
+  PolymerTransformerGroup(TransformOptions options)
+      : phases = _createDeployPhases(options);
+
+  PolymerTransformerGroup.asPlugin(Map args) : this(_parseArgs(args));
+}
+
+
+TransformOptions _parseArgs(Map args) {
+  var entryPoints;
+  if (args.containsKey('entry_points')) {
+    entryPoints = [];
+    var value = args['entry_points'];
+    bool error;
+    if (value is List) {
+      entryPoints = value;
+      error = value.any((e) => e is! String);
+    } else if (value is String) {
+      entryPoints = [value];
+      error = false;
+    } else {
+      error = true;
+    }
+
+    if (error) {
+      print('Invalid value for "entry_points" in the polymer transformer.');
+    }
+  }
+  return new TransformOptions(entryPoints: entryPoints);
+}
+
+List<List<Transformer>> _createDeployPhases(TransformOptions options) {
   return [
     [new InlineCodeExtractor(options)],
     [new ObservableTransformer()],
diff --git a/pkg/polymer/pubspec.yaml b/pkg/polymer/pubspec.yaml
index acd745f..34380cf 100644
--- a/pkg/polymer/pubspec.yaml
+++ b/pkg/polymer/pubspec.yaml
@@ -15,13 +15,13 @@
   html5lib: any
   html_import: any
   logging: any
-  mdv: any
   meta: any
   observe: any
   path: any
   polymer_expressions: any
   shadow_dom: any
   source_maps: any
+  template_binding: any
   yaml: any
 dev_dependencies:
   unittest: any
diff --git a/pkg/polymer/test/attr_deserialize_test.dart b/pkg/polymer/test/attr_deserialize_test.dart
index 911435d..4cee6c9 100644
--- a/pkg/polymer/test/attr_deserialize_test.dart
+++ b/pkg/polymer/test/attr_deserialize_test.dart
@@ -19,11 +19,14 @@
   @published Object json;
 }
 
-@initMethod _main() {
+main() {
+  initPolymer();
   useHtmlConfiguration();
 
+  setUp(() => Polymer.onReady);
+
   test('attributes were deserialized', () {
-    MyElement elem = query('my-element').xtag;
+    MyElement elem = query('my-element');
     final msg = 'property should match attribute.';
     expect(elem.volume, 11.0, reason: '"volume" should match attribute');
     expect(elem.factor, 3, reason: '"factor" should match attribute');
diff --git a/pkg/polymer/test/attr_deserialize_test.html b/pkg/polymer/test/attr_deserialize_test.html
index 48c2102..c6592af 100644
--- a/pkg/polymer/test/attr_deserialize_test.html
+++ b/pkg/polymer/test/attr_deserialize_test.html
@@ -5,6 +5,7 @@
 BSD-style license that can be found in the LICENSE file.
 -->
 <html>
+  <!--polymer-test: this comment is needed for test_suite.dart-->
   <head>
     <title>Polymer.dart attribute deserialization test</title>
     <script src="packages/unittest/test_controller.js"></script>
@@ -24,6 +25,5 @@
     </my-element>
 
     <script type="application/dart" src="attr_deserialize_test.dart"></script>
-    <script type="application/dart" src="packages/polymer/init.dart"></script>
   </body>
 </html>
diff --git a/pkg/polymer/test/attr_mustache_test.dart b/pkg/polymer/test/attr_mustache_test.dart
index 50753b3..6e61f92 100644
--- a/pkg/polymer/test/attr_mustache_test.dart
+++ b/pkg/polymer/test/attr_mustache_test.dart
@@ -4,9 +4,10 @@
 
 import 'dart:async';
 import 'dart:html';
+import 'package:polymer/polymer.dart';
 import 'package:unittest/unittest.dart';
 import 'package:unittest/html_config.dart';
-import 'package:polymer/polymer.dart';
+import 'package:template_binding/template_binding.dart';
 
 @CustomTag('x-target')
 class XTarget extends PolymerElement {
@@ -17,7 +18,7 @@
 
   // force an mdv binding
   bind(name, model, path) =>
-      TemplateElement.mdvPackage(this).bind(name, model, path);
+      nodeBindFallback(this).bind(name, model, path);
 
   inserted() {
     testSrcForMustache();
@@ -43,12 +44,15 @@
   @observable var src = 'testSource';
 }
 
-@initMethod _main() {
+main() {
+  initPolymer();
   useHtmlConfiguration();
 
+  setUp(() => Polymer.onReady);
+
   test('mustache attributes', () {
-    final xtest = document.query('#test').xtag;
-    final xtarget = xtest.shadowRoot.query('#target').xtag;
+    final xtest = document.query('#test');
+    final xtarget = xtest.shadowRoot.query('#target');
     return xtarget.foundSrc;
   });
 }
diff --git a/pkg/polymer/test/attr_mustache_test.html b/pkg/polymer/test/attr_mustache_test.html
index b4ef0e2..9bc3a77 100644
--- a/pkg/polymer/test/attr_mustache_test.html
+++ b/pkg/polymer/test/attr_mustache_test.html
@@ -6,6 +6,7 @@
 -->
 <html>
   <head>
+  <!--polymer-test: this comment is needed for test_suite.dart-->
     <title>take attributes</title>
     <script src="packages/unittest/test_controller.js"></script>
   </head>
@@ -22,6 +23,5 @@
     </polymer-element>
 
   <script type="application/dart" src="attr_mustache_test.dart"></script>
-  <script type="application/dart" src="packages/polymer/init.dart"></script>
   </body>
 </html>
diff --git a/pkg/polymer/test/bind_mdv_test.dart b/pkg/polymer/test/bind_mdv_test.dart
new file mode 100644
index 0000000..6706bde
--- /dev/null
+++ b/pkg/polymer/test/bind_mdv_test.dart
@@ -0,0 +1,95 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library polymer.test.bind_mdv_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:custom_element/polyfill.dart';
+import 'package:template_binding/template_binding.dart';
+import 'package:observe/observe.dart';
+import 'package:observe/src/microtask.dart' show runMicrotask;
+import 'package:polymer/platform.dart' as Platform;
+import 'package:unittest/html_config.dart';
+import 'package:unittest/unittest.dart';
+
+main() {
+  useHtmlConfiguration();
+
+  var registered = loadCustomElementPolyfill().then((_) {
+    document.register('my-div', MyDivElement);
+  });
+
+  setUp(() => registered);
+
+  group('bindModel', bindModelTests);
+}
+
+bindModelTests() {
+  var div;
+
+  setUp(() {
+    div = new MyDivElement();
+    document.body.append(div);
+  });
+
+  tearDown(() {
+    div.remove();
+  });
+
+  parseAndBindHTML(html, model) =>
+      templateBind(new Element.tag('template')
+        ..setInnerHtml(html, treeSanitizer: const NullTreeSanitizer()))
+        .createInstance(model);
+
+  test('bindModel', () {
+    var fragment = parseAndBindHTML('<div id="a" foo="{{bar}}"></div>', div);
+    div.append(fragment);
+    var a = div.query('#a');
+
+    div.bar = 5;
+    return onAttributeChange(a).then((_) {
+      expect(a.attributes['foo'], '5');
+      div.bar = 8;
+      return onAttributeChange(a).then((_) {
+        expect(a.attributes['foo'], '8');
+      });
+    });
+  });
+
+  test('bind input', () {
+    var fragment = parseAndBindHTML('<input value="{{bar}}" />', div);
+    div.append(fragment);
+    var a = div.query('input');
+
+    div.bar = 'hello';
+    // TODO(sorvell): fix this when observe-js lets us explicitly listen for
+    // a change on input.value
+    Observable.dirtyCheck();
+    Platform.endOfMicrotask(expectAsync0(() {
+      expect(a.value, 'hello');
+    }));
+  });
+}
+
+class MyDivElement extends HtmlElement with Observable {
+  factory MyDivElement() => new Element.tag('my-div');
+  MyDivElement.created() : super.created();
+  @observable var bar;
+}
+
+class NullTreeSanitizer implements NodeTreeSanitizer {
+  const NullTreeSanitizer();
+  void sanitizeTree(Node node) {}
+}
+
+Future onAttributeChange(Element node) {
+  var completer = new Completer();
+  new MutationObserver((records, observer) {
+    observer.disconnect();
+    completer.complete();
+  })..observe(node, attributes: true);
+  Platform.flush();
+  return completer.future;
+}
\ No newline at end of file
diff --git a/pkg/polymer/test/bind_test.dart b/pkg/polymer/test/bind_test.dart
new file mode 100644
index 0000000..2e726cc
--- /dev/null
+++ b/pkg/polymer/test/bind_test.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 'dart:async';
+import 'dart:html';
+import 'package:polymer/polymer.dart';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+import 'package:unittest/matcher.dart';
+
+@CustomTag('x-foo')
+class XFoo extends PolymerElement {
+  @observable var foo = 'foo!';
+  final _ready = new Completer();
+  Future onTestDone;
+
+  XFoo.created() : super.created() {
+    onTestDone = _ready.future.then(_runTest);
+  }
+
+  _runTest(_) {
+    expect(foo, $['foo'].attributes['foo']);
+    expect($['bool'].attributes['foo'], '');
+    expect($['bool'].attributes, isNot(contains('foo?')));
+    expect($['content'].innerHtml, foo);
+
+    expect(foo, $['bar'].attributes['foo']);
+    expect($['barBool'].attributes['foo'], '');
+    expect($['barBool'].attributes, isNot(contains('foo?')));
+    expect($['barContent'].innerHtml, foo);
+  }
+
+  ready() => _ready.complete();
+}
+
+main() {
+  initPolymer();
+  useHtmlConfiguration();
+
+  setUp(() => Polymer.onReady);
+
+  test('ready called', () => query('x-foo').onTestDone);
+}
diff --git a/pkg/polymer/test/bind_test.html b/pkg/polymer/test/bind_test.html
new file mode 100644
index 0000000..3b3970c
--- /dev/null
+++ b/pkg/polymer/test/bind_test.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<!--
+Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+for details. All rights reserved. Use of this source code is governed by a
+BSD-style license that can be found in the LICENSE file.
+-->
+<html>
+  <!--polymer-test: this comment is needed for test_suite.dart-->
+  <head>
+    <title>bind simple</title>
+    <script src="packages/unittest/test_controller.js"></script>
+  </head>
+  <body>
+    <x-foo></x-foo>
+
+    <polymer-element name="x-bar" noscript>
+      <template>
+        x-bar
+      </template>
+    </polymer-element>
+
+    <polymer-element name="x-foo">
+      <template>
+        <div id="foo" foo="{{foo}}"></div>
+        <div id="bool" foo?="{{foo}}"></div>
+        <div id="content">{{foo}}</div>
+        <x-bar id="bar" foo="{{foo}}" ></x-bar>
+        <x-bar id="barBool" foo?="{{foo}}"></x-bar>
+        <x-bar id="barContent">{{foo}}</x-bar>
+      </template>
+    </polymer-element>
+
+    <script type="application/dart" src="bind_test.dart"></script>
+  </body>
+</html>
diff --git a/pkg/polymer/test/build/all_phases_test.dart b/pkg/polymer/test/build/all_phases_test.dart
index 047dca4..9a1fccd 100644
--- a/pkg/polymer/test/build/all_phases_test.dart
+++ b/pkg/polymer/test/build/all_phases_test.dart
@@ -4,15 +4,16 @@
 
 library polymer.test.build.all_phases_test;
 
-import 'package:polymer/transformer.dart';
+import 'package:polymer/src/build/common.dart';
 import 'package:polymer/src/build/script_compactor.dart' show MAIN_HEADER;
+import 'package:polymer/transformer.dart';
 import 'package:unittest/compact_vm_config.dart';
 
 import 'common.dart';
 
 void main() {
   useCompactVMConfiguration();
-  var phases = createDeployPhases(new TransformOptions());
+  var phases = new PolymerTransformerGroup(new TransformOptions()).phases;
 
   testPhases('no changes', phases, {
       'a|web/test.html': '<!DOCTYPE html><html></html>',
@@ -35,23 +36,22 @@
       'a|web/test.dart': _sampleObservable('A', 'foo'),
     }, {
       'a|web/test.html':
-          '<!DOCTYPE html><html><head></head><body>'
+          '<!DOCTYPE html><html><head>'
           '$SHADOW_DOM_TAG'
           '$CUSTOM_ELEMENT_TAG'
           '$INTEROP_TAG'
-          '<script type="application/dart" '
-          'src="test.html_bootstrap.dart"></script>'
-          '<script src="packages/browser/dart.js"></script>'
-          '</body></html>',
+          '<script src="test.html_bootstrap.dart.js"></script>'
+          '</head><body></body></html>',
 
       'a|web/test.html_bootstrap.dart':
           '''$MAIN_HEADER
           import 'a.dart' as i0;
 
           void main() {
-            initPolymer([
+            configureForDeployment([
                 'a.dart',
               ]);
+            i0.main();
           }
           '''.replaceAll('\n          ', '\n'),
       'a|web/test.dart': _sampleObservableOutput('A', 'foo'),
@@ -64,23 +64,22 @@
           '${_sampleObservable("B", "bar")}</script>',
     }, {
       'a|web/test.html':
-          '<!DOCTYPE html><html><head></head><body>'
+          '<!DOCTYPE html><html><head>'
           '$SHADOW_DOM_TAG'
           '$CUSTOM_ELEMENT_TAG'
           '$INTEROP_TAG'
-          '<script type="application/dart" '
-          'src="test.html_bootstrap.dart"></script>'
-          '<script src="packages/browser/dart.js"></script>'
-          '</body></html>',
+          '<script src="test.html_bootstrap.dart.js"></script>'
+          '</head><body></body></html>',
 
       'a|web/test.html_bootstrap.dart':
           '''$MAIN_HEADER
           import 'test.html.0.dart' as i0;
 
           void main() {
-            initPolymer([
+            configureForDeployment([
                 'test.html.0.dart',
               ]);
+            i0.main();
           }
           '''.replaceAll('\n          ', '\n'),
       'a|web/test.html.0.dart': _sampleObservableOutput("B", "bar"),
@@ -90,6 +89,10 @@
       'a|web/test.html':
           '<!DOCTYPE html><html><head>'
           '<script type="application/dart" src="a.dart"></script>'
+          // TODO(sigmund): provide a way to see logging warnings and errors.
+          // For example, these extra tags produce warnings and are then removed
+          // by the transformers. The test below checks that the output looks
+          // correct, but we should also validate the messages logged.
           '<script type="application/dart">'
           '${_sampleObservable("B", "bar")}</script>'
           '</head><body><div>'
@@ -100,30 +103,24 @@
       'a|web/a.dart': _sampleObservable('A', 'foo'),
     }, {
       'a|web/test.html':
-          '<!DOCTYPE html><html><head></head><body>'
+          '<!DOCTYPE html><html><head>'
           '$SHADOW_DOM_TAG'
           '$CUSTOM_ELEMENT_TAG'
           '$INTEROP_TAG'
+          '<script src="test.html_bootstrap.dart.js"></script>'
+          '</head><body>'
           '<div></div>'
-          '<script type="application/dart" '
-          'src="test.html_bootstrap.dart"></script>'
-          '<script src="packages/browser/dart.js"></script>'
           '</body></html>',
 
       'a|web/test.html_bootstrap.dart':
           '''$MAIN_HEADER
           import 'a.dart' as i0;
-          import 'test.html.0.dart' as i1;
-          import 'test.html.1.dart' as i2;
-          import 'd.dart' as i3;
 
           void main() {
-            initPolymer([
+            configureForDeployment([
                 'a.dart',
-                'test.html.0.dart',
-                'test.html.1.dart',
-                'd.dart',
               ]);
+            i0.main();
           }
           '''.replaceAll('\n          ', '\n'),
       'a|web/a.dart': _sampleObservableOutput('A', 'foo'),
@@ -136,9 +133,7 @@
           '<!DOCTYPE html><html><head>'
           '<link rel="import" href="test2.html">'
           '</head><body>'
-          '<script type="application/dart" src="b.dart"></script>'
-          '<script type="application/dart">'
-          '${_sampleObservable("C", "car")}</script>',
+          '<script type="application/dart" src="b.dart"></script>',
       'a|web/b.dart': _sampleObservable('B', 'bar'),
       'a|web/test2.html':
           '<!DOCTYPE html><html><head></head><body>'
@@ -148,32 +143,28 @@
           '</polymer-element></html>',
     }, {
       'a|web/index.html':
-          '<!DOCTYPE html><html><head></head><body>'
+          '<!DOCTYPE html><html><head>'
           '$SHADOW_DOM_TAG'
           '$CUSTOM_ELEMENT_TAG'
           '$INTEROP_TAG'
-          '<polymer-element>1</polymer-element>'
-          '<script type="application/dart" '
-          'src="index.html_bootstrap.dart"></script>'
-          '<script src="packages/browser/dart.js"></script>'
+          '</head><body><polymer-element>1</polymer-element>'
+          '<script src="index.html_bootstrap.dart.js"></script>'
           '</body></html>',
       'a|web/index.html_bootstrap.dart':
           '''$MAIN_HEADER
           import 'test2.html.0.dart' as i0;
           import 'b.dart' as i1;
-          import 'index.html.0.dart' as i2;
 
           void main() {
-            initPolymer([
+            configureForDeployment([
                 'test2.html.0.dart',
                 'b.dart',
-                'index.html.0.dart',
               ]);
+            i1.main();
           }
           '''.replaceAll('\n          ', '\n'),
       'a|web/test2.html.0.dart': _sampleObservableOutput("A", "foo"),
       'a|web/b.dart': _sampleObservableOutput('B', 'bar'),
-      'a|web/index.html.0.dart': _sampleObservableOutput("C", "car"),
     });
 }
 
diff --git a/pkg/polymer/test/build/common.dart b/pkg/polymer/test/build/common.dart
index ce2de9f..95a798e 100644
--- a/pkg/polymer/test/build/common.dart
+++ b/pkg/polymer/test/build/common.dart
@@ -106,6 +106,7 @@
     '<script src="packages/shadow_dom/shadow_dom.debug.js"></script>\n';
 
 const INTEROP_TAG = '<script src="packages/browser/interop.js"></script>\n';
+const DART_JS_TAG = '<script src="packages/browser/dart.js"></script>';
 
 const CUSTOM_ELEMENT_TAG =
     '<script src="packages/custom_element/custom-elements.debug.js">'
diff --git a/pkg/polymer/test/build/import_inliner_test.dart b/pkg/polymer/test/build/import_inliner_test.dart
index b40eea5..05abda2 100644
--- a/pkg/polymer/test/build/import_inliner_test.dart
+++ b/pkg/polymer/test/build/import_inliner_test.dart
@@ -18,6 +18,7 @@
       'a|web/test.html': '<!DOCTYPE html><html></html>',
     }, {
       'a|web/test.html': '<!DOCTYPE html><html></html>',
+      'a|web/test.html.scriptUrls': '[]',
     });
 
   testPhases('empty import', phases, {
@@ -33,9 +34,11 @@
       'a|web/test.html':
           '<!DOCTYPE html><html><head>'
           '</head><body></body></html>',
+      'a|web/test.html.scriptUrls': '[]',
       'a|web/test2.html':
           '<!DOCTYPE html><html><head>'
           '</head><body></body></html>',
+      'a|web/test2.html.scriptUrls': '[]',
     });
 
   testPhases('shallow, no elements', phases, {
@@ -50,9 +53,11 @@
       'a|web/test.html':
           '<!DOCTYPE html><html><head>'
           '</head><body></body></html>',
+      'a|web/test.html.scriptUrls': '[]',
       'a|web/test2.html':
           '<!DOCTYPE html><html><head>'
           '</head></html>',
+      'a|web/test2.html.scriptUrls': '[]',
     });
 
   testPhases('shallow, elements, one import', phases,
@@ -70,9 +75,11 @@
           '</head><body>'
           '<polymer-element>2</polymer-element>'
           '</body></html>',
+      'a|web/test.html.scriptUrls': '[]',
       'a|web/test2.html':
           '<!DOCTYPE html><html><head>'
           '</head><body><polymer-element>2</polymer-element></html>',
+      'a|web/test2.html.scriptUrls': '[]',
     });
 
   testPhases('no transformation outside web/', phases,
@@ -289,6 +296,7 @@
           '<script src="s2"></script>'
           '<polymer-element>1</polymer-element>'
           '<script src="s1"></script></body></html>',
+      'a|web/test.html.scriptUrls': '[]',
       'a|web/test_1.html':
           '<!DOCTYPE html><html><head>'
           '</head><body>'
@@ -296,6 +304,7 @@
           '<script src="s2"></script>'
           '<polymer-element>1</polymer-element>'
           '<script src="s1"></script></body></html>',
+      'a|web/test_1.html.scriptUrls': '[]',
       'a|web/test_2.html':
           '<!DOCTYPE html><html><head>'
           '</head><body>'
@@ -303,6 +312,53 @@
           '<script src="s1"></script>'
           '<polymer-element>2</polymer-element>'
           '<script src="s2"></script></body></html>',
+      'a|web/test_2.html.scriptUrls': '[]',
+    });
+
+  testPhases('imports cycle, 1-step lasso, Dart scripts too', phases, {
+      'a|web/test.html':
+          '<!DOCTYPE html><html><head>'
+          '<link rel="import" href="test_1.html">'
+          '</head></html>',
+      'a|web/test_1.html':
+          '<!DOCTYPE html><html><head>'
+          '<link rel="import" href="test_2.html">'
+          '</head><body><polymer-element>1</polymer-element>'
+          '<script type="application/dart" src="s1.dart"></script></html>',
+      'a|web/test_2.html':
+          '<!DOCTYPE html><html><head>'
+          '<link rel="import" href="test_1.html">'
+          '</head><body><polymer-element>2'
+          '<script type="application/dart" src="s2.dart"></script>'
+          '</polymer-element>'
+          '</html>',
+    }, {
+      'a|web/test.html':
+          '<!DOCTYPE html><html><head>'
+          '</head><body>'
+          '<polymer-element>2</polymer-element>'
+          '<polymer-element>1</polymer-element>'
+          '</body></html>',
+      'a|web/test.html.scriptUrls': '[["a","web/s2.dart"],["a","web/s1.dart"]]',
+      'a|web/test_1.html':
+          '<!DOCTYPE html><html><head>'
+          '</head><body>'
+          '<polymer-element>2</polymer-element>'
+          '<polymer-element>1</polymer-element>'
+          '<script type="application/dart" src="s1.dart"></script>'
+          '</body></html>',
+      'a|web/test_1.html.scriptUrls':
+          '[["a","web/s2.dart"]]',
+      'a|web/test_2.html':
+          '<!DOCTYPE html><html><head>'
+          '</head><body>'
+          '<polymer-element>1</polymer-element>'
+          '<polymer-element>2'
+          '<script type="application/dart" src="s2.dart"></script>'
+          '</polymer-element>'
+          '</body></html>',
+      'a|web/test_2.html.scriptUrls':
+          '[["a","web/s1.dart"]]',
     });
 
   testPhases('imports cycle, 2-step lasso', phases, {
diff --git a/pkg/polymer/test/build/linter_test.dart b/pkg/polymer/test/build/linter_test.dart
index 98f4c3f..1e216e1 100644
--- a/pkg/polymer/test/build/linter_test.dart
+++ b/pkg/polymer/test/build/linter_test.dart
@@ -50,6 +50,48 @@
                                     '(web/test.html 1 0)',
       });
   });
+  group('single script tag per document', () {
+    _testLinter('two top-level tags', {
+        'a|web/test.html': '<!DOCTYPE html><html>'
+            '<script type="application/dart" src="a.dart">'
+            '</script>\n'
+            '<script type="application/dart" src="b.dart">'
+            '</script>'
+            '<script src="packages/browser/dart.js"></script>'
+      }, {
+        'a|web/test.html.messages': 
+            'warning: Only one "application/dart" script tag per document is'
+            ' allowed. (web/test.html 1 0)',
+      });
+
+    _testLinter('two top-level tags, non entrypoint', {
+        'a|lib/test.html': '<!DOCTYPE html><html>'
+            '<script type="application/dart" src="a.dart">'
+            '</script>\n'
+            '<script type="application/dart" src="b.dart">'
+            '</script>'
+            '<script src="packages/browser/dart.js"></script>'
+      }, {
+        'a|lib/test.html.messages': 
+            'warning: Only one "application/dart" script tag per document is'
+            ' allowed. (lib/test.html 1 0)',
+      });
+
+    _testLinter('tags inside elements', {
+        'a|web/test.html': '<!DOCTYPE html><html>'
+            '<polymer-element name="x-a">'
+            '<script type="application/dart" src="a.dart">'
+            '</script>'
+            '</polymer-element>\n'
+            '<script type="application/dart" src="b.dart">'
+            '</script>'
+            '<script src="packages/browser/dart.js"></script>'
+      }, {
+        'a|web/test.html.messages': 
+            'warning: Only one "application/dart" script tag per document is'
+            ' allowed. (web/test.html 1 0)',
+      });
+  });
 
   group('doctype warning', () {
     _testLinter('in web', {
@@ -213,8 +255,7 @@
             </html>'''.replaceAll('            ', ''),
       }, {
         'a|lib/test.html.messages':
-            'warning: script tag with .dart source file but no type will be '
-            'treated as JavaScript. Did you forget type="application/dart"?'
+            'warning: Wrong script type, expected type="application/dart".'
             ' (lib/test.html 1 0)'
       });
 
@@ -226,8 +267,7 @@
             </html>'''.replaceAll('            ', ''),
       }, {
         'a|lib/test.html.messages':
-            'warning: script tag with .dart source file but no type will be '
-            'treated as JavaScript. Did you forget type="application/dart"?'
+            'warning: Wrong script type, expected type="application/dart".'
             ' (lib/test.html 2 0)'
       });
 
@@ -256,7 +296,7 @@
 
     _testLinter('top-level, dart type & .dart url', {
         'a|lib/test.html': '''<html>
-            <script type="applicatino/dart" src="foo.dart"></script>
+            <script type="application/dart" src="foo.dart"></script>
             </html>'''.replaceAll('            ', ''),
       }, {
         'a|lib/test.html.messages': ''
diff --git a/pkg/polymer/test/build/polyfill_injector_test.dart b/pkg/polymer/test/build/polyfill_injector_test.dart
index 5f6b42e..8a28739 100644
--- a/pkg/polymer/test/build/polyfill_injector_test.dart
+++ b/pkg/polymer/test/build/polyfill_injector_test.dart
@@ -7,12 +7,26 @@
 import 'package:polymer/src/build/common.dart';
 import 'package:polymer/src/build/polyfill_injector.dart';
 import 'package:unittest/compact_vm_config.dart';
+import 'package:unittest/unittest.dart';
 
 import 'common.dart';
 
 void main() {
   useCompactVMConfiguration();
-  var phases = [[new PolyfillInjector(new TransformOptions())]];
+
+  group('js', () => runTests());
+  group('csp', () => runTests(csp: true));
+  group('dart', () => runTests(js: false));
+}
+
+void runTests({bool js: true, bool csp: false}) {
+  var phases = [[new PolyfillInjector(new TransformOptions(
+      directlyIncludeJS: js,
+      contentSecurityPolicy: csp))]];
+
+  var ext = js ? (csp ? '.precompiled.js' : '.js') : '';
+  var type = js ? '' : 'type="application/dart" ';
+  var dartJsTag = js ? '' : DART_JS_TAG;
 
   testPhases('no changes', phases, {
       'a|web/test.html': '<!DOCTYPE html><html></html>',
@@ -36,26 +50,32 @@
           '<script type="application/dart" src="a.dart"></script>',
     }, {
       'a|web/test.html':
-          '<!DOCTYPE html><html><head></head><body>'
+          '<!DOCTYPE html><html><head>'
           '$SHADOW_DOM_TAG$CUSTOM_ELEMENT_TAG$INTEROP_TAG'
-          '<script type="application/dart" src="a.dart"></script>'
+          '</head><body>'
+          '<script ${type}src="a.dart$ext"></script>'
+          '$dartJsTag'
           '</body></html>',
     });
 
   testPhases('interop/shadow dom already present', phases, {
       'a|web/test.html':
-          '<!DOCTYPE html><html><head></head><body>'
-          '<script type="application/dart" src="a.dart"></script>'
+          '<!DOCTYPE html><html><head>'
           '$SHADOW_DOM_TAG'
           '$CUSTOM_ELEMENT_TAG'
           '$INTEROP_TAG'
+          '</head><body>'
+          '<script type="application/dart" src="a.dart"></script>'
+          '$dartJsTag'
     }, {
       'a|web/test.html':
-          '<!DOCTYPE html><html><head></head><body>'
-          '<script type="application/dart" src="a.dart"></script>'
+          '<!DOCTYPE html><html><head>'
           '$SHADOW_DOM_TAG'
           '$CUSTOM_ELEMENT_TAG'
           '$INTEROP_TAG'
+          '</head><body>'
+          '<script ${type}src="a.dart$ext"></script>'
+          '$dartJsTag'
           '</body></html>',
     });
 }
diff --git a/pkg/polymer/test/build/script_compactor_test.dart b/pkg/polymer/test/build/script_compactor_test.dart
index 74eab9e..32bd762 100644
--- a/pkg/polymer/test/build/script_compactor_test.dart
+++ b/pkg/polymer/test/build/script_compactor_test.dart
@@ -16,6 +16,7 @@
 
   testPhases('no changes', phases, {
       'a|web/test.html': '<!DOCTYPE html><html></html>',
+      'a|web/test.html.scriptUrls': '[]',
     }, {
       'a|web/test.html': '<!DOCTYPE html><html></html>',
     });
@@ -34,22 +35,23 @@
       'a|web/test.html':
           '<!DOCTYPE html><html><head>'
           '<script type="application/dart" src="a.dart"></script>',
+      'a|web/test.html.scriptUrls': '[]',
     }, {
       'a|web/test.html':
-          '<!DOCTYPE html><html><head></head><body>'
+          '<!DOCTYPE html><html><head>'
           '<script type="application/dart" '
           'src="test.html_bootstrap.dart"></script>'
-          '<script src="packages/browser/dart.js"></script>'
-          '</body></html>',
+          '</head><body></body></html>',
 
       'a|web/test.html_bootstrap.dart':
           '''$MAIN_HEADER
           import 'a.dart' as i0;
 
           void main() {
-            initPolymer([
+            configureForDeployment([
                 'a.dart',
               ]);
+            i0.main();
           }
           '''.replaceAll('\n          ', '\n'),
     });
@@ -57,18 +59,17 @@
   testPhases('several scripts', phases, {
       'a|web/test.html':
           '<!DOCTYPE html><html><head>'
-          '<script type="application/dart" src="a.dart"></script>'
-          '<script type="application/dart" src="b.dart"></script>'
           '</head><body><div>'
-          '<script type="application/dart" src="c.dart"></script>'
-          '</div>'
-          '<script type="application/dart" src="d.dart"></script>',
+          '<script type="application/dart" src="d.dart"></script>'
+          '</div>',
+      'a|web/test.html.scriptUrls':
+          '[["a", "web/a.dart"],["a", "web/b.dart"],["a", "web/c.dart"]]',
     }, {
       'a|web/test.html':
-          '<!DOCTYPE html><html><head></head><body><div></div>'
-          '<script type="application/dart" '
-          'src="test.html_bootstrap.dart"></script>'
-          '<script src="packages/browser/dart.js"></script>'
+          '<!DOCTYPE html><html><head></head><body><div>'
+          '<script type="application/dart" src="test.html_bootstrap.dart">'
+          '</script>'
+          '</div>'
           '</body></html>',
 
       'a|web/test.html_bootstrap.dart':
@@ -79,12 +80,13 @@
           import 'd.dart' as i3;
 
           void main() {
-            initPolymer([
+            configureForDeployment([
                 'a.dart',
                 'b.dart',
                 'c.dart',
                 'd.dart',
               ]);
+            i3.main();
           }
           '''.replaceAll('\n          ', '\n'),
     });
diff --git a/pkg/polymer/test/custom_event_test.dart b/pkg/polymer/test/custom_event_test.dart
new file mode 100644
index 0000000..0a6b197
--- /dev/null
+++ b/pkg/polymer/test/custom_event_test.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library polymer.test.web.custom_event_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:polymer/polymer.dart';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+
+
+@CustomTag('foo-bar')
+class FooBar extends PolymerElement {
+  // A little too much boilerplate?
+  static const EventStreamProvider<CustomEvent> fooEvent =
+      const EventStreamProvider<CustomEvent>('foo');
+  static const EventStreamProvider<CustomEvent> barBazEvent =
+      const EventStreamProvider<CustomEvent>('barbaz');
+
+  FooBar.created() : super.created();
+
+  Stream<CustomEvent> get onFooEvent =>
+      FooBar.fooEvent.forTarget(this);
+  Stream<CustomEvent> get onBarBazEvent =>
+      FooBar.barBazEvent.forTarget(this);
+
+  fireFoo(x) => dispatchEvent(new CustomEvent('foo', detail: x));
+  fireBarBaz(x) => dispatchEvent(new CustomEvent('barbaz', detail: x));
+}
+
+@CustomTag('test-custom-event')
+class TestCustomEvent extends PolymerElement {
+  TestCustomEvent.created() : super.created();
+
+  get fooBar => getShadowRoot('test-custom-event').query('foo-bar');
+
+  final events = [];
+  fooHandler(e) => events.add(['foo', e]);
+  barBazHandler(e) => events.add(['barbaz', e]);
+}
+
+main() {
+  initPolymer();
+  useHtmlConfiguration();
+
+  setUp(() => Polymer.onReady);
+
+  test('custom event', () {
+    final testComp = query('test-custom-event');
+    final fooBar = testComp.fooBar;
+    fooBar.fireFoo(123);
+    fooBar.fireBarBaz(42);
+    fooBar.fireFoo(777);
+
+    final events = testComp.events;
+    expect(events.length, 3);
+    expect(events.map((e) => e[0]), ['foo', 'barbaz', 'foo']);
+    expect(events.map((e) => e[1].detail), [123, 42, 777]);
+  });
+}
diff --git a/pkg/polymer/test/custom_event_test.html b/pkg/polymer/test/custom_event_test.html
new file mode 100644
index 0000000..749bd26
--- /dev/null
+++ b/pkg/polymer/test/custom_event_test.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<!--
+Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+for details. All rights reserved. Use of this source code is governed by a
+BSD-style license that can be found in the LICENSE file.
+-->
+<html>
+  <head>
+    <!--polymer-test: this comment is needed for test_suite.dart-->
+    <title>custom events</title>
+    <script src="packages/unittest/test_controller.js"></script>
+  </head>
+  <body>
+
+  <polymer-element name="foo-bar">
+    <template></template>
+  </polymer-element>
+
+  <polymer-element name="test-custom-event">
+    <template>
+      <foo-bar on-foo="fooHandler" on-barbaz="barBazHandler"></foo-bar>
+    </template>
+  </polymer-element>
+
+  <test-custom-event></test-custom-event>
+
+  <script type="application/dart" src="custom_event_test.dart"></script>
+  </body>
+</html>
diff --git a/pkg/polymer/test/event_path_test.dart b/pkg/polymer/test/event_path_test.dart
index 3351502..f1e23eb 100644
--- a/pkg/polymer/test/event_path_test.dart
+++ b/pkg/polymer/test/event_path_test.dart
@@ -9,7 +9,28 @@
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
 
-@initMethod _main() {
+@CustomTag("x-selector")
+class XSelector extends PolymerElement {
+  XSelector.created() : super.created();
+}
+
+@CustomTag("x-overlay")
+class XOverlay extends PolymerElement {
+  XOverlay.created() : super.created();
+}
+
+@CustomTag("x-menu")
+class XMenu extends PolymerElement {
+  XMenu.created() : super.created();
+}
+
+@CustomTag("x-menu-button")
+class XMenuButton extends PolymerElement {
+  XMenuButton.created() : super.created();
+}
+
+main() {
+  initPolymer();
   useHtmlConfiguration();
 
   setUp(() => Polymer.onReady);
diff --git a/pkg/polymer/test/event_path_test.html b/pkg/polymer/test/event_path_test.html
index fff93dd..323f837 100644
--- a/pkg/polymer/test/event_path_test.html
+++ b/pkg/polymer/test/event_path_test.html
@@ -5,6 +5,7 @@
    BSD-style license that can be found in the LICENSE file.
 -->
 <html>
+  <!--polymer-test: this comment is needed for test_suite.dart-->
   <head>
     <title>event path</title>
     <script src="packages/unittest/test_controller.js"></script>
@@ -24,26 +25,12 @@
         <content id="selectorContent"></content>
       </div>
     </template>
-    <script type="application/dart">
-      import 'package:polymer/polymer.dart';
-      @CustomTag("x-selector")
-      class XSelector extends PolymerElement {
-        XSelector.created() : super.created();
-      }
-    </script>
   </polymer-element>
 
   <polymer-element name="x-overlay">
     <template>
       <content id="overlayContent"></content>
     </template>
-    <script type="application/dart">
-      import 'package:polymer/polymer.dart';
-      @CustomTag("x-overlay")
-      class XOverlay extends PolymerElement {
-        XOverlay.created() : super.created();
-      }
-    </script>
   </polymer-element>
 
   <polymer-element name="x-menu" extends="x-selector">
@@ -52,13 +39,6 @@
         <shadow id="menuShadow"></shadow>
       </div>
     </template>
-    <script type="application/dart">
-      import 'package:polymer/polymer.dart';
-      @CustomTag("x-menu")
-      class XMenu extends PolymerElement {
-        XMenu.created() : super.created();
-      }
-    </script>
   </polymer-element>
 
   <polymer-element name="x-menu-button">
@@ -73,13 +53,6 @@
         </x-overlay>
       </div>
     </template>
-    <script type="application/dart">
-      import 'package:polymer/polymer.dart';
-      @CustomTag("x-menu-button")
-      class XMenuButton extends PolymerElement {
-        XMenuButton.created() : super.created();
-      }
-    </script>
   </polymer-element>
 
   <x-menu-button id="menuButton">
@@ -89,6 +62,5 @@
 
 
   <script type="application/dart" src="event_path_test.dart"></script>
-  <script type="application/dart" src="packages/polymer/init.dart"></script>
   </body>
 </html>
diff --git a/pkg/polymer/test/events_test.dart b/pkg/polymer/test/events_test.dart
index 2b936a8..afd7e46 100644
--- a/pkg/polymer/test/events_test.dart
+++ b/pkg/polymer/test/events_test.dart
@@ -9,7 +9,28 @@
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
 
-@initMethod _main() {
+@CustomTag("test-b")
+class TestB extends PolymerElement {
+  TestB.created() : super.created();
+
+  List clicks = [];
+  void clickHandler(event, detail, target) {
+    clicks.add('local click under $localName (id $id) on ${target.id}');
+  }
+}
+
+@CustomTag("test-a")
+class TestA extends PolymerElement {
+  TestA.created() : super.created();
+
+  List clicks = [];
+  void clickHandler() {
+    clicks.add('host click on: $localName (id $id)');
+  }
+}
+
+main() {
+  initPolymer();
   useHtmlConfiguration();
 
   setUp(() => Polymer.onReady);
@@ -18,21 +39,21 @@
     // Note: this test is currently the only event in
     // polymer/test/js/events.js at commit #7936ff8
     var testA = query('#a');
-    expect(testA.xtag.clicks, isEmpty);
+    expect(testA.clicks, isEmpty);
     testA.click();
-    expect(testA.xtag.clicks, ['host click on: test-a (id a)']);
+    expect(testA.clicks, ['host click on: test-a (id a)']);
   });
 
   test('local event', () {
     var testB = query('#b');
-    expect(testB.xtag.clicks, isEmpty);
+    expect(testB.clicks, isEmpty);
     testB.click();
-    expect(testB.xtag.clicks, []);
+    expect(testB.clicks, []);
     var b1 = testB.shadowRoot.query('#b-1');
     b1.click();
-    expect(testB.xtag.clicks, []);
+    expect(testB.clicks, []);
     var b2 = testB.shadowRoot.query('#b-2');
     b2.click();
-    expect(testB.xtag.clicks, ['local click under test-b (id b) on b-2']);
+    expect(testB.clicks, ['local click under test-b (id b) on b-2']);
   });
 }
diff --git a/pkg/polymer/test/events_test.html b/pkg/polymer/test/events_test.html
index 54bce09..4fce9d5 100644
--- a/pkg/polymer/test/events_test.html
+++ b/pkg/polymer/test/events_test.html
@@ -5,6 +5,7 @@
    BSD-style license that can be found in the LICENSE file.
 -->
 <html>
+  <!--polymer-test: this comment is needed for test_suite.dart-->
   <head>
     <title>event path</title>
     <script src="packages/unittest/test_controller.js"></script>
@@ -20,19 +21,6 @@
 
   <polymer-element name="test-a" on-click="clickHandler">
     <template></template>
-    <script type="application/dart">
-      import 'package:polymer/polymer.dart';
-
-      @CustomTag("test-a")
-      class TestA extends PolymerElement {
-        TestA.created() : super.created();
-
-        List clicks = [];
-        void clickHandler() {
-          clicks.add('host click on: $localName (id $id)');
-        }
-      }
-    </script>
   </polymer-element>
 
   <polymer-element name="test-b">
@@ -42,25 +30,11 @@
         <span id="b-2" on-click="clickHandler">2</span>
       </div>
     </template>
-    <script type="application/dart">
-      import 'package:polymer/polymer.dart';
-
-      @CustomTag("test-b")
-      class TestB extends PolymerElement {
-        TestB.created() : super.created();
-
-        List clicks = [];
-        void clickHandler(event, detail, target) {
-          clicks.add('local click under $localName (id $id) on ${target.id}');
-        }
-      }
-    </script>
   </polymer-element>
 
   <test-a id="a"></test-a>
   <test-b id="b"></test-b>
 
   <script type="application/dart" src="events_test.dart"></script>
-  <script type="application/dart" src="packages/polymer/init.dart"></script>
   </body>
 </html>
diff --git a/pkg/polymer/test/instance_attrs_test.dart b/pkg/polymer/test/instance_attrs_test.dart
index 45508bc..a759ae9 100644
--- a/pkg/polymer/test/instance_attrs_test.dart
+++ b/pkg/polymer/test/instance_attrs_test.dart
@@ -17,9 +17,12 @@
   get attributes => super.attributes;
 }
 
-@initMethod _main() {
+main() {
+  initPolymer();
   useHtmlConfiguration();
 
+  setUp(() => Polymer.onReady);
+
   test('attributes were deserialized', () {
     var elem = query('my-element');
 
diff --git a/pkg/polymer/test/instance_attrs_test.html b/pkg/polymer/test/instance_attrs_test.html
index b8f3b23..38e42d4 100644
--- a/pkg/polymer/test/instance_attrs_test.html
+++ b/pkg/polymer/test/instance_attrs_test.html
@@ -5,6 +5,7 @@
 BSD-style license that can be found in the LICENSE file.
 -->
 <html>
+  <!--polymer-test: this comment is needed for test_suite.dart-->
   <head>
     <title>Polymer.dart attribute deserialization test</title>
     <script src="packages/unittest/test_controller.js"></script>
@@ -21,6 +22,5 @@
     <my-element baz="world"></my-element>
 
     <script type="application/dart" src="instance_attrs_test.dart"></script>
-    <script type="application/dart" src="packages/polymer/init.dart"></script>
   </body>
 </html>
diff --git a/pkg/polymer/test/prop_attr_bind_reflection_test.dart b/pkg/polymer/test/prop_attr_bind_reflection_test.dart
index 7ae9a7f..bf02da2 100644
--- a/pkg/polymer/test/prop_attr_bind_reflection_test.dart
+++ b/pkg/polymer/test/prop_attr_bind_reflection_test.dart
@@ -27,7 +27,8 @@
   MyElement.created() : super.created();
 }
 
-@initMethod _main() {
+main() {
+  initPolymer();
   useHtmlConfiguration();
 
   setUp(() => Polymer.onReady);
diff --git a/pkg/polymer/test/prop_attr_bind_reflection_test.html b/pkg/polymer/test/prop_attr_bind_reflection_test.html
index 53949ef..c7be8ca 100644
--- a/pkg/polymer/test/prop_attr_bind_reflection_test.html
+++ b/pkg/polymer/test/prop_attr_bind_reflection_test.html
@@ -1,5 +1,6 @@
 <!DOCTYPE html>
 <html>
+  <!--polymer-test: this comment is needed for test_suite.dart-->
   <head>
     <title>property to attribute reflection with bind</title>
     <script src="packages/unittest/test_controller.js"></script>
@@ -28,6 +29,5 @@
 
     <script type="application/dart" src="prop_attr_bind_reflection_test.dart">
     </script>
-    <script type="application/dart" src="packages/polymer/init.dart"></script>
   </body>
 </html>
diff --git a/pkg/polymer/test/prop_attr_reflection_test.dart b/pkg/polymer/test/prop_attr_reflection_test.dart
index 3fd29fd..e429114 100644
--- a/pkg/polymer/test/prop_attr_reflection_test.dart
+++ b/pkg/polymer/test/prop_attr_reflection_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:async';
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:unittest/html_config.dart';
@@ -30,20 +31,33 @@
   @observable bool zim = false;
 }
 
-@initMethod _main() {
+Future onAttributeChange(Element node) {
+  var completer = new Completer();
+  new MutationObserver((records, observer) {
+    observer.disconnect();
+    completer.complete();
+  })..observe(node, attributes: true);
+  Platform.flush();
+  return completer.future;
+}
+
+main() {
+  initPolymer();
   useHtmlConfiguration();
 
+  setUp(() => Polymer.onReady);
+
   // Most tests use @CustomTag, here we test out the impertive register:
   Polymer.register('x-foo', XFoo);
   Polymer.register('x-bar', XBar);
   Polymer.register('x-compose', XCompose);
 
   test('property attribute reflection', () {
-    var xcompose = query('x-compose').xtag;
-    var xfoo = query('x-foo').xtag;
+    var xcompose = query('x-compose');
+    var xfoo = query('x-foo');
+    var xbar = query('x-bar');
     xfoo.foo = 5;
-    Platform.flush();
-    Platform.endOfMicrotask(expectAsync0(() {
+    return onAttributeChange(xfoo).then((_) {
       expect(xcompose.$['bar'].attributes.containsKey('zim'), false,
           reason: 'attribute bound to property updates when binding is made');
 
@@ -56,61 +70,51 @@
           reason: 'property reflects attribute');
       //
       xfoo.baz = 'Hello';
-      Platform.flush();
-      Platform.endOfMicrotask(expectAsync0(() {
-        expect(xfoo.baz, xfoo.attributes['baz'],
-            reason: 'attribute reflects property');
-        //
-        var xbar = query('x-bar').xtag;
-        //
-        xbar.foo = 'foo!';
-        xbar.zot = 27;
-        xbar.zim = true;
-        xbar.str = 'str!';
-        xbar.obj = {'hello': 'world'};
-        Platform.flush();
-        Platform.endOfMicrotask(expectAsync0(() {
-          expect(xbar.foo, xbar.attributes['foo'],
-              reason: 'inherited published property is reflected');
-          expect('${xbar.zot}', xbar.attributes['zot'],
-              reason: 'attribute reflects property as number');
-          expect(xbar.attributes['zim'], '', reason:
-              'attribute reflects true valued boolean property as '
-              'having attribute');
-          expect(xbar.str, xbar.attributes['str'],
-              reason: 'attribute reflects property as published string');
-          expect(xbar.attributes.containsKey('obj'), false,
-              reason: 'attribute does not reflect object property');
-          xbar.attributes['zim'] = 'false';
-          xbar.attributes['foo'] = 'foo!!';
-          xbar.attributes['zot'] = '54';
-          xbar.attributes['str'] = 'str!!';
-          xbar.attributes['obj'] = "{'hello': 'world'}";
-          expect(xbar.foo, xbar.attributes['foo'],
-              reason: 'property reflects attribute as string');
-          expect(xbar.zot, 54,
-              reason: 'property reflects attribute as number');
-          expect(xbar.zim, false,
-              reason: 'property reflects attribute as boolean');
-          expect(xbar.str, 'str!!',
-              reason: 'property reflects attribute as published string');
-          expect(xbar.obj, {'hello': 'world'},
-              reason: 'property reflects attribute as object');
-          xbar.zim = false;
-          Platform.flush();
-          Platform.endOfMicrotask(expectAsync0(() {
-            expect(xbar.attributes.containsKey('zim'), false, reason:
-                'attribute reflects false valued boolean property as NOT '
-                'having attribute');
-            var objAttr = xbar.attributes['obj'];
-            xbar.obj = 'hi';
-            Platform.endOfMicrotask(expectAsync0(() {
-              expect(xbar.attributes['obj'], objAttr, reason:
-                  'do not reflect property with default type of object');
-            }));
-          }));
-        }));
-      }));
-    }));
+    }).then((_) => onAttributeChange(xfoo)).then((_) {
+      expect(xfoo.baz, xfoo.attributes['baz'],
+          reason: 'attribute reflects property');
+      //
+      xbar.foo = 'foo!';
+      xbar.zot = 27;
+      xbar.zim = true;
+      xbar.str = 'str!';
+      xbar.obj = {'hello': 'world'};
+    }).then((_) => onAttributeChange(xbar)).then((_) {
+      expect(xbar.foo, xbar.attributes['foo'],
+          reason: 'inherited published property is reflected');
+      expect('${xbar.zot}', xbar.attributes['zot'],
+          reason: 'attribute reflects property as number');
+      expect(xbar.attributes['zim'], '', reason:
+          'attribute reflects true valued boolean property as '
+          'having attribute');
+      expect(xbar.str, xbar.attributes['str'],
+          reason: 'attribute reflects property as published string');
+      expect(xbar.attributes.containsKey('obj'), false,
+          reason: 'attribute does not reflect object property');
+      xbar.attributes['zim'] = 'false';
+      xbar.attributes['foo'] = 'foo!!';
+      xbar.attributes['zot'] = '54';
+      xbar.attributes['str'] = 'str!!';
+      xbar.attributes['obj'] = "{'hello': 'world'}";
+      expect(xbar.foo, xbar.attributes['foo'],
+          reason: 'property reflects attribute as string');
+      expect(xbar.zot, 54,
+          reason: 'property reflects attribute as number');
+      expect(xbar.zim, false,
+          reason: 'property reflects attribute as boolean');
+      expect(xbar.str, 'str!!',
+          reason: 'property reflects attribute as published string');
+      expect(xbar.obj, {'hello': 'world'},
+          reason: 'property reflects attribute as object');
+      xbar.zim = false;
+    }).then((_) => onAttributeChange(xbar)).then((_) {
+      expect(xbar.attributes.containsKey('zim'), false, reason:
+          'attribute reflects false valued boolean property as NOT '
+          'having attribute');
+      xbar.obj = 'hi';
+    }).then((_) => onAttributeChange(xbar)).then((_) {
+      expect(xbar.attributes['obj'], 'hi', reason:
+          'reflect property based on current type');
+    });
   });
 }
diff --git a/pkg/polymer/test/prop_attr_reflection_test.html b/pkg/polymer/test/prop_attr_reflection_test.html
index 1f86f45..c77d009 100644
--- a/pkg/polymer/test/prop_attr_reflection_test.html
+++ b/pkg/polymer/test/prop_attr_reflection_test.html
@@ -6,6 +6,7 @@
 -->
 <html>
   <head>
+  <!--polymer-test: this comment is needed for test_suite.dart-->
     <title>publish attributes</title>
     <script src="packages/unittest/test_controller.js"></script>
   </head>
@@ -27,6 +28,5 @@
     </polymer-element>
 
   <script type="application/dart" src="prop_attr_reflection_test.dart"></script>
-  <script type="application/dart" src="packages/polymer/init.dart"></script>
   </body>
 </html>
diff --git a/pkg/polymer/test/publish_attributes_test.dart b/pkg/polymer/test/publish_attributes_test.dart
index b07df0c..bd0e071 100644
--- a/pkg/polymer/test/publish_attributes_test.dart
+++ b/pkg/polymer/test/publish_attributes_test.dart
@@ -41,12 +41,15 @@
   @published int squid = 7;
 }
 
-@initMethod _main() {
+main() {
+  initPolymer();
   useHtmlConfiguration();
 
+  setUp(() => Polymer.onReady);
+
   test('published properties', () {
     published(tag) =>
-        query('polymer-element[name=$tag]').xtag.publishedProperties;
+        query('polymer-element[name=$tag]').publishedProperties;
 
     print(published('x-foo'));
     print(published('x-bar'));
diff --git a/pkg/polymer/test/publish_attributes_test.html b/pkg/polymer/test/publish_attributes_test.html
index b79329d..9c0969d 100644
--- a/pkg/polymer/test/publish_attributes_test.html
+++ b/pkg/polymer/test/publish_attributes_test.html
@@ -6,6 +6,7 @@
 -->
 <html>
   <head>
+  <!--polymer-test: this comment is needed for test_suite.dart-->
     <title>publish attributes</title>
     <script src="packages/unittest/test_controller.js"></script>
   </head>
@@ -24,6 +25,5 @@
     </polymer-element>
 
   <script type="application/dart" src="publish_attributes_test.dart"></script>
-  <script type="application/dart" src="packages/polymer/init.dart"></script>
   </body>
 </html>
diff --git a/pkg/polymer/test/register_test.dart b/pkg/polymer/test/register_test.dart
new file mode 100644
index 0000000..070ee0f
--- /dev/null
+++ b/pkg/polymer/test/register_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+import 'package:polymer/polymer.dart';
+
+@CustomTag('x-html')
+class XHtmlElement extends PolymerElement {
+  XHtmlElement.created() : super.created();
+}
+
+@CustomTag('x-html-two')
+class XHtml2Element extends XHtmlElement {
+  XHtml2Element.created() : super.created();
+}
+
+@CustomTag('x-div')
+class XDivElement extends DivElement with Polymer, Observable {
+  XDivElement.created() : super.created();
+}
+
+@CustomTag('x-div-two')
+class XDiv2lElement extends XDivElement {
+  XDiv2lElement.created() : super.created();
+}
+
+main() {
+  initPolymer();
+  useHtmlConfiguration();
+
+  setUp(() => Polymer.onReady);
+
+  test('elements upgraded', () {
+    expect(querySelector('x-html') is XHtmlElement, isTrue);
+    expect(querySelector('x-html-two') is XHtml2Element, isTrue);
+    expect(querySelector('#x-div') is XDivElement, isTrue);
+    expect(querySelector('#x-div-two') is XDiv2Element, isTrue);
+  });
+}
diff --git a/pkg/polymer/test/register_test.html b/pkg/polymer/test/register_test.html
new file mode 100644
index 0000000..970f9c5
--- /dev/null
+++ b/pkg/polymer/test/register_test.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<!--
+Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+for details. All rights reserved. Use of this source code is governed by a
+BSD-style license that can be found in the LICENSE file.
+-->
+<html>
+  <head>
+  <!--polymer-test: this comment is needed for test_suite.dart-->
+    <title>register test</title>
+    <script src="packages/unittest/test_controller.js"></script>
+  </head>
+  <body>
+
+    <polymer-element name="x-html">
+    </polymer-element>
+
+    <polymer-element name="x-html-two" extends="x-html">
+    </polymer-element>
+
+    <polymer-element name="x-div" extends="div">
+    </polymer-element>
+
+    <polymer-element name="x-div-two" extends="x-div">
+    </polymer-element>
+
+    <x-html></x-html>
+    <x-html-two></x-html-two>
+    <div is='x-div' id='x-div'></div>
+    <div is='x-div-two' id='x-div-two'></div>
+
+  <script type="application/dart" src="register_test.dart"></script>
+  </body>
+</html>
diff --git a/pkg/polymer/test/run.sh b/pkg/polymer/test/run.sh
index f57855c..62497be 100755
--- a/pkg/polymer/test/run.sh
+++ b/pkg/polymer/test/run.sh
@@ -16,7 +16,12 @@
 
 SUITES="pkg/polymer samples/third_party/todomvc"
 
-CONFIG="-m release -r vm,drt,ff,chrome,d8,jsshell -c none,dart2js,dartanalyzer --checked $*"
+ANALYZER_CONFIG="-m release -r none -c dartanalyzer $*"
+CONFIG="-m release -r vm,drt,ff,chrome,d8,jsshell -c none,dart2js --checked $*"
+
+CMD="./tools/test.py $ANALYZER_CONFIG $SUITES"
+echo "*** $CMD"
+$CMD
 
 CMD="xvfb-run ./tools/test.py $CONFIG $SUITES"
 echo "*** $CMD"
diff --git a/pkg/polymer/test/take_attributes_test.dart b/pkg/polymer/test/take_attributes_test.dart
index 9dc0023f..f5778c5 100644
--- a/pkg/polymer/test/take_attributes_test.dart
+++ b/pkg/polymer/test/take_attributes_test.dart
@@ -49,13 +49,14 @@
   @observable var values = {};
 }
 
-@initMethod _main() {
+main() {
+  initPolymer();
   useHtmlConfiguration();
 
   setUp(() => Polymer.onReady);
 
   test('take attributes', () {
-    queryXTag(x) => document.query(x).xtag;
+    queryXTag(x) => document.query(x);
 
     expect(queryXTag("#foo0").boolean, true);
     expect(queryXTag("#foo1").boolean, false);
diff --git a/pkg/polymer/test/take_attributes_test.html b/pkg/polymer/test/take_attributes_test.html
index 941051c..e105f6c 100644
--- a/pkg/polymer/test/take_attributes_test.html
+++ b/pkg/polymer/test/take_attributes_test.html
@@ -6,6 +6,7 @@
 -->
 <html>
   <head>
+  <!--polymer-test: this comment is needed for test_suite.dart-->
     <title>take attributes</title>
     <script src="packages/unittest/test_controller.js"></script>
   </head>
@@ -70,6 +71,5 @@
     </x-obj>
 
   <script type="application/dart" src="take_attributes_test.dart"></script>
-  <script type="application/dart" src="packages/polymer/init.dart"></script>
   </body>
 </html>
diff --git a/pkg/polymer/test/template_distribute_dynamic_test.dart b/pkg/polymer/test/template_distribute_dynamic_test.dart
new file mode 100644
index 0000000..130264a
--- /dev/null
+++ b/pkg/polymer/test/template_distribute_dynamic_test.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:polymer/polymer.dart';
+import 'package:polymer/platform.dart' as Platform;
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+
+@CustomTag('x-test')
+class XTest extends PolymerElement {
+  @observable List list;
+
+  final _enteredView = new Completer();
+  Future onTestDone;
+
+  XTest.created() : super.created() {
+    onTestDone = _enteredView.future.then(_runTest);
+  }
+
+  enteredView() {
+    super.enteredView();
+    _enteredView.complete();
+  }
+
+  _runTest(_) {
+    list = [
+      {'name': 'foo'},
+      {'name': 'bar'}
+    ];
+
+    Platform.flush();
+    Platform.endOfMicrotask(expectAsync0(() {
+      // tickle SD polyfill
+      offsetHeight;
+      var children = this.$['echo'].children;
+      expect(children[0].localName, 'template', reason:
+          'shadowDOM dynamic distribution via template');
+      expect(children[1].text, 'foo', reason:
+          'shadowDOM dynamic distribution via template');
+      expect(children[2].text, 'bar', reason:
+          'shadowDOM dynamic distribution via template');
+
+      // TODO(jmesserly): restore this if we get the JS interop capability.
+      /*
+      if (window.ShadowDOMPolyfill) {
+        var actualChildren = this.$.echo.impl.children;
+        chai.assert.equal(actualChildren.length, 4,
+          'shadowDOMPolyfill distributes expected number of actual children.');
+      }
+      */
+    }));
+  }
+}
+
+main() {
+  initPolymer();
+  useHtmlConfiguration();
+
+  setUp(() => Polymer.onReady);
+
+  test('inserted called', () => query('x-test').onTestDone);
+}
diff --git a/pkg/polymer/test/template_distribute_dynamic_test.html b/pkg/polymer/test/template_distribute_dynamic_test.html
new file mode 100644
index 0000000..7666ee7
--- /dev/null
+++ b/pkg/polymer/test/template_distribute_dynamic_test.html
@@ -0,0 +1,37 @@
+<!doctype html>
+<!--
+Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+for details. All rights reserved. Use of this source code is governed by a
+BSD-style license that can be found in the LICENSE file.
+-->
+<html>
+  <!--polymer-test: this comment is needed for test_suite.dart-->
+  <head>
+    <title>template distribute</title>
+    <script src="packages/unittest/test_controller.js"></script>
+  </head>
+  <body>
+
+  <x-test></x-test>
+
+  <polymer-element name="x-echo" noscript>
+    <template>
+      <div>Echoing:</div>
+      <content select="*"></content>
+    </template>
+  </polymer-element>
+
+  <polymer-element name="x-test">
+    <template>
+      <x-echo id="echo">
+        <template repeat="{{list}}">
+          <div>{{this['name']}}</div>
+        </template>
+      </x-echo>
+    </template>
+  </polymer-element>
+
+  <script type="application/dart" src="template_distribute_dynamic_test.dart">
+  </script>
+  </body>
+</html>
diff --git a/pkg/polymer/test/unbind_test.dart b/pkg/polymer/test/unbind_test.dart
new file mode 100644
index 0000000..e41e038
--- /dev/null
+++ b/pkg/polymer/test/unbind_test.dart
@@ -0,0 +1,116 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library polymer.test.unbind_test;
+
+import 'dart:async' show Future;
+import 'dart:html';
+
+@MirrorsUsed(targets: const [Polymer], override: 'polymer.test.unbind_test')
+import 'dart:mirrors' show reflect, reflectClass, MirrorSystem, MirrorsUsed;
+
+import 'package:polymer/polymer.dart';
+import 'package:polymer/platform.dart' as Platform;
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+
+@CustomTag('x-test')
+class XTest extends PolymerElement {
+  @observable var foo = '';
+  @observable var bar;
+
+  bool forceReady = true;
+  bool fooWasChanged = false;
+  var validBar;
+
+  factory XTest() => new Element.tag('x-test');
+  XTest.created() : super.created();
+
+  ready() {}
+
+  fooChanged() {
+    fooWasChanged = true;
+  }
+
+  barChanged() {
+    validBar = bar;
+  }
+
+  bool get isBarValid => validBar == bar;
+}
+
+main() {
+  initPolymer();
+  useHtmlConfiguration();
+
+  setUp(() => Polymer.onReady);
+
+  test('unbind', unbindTests);
+}
+
+Future testAsync(List<Function> tests, int delayMs, [List args]) {
+  if (tests.length == 0) return new Future.value();
+  // TODO(jmesserly): CustomElements.takeRecords();
+  return new Future.delayed(new Duration(milliseconds: delayMs), () {
+    if (args == null) args = [];
+    var lastArgs = Function.apply(tests.removeAt(0), args);
+    return testAsync(tests, delayMs, lastArgs);
+  });
+}
+
+// TODO(sorvell): In IE, the unbind time is indeterminate, so wait an
+// extra beat.
+delay(x) => new Future.delayed(new Duration(milliseconds: 50), () => x);
+
+// TODO(jmesserly): fix this when it's easier to get a private symbol.
+final unboundSymbol = reflectClass(Polymer).variables.keys
+    .firstWhere((s) => MirrorSystem.getName(s) == '_unbound');
+
+_unbound(node) => reflect(node).getField(unboundSymbol).reflectee;
+
+unbindTests() {
+  var xTest = document.query('x-test');
+  xTest.foo = 'bar';
+  Platform.flush();
+
+  return delay(null).then((_) {
+    expect(_unbound(xTest), null, reason:
+        'element is bound when inserted');
+    expect(xTest.fooWasChanged, true, reason:
+        'element is actually bound');
+    xTest.remove();
+  }).then(delay).then((_) {
+    expect(_unbound(xTest), true, reason:
+        'element is unbound when removed');
+    return new XTest();
+  }).then(delay).then((node) {
+    expect(_unbound(node), null, reason:
+        'element is bound when not inserted');
+    node.foo = 'bar';
+    Platform.flush();
+    return node;
+  }).then(delay).then((node) {
+    expect(node.fooWasChanged, true, reason: 'node is actually bound');
+    var n = new XTest();
+    n.cancelUnbindAll();
+    return n;
+  }).then(delay).then((node) {
+    expect(_unbound(node), null, reason:
+        'element is bound when cancelUnbindAll is called');
+    node.unbindAll();
+    expect(_unbound(node), true, reason:
+        'element is unbound when unbindAll is called');
+    var n = new XTest()..id = 'foobar!!!';
+    document.body.append(n);
+    return n;
+  }).then(delay).then((node) {
+    expect(_unbound(node), null, reason:
+        'element is bound when manually inserted');
+    node.remove();
+    return node;
+  }).then(delay).then((node) {
+    expect(_unbound(node), true, reason:
+        'element is unbound when manually removed is called');
+  });
+}
diff --git a/pkg/polymer/test/unbind_test.html b/pkg/polymer/test/unbind_test.html
new file mode 100644
index 0000000..e6b34aa
--- /dev/null
+++ b/pkg/polymer/test/unbind_test.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<!--
+Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+for details. All rights reserved. Use of this source code is governed by a
+BSD-style license that can be found in the LICENSE file.
+-->
+<html>
+  <!--polymer-test: this comment is needed for test_suite.dart-->
+  <head>
+    <title>unbind</title>
+    <script src="packages/unittest/test_controller.js"></script>
+  </head>
+  <body>
+
+  <x-test></x-test>
+
+  <polymer-element name="x-test" attributes="bar"></polymer-element>
+
+  <script type="application/dart" src="unbind_test.dart"></script>
+  </body>
+</html>
diff --git a/pkg/polymer_expressions/example/example.dart b/pkg/polymer_expressions/example/example.dart
index 5266311..380e155 100644
--- a/pkg/polymer_expressions/example/example.dart
+++ b/pkg/polymer_expressions/example/example.dart
@@ -5,13 +5,12 @@
 import 'dart:html';
 
 import 'package:logging/logging.dart';
-import 'package:mdv/mdv.dart' as mdv;
 import 'package:polymer_expressions/polymer_expressions.dart';
+import 'package:template_binding/template_binding.dart' show templateBind;
 
 import 'person.dart';
 
 main() {
-  mdv.initialize();
   new Logger('polymer_expressions').onRecord.listen((LogRecord r) {
     print("${r.loggerName} ${r.level} ${r.message}");
   });
@@ -23,9 +22,9 @@
     'people': [john, justin],
   };
 
-  query('#test')
+  templateBind(querySelector('#test'))
       ..bindingDelegate = new PolymerExpressions(globals: globals)
       ..model = john;
 
-  query('#test2').model = john;
+  templateBind(querySelector('#test2')).model = john;
 }
diff --git a/pkg/polymer_expressions/example/streams/collect_key_press.html b/pkg/polymer_expressions/example/streams/collect_key_press.html
index 48221c1..f214056 100644
--- a/pkg/polymer_expressions/example/streams/collect_key_press.html
+++ b/pkg/polymer_expressions/example/streams/collect_key_press.html
@@ -25,15 +25,13 @@
       }
 
       main() {
-        mdv.initialize();
-
         var globals = {
           'keyPress': document.onKeyPress
               .map((e) => new String.fromCharCode(e.charCode)),
           'collect': collect,
         };
 
-        query('#test')
+        templateBind(query('#test'))
             ..bindingDelegate = new PolymerExpressions(globals: globals)
             ..model = null;
       }
diff --git a/pkg/polymer_expressions/example/streams/count_clicks.html b/pkg/polymer_expressions/example/streams/count_clicks.html
index e164719..705a180 100644
--- a/pkg/polymer_expressions/example/streams/count_clicks.html
+++ b/pkg/polymer_expressions/example/streams/count_clicks.html
@@ -26,14 +26,12 @@
       }
 
       main() {
-        mdv.initialize();
-
         var globals = {
           'mouseDown': document.onMouseDown,
           'count': count,
         };
 
-        query('#test')
+        templateBind(query('#test'))
             ..bindingDelegate = new PolymerExpressions(globals: globals)
             ..model = null;
       }
diff --git a/pkg/polymer_expressions/example/streams/mouse_move.html b/pkg/polymer_expressions/example/streams/mouse_move.html
index c6cd1cc..d4ef3f3 100644
--- a/pkg/polymer_expressions/example/streams/mouse_move.html
+++ b/pkg/polymer_expressions/example/streams/mouse_move.html
@@ -16,13 +16,11 @@
       import 'package:mdv/mdv.dart' as mdv;
 
       main() {
-        mdv.initialize();
-
         var globals = {
           'mouse': document.onMouseMove,
         };
 
-        query('#test')
+        templateBind(query('#test'))
             ..bindingDelegate = new PolymerExpressions(globals: globals)
             ..model = null;
       }
diff --git a/pkg/polymer_expressions/example/streams/mouse_resize_image.html b/pkg/polymer_expressions/example/streams/mouse_resize_image.html
index a056d2e..2021ec1 100644
--- a/pkg/polymer_expressions/example/streams/mouse_resize_image.html
+++ b/pkg/polymer_expressions/example/streams/mouse_resize_image.html
@@ -19,15 +19,13 @@
       import 'package:mdv/mdv.dart' as mdv;
 
       main() {
-        mdv.initialize();
-
         var globals = {
           'mouse': document.onMouseMove,
           'mouseMax':
               document.onMouseMove.map((e) => max(e.offsetX, e.offsetY)),
         };
 
-        query('#test')
+        templateBind(query('#test'))
             ..bindingDelegate = new PolymerExpressions(globals: globals)
             ..model = null;
       }
diff --git a/pkg/polymer_expressions/lib/eval.dart b/pkg/polymer_expressions/lib/eval.dart
index 4f624b1..c12d4d1 100644
--- a/pkg/polymer_expressions/lib/eval.dart
+++ b/pkg/polymer_expressions/lib/eval.dart
@@ -420,7 +420,7 @@
 
   IdentifierObserver(Identifier value) : super(value);
 
-  String get value => (_expr as Identifier).value;
+  String get value => _expr.value;
 
   _updateSelf(Scope scope) {
     _value = scope[value];
diff --git a/pkg/polymer_expressions/lib/polymer_expressions.dart b/pkg/polymer_expressions/lib/polymer_expressions.dart
index 02d2afb..3f70c4b 100644
--- a/pkg/polymer_expressions/lib/polymer_expressions.dart
+++ b/pkg/polymer_expressions/lib/polymer_expressions.dart
@@ -30,8 +30,9 @@
 import 'dart:async';
 import 'dart:html';
 
-import 'package:observe/observe.dart';
 import 'package:logging/logging.dart';
+import 'package:observe/observe.dart';
+import 'package:template_binding/template_binding.dart';
 
 import 'eval.dart';
 import 'expression.dart';
diff --git a/pkg/polymer_expressions/pubspec.yaml b/pkg/polymer_expressions/pubspec.yaml
index 3a1d563..5686381 100644
--- a/pkg/polymer_expressions/pubspec.yaml
+++ b/pkg/polymer_expressions/pubspec.yaml
@@ -4,7 +4,7 @@
 homepage: http://www.dartlang.org/polymer-dart/
 dependencies:
   browser: any
-  mdv: any
   observe: any
+  template_binding: any
 dev_dependencies:
   unittest: any
diff --git a/pkg/polymer_expressions/test/bindings_test.dart b/pkg/polymer_expressions/test/bindings_test.dart
index cf37e1d..9851ded 100644
--- a/pkg/polymer_expressions/test/bindings_test.dart
+++ b/pkg/polymer_expressions/test/bindings_test.dart
@@ -7,15 +7,14 @@
 import 'dart:html';
 
 import 'package:logging/logging.dart';
-import 'package:mdv/mdv.dart' as mdv;
 import 'package:observe/observe.dart';
 import 'package:observe/src/microtask.dart';
 import 'package:polymer_expressions/polymer_expressions.dart';
+import 'package:template_binding/template_binding.dart' show templateBind;
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
 
 main() {
-  mdv.initialize();
   useHtmlConfiguration();
 
   group('bindings', () {
@@ -48,8 +47,8 @@
 
     observeTest('should update text content when data changes', () {
       var model = new NotifyModel('abcde');
-      var template = new Element.html(
-          '<template><span>{{x}}</span></template>');
+      var template = templateBind(new Element.html(
+          '<template><span>{{x}}</span></template>'));
       testDiv.append(template.createInstance(model, new PolymerExpressions()));
 
       performMicrotaskCheckpoint();
@@ -65,8 +64,8 @@
 
     observeTest('should log eval exceptions', () {
       var model = new NotifyModel('abcde');
-      var template = new Element.html(
-          '<template><span>{{foo}}</span></template>');
+      var template = templateBind(new Element.html(
+          '<template><span>{{foo}}</span></template>'));
       testDiv.append(template.createInstance(model, new PolymerExpressions()));
       performMicrotaskCheckpoint();
       expect(messages.length, 1);
@@ -76,8 +75,8 @@
 
     observeTest('should preserve the cursor position', () {
       var model = new NotifyModel('abcde');
-      var template = new Element.html(
-          '<template><input id="i1" value={{x}}></template>');
+      var template = templateBind(new Element.html(
+          '<template><input id="i1" value={{x}}></template>'));
       testDiv.append(template.createInstance(model, new PolymerExpressions()));
 
       performMicrotaskCheckpoint();
diff --git a/pkg/polymer_expressions/test/eval_test.dart b/pkg/polymer_expressions/test/eval_test.dart
index 87ecb3b..3094994 100644
--- a/pkg/polymer_expressions/test/eval_test.dart
+++ b/pkg/polymer_expressions/test/eval_test.dart
@@ -6,8 +6,8 @@
 
 import 'dart:async';
 
-// NOTE: this import is unused, but we use it to cause all mirrors to be
-// enabled. The tests reflect on LinkedHashMap.length and String.length.
+// Import mirrors to cause all mirrors to be retained by dart2js.
+// The tests reflect on LinkedHashMap.length and String.length.
 import 'dart:mirrors';
 
 import 'package:polymer_expressions/eval.dart';
@@ -17,6 +17,7 @@
 import 'package:observe/observe.dart';
 
 main() {
+  reflectClass(Object); // suppress unused import warning
 
   group('eval', () {
     test('should return the model for an empty expression', () {
diff --git a/pkg/polymer_expressions/test/globals_test.dart b/pkg/polymer_expressions/test/globals_test.dart
index 4a2f3af..4a7907e 100644
--- a/pkg/polymer_expressions/test/globals_test.dart
+++ b/pkg/polymer_expressions/test/globals_test.dart
@@ -4,15 +4,14 @@
 
 import 'dart:html';
 
-import 'package:mdv/mdv.dart' as mdv;
 import 'package:observe/observe.dart';
 import 'package:observe/src/microtask.dart';
 import 'package:polymer_expressions/polymer_expressions.dart';
+import 'package:template_binding/template_binding.dart';
 import 'package:unittest/unittest.dart';
 import 'package:unittest/html_enhanced_config.dart';
 
 main() {
-  mdv.initialize();
   useHtmlEnhancedConfiguration();
 
   var testDiv;
@@ -30,12 +29,13 @@
     });
 
     tearDown(() {
-      testDiv..unbindAll()..remove();
+      nodeBind(testDiv).unbindAll();
+      testDiv.remove();
       testDiv = null;
     });
 
     test('should enumerate item and index', wrapMicrotask(() {
-      testDiv.query('template')
+      templateBind(testDiv.query('template'))
           ..bindingDelegate = new PolymerExpressions()
           ..model = toObservable(
               ['hello', 'from', 'polymer', 'expressions']);
diff --git a/pkg/polymer_expressions/test/syntax_test.dart b/pkg/polymer_expressions/test/syntax_test.dart
index c0a92e1..b5dc01f 100644
--- a/pkg/polymer_expressions/test/syntax_test.dart
+++ b/pkg/polymer_expressions/test/syntax_test.dart
@@ -5,15 +5,14 @@
 import 'dart:async';
 import 'dart:html';
 
-import 'package:mdv/mdv.dart' as mdv;
 import 'package:logging/logging.dart';
 import 'package:observe/observe.dart';
 import 'package:polymer_expressions/polymer_expressions.dart';
+import 'package:template_binding/template_binding.dart';
 import 'package:unittest/html_enhanced_config.dart';
 import 'package:unittest/unittest.dart';
 
 main() {
-  mdv.initialize();
   useHtmlEnhancedConfiguration();
 
   group('PolymerExpressions', () {
@@ -34,7 +33,7 @@
             <input id="input" value="{{ firstName }}">
           </template>'''));
       var person = new Person('John', 'Messerly', ['A', 'B', 'C']);
-      query('#test')
+      templateBind(query('#test'))
           ..bindingDelegate = new PolymerExpressions()
           ..model = person;
       return new Future.delayed(new Duration()).then((_) {
@@ -56,7 +55,7 @@
               {{ item }}
             </template>
           </template>'''));
-      query('#test').bindingDelegate =
+      templateBind(query('#test')).bindingDelegate =
           new PolymerExpressions(globals: {'items': null});
       // the template should be the only node
       expect(testDiv.nodes.length, 1);
@@ -68,7 +67,7 @@
       var logFuture = logger.onRecord.toList();
       testDiv.nodes.add(new Element.html('''
           <template id="test" bind>{{ foo }}</template>'''));
-      query('#test').bindingDelegate = new PolymerExpressions();
+      templateBind(query('#test')).bindingDelegate = new PolymerExpressions();
       return new Future(() {
         logger.clearListeners();
         return logFuture.then((records) {
diff --git a/pkg/shadow_dom/lib/shadow_dom.debug.js b/pkg/shadow_dom/lib/shadow_dom.debug.js
index 91f2c30..158c3d1 100644
--- a/pkg/shadow_dom/lib/shadow_dom.debug.js
+++ b/pkg/shadow_dom/lib/shadow_dom.debug.js
@@ -1375,9 +1375,7 @@
  * license that can be found in the LICENSE file.
  */
 
-// If WeakMap is not available, the association is stored as an expando property on the "key".
-// TODO(arv): WeakMap does not allow for Node etc to be keys in Firefox
-if (typeof WeakMap === 'undefined' || navigator.userAgent.indexOf('Firefox/') > -1) {
+if (typeof WeakMap === 'undefined') {
   (function() {
     var defineProperty = Object.defineProperty;
     var counter = Date.now() % 1e9;
@@ -5460,6 +5458,19 @@
 
     x-foo [pseudo=x-special] { ... }
 
+  * ::part(): These rules are converted to rules that take advantage of the
+  part attribute. For example, a shadowRoot like this inside an x-foo
+
+    <div part="special">Special</div>
+
+  with a rule like this:
+
+    x-foo::part(special) { ... }
+
+  becomes:
+
+    x-foo [part=special] { ... }
+
   Unaddressed ShadowDOM styling features:
 
   * upper/lower bound encapsulation: Styles which are defined outside a
@@ -5511,27 +5522,37 @@
   // Shim styles for a given root associated with a name and extendsName
   // 1. cache root styles by name
   // 2. optionally tag root nodes with scope name
-  // 3. shim polyfill directives /* @polyfill */
+  // 3. shim polyfill directives /* @polyfill */ and /* @polyfill-rule */
   // 4. shim @host and scoping
   shimStyling: function(root, name, extendsName) {
-    if (root) {
-      // use caching to make working with styles nodes easier and to facilitate
-      // lookup of extendee
-      var def = this.registerDefinition(root, name, extendsName);
-      // find styles and apply shimming...
-      if (this.strictStyling) {
-        this.applyScopeToContent(root, name);
-      }
-      this.shimPolyfillDirectives(def.rootStyles, name);
-      this.applyShimming(def.scopeStyles, name);
+    var typeExtension = this.isTypeExtension(extendsName);
+    // use caching to make working with styles nodes easier and to facilitate
+    // lookup of extendee
+    var def = this.registerDefinition(root, name, extendsName);
+    // find styles and apply shimming...
+    if (this.strictStyling) {
+      this.applyScopeToContent(root, name);
     }
-  },
-  // Shim styles to be placed inside a shadowRoot.
-  // 1. shim polyfill directives /* @polyfill */
-  // 2. shim @host and scoping
-  shimShadowDOMStyling: function(styles, name) {
-    this.shimPolyfillDirectives(styles, name);
-    this.applyShimming(styles, name);
+    // insert @polyfill and @polyfill-rule rules into style elements
+    // scoping process takes care of shimming these
+    this.insertPolyfillDirectives(def.rootStyles);
+    this.insertPolyfillRules(def.rootStyles);
+    var cssText = this.stylesToShimmedCssText(def.scopeStyles, name,
+        typeExtension);
+    // note: we only need to do rootStyles since these are unscoped.
+    cssText += this.extractPolyfillUnscopedRules(def.rootStyles);
+    // provide shimmedStyle for user extensibility
+    def.shimmedStyle = cssTextToStyle(cssText);
+    if (root) {
+      root.shimmedStyle = def.shimmedStyle;
+    }
+    // remove existing style elements
+    for (var i=0, l=def.rootStyles.length, s; (i<l) && (s=def.rootStyles[i]);
+        i++) {
+      s.parentNode.removeChild(s);
+    }
+    // add style to document
+    addCssToDocument(cssText);
   },
   registerDefinition: function(root, name, extendsName) {
     var def = this.registry[name] = {
@@ -5539,16 +5560,19 @@
       name: name,
       extendsName: extendsName
     }
-    var styles = root.querySelectorAll('style');
+    var styles = root ? root.querySelectorAll('style') : [];
     styles = styles ? Array.prototype.slice.call(styles, 0) : [];
     def.rootStyles = styles;
     def.scopeStyles = def.rootStyles;
     var extendee = this.registry[def.extendsName];
-    if (extendee) {
-      def.scopeStyles = def.scopeStyles.concat(extendee.scopeStyles);
+    if (extendee && (!root || root.querySelector('shadow'))) {
+      def.scopeStyles = extendee.scopeStyles.concat(def.scopeStyles);
     }
     return def;
   },
+  isTypeExtension: function(extendsName) {
+    return extendsName && extendsName.indexOf('-') < 0;
+  },
   applyScopeToContent: function(root, name) {
     if (root) {
       // add the name attribute to each node in root.
@@ -5570,78 +5594,123 @@
    *
    * For example, we convert this rule:
    *
-   * (comment start) @polyfill @host g-menu-item (comment end)
-   * shadow::-webkit-distributed(g-menu-item) {
+   * (comment start) @polyfill :host menu-item (comment end)
+   * shadow::-webkit-distributed(menu-item) {
    *
    * to this:
    *
-   * scopeName g-menu-item {
+   * scopeName menu-item {
    *
   **/
-  shimPolyfillDirectives: function(styles, name) {
+  insertPolyfillDirectives: function(styles) {
     if (styles) {
       Array.prototype.forEach.call(styles, function(s) {
-        s.textContent = this.convertPolyfillDirectives(s.textContent, name);
+        s.textContent = this.insertPolyfillDirectivesInCssText(s.textContent);
       }, this);
     }
   },
-  convertPolyfillDirectives: function(cssText, name) {
-    var r = '', l = 0, matches, selector;
-    while (matches = cssPolyfillCommentRe.exec(cssText)) {
-      r += cssText.substring(l, matches.index);
-      // remove end comment delimiter (*/)
-      selector = matches[1].slice(0, -2).replace(hostRe, name);
-      r += this.scopeSelector(selector, name) + '{';
-      l = cssPolyfillCommentRe.lastIndex;
+  insertPolyfillDirectivesInCssText: function(cssText) {
+    return cssText.replace(cssPolyfillCommentRe, function(match, p1) {
+      // remove end comment delimiter and add block start
+      return p1.slice(0, -2) + '{';
+    });
+  },
+  /*
+   * Process styles to add rules which will only apply under the polyfill
+   *
+   * For example, we convert this rule:
+   *
+   * (comment start) @polyfill-rule :host menu-item {
+   * ... } (comment end)
+   *
+   * to this:
+   *
+   * scopeName menu-item {...}
+   *
+  **/
+  insertPolyfillRules: function(styles) {
+    if (styles) {
+      Array.prototype.forEach.call(styles, function(s) {
+        s.textContent = this.insertPolyfillRulesInCssText(s.textContent);
+      }, this);
     }
-    r += cssText.substring(l, cssText.length);
+  },
+  insertPolyfillRulesInCssText: function(cssText) {
+    return cssText.replace(cssPolyfillRuleCommentRe, function(match, p1) {
+      // remove end comment delimiter
+      return p1.slice(0, -1);
+    });
+  },
+  /*
+   * Process styles to add rules which will only apply under the polyfill
+   * and do not process via CSSOM. (CSSOM is destructive to rules on rare
+   * occasions, e.g. -webkit-calc on Safari.)
+   * For example, we convert this rule:
+   *
+   * (comment start) @polyfill-unscoped-rule menu-item {
+   * ... } (comment end)
+   *
+   * to this:
+   *
+   * menu-item {...}
+   *
+  **/
+  extractPolyfillUnscopedRules: function(styles) {
+    var cssText = '';
+    if (styles) {
+      Array.prototype.forEach.call(styles, function(s) {
+        cssText += this.extractPolyfillUnscopedRulesFromCssText(
+            s.textContent) + '\n\n';
+      }, this);
+    }
+    return cssText;
+  },
+  extractPolyfillUnscopedRulesFromCssText: function(cssText) {
+    var r = '', matches;
+    while (matches = cssPolyfillUnscopedRuleCommentRe.exec(cssText)) {
+      r += matches[1].slice(0, -1) + '\n\n';
+    }
     return r;
   },
   // apply @host and scope shimming
-  applyShimming: function(styles, name) {
-    var cssText = this.shimAtHost(styles, name);
-    cssText += this.shimScoping(styles, name);
-    addCssToDocument(cssText);
+  stylesToShimmedCssText: function(styles, name, typeExtension) {
+    return this.shimAtHost(styles, name, typeExtension) +
+        this.shimScoping(styles, name, typeExtension);
   },
   // form: @host { .foo { declarations } }
   // becomes: scopeName.foo { declarations }
-  shimAtHost: function(styles, name) {
+  shimAtHost: function(styles, name, typeExtension) {
     if (styles) {
-      return this.convertAtHostStyles(styles, name);
+      return this.convertAtHostStyles(styles, name, typeExtension);
     }
   },
-  convertAtHostStyles: function(styles, name) {
-    var cssText = stylesToCssText(styles);
-    var r = '', l=0, matches;
-    while (matches = hostRuleRe.exec(cssText)) {
-      r += cssText.substring(l, matches.index);
-      r += this.scopeHostCss(matches[1], name);
-      l = hostRuleRe.lastIndex;
-    }
-    r += cssText.substring(l, cssText.length);
-    var re = new RegExp('^' + name + selectorReSuffix, 'm');
-    var cssText = rulesToCss(this.findAtHostRules(cssToRules(r),
-      re));
+  convertAtHostStyles: function(styles, name, typeExtension) {
+    var cssText = stylesToCssText(styles), self = this;
+    cssText = cssText.replace(hostRuleRe, function(m, p1) {
+      return self.scopeHostCss(p1, name, typeExtension);
+    });
+    cssText = rulesToCss(this.findAtHostRules(cssToRules(cssText),
+      new RegExp('^' + name + selectorReSuffix, 'm')));
     return cssText;
   },
-  scopeHostCss: function(cssText, name) {
-    var r = '', matches;
-    while (matches = selectorRe.exec(cssText)) {
-      r += this.scopeHostSelector(matches[1], name) +' ' + matches[2] + '\n\t';
-    }
-    return r;
+  scopeHostCss: function(cssText, name, typeExtension) {
+    var self = this;
+    return cssText.replace(selectorRe, function(m, p1, p2) {
+      return self.scopeHostSelector(p1, name, typeExtension) + ' ' + p2 + '\n\t';
+    });
   },
   // supports scopig by name and  [is=name] syntax
-  scopeHostSelector: function(selector, name) {
+  scopeHostSelector: function(selector, name, typeExtension) {
     var r = [], parts = selector.split(','), is = '[is=' + name + ']';
     parts.forEach(function(p) {
       p = p.trim();
       // selector: *|:scope -> name
       if (p.match(hostElementRe)) {
-        p = p.replace(hostElementRe, name + '$1$3, ' + is + '$1$3');
-      // selector: .foo -> name.foo, [bar] -> name[bar]
+        p = p.replace(hostElementRe, typeExtension ? is + '$1$3' :
+            name + '$1$3');
+      // selector: .foo -> name.foo (OR) [bar] -> name[bar]
       } else if (p.match(hostFixableRe)) {
-        p = name + p + ', ' + is + p;
+        p = typeExtension ? is + p : name + p;
       }
       r.push(p);
     }, this);
@@ -5667,32 +5736,57 @@
    *
    *  scopeName .foo { ... }
   */
-  shimScoping: function(styles, name) {
+  shimScoping: function(styles, name, typeExtension) {
     if (styles) {
-      return this.convertScopedStyles(styles, name);
+      return this.convertScopedStyles(styles, name, typeExtension);
     }
   },
-  convertScopedStyles: function(styles, name) {
-    Array.prototype.forEach.call(styles, function(s) {
-      if (s.parentNode) {
-        s.parentNode.removeChild(s);
-      }
-    });
+  convertScopedStyles: function(styles, name, typeExtension) {
     var cssText = stylesToCssText(styles).replace(hostRuleRe, '');
+    cssText = this.insertPolyfillHostInCssText(cssText);
+    cssText = this.convertColonHost(cssText);
     cssText = this.convertPseudos(cssText);
+    cssText = this.convertParts(cssText);
+    cssText = this.convertCombinators(cssText);
     var rules = cssToRules(cssText);
-    cssText = this.scopeRules(rules, name);
+    cssText = this.scopeRules(rules, name, typeExtension);
     return cssText;
   },
   convertPseudos: function(cssText) {
     return cssText.replace(cssPseudoRe, ' [pseudo=$1]');
   },
+  convertParts: function(cssText) {
+    return cssText.replace(cssPartRe, ' [part=$1]');
+  },
+  /*
+   * convert a rule like :host(.foo) > .bar { }
+   *
+   * to
+   *
+   * scopeName.foo > .bar, .foo scopeName > .bar { }
+   * TODO(sorvell): file bug since native impl does not do the former yet.
+   * http://jsbin.com/OganOCI/2/edit
+  */
+  convertColonHost: function(cssText) {
+    // p1 = :host, p2 = contents of (), p3 rest of rule
+    return cssText.replace(cssColonHostRe, function(m, p1, p2, p3) {
+      return p2 ? polyfillHostNoCombinator + p2 + p3 + ', '
+          + p2 + ' ' + p1 + p3 :
+          p1 + p3;
+    });
+  },
+  /*
+   * Convert ^ and ^^ combinators by replacing with space.
+  */
+  convertCombinators: function(cssText) {
+    return cssText.replace('^^', ' ').replace('^', ' ');
+  },
   // change a selector like 'div' to 'name div'
-  scopeRules: function(cssRules, name) {
+  scopeRules: function(cssRules, name, typeExtension) {
     var cssText = '';
     Array.prototype.forEach.call(cssRules, function(rule) {
       if (rule.selectorText && (rule.style && rule.style.cssText)) {
-        cssText += this.scopeSelector(rule.selectorText, name,
+        cssText += this.scopeSelector(rule.selectorText, name, typeExtension,
           this.strictStyling) + ' {\n\t';
         cssText += this.propertiesFromRule(rule) + '\n}\n\n';
       } else if (rule.media) {
@@ -5705,26 +5799,32 @@
     }, this);
     return cssText;
   },
-  scopeSelector: function(selector, name, strict) {
+  scopeSelector: function(selector, name, typeExtension, strict) {
     var r = [], parts = selector.split(',');
     parts.forEach(function(p) {
       p = p.trim();
-      if (this.selectorNeedsScoping(p, name)) {
+      if (this.selectorNeedsScoping(p, name, typeExtension)) {
         p = strict ? this.applyStrictSelectorScope(p, name) :
-          this.applySimpleSelectorScope(p, name);
+          this.applySimpleSelectorScope(p, name, typeExtension);
       }
       r.push(p);
     }, this);
     return r.join(', ');
   },
-  selectorNeedsScoping: function(selector, name) {
-    var matchScope = '(' + name + '|\\[is=' + name + '\\])';
-    var re = new RegExp('^' + matchScope + selectorReSuffix, 'm');
+  selectorNeedsScoping: function(selector, name, typeExtension) {
+    var matchScope = typeExtension ? name : '\\[is=' + name + '\\]';
+    var re = new RegExp('^(' + matchScope + ')' + selectorReSuffix, 'm');
     return !selector.match(re);
   },
   // scope via name and [is=name]
-  applySimpleSelectorScope: function(selector, name) {
-    return name + ' ' + selector + ', ' + '[is=' + name + '] ' + selector;
+  applySimpleSelectorScope: function(selector, name, typeExtension) {
+    var scoper = typeExtension ? '[is=' + name + ']' : name;
+    if (selector.match(polyfillHostRe)) {
+      selector = selector.replace(polyfillHostNoCombinator, scoper);
+      return selector.replace(polyfillHostRe, scoper + ' ');
+    } else {
+      return scoper + ' ' + selector;
+    }
   },
   // return a selector with [name] suffix on each simple selector
   // e.g. .foo.bar > .zot becomes .foo[name].bar[name] > .zot[name]
@@ -5735,7 +5835,8 @@
     splits.forEach(function(sep) {
       var parts = scoped.split(sep);
       scoped = parts.map(function(p) {
-        var t = p.trim();
+        // remove :host since it should be unnecessary
+        var t = p.trim().replace(polyfillHostRe, '');
         if (t && (splits.indexOf(t) < 0) && (t.indexOf(attrName) < 0)) {
           p = t.replace(/([^:]*)(:*)(.*)/, '$1' + attrName + '$2$3')
         }
@@ -5744,6 +5845,10 @@
     });
     return scoped;
   },
+  insertPolyfillHostInCssText: function(selector) {
+    return selector.replace(hostRe, polyfillHost).replace(colonHostRe,
+        polyfillHost);
+  },
   propertiesFromRule: function(rule) {
     var properties = rule.style.cssText;
     // TODO(sorvell): Chrome cssom incorrectly removes quotes from the content
@@ -5762,9 +5867,19 @@
     hostFixableRe = /^[.\[:]/,
     cssCommentRe = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,
     cssPolyfillCommentRe = /\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim,
+    cssPolyfillRuleCommentRe = /\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,
+    cssPolyfillUnscopedRuleCommentRe = /\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,
     cssPseudoRe = /::(x-[^\s{,(]*)/gim,
+    cssPartRe = /::part\(([^)]*)\)/gim,
+    // note: :host pre-processed to -host.
+    cssColonHostRe = /(-host)(?:\(([^)]*)\))?([^,{]*)/gim,
     selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$',
-    hostRe = /@host/gim;
+    hostRe = /@host/gim,
+    colonHostRe = /\:host/gim,
+    polyfillHost = '-host',
+    /* host name without combinator */
+    polyfillHostNoCombinator = '-host-no-combinator',
+    polyfillHostRe = /-host/gim;
 
 function stylesToCssText(styles, preserveComments) {
   var cssText = '';
@@ -5778,9 +5893,14 @@
   return cssText;
 }
 
-function cssToRules(cssText) {
+function cssTextToStyle(cssText) {
   var style = document.createElement('style');
   style.textContent = cssText;
+  return style;
+}
+
+function cssToRules(cssText) {
+  var style = cssTextToStyle(cssText);
   document.head.appendChild(style);
   var rules = style.sheet.cssRules;
   style.parentNode.removeChild(style);
@@ -5820,70 +5940,5 @@
 scope.ShadowCSS = ShadowCSS;
 
 })(window.Platform);
-// 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.
-
-(function(scope) {
-  // TODO(terry): Remove shimShadowDOMStyling2 until wrap/unwrap from a
-  //              dart:html Element to a JS DOM node is available.
-  /**
-   * Given the content of a STYLE tag and the name of a component shim the CSS
-   * and return the new scoped CSS to replace the STYLE's content.  The content
-   * is replaced in Dart's implementation of PolymerElement.
-   */
-  function shimShadowDOMStyling2(styleContent, name) {
-    if (window.ShadowDOMPolyfill) {
-      var content = this.convertPolyfillDirectives(styleContent, name);
-
-      // applyShimming calls shimAtHost and shipScoping
-      // shimAtHost code:
-      var r = '', l=0, matches;
-      while (matches = hostRuleRe.exec(content)) {
-        r += content.substring(l, matches.index);
-        r += this.scopeHostCss(matches[1], name);
-        l = hostRuleRe.lastIndex;
-      }
-      r += content.substring(l, content.length);
-      var re = new RegExp('^' + name + selectorReSuffix, 'm');
-      var atHostCssText = rulesToCss(this.findAtHostRules(cssToRules(r), re));
-
-      // shimScoping code:
-      // strip comments for easier processing
-      content = content.replace(cssCommentRe, '');
-
-      content = this.convertPseudos(content);
-      var rules = cssToRules(content);
-      var cssText = this.scopeRules(rules, name);
-
-      return atHostCssText + cssText;
-    }
-  }
-
-  // Minimal copied code from ShadowCSS, that is not exposed in
-  // PlatForm.ShadowCSS (local code).
-  var hostRuleRe = /@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim,
-    cssCommentRe = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,
-    selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$';
-
-  function cssToRules(cssText) {
-    var style = document.createElement('style');
-    style.textContent = cssText;
-    document.head.appendChild(style);
-    var rules = style.sheet.cssRules;
-    style.parentNode.removeChild(style);
-    return rules;
-  }
-
-  function rulesToCss(cssRules) {
-    for (var i=0, css=[]; i < cssRules.length; i++) {
-      css.push(cssRules[i].cssText);
-    }
-    return css.join('\n\n');
-  }
-
-  // exports
-  scope.ShadowCSS.shimShadowDOMStyling2 = shimShadowDOMStyling2;
-})(window.Platform);
 
 }
\ No newline at end of file
diff --git a/pkg/shadow_dom/lib/shadow_dom.min.js b/pkg/shadow_dom/lib/shadow_dom.min.js
index 4b4a08a..9108bae 100644
--- a/pkg/shadow_dom/lib/shadow_dom.min.js
+++ b/pkg/shadow_dom/lib/shadow_dom.min.js
@@ -1,2 +1,3 @@
-if(!HTMLElement.prototype.createShadowRoot||window.__forceShadowDomPolyfill){!function(){Element.prototype.webkitCreateShadowRoot&&(Element.prototype.webkitCreateShadowRoot=function(){return window.ShadowDOMPolyfill.wrapIfNeeded(this).createShadowRoot()})}(),function(a){"use strict";function b(){function a(a){"splice"===a[0].type&&"splice"===a[1].type&&(b=!0)}if("function"!=typeof Object.observe||"function"!=typeof Array.observe)return!1;var b=!1,c=[0];return Array.observe(c,a),c[1]=1,c.length=0,Object.deliverChangeRecords(a),b}function c(){if(a.document&&"securityPolicy"in a.document&&!a.document.securityPolicy.allowsEval)return!1;try{var b=new Function("","return true;");return b()}catch(c){return!1}}function d(a){return+a===a>>>0}function e(a){return+a}function f(a){return a===Object(a)}function g(a,b){return a===b?0!==a||1/a===1/b:H(a)&&H(b)?!0:a!==a&&b!==b}function h(a){return"string"!=typeof a?!1:(a=a.trim(),""==a?!0:"."==a[0]?!1:P.test(a))}function i(a,b){if(b!==Q)throw Error("Use Path.get to retrieve path objects");return""==a.trim()?this:d(a)?(this.push(a),this):(a.split(/\s*\.\s*/).filter(function(a){return a}).forEach(function(a){this.push(a)},this),G&&!F&&this.length&&(this.getValueFrom=this.compiledGetValueFromFn()),void 0)}function j(a){if(a instanceof i)return a;null==a&&(a=""),"string"!=typeof a&&(a=String(a));var b=R[a];if(b)return b;if(!h(a))return S;var b=new i(a,Q);return R[a]=b,b}function k(b){for(var c=0;T>c&&b.check();)b.report(),c++;a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=c)}function l(a){for(var b in a)return!1;return!0}function m(a){return l(a.added)&&l(a.removed)&&l(a.changed)}function n(a,b){var c={},d={},e={};for(var f in b){var g=a[f];(void 0===g||g!==b[f])&&(f in a?g!==b[f]&&(e[f]=g):d[f]=void 0)}for(var f in a)f in b||(c[f]=a[f]);return Array.isArray(a)&&a.length!==b.length&&(e.length=a.length),{added:c,removed:d,changed:e}}function o(a,b){var c=b||(Array.isArray(a)?[]:{});for(var d in a)c[d]=a[d];return Array.isArray(a)&&(c.length=a.length),c}function p(a,b,c,d){if(this.closed=!1,this.object=a,this.callback=b,this.target=c,this.token=d,this.reporting=!0,F){var e=this;this.boundInternalCallback=function(a){e.internalCallback(a)}}q(this)}function q(a){V&&(U.push(a),p._allObserversCount++)}function r(a,b,c,d){p.call(this,a,b,c,d),this.connect(),this.sync(!0)}function s(a,b,c,d){if(!Array.isArray(a))throw Error("Provided object is not an Array");r.call(this,a,b,c,d)}function t(a){this.arr=[],this.callback=a,this.isObserved=!0}function u(a,b,c,d,e,g,h){var b=b instanceof i?b:j(b);return b&&b.length&&f(a)?(p.call(this,a,c,d,e),this.valueFn=g,this.setValueFn=h,this.path=b,this.connect(),this.sync(!0),void 0):(this.value_=b?b.getValueFrom(a):void 0,this.value=g?g(this.value_):this.value_,this.closed=!0,void 0)}function v(a,b,c,d){p.call(this,void 0,a,b,c),this.valueFn=d,this.observed=[],this.values=[],this.value=void 0,this.oldValue=void 0,this.oldValues=void 0,this.changeFlags=void 0,this.started=!1}function w(a,b){if("function"==typeof Object.observe){var c=Object.getNotifier(a);return function(d,e){var f={object:a,type:d,name:b};2===arguments.length&&(f.oldValue=e),c.notify(f)}}}function x(a,b,c){for(var d={},e={},f=0;f<b.length;f++){var g=b[f];$[g.type]?(g.name in c||(c[g.name]=g.oldValue),"updated"!=g.type&&("new"!=g.type?g.name in d?(delete d[g.name],delete c[g.name]):e[g.name]=!0:g.name in e?delete e[g.name]:d[g.name]=!0)):(console.error("Unknown changeRecord type: "+g.type),console.error(g))}for(var h in d)d[h]=a[h];for(var h in e)e[h]=void 0;var i={};for(var h in c)if(!(h in d||h in e)){var j=a[h];c[h]!==j&&(i[h]=j)}return{added:d,removed:e,changed:i}}function y(a,b,c){return{index:a,removed:b,addedCount:c}}function z(){}function A(a,b,c,d,e,f){return db.calcSplices(a,b,c,d,e,f)}function B(a,b,c,d){return c>b||a>d?-1:b==c||d==a?0:c>a?d>b?b-c:d-c:b>d?d-a:b-a}function C(a,b,c,d){for(var e=y(b,c,d),f=!1,g=0,h=0;h<a.length;h++){var i=a[h];if(i.index+=g,!f){var j=B(e.index,e.index+e.removed.length,i.index,i.index+i.addedCount);if(j>=0){a.splice(h,1),h--,g-=i.addedCount-i.removed.length,e.addedCount+=i.addedCount-j;var k=e.removed.length+i.removed.length-j;if(e.addedCount||k){var c=i.removed;if(e.index<i.index){var l=e.removed.slice(0,i.index-e.index);Array.prototype.push.apply(l,c),c=l}if(e.index+e.removed.length>i.index+i.addedCount){var m=e.removed.slice(i.index+i.addedCount-e.index);Array.prototype.push.apply(c,m)}e.removed=c,i.index<e.index&&(e.index=i.index)}else f=!0}else if(e.index<i.index){f=!0,a.splice(h,0,e),h++;var n=e.addedCount-e.removed.length;i.index+=n,g+=n}}}f||a.push(e)}function D(a,b){for(var c=[],f=0;f<b.length;f++){var g=b[f];switch(g.type){case"splice":C(c,g.index,g.removed.slice(),g.addedCount);break;case"new":case"updated":case"deleted":if(!d(g.name))continue;var h=e(g.name);if(0>h)continue;C(c,h,[g.oldValue],1);break;default:console.error("Unexpected record type: "+JSON.stringify(g))}}return c}function E(a,b){var c=[];return D(a,b).forEach(function(b){return 1==b.addedCount&&1==b.removed.length?(b.removed[0]!==a[b.index]&&c.push(b),void 0):(c=c.concat(A(a,b.index,b.index+b.addedCount,b.removed,0,b.removed.length)),void 0)}),c}var F=b(),G=c(),H=a.Number.isNaN||function(b){return"number"==typeof b&&a.isNaN(b)},I="__proto__"in{}?function(a){return a}:function(a){var b=a.__proto__;if(!b)return a;var c=Object.create(b);return Object.getOwnPropertyNames(a).forEach(function(b){Object.defineProperty(c,b,Object.getOwnPropertyDescriptor(a,b))}),c},J="[$_a-zA-Z]",K="[$_a-zA-Z0-9]",L=J+"+"+K+"*",M="(?:[0-9]|[1-9]+[0-9]+)",N="(?:"+L+"|"+M+")",O="(?:"+N+")(?:\\s*\\.\\s*"+N+")*",P=new RegExp("^"+O+"$"),Q={},R={};i.get=j,i.prototype=I({__proto__:[],valid:!0,toString:function(){return this.join(".")},getValueFrom:function(a,b){for(var c=0;c<this.length;c++){if(null==a)return;b&&b.observe(a),a=a[this[c]]}return a},compiledGetValueFromFn:function(){var a=this.map(function(a){return d(a)?'["'+a+'"]':"."+a}),b="",c="obj";b+="if (obj != null";for(var e=0;e<this.length-1;e++)this[e],c+=a[e],b+=" &&\n     "+c+" != null";return b+=")\n",c+=a[e],b+="  return "+c+";\nelse\n  return undefined;",new Function("obj",b)},setValueFrom:function(a,b){if(!this.length)return!1;for(var c=0;c<this.length-1;c++){if(!f(a))return!1;a=a[this[c]]}return f(a)?(a[this[c]]=b,!0):!1}});var S=new i("",Q);S.valid=!1,S.getValueFrom=S.setValueFrom=function(){};var T=1e3;p.prototype={internalCallback:function(a){this.closed||this.reporting&&this.check(a)&&(this.report(),this.testingResults&&(this.testingResults.anyChanged=!0))},close:function(){this.closed||(this.object&&"function"==typeof this.object.close&&this.object.close(),this.disconnect(),this.object=void 0,this.closed=!0)},deliver:function(a){this.closed||(F?(this.testingResults=a,Object.deliverChangeRecords(this.boundInternalCallback),this.testingResults=void 0):k(this))},report:function(){this.reporting&&(this.sync(!1),this.callback&&(this.reportArgs.push(this.token),this.invokeCallback(this.reportArgs)),this.reportArgs=void 0)},invokeCallback:function(a){try{this.callback.apply(this.target,a)}catch(b){p._errorThrownDuringCallback=!0,console.error("Exception caught during observer callback: "+(b.stack||b))}},reset:function(){this.closed||(F&&(this.reporting=!1,Object.deliverChangeRecords(this.boundInternalCallback),this.reporting=!0),this.sync(!0))}};var U,V=!F||a.forceCollectObservers;p._allObserversCount=0,V&&(U=[]);var W=!1,X="function"==typeof Object.deliverAllChangeRecords;a.Platform=a.Platform||{},a.Platform.performMicrotaskCheckpoint=function(){if(!W){if(X)return Object.deliverAllChangeRecords(),void 0;if(V){W=!0;var b=0,c={};do{b++;var d=U;U=[],c.anyChanged=!1;for(var e=0;e<d.length;e++){var f=d[e];f.closed||(F?f.deliver(c):f.check()&&(c.anyChanged=!0,f.report()),U.push(f))}}while(T>b&&c.anyChanged);a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=b),p._allObserversCount=U.length,W=!1}}},V&&(a.Platform.clearObservers=function(){U=[]}),r.prototype=I({__proto__:p.prototype,connect:function(){F&&Object.observe(this.object,this.boundInternalCallback)},sync:function(){F||(this.oldObject=o(this.object))},check:function(a){var b,c;if(F){if(!a)return!1;c={},b=x(this.object,a,c)}else c=this.oldObject,b=n(this.object,this.oldObject);return m(b)?!1:(this.reportArgs=[b.added||{},b.removed||{},b.changed||{}],this.reportArgs.push(function(a){return c[a]}),!0)},disconnect:function(){F?this.object&&Object.unobserve(this.object,this.boundInternalCallback):this.oldObject=void 0}}),s.prototype=I({__proto__:r.prototype,connect:function(){F&&Array.observe(this.object,this.boundInternalCallback)},sync:function(){F||(this.oldObject=this.object.slice())},check:function(a){var b;if(F){if(!a)return!1;b=E(this.object,a)}else b=A(this.object,0,this.object.length,this.oldObject,0,this.oldObject.length);return b&&b.length?(this.reportArgs=[b],!0):!1}}),s.applySplices=function(a,b,c){c.forEach(function(c){for(var d=[c.index,c.removed.length],e=c.index;e<c.index+c.addedCount;)d.push(b[e]),e++;Array.prototype.splice.apply(a,d)})};var Y=Object.getPrototypeOf({}),Z=Object.getPrototypeOf([]);t.prototype={reset:function(){this.isObserved=!this.isObserved},observe:function(a){if(f(a)&&a!==Y&&a!==Z){var b=this.arr.indexOf(a);b>=0&&this.arr[b+1]===this.isObserved||(0>b&&(b=this.arr.length,this.arr[b]=a,Object.observe(a,this.callback)),this.arr[b+1]=this.isObserved,this.observe(Object.getPrototypeOf(a)))}},cleanup:function(){for(var a=0,b=0,c=this.isObserved;b<this.arr.length;){var d=this.arr[b];this.arr[b+1]==c?(b>a&&(this.arr[a]=d,this.arr[a+1]=c),a+=2):Object.unobserve(d,this.callback),b+=2}this.arr.length=a}},u.prototype=I({__proto__:p.prototype,connect:function(){F&&(this.observedSet=new t(this.boundInternalCallback))},disconnect:function(){this.value=void 0,this.value_=void 0,this.observedSet&&(this.observedSet.reset(),this.observedSet.cleanup(),this.observedSet=void 0)},check:function(){return this.observedSet&&this.observedSet.reset(),this.value_=this.path.getValueFrom(this.object,this.observedSet),this.observedSet&&this.observedSet.cleanup(),g(this.value_,this.oldValue_)?!1:(this.value=this.valueFn?this.valueFn(this.value_):this.value_,this.reportArgs=[this.value,this.oldValue],!0)},sync:function(a){a&&(this.observedSet&&this.observedSet.reset(),this.value_=this.path.getValueFrom(this.object,this.observedSet),this.value=this.valueFn?this.valueFn(this.value_):this.value_,this.observedSet&&this.observedSet.cleanup()),this.oldValue_=this.value_,this.oldValue=this.value},setValue:function(a){this.path&&("function"==typeof this.setValueFn&&(a=this.setValueFn(a)),this.path.setValueFrom(this.object,a))}}),v.prototype=I({__proto__:u.prototype,addPath:function(a,b){if(this.started)throw Error("Cannot add more paths once started.");var b=b instanceof i?b:j(b),c=b?b.getValueFrom(a):void 0;this.observed.push(a,b),this.values.push(c)},start:function(){this.connect(),this.sync(!0)},getValues:function(){this.observedSet&&this.observedSet.reset();for(var a=!1,b=0;b<this.observed.length;b+=2){var c=this.observed[b+1];if(c){var d=this.observed[b],e=c.getValueFrom(d,this.observedSet),f=this.values[b/2];if(!g(e,f)){if(!a&&!this.valueFn){this.oldValues=this.oldValues||[],this.changeFlags=this.changeFlags||[];for(var h=0;h<this.values.length;h++)this.oldValues[h]=this.values[h],this.changeFlags[h]=!1}this.valueFn||(this.changeFlags[b/2]=!0),this.values[b/2]=e,a=!0}}}return this.observedSet&&this.observedSet.cleanup(),a},check:function(){if(this.getValues()){if(this.valueFn){if(this.value=this.valueFn(this.values),g(this.value,this.oldValue))return!1;this.reportArgs=[this.value,this.oldValue]}else this.reportArgs=[this.values,this.oldValues,this.changeFlags,this.observed];return!0}},sync:function(a){a&&(this.getValues(),this.valueFn&&(this.value=this.valueFn(this.values))),this.valueFn&&(this.oldValue=this.value)},close:function(){if(this.observed){for(var a=0;a<this.observed.length;a+=2){var b=this.observed[a];b&&"function"==typeof b.close&&b.close()}this.observed=void 0,this.values=void 0}p.prototype.close.call(this)}});var $={"new":!0,updated:!0,deleted:!0};u.defineProperty=function(a,b,c){var d=c.object,e=j(c.path),f=w(a,b),g=new u(d,c.path,function(a,b){f&&f("updated",b)});return Object.defineProperty(a,b,{get:function(){return e.getValueFrom(d)},set:function(a){e.setValueFrom(d,a)},configurable:!0}),{close:function(){var c=e.getValueFrom(d);f&&g.deliver(),g.close(),Object.defineProperty(a,b,{value:c,writable:!0,configurable:!0})}}};var _=0,ab=1,bb=2,cb=3;z.prototype={calcEditDistances:function(a,b,c,d,e,f){for(var g=f-e+1,h=c-b+1,i=new Array(g),j=0;g>j;j++)i[j]=new Array(h),i[j][0]=j;for(var k=0;h>k;k++)i[0][k]=k;for(var j=1;g>j;j++)for(var k=1;h>k;k++)if(this.equals(a[b+k-1],d[e+j-1]))i[j][k]=i[j-1][k-1];else{var l=i[j-1][k]+1,m=i[j][k-1]+1;i[j][k]=m>l?l:m}return i},spliceOperationsFromEditDistances:function(a){for(var b=a.length-1,c=a[0].length-1,d=a[b][c],e=[];b>0||c>0;)if(0!=b)if(0!=c){var f,g=a[b-1][c-1],h=a[b-1][c],i=a[b][c-1];f=i>h?g>h?h:g:g>i?i:g,f==g?(g==d?e.push(_):(e.push(ab),d=g),b--,c--):f==h?(e.push(cb),b--,d=h):(e.push(bb),c--,d=i)}else e.push(cb),b--;else e.push(bb),c--;return e.reverse(),e},calcSplices:function(a,b,c,d,e,f){var g=0,h=0,i=Math.min(c-b,f-e);if(0==b&&0==e&&(g=this.sharedPrefix(a,d,i)),c==a.length&&f==d.length&&(h=this.sharedSuffix(a,d,i-g)),b+=g,e+=g,c-=h,f-=h,0==c-b&&0==f-e)return[];if(b==c){for(var j=y(b,[],0);f>e;)j.removed.push(d[e++]);return[j]}if(e==f)return[y(b,[],c-b)];for(var k=this.spliceOperationsFromEditDistances(this.calcEditDistances(a,b,c,d,e,f)),j=void 0,l=[],m=b,n=e,o=0;o<k.length;o++)switch(k[o]){case _:j&&(l.push(j),j=void 0),m++,n++;break;case ab:j||(j=y(m,[],0)),j.addedCount++,m++,j.removed.push(d[n]),n++;break;case bb:j||(j=y(m,[],0)),j.addedCount++,m++;break;case cb:j||(j=y(m,[],0)),j.removed.push(d[n]),n++}return j&&l.push(j),l},sharedPrefix:function(a,b,c){for(var d=0;c>d;d++)if(!this.equals(a[d],b[d]))return d;return c},sharedSuffix:function(a,b,c){for(var d=a.length,e=b.length,f=0;c>f&&this.equals(a[--d],b[--e]);)f++;return f},calculateSplices:function(a,b){return this.calcSplices(a,0,a.length,b,0,b.length)},equals:function(a,b){return a===b}};var db=new z;a.Observer=p,a.Observer.hasObjectObserve=F,a.ArrayObserver=s,a.ArrayObserver.calculateSplices=function(a,b){return db.calculateSplices(a,b)},a.ArraySplice=z,a.ObjectObserver=r,a.PathObserver=u,a.CompoundPathObserver=v,a.Path=i}("undefined"!=typeof global&&global?global:this),("undefined"==typeof WeakMap||navigator.userAgent.indexOf("Firefox/")>-1)&&!function(){var a=Object.defineProperty,b=Date.now()%1e9,c=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")};c.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}},window.WeakMap=c}();var ShadowDOMPolyfill={};!function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a,b){return Object.getOwnPropertyNames(b).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))}),a}function d(a,b){return Object.getOwnPropertyNames(b).forEach(function(c){switch(c){case"arguments":case"caller":case"length":case"name":case"prototype":case"toString":return}Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))}),a}function e(a,b){for(var c=0;c<b.length;c++)if(b[c]in a)return b[c]}function f(a){var b=a.__proto__||Object.getPrototypeOf(a),c=C.get(b);if(c)return c;var d=f(b),e=r(d);return o(b,e,a),e}function g(a,b){m(a,b,!0)}function h(a,b){m(b,a,!1)}function i(a){return/^on[a-z]+$/.test(a)}function j(a){return F?new Function("return this.impl."+a):function(){return this.impl[a]}}function k(a){return F?new Function("v","this.impl."+a+" = v"):function(b){this.impl[a]=b}}function l(a){return F?new Function("return this.impl."+a+".apply(this.impl, arguments)"):function(){return this.impl[a].apply(this.impl,arguments)}}function m(b,c,d){Object.getOwnPropertyNames(b).forEach(function(e){if(!(e in c)){I&&b.__lookupGetter__(e);var f;try{f=Object.getOwnPropertyDescriptor(b,e)}catch(g){f=J}var h,m;if(d&&"function"==typeof f.value)return c[e]=l(e),void 0;var n=i(e);h=n?a.getEventHandlerGetter(e):j(e),(f.writable||f.set)&&(m=n?a.getEventHandlerSetter(e):k(e)),Object.defineProperty(c,e,{get:h,set:m,configurable:f.configurable,enumerable:f.enumerable})}})}function n(a,b,c){var e=a.prototype;o(e,b,c),d(b,a)}function o(a,c,d){var e=c.prototype;b(void 0===C.get(a)),C.set(a,c),D.set(e,a),g(a,e),d&&h(e,d)}function p(a,b){return C.get(b.prototype)===a}function q(a){var b=Object.getPrototypeOf(a),c=f(b),d=r(c);return o(b,d,a),d}function r(a){function b(b){a.call(this,b)}return b.prototype=Object.create(a.prototype),b.prototype.constructor=b,b}function s(a){return a instanceof E.EventTarget||a instanceof E.Event||a instanceof E.Range||a instanceof E.DOMImplementation||a instanceof E.CanvasRenderingContext2D||E.WebGLRenderingContext&&a instanceof E.WebGLRenderingContext}function t(a){return a instanceof M||a instanceof L||a instanceof N||a instanceof O||a instanceof K||a instanceof P||Q&&a instanceof Q}function u(a){return null===a?null:(b(t(a)),a.polymerWrapper_||(a.polymerWrapper_=new(f(a))(a)))}function v(a){return null===a?null:(b(s(a)),a.impl)}function w(a){return a&&s(a)?v(a):a}function x(a){return a&&!s(a)?u(a):a}function y(a,c){null!==c&&(b(t(a)),b(void 0===c||s(c)),a.polymerWrapper_=c)}function z(a,b,c){Object.defineProperty(a.prototype,b,{get:c,configurable:!0,enumerable:!0})}function A(a,b){z(a,b,function(){return u(this.impl[b])})}function B(a,b){a.forEach(function(a){b.forEach(function(b){a.prototype[b]=function(){var a=x(this);return a[b].apply(a,arguments)}})})}var C=new WeakMap,D=new WeakMap,E=Object.create(null),F=!("securityPolicy"in document)||document.securityPolicy.allowsEval;if(F)try{var G=new Function("","return true;");F=G()}catch(H){}Object.getOwnPropertyNames(window);var I=/Firefox/.test(navigator.userAgent),J={get:function(){},set:function(){},configurable:!0,enumerable:!0},K=window.DOMImplementation,L=window.Event,M=window.Node,N=window.Window,O=window.Range,P=window.CanvasRenderingContext2D,Q=window.WebGLRenderingContext;a.assert=b,a.constructorTable=C,a.defineGetter=z,a.defineWrapGetter=A,a.forwardMethodsToWrapper=B,a.isWrapperFor=p,a.mixin=c,a.nativePrototypeTable=D,a.oneOf=e,a.registerObject=q,a.registerWrapper=n,a.rewrap=y,a.unwrap=v,a.unwrapIfNeeded=w,a.wrap=u,a.wrapIfNeeded=x,a.wrappers=E}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a instanceof O.ShadowRoot}function c(a){var b=a.localName;return"content"===b||"shadow"===b}function d(a){return!!a.shadowRoot}function e(a){var b;return a.parentNode||(b=a.defaultView)&&N(b)||null}function f(f,g,h){if(h.length)return h.shift();if(b(f))return j(f)||a.getHostForShadowRoot(f);var i=a.eventParentsTable.get(f);if(i){for(var k=1;k<i.length;k++)h[k-1]=i[k];return i[0]}if(g&&c(f)){var l=f.parentNode;if(l&&d(l))for(var m=a.getShadowTrees(l),n=j(g),k=0;k<m.length;k++)if(m[k].contains(n))return n}return e(f)}function g(a){for(var d=[],e=a,g=[],i=[];e;){var j=null;if(c(e)){j=h(d);var k=d[d.length-1]||e;d.push(k)}else d.length||d.push(e);var l=d[d.length-1];g.push({target:l,currentTarget:e}),b(e)&&d.pop(),e=f(e,j,i)}return g}function h(a){for(var b=a.length-1;b>=0;b--)if(!c(a[b]))return a[b];return null}function i(d,e){for(var g=[];d;){for(var i=[],j=e,l=void 0;j;){var n=null;if(i.length){if(c(j)&&(n=h(i),k(l))){var o=i[i.length-1];i.push(o)}}else i.push(j);if(m(j,d))return i[i.length-1];b(j)&&i.pop(),l=j,j=f(j,n,g)}d=b(d)?a.getHostForShadowRoot(d):d.parentNode}}function j(b){return a.insertionParentTable.get(b)}function k(a){return j(a)}function l(a){for(var b;b=a.parentNode;)a=b;return a}function m(a,b){return l(a)===l(b)}function n(b,c){if(b===c)return!0;if(b instanceof O.ShadowRoot){var d=a.getHostForShadowRoot(b);return n(l(d),c)}return!1}function o(){Z++}function p(){Z--}function q(b){if(!Q.get(b)){if(Q.set(b,!0),b instanceof $){if(Z)return}else a.renderAllPending();var c=N(b.target),d=N(b);return r(d,c)}}function r(a,b){var c=g(b);return"load"===a.type&&2===c.length&&c[0].target instanceof O.Document&&c.shift(),Y.set(a,c),s(a,c)&&t(a,c)&&u(a,c),U.set(a,x.NONE),S.set(a,null),a.defaultPrevented}function s(a,b){for(var c,d=b.length-1;d>0;d--){var e=b[d].target,f=b[d].currentTarget;if(e!==f&&(c=x.CAPTURING_PHASE,!v(b[d],a,c)))return!1}return!0}function t(a,b){var c=x.AT_TARGET;return v(b[0],a,c)}function u(a,b){for(var c,d=a.bubbles,e=1;e<b.length;e++){var f=b[e].target,g=b[e].currentTarget;if(f===g)c=x.AT_TARGET;else{if(!d||W.get(a))continue;c=x.BUBBLING_PHASE}if(!v(b[e],a,c))return}}function v(a,b,c){var d=a.target,e=a.currentTarget,f=P.get(e);if(!f)return!0;if("relatedTarget"in b){var g=M(b);if(g.relatedTarget){var h=N(g.relatedTarget),j=i(e,h);if(j===d)return!0;T.set(b,j)}}U.set(b,c);var k=b.type,l=!1;R.set(b,d),S.set(b,e);for(var m=0;m<f.length;m++){var n=f[m];if(n.removed)l=!0;else if(!(n.type!==k||!n.capture&&c===x.CAPTURING_PHASE||n.capture&&c===x.BUBBLING_PHASE))try{if("function"==typeof n.handler?n.handler.call(e,b):n.handler.handleEvent(b),W.get(b))return!1}catch(o){window.onerror?window.onerror(o.message):console.error(o,o.stack)}}if(l){var p=f.slice();f.length=0;for(var m=0;m<p.length;m++)p[m].removed||f.push(p[m])}return!V.get(b)}function w(a,b,c){this.type=a,this.handler=b,this.capture=Boolean(c)}function x(a,b){return a instanceof _?(this.impl=a,void 0):N(B(_,"Event",a,b))}function y(a){return a&&a.relatedTarget?Object.create(a,{relatedTarget:{value:M(a.relatedTarget)}}):a}function z(a,b,c){var d=window[a],e=function(b,c){return b instanceof d?(this.impl=b,void 0):N(B(d,a,b,c))};return e.prototype=Object.create(b.prototype),c&&K(e.prototype,c),d&&(d.prototype["init"+a]?L(d,e,document.createEvent(a)):L(d,e,new d("temp"))),e}function A(a,b){return function(){arguments[b]=M(arguments[b]);var c=M(this);c[a].apply(c,arguments)}}function B(a,b,c,d){if(jb)return new a(c,y(d));var e=M(document.createEvent(b)),f=ib[b],g=[c];return Object.keys(f).forEach(function(a){var b=null!=d&&a in d?d[a]:f[a];"relatedTarget"===a&&(b=M(b)),g.push(b)}),e["init"+b].apply(e,g),e}function C(a){return"function"==typeof a?!0:a&&a.handleEvent}function D(a){this.impl=a}function E(b){return b instanceof O.ShadowRoot&&(b=a.getHostForShadowRoot(b)),M(b)}function F(a){J(a,mb)}function G(b,c,d,e){a.renderAllPending();for(var f=N(nb.call(c.impl,d,e)),h=g(f,this),i=0;i<h.length;i++){var j=h[i];if(j.currentTarget===b)return j.target}return null}function H(a){return function(){var b=X.get(this);return b&&b[a]&&b[a].value||null}}function I(a){var b=a.slice(2);return function(c){var d=X.get(this);d||(d=Object.create(null),X.set(this,d));var e=d[a];if(e&&this.removeEventListener(b,e.wrapped,!1),"function"==typeof c){var f=function(b){var d=c.call(this,b);d===!1?b.preventDefault():"onbeforeunload"===a&&"string"==typeof d&&(b.returnValue=d)};this.addEventListener(b,f,!1),d[a]={value:c,wrapped:f}}}}var J=a.forwardMethodsToWrapper,K=a.mixin,L=a.registerWrapper,M=a.unwrap,N=a.wrap,O=a.wrappers;new WeakMap;var P=new WeakMap,Q=new WeakMap,R=new WeakMap,S=new WeakMap,T=new WeakMap,U=new WeakMap,V=new WeakMap,W=new WeakMap,X=new WeakMap,Y=new WeakMap,Z=0,$=window.MutationEvent;w.prototype={equals:function(a){return this.handler===a.handler&&this.type===a.type&&this.capture===a.capture},get removed(){return null===this.handler},remove:function(){this.handler=null}};var _=window.Event;x.prototype={get target(){return R.get(this)},get currentTarget(){return S.get(this)},get eventPhase(){return U.get(this)},get path(){var a=new O.NodeList,b=Y.get(this);if(b){for(var c=0,d=b.length-1,e=l(S.get(this)),f=0;d>=f;f++){var g=b[f].currentTarget,h=l(g);n(e,h)&&(f!==d||g instanceof O.Node)&&(a[c++]=g)}a.length=c}return a},stopPropagation:function(){V.set(this,!0)},stopImmediatePropagation:function(){V.set(this,!0),W.set(this,!0)}},L(_,x,document.createEvent("Event"));var ab=z("UIEvent",x),bb=z("CustomEvent",x),cb={get relatedTarget(){return T.get(this)||N(M(this).relatedTarget)}},db=K({initMouseEvent:A("initMouseEvent",14)},cb),eb=K({initFocusEvent:A("initFocusEvent",5)},cb),fb=z("MouseEvent",ab,db),gb=z("FocusEvent",ab,eb),hb=z("MutationEvent",x,{initMutationEvent:A("initMutationEvent",3),get relatedNode(){return N(this.impl.relatedNode)}}),ib=Object.create(null),jb=function(){try{new window.MouseEvent("click")}catch(a){return!1}return!0}();if(!jb){var kb=function(a,b,c){if(c){var d=ib[c];b=K(K({},d),b)}ib[a]=b};kb("Event",{bubbles:!1,cancelable:!1}),kb("CustomEvent",{detail:null},"Event"),kb("UIEvent",{view:null,detail:0},"Event"),kb("MouseEvent",{screenX:0,screenY:0,clientX:0,clientY:0,ctrlKey:!1,altKey:!1,shiftKey:!1,metaKey:!1,button:0,relatedTarget:null},"UIEvent"),kb("FocusEvent",{relatedTarget:null},"UIEvent")}var lb=window.EventTarget,mb=["addEventListener","removeEventListener","dispatchEvent"];[Node,Window].forEach(function(a){var b=a.prototype;mb.forEach(function(a){Object.defineProperty(b,a+"_",{value:b[a]})})}),D.prototype={addEventListener:function(a,b,c){if(C(b)){var d=new w(a,b,c),e=P.get(this);if(e){for(var f=0;f<e.length;f++)if(d.equals(e[f]))return}else e=[],P.set(this,e);e.push(d);var g=E(this);g.addEventListener_(a,q,!0)}},removeEventListener:function(a,b,c){c=Boolean(c);var d=P.get(this);if(d){for(var e=0,f=!1,g=0;g<d.length;g++)d[g].type===a&&d[g].capture===c&&(e++,d[g].handler===b&&(f=!0,d[g].remove()));if(f&&1===e){var h=E(this);h.removeEventListener_(a,q,!0)}}},dispatchEvent:function(a){var b=E(this),c=M(a);return Q.set(c,!1),b.dispatchEvent_(c)}},lb&&L(lb,D);var nb=document.elementFromPoint;a.adjustRelatedTarget=i,a.elementFromPoint=G,a.getEventHandlerGetter=H,a.getEventHandlerSetter=I,a.muteMutationEvents=o,a.unmuteMutationEvents=p,a.wrapEventTargetMethods=F,a.wrappers.CustomEvent=bb,a.wrappers.Event=x,a.wrappers.EventTarget=D,a.wrappers.FocusEvent=gb,a.wrappers.MouseEvent=fb,a.wrappers.MutationEvent=hb,a.wrappers.UIEvent=ab}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a,b){Object.defineProperty(a,b,{enumerable:!1})}function c(){this.length=0,b(this,"length")}function d(a){if(null==a)return a;for(var b=new c,d=0,e=a.length;e>d;d++)b[d]=f(a[d]);return b.length=e,b}function e(a,b){a.prototype[b]=function(){return d(this.impl[b].apply(this.impl,arguments))}}var f=a.wrap;c.prototype={item:function(a){return this[a]}},b(c.prototype,"item"),a.wrappers.NodeList=c,a.addWrapNodeListMethod=e,a.wrapNodeList=d}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){o(a instanceof k)}function c(a,b,c,d){if(!(a instanceof DocumentFragment))return a.parentNode&&a.parentNode.removeChild(a),a.parentNode_=b,a.previousSibling_=c,a.nextSibling_=d,c&&(c.nextSibling_=a),d&&(d.previousSibling_=a),[a];for(var e,f=[];e=a.firstChild;)a.removeChild(e),f.push(e),e.parentNode_=b;for(var g=0;g<f.length;g++)f[g].previousSibling_=f[g-1]||c,f[g].nextSibling_=f[g+1]||d;return c&&(c.nextSibling_=f[0]),d&&(d.previousSibling_=f[f.length-1]),f}function d(a){if(a instanceof DocumentFragment){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}return[a]}function e(a){for(var b=0;b<a.length;b++)a[b].nodeWasAdded_()}function f(a,b){var c=a.nodeType===k.DOCUMENT_NODE?a:a.ownerDocument;c!==b.ownerDocument&&c.adoptNode(b)}function g(b,c){if(c.length){var d=b.ownerDocument;if(d!==c[0].ownerDocument)for(var e=0;e<c.length;e++)a.adoptNodeNoRemove(c[e],d)}}function h(a,b){g(a,b);var c=b.length;if(1===c)return r(b[0]);for(var d=r(a.ownerDocument.createDocumentFragment()),e=0;c>e;e++)d.appendChild(r(b[e]));return d}function i(a){if(a.invalidateShadowRenderer()){for(var b=a.firstChild;b;){o(b.parentNode===a);var c=b.nextSibling,d=r(b),e=d.parentNode;e&&y.call(e,d),b.previousSibling_=b.nextSibling_=b.parentNode_=null,b=c}a.firstChild_=a.lastChild_=null}else for(var c,f=r(a),g=f.firstChild;g;)c=g.nextSibling,y.call(f,g),g=c}function j(a){var b=a.parentNode;return b&&b.invalidateShadowRenderer()}function k(a){o(a instanceof u),l.call(this,a),this.parentNode_=void 0,this.firstChild_=void 0,this.lastChild_=void 0,this.nextSibling_=void 0,this.previousSibling_=void 0}var l=a.wrappers.EventTarget,m=a.wrappers.NodeList,n=a.defineWrapGetter,o=a.assert,p=a.mixin,q=a.registerWrapper,r=a.unwrap,s=a.wrap,t=a.wrapIfNeeded,u=window.Node,v=u.prototype.appendChild,w=u.prototype.insertBefore,x=u.prototype.replaceChild,y=u.prototype.removeChild,z=u.prototype.compareDocumentPosition;k.prototype=Object.create(l.prototype),p(k.prototype,{appendChild:function(a){b(a);var g;if(this.invalidateShadowRenderer()||j(a)){var i=this.lastChild,k=null;g=c(a,this,i,k),this.lastChild_=g[g.length-1],i||(this.firstChild_=g[0]),v.call(this.impl,h(this,g))}else g=d(a),f(this,a),v.call(this.impl,r(a));return e(g),a},insertBefore:function(a,i){if(!i)return this.appendChild(a);b(a),b(i),o(i.parentNode===this);var k;if(this.invalidateShadowRenderer()||j(a)){var l=i.previousSibling,m=i;k=c(a,this,l,m),this.firstChild===i&&(this.firstChild_=k[0]);var n=r(i),p=n.parentNode;p?w.call(p,h(this,k),n):g(this,k)}else k=d(a),f(this,a),w.call(this.impl,r(a),r(i));return e(k),a},removeChild:function(a){if(b(a),a.parentNode!==this)throw new Error("NotFoundError");var c=r(a);if(this.invalidateShadowRenderer()){var d=this.firstChild,e=this.lastChild,f=a.nextSibling,g=a.previousSibling,h=c.parentNode;h&&y.call(h,c),d===a&&(this.firstChild_=f),e===a&&(this.lastChild_=g),g&&(g.nextSibling_=f),f&&(f.previousSibling_=g),a.previousSibling_=a.nextSibling_=a.parentNode_=void 0}else y.call(this.impl,c);return a},replaceChild:function(a,g){if(b(a),b(g),g.parentNode!==this)throw new Error("NotFoundError");var i,k=r(g);if(this.invalidateShadowRenderer()||j(a)){var l=g.previousSibling,m=g.nextSibling;m===a&&(m=a.nextSibling),i=c(a,this,l,m),this.firstChild===g&&(this.firstChild_=i[0]),this.lastChild===g&&(this.lastChild_=i[i.length-1]),g.previousSibling_=g.nextSibling_=g.parentNode_=void 0,k.parentNode&&x.call(k.parentNode,h(this,i),k)}else i=d(a),f(this,a),x.call(this.impl,r(a),k);return e(i),g},nodeWasAdded_:function(){for(var a=this.firstChild;a;a=a.nextSibling)a.nodeWasAdded_()},hasChildNodes:function(){return null!==this.firstChild},get parentNode(){return void 0!==this.parentNode_?this.parentNode_:s(this.impl.parentNode)},get firstChild(){return void 0!==this.firstChild_?this.firstChild_:s(this.impl.firstChild)},get lastChild(){return void 0!==this.lastChild_?this.lastChild_:s(this.impl.lastChild)},get nextSibling(){return void 0!==this.nextSibling_?this.nextSibling_:s(this.impl.nextSibling)},get previousSibling(){return void 0!==this.previousSibling_?this.previousSibling_:s(this.impl.previousSibling)},get parentElement(){for(var a=this.parentNode;a&&a.nodeType!==k.ELEMENT_NODE;)a=a.parentNode;return a},get textContent(){for(var a="",b=this.firstChild;b;b=b.nextSibling)a+=b.textContent;return a},set textContent(a){if(this.invalidateShadowRenderer()){if(i(this),""!==a){var b=this.impl.ownerDocument.createTextNode(a);this.appendChild(b)}}else this.impl.textContent=a},get childNodes(){for(var a=new m,b=0,c=this.firstChild;c;c=c.nextSibling)a[b++]=c;return a.length=b,a},cloneNode:function(a){if(!this.invalidateShadowRenderer())return s(this.impl.cloneNode(a));var b=s(this.impl.cloneNode(!1));if(a)for(var c=this.firstChild;c;c=c.nextSibling)b.appendChild(c.cloneNode(!0));return b},contains:function(a){if(!a)return!1;if(a=t(a),a===this)return!0;var b=a.parentNode;return b?this.contains(b):!1},compareDocumentPosition:function(a){return z.call(this.impl,r(a))}}),n(k,"ownerDocument"),q(u,k,document.createDocumentFragment()),delete k.prototype.querySelector,delete k.prototype.querySelectorAll,k.prototype=p(Object.create(l.prototype),k.prototype),a.wrappers.Node=k}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a,c){for(var d,e=a.firstElementChild;e;){if(e.matches(c))return e;if(d=b(e,c))return d;
-e=e.nextElementSibling}return null}function c(a,b,d){for(var e=a.firstElementChild;e;)e.matches(b)&&(d[d.length++]=e),c(e,b,d),e=e.nextElementSibling;return d}var d={querySelector:function(a){return b(this,a)},querySelectorAll:function(a){return c(this,a,new NodeList)}},e={getElementsByTagName:function(a){return this.querySelectorAll(a)},getElementsByClassName:function(a){return this.querySelectorAll("."+a)},getElementsByTagNameNS:function(a,b){if("*"===a)return this.getElementsByTagName(b);for(var c=new NodeList,d=this.getElementsByTagName(b),e=0,f=0;e<d.length;e++)d[e].namespaceURI===a&&(c[f++]=d[e]);return c.length=f,c}};a.GetElementsByInterface=e,a.SelectorsInterface=d}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.nextSibling;return a}function c(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.previousSibling;return a}var d=a.wrappers.NodeList,e={get firstElementChild(){return b(this.firstChild)},get lastElementChild(){return c(this.lastChild)},get childElementCount(){for(var a=0,b=this.firstElementChild;b;b=b.nextElementSibling)a++;return a},get children(){for(var a=new d,b=0,c=this.firstElementChild;c;c=c.nextElementSibling)a[b++]=c;return a.length=b,a}},f={get nextElementSibling(){return b(this.nextSibling)},get previousElementSibling(){return c(this.previousSibling)}};a.ChildNodeInterface=f,a.ParentNodeInterface=e}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}var c=a.ChildNodeInterface,d=a.wrappers.Node,e=a.mixin,f=a.registerWrapper,g=window.CharacterData;b.prototype=Object.create(d.prototype),e(b.prototype,{get textContent(){return this.data},set textContent(a){this.data=a}}),e(b.prototype,c),f(g,b,document.createTextNode("")),a.wrappers.CharacterData=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(b,c){var d=b.parentNode;if(d&&d.shadowRoot){var e=a.getRendererForHost(d);e.dependsOnAttribute(c)&&e.invalidate()}}function c(a){g.call(this,a)}function d(a,c,d){var e=d||c;Object.defineProperty(a,c,{get:function(){return this.impl[c]},set:function(a){this.impl[c]=a,b(this,e)},configurable:!0,enumerable:!0})}var e=a.ChildNodeInterface,f=a.GetElementsByInterface,g=a.wrappers.Node,h=a.ParentNodeInterface,i=a.SelectorsInterface;a.addWrapNodeListMethod;var j=a.mixin,k=a.oneOf,l=a.registerWrapper,m=a.wrappers,n=window.Element,o=k(n.prototype,["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"]),p=n.prototype[o];c.prototype=Object.create(g.prototype),j(c.prototype,{createShadowRoot:function(){var b=new m.ShadowRoot(this);this.impl.polymerShadowRoot_=b;var c=a.getRendererForHost(this);return c.invalidate(),b},get shadowRoot(){return this.impl.polymerShadowRoot_||null},setAttribute:function(a,c){this.impl.setAttribute(a,c),b(this,a)},removeAttribute:function(a){this.impl.removeAttribute(a),b(this,a)},matches:function(a){return p.call(this.impl,a)}}),c.prototype[o]=function(a){return this.matches(a)},n.prototype.webkitCreateShadowRoot&&(c.prototype.webkitCreateShadowRoot=c.prototype.createShadowRoot),d(c.prototype,"id"),d(c.prototype,"className","class"),j(c.prototype,e),j(c.prototype,f),j(c.prototype,h),j(c.prototype,i),l(n,c),a.matchesName=o,a.wrappers.Element=c}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a){case"&":return"&amp;";case"<":return"&lt;";case'"':return"&quot;"}}function c(a){return a.replace(r,b)}function d(a){switch(a.nodeType){case Node.ELEMENT_NODE:for(var b,d=a.tagName.toLowerCase(),f="<"+d,g=a.attributes,h=0;b=g[h];h++)f+=" "+b.name+'="'+c(b.value)+'"';return f+=">",s[d]?f:f+e(a)+"</"+d+">";case Node.TEXT_NODE:return c(a.nodeValue);case Node.COMMENT_NODE:return"<!--"+c(a.nodeValue)+"-->";default:throw console.error(a),new Error("not implemented")}}function e(a){for(var b="",c=a.firstChild;c;c=c.nextSibling)b+=d(c);return b}function f(a,b,c){var d=c||"div";a.textContent="";var e=p(a.ownerDocument.createElement(d));e.innerHTML=b;for(var f;f=e.firstChild;)a.appendChild(q(f))}function g(a){l.call(this,a)}function h(b){return function(){return a.renderAllPending(),this.impl[b]}}function i(a){m(g,a,h(a))}function j(b){Object.defineProperty(g.prototype,b,{get:h(b),set:function(c){a.renderAllPending(),this.impl[b]=c},configurable:!0,enumerable:!0})}function k(b){Object.defineProperty(g.prototype,b,{value:function(){return a.renderAllPending(),this.impl[b].apply(this.impl,arguments)},configurable:!0,enumerable:!0})}var l=a.wrappers.Element,m=a.defineGetter,n=a.mixin,o=a.registerWrapper,p=a.unwrap,q=a.wrap,r=/&|<|"/g,s={area:!0,base:!0,br:!0,col:!0,command:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0},t=window.HTMLElement;g.prototype=Object.create(l.prototype),n(g.prototype,{get innerHTML(){return e(this)},set innerHTML(a){this.invalidateShadowRenderer()?f(this,a,this.tagName):this.impl.innerHTML=a},get outerHTML(){return d(this)},set outerHTML(a){var b=this.parentNode;b&&(b.invalidateShadowRenderer(),this.impl.outerHTML=a)}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(i),["scrollLeft","scrollTop"].forEach(j),["getBoundingClientRect","getClientRects","scrollIntoView"].forEach(k),o(t,g,document.createElement("b")),a.wrappers.HTMLElement=g,a.getInnerHTML=e,a.setInnerHTML=f}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrap,g=window.HTMLCanvasElement;b.prototype=Object.create(c.prototype),d(b.prototype,{getContext:function(){var a=this.impl.getContext.apply(this.impl,arguments);return a&&f(a)}}),e(g,b),a.wrappers.HTMLCanvasElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLContentElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get select(){return this.getAttribute("select")},set select(a){this.setAttribute("select",a)},setAttribute:function(a,b){c.prototype.setAttribute.call(this,a,b),"select"===String(a).toLowerCase()&&this.invalidateShadowRenderer(!0)}}),f&&e(f,b),a.wrappers.HTMLContentElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLShadowElement;b.prototype=Object.create(c.prototype),d(b.prototype,{}),f&&e(f,b),a.wrappers.HTMLShadowElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){if(!a.defaultView)return a;var b=o.get(a);if(!b){for(b=a.implementation.createHTMLDocument("");b.lastChild;)b.removeChild(b.lastChild);o.set(a,b)}return b}function c(a){var c,d=b(a.ownerDocument),e=l(d.createDocumentFragment());for(h();c=a.firstChild;)e.appendChild(c);return k(),e}function d(a){if(e.call(this,a),!p){var b=c(a);n.set(this,m(b))}}var e=a.wrappers.HTMLElement,f=a.getInnerHTML,g=a.mixin,h=a.muteMutationEvents,i=a.registerWrapper,j=a.setInnerHTML,k=a.unmuteMutationEvents,l=a.unwrap,m=a.wrap,n=new WeakMap,o=new WeakMap,p=window.HTMLTemplateElement;d.prototype=Object.create(e.prototype),g(d.prototype,{get content(){return p?m(this.impl.content):n.get(this)},get innerHTML(){return f(this.content)},set innerHTML(a){j(this.content,a)}}),p&&i(p,d),a.wrappers.HTMLTemplateElement=d}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a.localName){case"content":return new c(a);case"shadow":return new e(a);case"template":return new f(a)}d.call(this,a)}var c=a.wrappers.HTMLContentElement,d=a.wrappers.HTMLElement,e=a.wrappers.HTMLShadowElement,f=a.wrappers.HTMLTemplateElement;a.mixin;var g=a.registerWrapper,h=window.HTMLUnknownElement;b.prototype=Object.create(d.prototype),g(h,b),a.wrappers.HTMLUnknownElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.wrap,g=window.CanvasRenderingContext2D;c(b.prototype,{get canvas(){return f(this.impl.canvas)},drawImage:function(){arguments[0]=e(arguments[0]),this.impl.drawImage.apply(this.impl,arguments)},createPattern:function(){return arguments[0]=e(arguments[0]),this.impl.createPattern.apply(this.impl,arguments)}}),d(g,b),a.wrappers.CanvasRenderingContext2D=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.wrap,g=window.WebGLRenderingContext;g&&(c(b.prototype,{get canvas(){return f(this.impl.canvas)},texImage2D:function(){arguments[5]=e(arguments[5]),this.impl.texImage2D.apply(this.impl,arguments)},texSubImage2D:function(){arguments[6]=e(arguments[6]),this.impl.texSubImage2D.apply(this.impl,arguments)}}),d(g,b),a.wrappers.WebGLRenderingContext=b)}(this.ShadowDOMPolyfill),function(a){"use strict";var b=a.GetElementsByInterface,c=a.ParentNodeInterface,d=a.SelectorsInterface,e=a.mixin,f=a.registerObject,g=f(document.createDocumentFragment());e(g.prototype,c),e(g.prototype,d),e(g.prototype,b);var h=f(document.createTextNode("")),i=f(document.createComment(""));a.wrappers.Comment=i,a.wrappers.DocumentFragment=g,a.wrappers.Text=h}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=i(a.impl.ownerDocument.createDocumentFragment());c.call(this,b),g(b,this);var d=a.shadowRoot;k.set(this,d),j.set(this,a)}var c=a.wrappers.DocumentFragment,d=a.elementFromPoint,e=a.getInnerHTML,f=a.mixin,g=a.rewrap,h=a.setInnerHTML,i=a.unwrap,j=new WeakMap,k=new WeakMap;b.prototype=Object.create(c.prototype),f(b.prototype,{get innerHTML(){return e(this)},set innerHTML(a){h(this,a),this.invalidateShadowRenderer()},get olderShadowRoot(){return k.get(this)||null},invalidateShadowRenderer:function(){return j.get(this).invalidateShadowRenderer()},elementFromPoint:function(a,b){return d(this,this.ownerDocument,a,b)},getElementById:function(a){return this.querySelector("#"+a)}}),a.wrappers.ShadowRoot=b,a.getHostForShadowRoot=function(a){return j.get(a)}}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){a.previousSibling_=a.previousSibling,a.nextSibling_=a.nextSibling,a.parentNode_=a.parentNode}function c(a,c,e){var f=G(a),g=G(c),h=e?G(e):null;if(d(c),b(c),e)a.firstChild===e&&(a.firstChild_=e),e.previousSibling_=e.previousSibling;else{a.lastChild_=a.lastChild,a.lastChild===a.firstChild&&(a.firstChild_=a.firstChild);var i=H(f.lastChild);i&&(i.nextSibling_=i.nextSibling)}f.insertBefore(g,h)}function d(a){var c=G(a),d=c.parentNode;if(d){var e=H(d);b(a),a.previousSibling&&(a.previousSibling.nextSibling_=a),a.nextSibling&&(a.nextSibling.previousSibling_=a),e.lastChild===a&&(e.lastChild_=a),e.firstChild===a&&(e.firstChild_=a),d.removeChild(c)}}function e(a,b){g(b).push(a),x(a,b);var c=J.get(a);c||J.set(a,c=[]),c.push(b)}function f(a){I.set(a,[])}function g(a){return I.get(a)}function h(a){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}function i(a,b,c){for(var d=a.firstChild;d;d=d.nextSibling)if(b(d)){if(c(d)===!1)return}else i(d,b,c)}function j(a,b){var c=b.getAttribute("select");if(!c)return!0;if(c=c.trim(),!c)return!0;if(!(a instanceof y))return!1;if(!M.test(c))return!1;if(":"===c[0]&&!N.test(c))return!1;try{return a.matches(c)}catch(d){return!1}}function k(){for(var a=0;a<P.length;a++)P[a].render();P=[]}function l(){F=null,k()}function m(a){var b=L.get(a);return b||(b=new q(a),L.set(a,b)),b}function n(a){for(;a;a=a.parentNode)if(a instanceof C)return a;return null}function o(a){return m(D(a))}function p(a){this.skip=!1,this.node=a,this.childNodes=[]}function q(a){this.host=a,this.dirty=!1,this.invalidateAttributes(),this.associateNode(a)}function r(a){return a instanceof z}function s(a){return a instanceof z}function t(a){return a instanceof A}function u(a){return a instanceof A}function v(a){return a.shadowRoot}function w(a){for(var b=[],c=a.shadowRoot;c;c=c.olderShadowRoot)b.push(c);return b}function x(a,b){K.set(a,b)}var y=a.wrappers.Element,z=a.wrappers.HTMLContentElement,A=a.wrappers.HTMLShadowElement,B=a.wrappers.Node,C=a.wrappers.ShadowRoot;a.assert;var D=a.getHostForShadowRoot;a.mixin,a.muteMutationEvents;var E=a.oneOf;a.unmuteMutationEvents;var F,G=a.unwrap,H=a.wrap,I=new WeakMap,J=new WeakMap,K=new WeakMap,L=new WeakMap,M=/^[*.:#[a-zA-Z_|]/,N=new RegExp("^:("+["link","visited","target","enabled","disabled","checked","indeterminate","nth-child","nth-last-child","nth-of-type","nth-last-of-type","first-child","last-child","first-of-type","last-of-type","only-of-type"].join("|")+")"),O=E(window,["requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","setTimeout"]),P=[],Q=new ArraySplice;Q.equals=function(a,b){return G(a.node)===b},p.prototype={append:function(a){var b=new p(a);return this.childNodes.push(b),b},sync:function(a){if(!this.skip){for(var b=this.node,e=this.childNodes,f=h(G(b)),g=a||new WeakMap,i=Q.calculateSplices(e,f),j=0,k=0,l=0,m=0;m<i.length;m++){for(var n=i[m];l<n.index;l++)k++,e[j++].sync(g);for(var o=n.removed.length,p=0;o>p;p++){var q=H(f[k++]);g.get(q)||d(q)}for(var r=n.addedCount,s=f[k]&&H(f[k]),p=0;r>p;p++){var t=e[j++],u=t.node;c(b,u,s),g.set(u,!0),t.sync(g)}l+=r}for(var m=l;m<e.length;m++)e[m].sync(g)}}},q.prototype={render:function(a){if(this.dirty){this.invalidateAttributes(),this.treeComposition();var b=this.host,c=b.shadowRoot;this.associateNode(b);for(var d=!e,e=a||new p(b),f=c.firstChild;f;f=f.nextSibling)this.renderNode(c,e,f,!1);d&&e.sync(),this.dirty=!1}},invalidate:function(){if(!this.dirty){if(this.dirty=!0,P.push(this),F)return;F=window[O](l,0)}},renderNode:function(a,b,c,d){if(v(c)){b=b.append(c);var e=m(c);e.dirty=!0,e.render(b)}else r(c)?this.renderInsertionPoint(a,b,c,d):t(c)?this.renderShadowInsertionPoint(a,b,c):this.renderAsAnyDomTree(a,b,c,d)},renderAsAnyDomTree:function(a,b,c,d){if(b=b.append(c),v(c)){var e=m(c);b.skip=!e.dirty,e.render(b)}else for(var f=c.firstChild;f;f=f.nextSibling)this.renderNode(a,b,f,d)},renderInsertionPoint:function(a,b,c,d){var e=g(c);if(e.length){this.associateNode(c);for(var f=0;f<e.length;f++){var h=e[f];r(h)&&d?this.renderInsertionPoint(a,b,h,d):this.renderAsAnyDomTree(a,b,h,d)}}else this.renderFallbackContent(a,b,c);this.associateNode(c.parentNode)},renderShadowInsertionPoint:function(a,b,c){var d=a.olderShadowRoot;if(d){x(d,c),this.associateNode(c.parentNode);for(var e=d.firstChild;e;e=e.nextSibling)this.renderNode(d,b,e,!0)}else this.renderFallbackContent(a,b,c)},renderFallbackContent:function(a,b,c){this.associateNode(c),this.associateNode(c.parentNode);for(var d=c.firstChild;d;d=d.nextSibling)this.renderAsAnyDomTree(a,b,d,!1)},invalidateAttributes:function(){this.attributes=Object.create(null)},updateDependentAttributes:function(a){if(a){var b=this.attributes;/\.\w+/.test(a)&&(b["class"]=!0),/#\w+/.test(a)&&(b.id=!0),a.replace(/\[\s*([^\s=\|~\]]+)/g,function(a,c){b[c]=!0})}},dependsOnAttribute:function(a){return this.attributes[a]},distribute:function(a,b){var c=this;i(a,s,function(a){f(a),c.updateDependentAttributes(a.getAttribute("select"));for(var d=0;d<b.length;d++){var g=b[d];void 0!==g&&j(g,a)&&(e(g,a),b[d]=void 0)}})},treeComposition:function(){for(var a=this.host,b=a.shadowRoot,c=[],d=a.firstChild;d;d=d.nextSibling)if(r(d)){var e=g(d);e&&e.length||(e=h(d)),c.push.apply(c,e)}else c.push(d);for(var f,j;b;){if(f=void 0,i(b,u,function(a){return f=a,!1}),j=f,this.distribute(b,c),j){var k=b.olderShadowRoot;if(k){b=k,x(b,j);continue}break}break}},associateNode:function(a){a.impl.polymerShadowRenderer_=this}},B.prototype.invalidateShadowRenderer=function(){var a=this.impl.polymerShadowRenderer_;return a?(a.invalidate(),!0):!1},z.prototype.getDistributedNodes=function(){return k(),g(this)},A.prototype.nodeWasAdded_=z.prototype.nodeWasAdded_=function(){this.invalidateShadowRenderer();var a,b=n(this);b&&(a=o(b)),this.impl.polymerShadowRenderer_=a,a&&a.invalidate()},a.eventParentsTable=J,a.getRendererForHost=m,a.getShadowTrees=w,a.insertionParentTable=K,a.renderAllPending=k,a.visual={insertBefore:c,remove:d}}(this.ShadowDOMPolyfill),function(a){"use strict";function b(b){if(window[b]){d(!a.wrappers[b]);var i=function(a){c.call(this,a)};i.prototype=Object.create(c.prototype),e(i.prototype,{get form(){return h(g(this).form)}}),f(window[b],i,document.createElement(b.slice(4,-7))),a.wrappers[b]=i}}var c=a.wrappers.HTMLElement,d=a.assert,e=a.mixin,f=a.registerWrapper,g=a.unwrap,h=a.wrap,i=["HTMLButtonElement","HTMLFieldSetElement","HTMLInputElement","HTMLKeygenElement","HTMLLabelElement","HTMLLegendElement","HTMLObjectElement","HTMLOptionElement","HTMLOutputElement","HTMLSelectElement","HTMLTextAreaElement"];i.forEach(b)}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){k.call(this,a)}function c(a){var c=document[a];b.prototype[a]=function(){return v(c.apply(this.impl,arguments))}}function d(a,b){y.call(b.impl,u(a)),e(a,b)}function e(a,b){a.shadowRoot&&b.adoptNode(a.shadowRoot),a instanceof n&&f(a,b);for(var c=a.firstChild;c;c=c.nextSibling)e(c,b)}function f(a,b){var c=a.olderShadowRoot;c&&b.adoptNode(c)}function g(a){this.impl=a}function h(a,b){var c=document.implementation[b];a.prototype[b]=function(){return v(c.apply(this.impl,arguments))}}function i(a,b){var c=document.implementation[b];a.prototype[b]=function(){return c.apply(this.impl,arguments)}}var j=a.GetElementsByInterface,k=a.wrappers.Node,l=a.ParentNodeInterface,m=a.SelectorsInterface,n=a.wrappers.ShadowRoot,o=a.defineWrapGetter,p=a.elementFromPoint,q=a.forwardMethodsToWrapper,r=a.matchesName,s=a.mixin,t=a.registerWrapper,u=a.unwrap,v=a.wrap,w=a.wrapEventTargetMethods;a.wrapNodeList;var x=new WeakMap;b.prototype=Object.create(k.prototype),o(b,"documentElement"),o(b,"body"),o(b,"head"),["createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","getElementById"].forEach(c);var y=document.adoptNode;if(s(b.prototype,{adoptNode:function(a){return a.parentNode&&a.parentNode.removeChild(a),d(a,this),a},elementFromPoint:function(a,b){return p(this,this,a,b)}}),document.register){var z=document.register;b.prototype.register=function(b,c){function d(a){return a?(this.impl=a,void 0):document.createElement(b)}var e=c.prototype;if(a.nativePrototypeTable.get(e))throw new Error("NotSupportedError");for(var f,g=Object.getPrototypeOf(e),h=[];g&&!(f=a.nativePrototypeTable.get(g));)h.push(g),g=Object.getPrototypeOf(g);if(!f)throw new Error("NotSupportedError");for(var i=Object.create(f),j=h.length-1;j>=0;j--)i=Object.create(i);return["createdCallback","enteredViewCallback","leftViewCallback","attributeChangedCallback"].forEach(function(a){var b=e[a];b&&(i[a]=function(){b.apply(v(this),arguments)})}),z.call(u(this),b,{prototype:i}),d.prototype=e,d.prototype.constructor=d,a.constructorTable.set(i,d),a.nativePrototypeTable.set(e,i),d},q([window.HTMLDocument||window.Document],["register"])}q([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild",r]),q([window.HTMLDocument||window.Document],["adoptNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","elementFromPoint","getElementById"]),s(b.prototype,j),s(b.prototype,l),s(b.prototype,m),s(b.prototype,{get implementation(){var a=x.get(this);return a?a:(a=new g(u(this).implementation),x.set(this,a),a)}}),t(window.Document,b,document.implementation.createHTMLDocument("")),window.HTMLDocument&&t(window.HTMLDocument,b),w([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]),h(g,"createDocumentType"),h(g,"createDocument"),h(g,"createHTMLDocument"),i(g,"hasFeature"),t(window.DOMImplementation,g),q([window.DOMImplementation],["createDocumentType","createDocument","createHTMLDocument","hasFeature"]),a.adoptNodeNoRemove=d,a.wrappers.DOMImplementation=g,a.wrappers.Document=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.EventTarget,d=a.mixin,e=a.registerWrapper,f=a.unwrap,g=a.unwrapIfNeeded,h=a.wrap,i=a.renderAllPending,j=window.Window;b.prototype=Object.create(c.prototype);var k=window.getComputedStyle;j.prototype.getComputedStyle=function(a,b){return i(),k.call(this||window,g(a),b)},["addEventListener","removeEventListener","dispatchEvent"].forEach(function(a){j.prototype[a]=function(){var b=h(this||window);return b[a].apply(b,arguments)}}),d(b.prototype,{getComputedStyle:function(a,b){return k.call(f(this),g(a),b)}}),e(j,b),a.wrappers.Window=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}function c(a){return new b(a)}function d(a){return a.map(c)}function e(a){var b=this;this.impl=new k(function(c){a.call(b,d(c),b)})}var f=a.defineGetter,g=a.defineWrapGetter,h=a.registerWrapper,i=a.unwrapIfNeeded,j=a.wrapNodeList;a.wrappers;var k=window.MutationObserver||window.WebKitMutationObserver;if(k){var l=window.MutationRecord;b.prototype={get addedNodes(){return j(this.impl.addedNodes)},get removedNodes(){return j(this.impl.removedNodes)}},["target","previousSibling","nextSibling"].forEach(function(a){g(b,a)}),["type","attributeName","attributeNamespace","oldValue"].forEach(function(a){f(b,a,function(){return this.impl[a]})}),l&&h(l,b),window.Node,e.prototype={observe:function(a,b){this.impl.observe(i(a),b)},disconnect:function(){this.impl.disconnect()},takeRecords:function(){return d(this.impl.takeRecords())}},a.wrappers.MutationObserver=e,a.wrappers.MutationRecord=b}}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.registerWrapper,d=a.unwrap,e=a.unwrapIfNeeded,f=a.wrap,g=window.Range;b.prototype={get startContainer(){return f(this.impl.startContainer)},get endContainer(){return f(this.impl.endContainer)},get commonAncestorContainer(){return f(this.impl.commonAncestorContainer)},setStart:function(a,b){this.impl.setStart(e(a),b)},setEnd:function(a,b){this.impl.setEnd(e(a),b)},setStartBefore:function(a){this.impl.setStartBefore(e(a))},setStartAfter:function(a){this.impl.setStartAfter(e(a))},setEndBefore:function(a){this.impl.setEndBefore(e(a))},setEndAfter:function(a){this.impl.setEndAfter(e(a))},selectNode:function(a){this.impl.selectNode(e(a))},selectNodeContents:function(a){this.impl.selectNodeContents(e(a))},compareBoundaryPoints:function(a,b){return this.impl.compareBoundaryPoints(a,d(b))},extractContents:function(){return f(this.impl.extractContents())},cloneContents:function(){return f(this.impl.cloneContents())},insertNode:function(a){this.impl.insertNode(e(a))},surroundContents:function(a){this.impl.surroundContents(e(a))},cloneRange:function(){return f(this.impl.cloneRange())},isPointInRange:function(a,b){return this.impl.isPointInRange(e(a),b)},comparePoint:function(a,b){return this.impl.comparePoint(e(a),b)},intersectsNode:function(a){return this.impl.intersectsNode(e(a))}},g.prototype.createContextualFragment&&(b.prototype.createContextualFragment=function(a){return f(this.impl.createContextualFragment(a))}),c(window.Range,b),a.wrappers.Range=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=c[a],d=window[b];if(d){var e=document.createElement(a),f=e.constructor;window[b]=f}}a.isWrapperFor;var c={a:"HTMLAnchorElement",applet:"HTMLAppletElement",area:"HTMLAreaElement",audio:"HTMLAudioElement",br:"HTMLBRElement",base:"HTMLBaseElement",body:"HTMLBodyElement",button:"HTMLButtonElement",canvas:"HTMLCanvasElement",dl:"HTMLDListElement",datalist:"HTMLDataListElement",dir:"HTMLDirectoryElement",div:"HTMLDivElement",embed:"HTMLEmbedElement",fieldset:"HTMLFieldSetElement",font:"HTMLFontElement",form:"HTMLFormElement",frame:"HTMLFrameElement",frameset:"HTMLFrameSetElement",hr:"HTMLHRElement",head:"HTMLHeadElement",h1:"HTMLHeadingElement",html:"HTMLHtmlElement",iframe:"HTMLIFrameElement",input:"HTMLInputElement",li:"HTMLLIElement",label:"HTMLLabelElement",legend:"HTMLLegendElement",link:"HTMLLinkElement",map:"HTMLMapElement",menu:"HTMLMenuElement",menuitem:"HTMLMenuItemElement",meta:"HTMLMetaElement",meter:"HTMLMeterElement",del:"HTMLModElement",ol:"HTMLOListElement",object:"HTMLObjectElement",optgroup:"HTMLOptGroupElement",option:"HTMLOptionElement",output:"HTMLOutputElement",p:"HTMLParagraphElement",param:"HTMLParamElement",pre:"HTMLPreElement",progress:"HTMLProgressElement",q:"HTMLQuoteElement",script:"HTMLScriptElement",select:"HTMLSelectElement",source:"HTMLSourceElement",span:"HTMLSpanElement",style:"HTMLStyleElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",table:"HTMLTableElement",tr:"HTMLTableRowElement",thead:"HTMLTableSectionElement",tbody:"HTMLTableSectionElement",textarea:"HTMLTextAreaElement",title:"HTMLTitleElement",ul:"HTMLUListElement",video:"HTMLVideoElement"};Object.keys(c).forEach(b),Object.getOwnPropertyNames(a.wrappers).forEach(function(b){window[b]=a.wrappers[b]}),a.knownElements=c}(this.ShadowDOMPolyfill),function(){var a=window.ShadowDOMPolyfill;a.wrap,Object.defineProperties(HTMLElement.prototype,{webkitShadowRoot:{get:function(){return this.shadowRoot}}}),HTMLElement.prototype.webkitCreateShadowRoot=HTMLElement.prototype.createShadowRoot,window.dartExperimentalFixupGetTag=function(b){function c(a){if(a instanceof d)return"NodeList";if(a instanceof e)return"ShadowRoot";if(window.MutationRecord&&a instanceof MutationRecord)return"MutationRecord";if(window.MutationObserver&&a instanceof MutationObserver)return"MutationObserver";if(a instanceof HTMLTemplateElement)return"HTMLTemplateElement";var c=f(a);if(a!==c){var g=a.constructor;if(g===c.constructor){var h=g._ShadowDOMPolyfill$cacheTag_;return h||(h=Object.prototype.toString.call(c),h=h.substring(8,h.length-1),g._ShadowDOMPolyfill$cacheTag_=h),h}a=c}return b(a)}var d=a.wrappers.NodeList,e=a.wrappers.ShadowRoot,f=a.unwrapIfNeeded;return c}}();var Platform={};!function(a){function b(a,b){var c="";return Array.prototype.forEach.call(a,function(a){c+=a.textContent+"\n\n"}),b||(c=c.replace(m,"")),c}function c(a){var b=document.createElement("style");b.textContent=a,document.head.appendChild(b);var c=b.sheet.cssRules;return b.parentNode.removeChild(b),c}function d(a){for(var b=0,c=[];b<a.length;b++)c.push(a[b].cssText);return c.join("\n\n")}function e(a){a&&f().appendChild(document.createTextNode(a))}function f(){return g||(g=document.createElement("style"),g.setAttribute("ShadowCSSShim","")),g}var g,h={strictStyling:!1,registry:{},shimStyling:function(a,b,c){if(a){var d=this.registerDefinition(a,b,c);this.strictStyling&&this.applyScopeToContent(a,b),this.shimPolyfillDirectives(d.rootStyles,b),this.applyShimming(d.scopeStyles,b)}},shimShadowDOMStyling:function(a,b){this.shimPolyfillDirectives(a,b),this.applyShimming(a,b)},registerDefinition:function(a,b,c){var d=this.registry[b]={root:a,name:b,extendsName:c},e=a.querySelectorAll("style");e=e?Array.prototype.slice.call(e,0):[],d.rootStyles=e,d.scopeStyles=d.rootStyles;var f=this.registry[d.extendsName];return f&&(d.scopeStyles=d.scopeStyles.concat(f.scopeStyles)),d},applyScopeToContent:function(a,b){a&&(Array.prototype.forEach.call(a.querySelectorAll("*"),function(a){a.setAttribute(b,"")}),Array.prototype.forEach.call(a.querySelectorAll("template"),function(a){this.applyScopeToContent(a.content,b)},this))},shimPolyfillDirectives:function(a,b){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.convertPolyfillDirectives(a.textContent,b)},this)},convertPolyfillDirectives:function(a,b){for(var c,d,e="",f=0;c=n.exec(a);)e+=a.substring(f,c.index),d=c[1].slice(0,-2).replace(q,b),e+=this.scopeSelector(d,b)+"{",f=n.lastIndex;return e+=a.substring(f,a.length)},applyShimming:function(a,b){var c=this.shimAtHost(a,b);c+=this.shimScoping(a,b),e(c)},shimAtHost:function(a,b){return a?this.convertAtHostStyles(a,b):void 0},convertAtHostStyles:function(a,e){for(var f,g=b(a),h="",j=0;f=i.exec(g);)h+=g.substring(j,f.index),h+=this.scopeHostCss(f[1],e),j=i.lastIndex;h+=g.substring(j,g.length);var k=new RegExp("^"+e+p,"m"),g=d(this.findAtHostRules(c(h),k));return g},scopeHostCss:function(a,b){for(var c,d="";c=j.exec(a);)d+=this.scopeHostSelector(c[1],b)+" "+c[2]+"\n	";return d},scopeHostSelector:function(a,b){var c=[],d=a.split(","),e="[is="+b+"]";return d.forEach(function(a){a=a.trim(),a.match(k)?a=a.replace(k,b+"$1$3, "+e+"$1$3"):a.match(l)&&(a=b+a+", "+e+a),c.push(a)},this),c.join(", ")},findAtHostRules:function(a,b){return Array.prototype.filter.call(a,this.isHostRule.bind(this,b))},isHostRule:function(a,b){return b.selectorText&&b.selectorText.match(a)||b.cssRules&&this.findAtHostRules(b.cssRules,a).length||b.type==CSSRule.WEBKIT_KEYFRAMES_RULE},shimScoping:function(a,b){return a?this.convertScopedStyles(a,b):void 0},convertScopedStyles:function(a,d){Array.prototype.forEach.call(a,function(a){a.parentNode&&a.parentNode.removeChild(a)});var e=b(a).replace(i,"");e=this.convertPseudos(e);var f=c(e);return e=this.scopeRules(f,d)},convertPseudos:function(a){return a.replace(o," [pseudo=$1]")},scopeRules:function(a,b){var c="";return Array.prototype.forEach.call(a,function(a){a.selectorText&&a.style&&a.style.cssText?(c+=this.scopeSelector(a.selectorText,b,this.strictStyling)+" {\n	",c+=this.propertiesFromRule(a)+"\n}\n\n"):a.media?(c+="@media "+a.media.mediaText+" {\n",c+=this.scopeRules(a.cssRules,b),c+="\n}\n\n"):a.cssText&&(c+=a.cssText+"\n\n")},this),c},scopeSelector:function(a,b,c){var d=[],e=a.split(",");return e.forEach(function(a){a=a.trim(),this.selectorNeedsScoping(a,b)&&(a=c?this.applyStrictSelectorScope(a,b):this.applySimpleSelectorScope(a,b)),d.push(a)},this),d.join(", ")},selectorNeedsScoping:function(a,b){var c="("+b+"|\\[is="+b+"\\])",d=new RegExp("^"+c+p,"m");return!a.match(d)},applySimpleSelectorScope:function(a,b){return b+" "+a+", "+"[is="+b+"] "+a},applyStrictSelectorScope:function(a,b){var c=[" ",">","+","~"],d=a,e="["+b+"]";return c.forEach(function(a){var b=d.split(a);d=b.map(function(a){var b=a.trim();return b&&c.indexOf(b)<0&&b.indexOf(e)<0&&(a=b.replace(/([^:]*)(:*)(.*)/,"$1"+e+"$2$3")),a}).join(a)}),d},propertiesFromRule:function(a){var b=a.style.cssText;return a.style.content&&!a.style.content.match(/['"]+/)&&(b="content: '"+a.style.content+"';\n"+a.style.cssText.replace(/content:[^;]*;/g,"")),b}},i=/@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim,j=/([^{]*)({[\s\S]*?})/gim,k=/(.*)((?:\*)|(?:\:scope))(.*)/,l=/^[.\[:]/,m=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,n=/\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim,o=/::(x-[^\s{,(]*)/gim,p="([>\\s~+[.,{:][\\s\\S]*)?$",q=/@host/gim;if(window.ShadowDOMPolyfill){e("style { display: none !important; }\n");var r=document.querySelector("head");r.insertBefore(f(),r.childNodes[0])}a.ShadowCSS=h}(window.Platform),function(a){function b(a,b){if(window.ShadowDOMPolyfill){for(var h,i=this.convertPolyfillDirectives(a,b),j="",k=0;h=e.exec(i);)j+=i.substring(k,h.index),j+=this.scopeHostCss(h[1],b),k=e.lastIndex;j+=i.substring(k,i.length);var l=new RegExp("^"+b+g,"m"),m=d(this.findAtHostRules(c(j),l));i=i.replace(f,""),i=this.convertPseudos(i);var n=c(i),o=this.scopeRules(n,b);return m+o}}function c(a){var b=document.createElement("style");b.textContent=a,document.head.appendChild(b);var c=b.sheet.cssRules;return b.parentNode.removeChild(b),c}function d(a){for(var b=0,c=[];b<a.length;b++)c.push(a[b].cssText);return c.join("\n\n")}var e=/@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim,f=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,g="([>\\s~+[.,{:][\\s\\S]*)?$";a.ShadowCSS.shimShadowDOMStyling2=b}(window.Platform)}
\ No newline at end of file
+if(!HTMLElement.prototype.createShadowRoot||window.__forceShadowDomPolyfill){!function(){Element.prototype.webkitCreateShadowRoot&&(Element.prototype.webkitCreateShadowRoot=function(){return window.ShadowDOMPolyfill.wrapIfNeeded(this).createShadowRoot()})}(),function(a){"use strict";function b(){function a(a){"splice"===a[0].type&&"splice"===a[1].type&&(b=!0)}if("function"!=typeof Object.observe||"function"!=typeof Array.observe)return!1;var b=!1,c=[0];return Array.observe(c,a),c[1]=1,c.length=0,Object.deliverChangeRecords(a),b}function c(){if(a.document&&"securityPolicy"in a.document&&!a.document.securityPolicy.allowsEval)return!1;try{var b=new Function("","return true;");return b()}catch(c){return!1}}function d(a){return+a===a>>>0}function e(a){return+a}function f(a){return a===Object(a)}function g(a,b){return a===b?0!==a||1/a===1/b:H(a)&&H(b)?!0:a!==a&&b!==b}function h(a){return"string"!=typeof a?!1:(a=a.trim(),""==a?!0:"."==a[0]?!1:P.test(a))}function i(a,b){if(b!==Q)throw Error("Use Path.get to retrieve path objects");return""==a.trim()?this:d(a)?(this.push(a),this):(a.split(/\s*\.\s*/).filter(function(a){return a}).forEach(function(a){this.push(a)},this),G&&!F&&this.length&&(this.getValueFrom=this.compiledGetValueFromFn()),void 0)}function j(a){if(a instanceof i)return a;null==a&&(a=""),"string"!=typeof a&&(a=String(a));var b=R[a];if(b)return b;if(!h(a))return S;var b=new i(a,Q);return R[a]=b,b}function k(b){for(var c=0;T>c&&b.check();)b.report(),c++;a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=c)}function l(a){for(var b in a)return!1;return!0}function m(a){return l(a.added)&&l(a.removed)&&l(a.changed)}function n(a,b){var c={},d={},e={};for(var f in b){var g=a[f];(void 0===g||g!==b[f])&&(f in a?g!==b[f]&&(e[f]=g):d[f]=void 0)}for(var f in a)f in b||(c[f]=a[f]);return Array.isArray(a)&&a.length!==b.length&&(e.length=a.length),{added:c,removed:d,changed:e}}function o(a,b){var c=b||(Array.isArray(a)?[]:{});for(var d in a)c[d]=a[d];return Array.isArray(a)&&(c.length=a.length),c}function p(a,b,c,d){if(this.closed=!1,this.object=a,this.callback=b,this.target=c,this.token=d,this.reporting=!0,F){var e=this;this.boundInternalCallback=function(a){e.internalCallback(a)}}q(this)}function q(a){V&&(U.push(a),p._allObserversCount++)}function r(a,b,c,d){p.call(this,a,b,c,d),this.connect(),this.sync(!0)}function s(a,b,c,d){if(!Array.isArray(a))throw Error("Provided object is not an Array");r.call(this,a,b,c,d)}function t(a){this.arr=[],this.callback=a,this.isObserved=!0}function u(a,b,c,d,e,g,h){var b=b instanceof i?b:j(b);return b&&b.length&&f(a)?(p.call(this,a,c,d,e),this.valueFn=g,this.setValueFn=h,this.path=b,this.connect(),this.sync(!0),void 0):(this.value_=b?b.getValueFrom(a):void 0,this.value=g?g(this.value_):this.value_,this.closed=!0,void 0)}function v(a,b,c,d){p.call(this,void 0,a,b,c),this.valueFn=d,this.observed=[],this.values=[],this.value=void 0,this.oldValue=void 0,this.oldValues=void 0,this.changeFlags=void 0,this.started=!1}function w(a,b){if("function"==typeof Object.observe){var c=Object.getNotifier(a);return function(d,e){var f={object:a,type:d,name:b};2===arguments.length&&(f.oldValue=e),c.notify(f)}}}function x(a,b,c){for(var d={},e={},f=0;f<b.length;f++){var g=b[f];$[g.type]?(g.name in c||(c[g.name]=g.oldValue),"updated"!=g.type&&("new"!=g.type?g.name in d?(delete d[g.name],delete c[g.name]):e[g.name]=!0:g.name in e?delete e[g.name]:d[g.name]=!0)):(console.error("Unknown changeRecord type: "+g.type),console.error(g))}for(var h in d)d[h]=a[h];for(var h in e)e[h]=void 0;var i={};for(var h in c)if(!(h in d||h in e)){var j=a[h];c[h]!==j&&(i[h]=j)}return{added:d,removed:e,changed:i}}function y(a,b,c){return{index:a,removed:b,addedCount:c}}function z(){}function A(a,b,c,d,e,f){return db.calcSplices(a,b,c,d,e,f)}function B(a,b,c,d){return c>b||a>d?-1:b==c||d==a?0:c>a?d>b?b-c:d-c:b>d?d-a:b-a}function C(a,b,c,d){for(var e=y(b,c,d),f=!1,g=0,h=0;h<a.length;h++){var i=a[h];if(i.index+=g,!f){var j=B(e.index,e.index+e.removed.length,i.index,i.index+i.addedCount);if(j>=0){a.splice(h,1),h--,g-=i.addedCount-i.removed.length,e.addedCount+=i.addedCount-j;var k=e.removed.length+i.removed.length-j;if(e.addedCount||k){var c=i.removed;if(e.index<i.index){var l=e.removed.slice(0,i.index-e.index);Array.prototype.push.apply(l,c),c=l}if(e.index+e.removed.length>i.index+i.addedCount){var m=e.removed.slice(i.index+i.addedCount-e.index);Array.prototype.push.apply(c,m)}e.removed=c,i.index<e.index&&(e.index=i.index)}else f=!0}else if(e.index<i.index){f=!0,a.splice(h,0,e),h++;var n=e.addedCount-e.removed.length;i.index+=n,g+=n}}}f||a.push(e)}function D(a,b){for(var c=[],f=0;f<b.length;f++){var g=b[f];switch(g.type){case"splice":C(c,g.index,g.removed.slice(),g.addedCount);break;case"new":case"updated":case"deleted":if(!d(g.name))continue;var h=e(g.name);if(0>h)continue;C(c,h,[g.oldValue],1);break;default:console.error("Unexpected record type: "+JSON.stringify(g))}}return c}function E(a,b){var c=[];return D(a,b).forEach(function(b){return 1==b.addedCount&&1==b.removed.length?(b.removed[0]!==a[b.index]&&c.push(b),void 0):(c=c.concat(A(a,b.index,b.index+b.addedCount,b.removed,0,b.removed.length)),void 0)}),c}var F=b(),G=c(),H=a.Number.isNaN||function(b){return"number"==typeof b&&a.isNaN(b)},I="__proto__"in{}?function(a){return a}:function(a){var b=a.__proto__;if(!b)return a;var c=Object.create(b);return Object.getOwnPropertyNames(a).forEach(function(b){Object.defineProperty(c,b,Object.getOwnPropertyDescriptor(a,b))}),c},J="[$_a-zA-Z]",K="[$_a-zA-Z0-9]",L=J+"+"+K+"*",M="(?:[0-9]|[1-9]+[0-9]+)",N="(?:"+L+"|"+M+")",O="(?:"+N+")(?:\\s*\\.\\s*"+N+")*",P=new RegExp("^"+O+"$"),Q={},R={};i.get=j,i.prototype=I({__proto__:[],valid:!0,toString:function(){return this.join(".")},getValueFrom:function(a,b){for(var c=0;c<this.length;c++){if(null==a)return;b&&b.observe(a),a=a[this[c]]}return a},compiledGetValueFromFn:function(){var a=this.map(function(a){return d(a)?'["'+a+'"]':"."+a}),b="",c="obj";b+="if (obj != null";for(var e=0;e<this.length-1;e++)this[e],c+=a[e],b+=" &&\n     "+c+" != null";return b+=")\n",c+=a[e],b+="  return "+c+";\nelse\n  return undefined;",new Function("obj",b)},setValueFrom:function(a,b){if(!this.length)return!1;for(var c=0;c<this.length-1;c++){if(!f(a))return!1;a=a[this[c]]}return f(a)?(a[this[c]]=b,!0):!1}});var S=new i("",Q);S.valid=!1,S.getValueFrom=S.setValueFrom=function(){};var T=1e3;p.prototype={internalCallback:function(a){this.closed||this.reporting&&this.check(a)&&(this.report(),this.testingResults&&(this.testingResults.anyChanged=!0))},close:function(){this.closed||(this.object&&"function"==typeof this.object.close&&this.object.close(),this.disconnect(),this.object=void 0,this.closed=!0)},deliver:function(a){this.closed||(F?(this.testingResults=a,Object.deliverChangeRecords(this.boundInternalCallback),this.testingResults=void 0):k(this))},report:function(){this.reporting&&(this.sync(!1),this.callback&&(this.reportArgs.push(this.token),this.invokeCallback(this.reportArgs)),this.reportArgs=void 0)},invokeCallback:function(a){try{this.callback.apply(this.target,a)}catch(b){p._errorThrownDuringCallback=!0,console.error("Exception caught during observer callback: "+(b.stack||b))}},reset:function(){this.closed||(F&&(this.reporting=!1,Object.deliverChangeRecords(this.boundInternalCallback),this.reporting=!0),this.sync(!0))}};var U,V=!F||a.forceCollectObservers;p._allObserversCount=0,V&&(U=[]);var W=!1,X="function"==typeof Object.deliverAllChangeRecords;a.Platform=a.Platform||{},a.Platform.performMicrotaskCheckpoint=function(){if(!W){if(X)return Object.deliverAllChangeRecords(),void 0;if(V){W=!0;var b=0,c={};do{b++;var d=U;U=[],c.anyChanged=!1;for(var e=0;e<d.length;e++){var f=d[e];f.closed||(F?f.deliver(c):f.check()&&(c.anyChanged=!0,f.report()),U.push(f))}}while(T>b&&c.anyChanged);a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=b),p._allObserversCount=U.length,W=!1}}},V&&(a.Platform.clearObservers=function(){U=[]}),r.prototype=I({__proto__:p.prototype,connect:function(){F&&Object.observe(this.object,this.boundInternalCallback)},sync:function(){F||(this.oldObject=o(this.object))},check:function(a){var b,c;if(F){if(!a)return!1;c={},b=x(this.object,a,c)}else c=this.oldObject,b=n(this.object,this.oldObject);return m(b)?!1:(this.reportArgs=[b.added||{},b.removed||{},b.changed||{}],this.reportArgs.push(function(a){return c[a]}),!0)},disconnect:function(){F?this.object&&Object.unobserve(this.object,this.boundInternalCallback):this.oldObject=void 0}}),s.prototype=I({__proto__:r.prototype,connect:function(){F&&Array.observe(this.object,this.boundInternalCallback)},sync:function(){F||(this.oldObject=this.object.slice())},check:function(a){var b;if(F){if(!a)return!1;b=E(this.object,a)}else b=A(this.object,0,this.object.length,this.oldObject,0,this.oldObject.length);return b&&b.length?(this.reportArgs=[b],!0):!1}}),s.applySplices=function(a,b,c){c.forEach(function(c){for(var d=[c.index,c.removed.length],e=c.index;e<c.index+c.addedCount;)d.push(b[e]),e++;Array.prototype.splice.apply(a,d)})};var Y=Object.getPrototypeOf({}),Z=Object.getPrototypeOf([]);t.prototype={reset:function(){this.isObserved=!this.isObserved},observe:function(a){if(f(a)&&a!==Y&&a!==Z){var b=this.arr.indexOf(a);b>=0&&this.arr[b+1]===this.isObserved||(0>b&&(b=this.arr.length,this.arr[b]=a,Object.observe(a,this.callback)),this.arr[b+1]=this.isObserved,this.observe(Object.getPrototypeOf(a)))}},cleanup:function(){for(var a=0,b=0,c=this.isObserved;b<this.arr.length;){var d=this.arr[b];this.arr[b+1]==c?(b>a&&(this.arr[a]=d,this.arr[a+1]=c),a+=2):Object.unobserve(d,this.callback),b+=2}this.arr.length=a}},u.prototype=I({__proto__:p.prototype,connect:function(){F&&(this.observedSet=new t(this.boundInternalCallback))},disconnect:function(){this.value=void 0,this.value_=void 0,this.observedSet&&(this.observedSet.reset(),this.observedSet.cleanup(),this.observedSet=void 0)},check:function(){return this.observedSet&&this.observedSet.reset(),this.value_=this.path.getValueFrom(this.object,this.observedSet),this.observedSet&&this.observedSet.cleanup(),g(this.value_,this.oldValue_)?!1:(this.value=this.valueFn?this.valueFn(this.value_):this.value_,this.reportArgs=[this.value,this.oldValue],!0)},sync:function(a){a&&(this.observedSet&&this.observedSet.reset(),this.value_=this.path.getValueFrom(this.object,this.observedSet),this.value=this.valueFn?this.valueFn(this.value_):this.value_,this.observedSet&&this.observedSet.cleanup()),this.oldValue_=this.value_,this.oldValue=this.value},setValue:function(a){this.path&&("function"==typeof this.setValueFn&&(a=this.setValueFn(a)),this.path.setValueFrom(this.object,a))}}),v.prototype=I({__proto__:u.prototype,addPath:function(a,b){if(this.started)throw Error("Cannot add more paths once started.");var b=b instanceof i?b:j(b),c=b?b.getValueFrom(a):void 0;this.observed.push(a,b),this.values.push(c)},start:function(){this.connect(),this.sync(!0)},getValues:function(){this.observedSet&&this.observedSet.reset();for(var a=!1,b=0;b<this.observed.length;b+=2){var c=this.observed[b+1];if(c){var d=this.observed[b],e=c.getValueFrom(d,this.observedSet),f=this.values[b/2];if(!g(e,f)){if(!a&&!this.valueFn){this.oldValues=this.oldValues||[],this.changeFlags=this.changeFlags||[];for(var h=0;h<this.values.length;h++)this.oldValues[h]=this.values[h],this.changeFlags[h]=!1}this.valueFn||(this.changeFlags[b/2]=!0),this.values[b/2]=e,a=!0}}}return this.observedSet&&this.observedSet.cleanup(),a},check:function(){if(this.getValues()){if(this.valueFn){if(this.value=this.valueFn(this.values),g(this.value,this.oldValue))return!1;this.reportArgs=[this.value,this.oldValue]}else this.reportArgs=[this.values,this.oldValues,this.changeFlags,this.observed];return!0}},sync:function(a){a&&(this.getValues(),this.valueFn&&(this.value=this.valueFn(this.values))),this.valueFn&&(this.oldValue=this.value)},close:function(){if(this.observed){for(var a=0;a<this.observed.length;a+=2){var b=this.observed[a];b&&"function"==typeof b.close&&b.close()}this.observed=void 0,this.values=void 0}p.prototype.close.call(this)}});var $={"new":!0,updated:!0,deleted:!0};u.defineProperty=function(a,b,c){var d=c.object,e=j(c.path),f=w(a,b),g=new u(d,c.path,function(a,b){f&&f("updated",b)});return Object.defineProperty(a,b,{get:function(){return e.getValueFrom(d)},set:function(a){e.setValueFrom(d,a)},configurable:!0}),{close:function(){var c=e.getValueFrom(d);f&&g.deliver(),g.close(),Object.defineProperty(a,b,{value:c,writable:!0,configurable:!0})}}};var _=0,ab=1,bb=2,cb=3;z.prototype={calcEditDistances:function(a,b,c,d,e,f){for(var g=f-e+1,h=c-b+1,i=new Array(g),j=0;g>j;j++)i[j]=new Array(h),i[j][0]=j;for(var k=0;h>k;k++)i[0][k]=k;for(var j=1;g>j;j++)for(var k=1;h>k;k++)if(this.equals(a[b+k-1],d[e+j-1]))i[j][k]=i[j-1][k-1];else{var l=i[j-1][k]+1,m=i[j][k-1]+1;i[j][k]=m>l?l:m}return i},spliceOperationsFromEditDistances:function(a){for(var b=a.length-1,c=a[0].length-1,d=a[b][c],e=[];b>0||c>0;)if(0!=b)if(0!=c){var f,g=a[b-1][c-1],h=a[b-1][c],i=a[b][c-1];f=i>h?g>h?h:g:g>i?i:g,f==g?(g==d?e.push(_):(e.push(ab),d=g),b--,c--):f==h?(e.push(cb),b--,d=h):(e.push(bb),c--,d=i)}else e.push(cb),b--;else e.push(bb),c--;return e.reverse(),e},calcSplices:function(a,b,c,d,e,f){var g=0,h=0,i=Math.min(c-b,f-e);if(0==b&&0==e&&(g=this.sharedPrefix(a,d,i)),c==a.length&&f==d.length&&(h=this.sharedSuffix(a,d,i-g)),b+=g,e+=g,c-=h,f-=h,0==c-b&&0==f-e)return[];if(b==c){for(var j=y(b,[],0);f>e;)j.removed.push(d[e++]);return[j]}if(e==f)return[y(b,[],c-b)];for(var k=this.spliceOperationsFromEditDistances(this.calcEditDistances(a,b,c,d,e,f)),j=void 0,l=[],m=b,n=e,o=0;o<k.length;o++)switch(k[o]){case _:j&&(l.push(j),j=void 0),m++,n++;break;case ab:j||(j=y(m,[],0)),j.addedCount++,m++,j.removed.push(d[n]),n++;break;case bb:j||(j=y(m,[],0)),j.addedCount++,m++;break;case cb:j||(j=y(m,[],0)),j.removed.push(d[n]),n++}return j&&l.push(j),l},sharedPrefix:function(a,b,c){for(var d=0;c>d;d++)if(!this.equals(a[d],b[d]))return d;return c},sharedSuffix:function(a,b,c){for(var d=a.length,e=b.length,f=0;c>f&&this.equals(a[--d],b[--e]);)f++;return f},calculateSplices:function(a,b){return this.calcSplices(a,0,a.length,b,0,b.length)},equals:function(a,b){return a===b}};var db=new z;a.Observer=p,a.Observer.hasObjectObserve=F,a.ArrayObserver=s,a.ArrayObserver.calculateSplices=function(a,b){return db.calculateSplices(a,b)},a.ArraySplice=z,a.ObjectObserver=r,a.PathObserver=u,a.CompoundPathObserver=v,a.Path=i}("undefined"!=typeof global&&global?global:this),"undefined"==typeof WeakMap&&!function(){var a=Object.defineProperty,b=Date.now()%1e9,c=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")};c.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}},window.WeakMap=c}();var ShadowDOMPolyfill={};!function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a,b){return Object.getOwnPropertyNames(b).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))}),a}function d(a,b){return Object.getOwnPropertyNames(b).forEach(function(c){switch(c){case"arguments":case"caller":case"length":case"name":case"prototype":case"toString":return}Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))}),a}function e(a,b){for(var c=0;c<b.length;c++)if(b[c]in a)return b[c]}function f(a){var b=a.__proto__||Object.getPrototypeOf(a),c=C.get(b);if(c)return c;var d=f(b),e=r(d);return o(b,e,a),e}function g(a,b){m(a,b,!0)}function h(a,b){m(b,a,!1)}function i(a){return/^on[a-z]+$/.test(a)}function j(a){return F?new Function("return this.impl."+a):function(){return this.impl[a]}}function k(a){return F?new Function("v","this.impl."+a+" = v"):function(b){this.impl[a]=b}}function l(a){return F?new Function("return this.impl."+a+".apply(this.impl, arguments)"):function(){return this.impl[a].apply(this.impl,arguments)}}function m(b,c,d){Object.getOwnPropertyNames(b).forEach(function(e){if(!(e in c)){I&&b.__lookupGetter__(e);var f;try{f=Object.getOwnPropertyDescriptor(b,e)}catch(g){f=J}var h,m;if(d&&"function"==typeof f.value)return c[e]=l(e),void 0;var n=i(e);h=n?a.getEventHandlerGetter(e):j(e),(f.writable||f.set)&&(m=n?a.getEventHandlerSetter(e):k(e)),Object.defineProperty(c,e,{get:h,set:m,configurable:f.configurable,enumerable:f.enumerable})}})}function n(a,b,c){var e=a.prototype;o(e,b,c),d(b,a)}function o(a,c,d){var e=c.prototype;b(void 0===C.get(a)),C.set(a,c),D.set(e,a),g(a,e),d&&h(e,d)}function p(a,b){return C.get(b.prototype)===a}function q(a){var b=Object.getPrototypeOf(a),c=f(b),d=r(c);return o(b,d,a),d}function r(a){function b(b){a.call(this,b)}return b.prototype=Object.create(a.prototype),b.prototype.constructor=b,b}function s(a){return a instanceof E.EventTarget||a instanceof E.Event||a instanceof E.Range||a instanceof E.DOMImplementation||a instanceof E.CanvasRenderingContext2D||E.WebGLRenderingContext&&a instanceof E.WebGLRenderingContext}function t(a){return a instanceof M||a instanceof L||a instanceof N||a instanceof O||a instanceof K||a instanceof P||Q&&a instanceof Q}function u(a){return null===a?null:(b(t(a)),a.polymerWrapper_||(a.polymerWrapper_=new(f(a))(a)))}function v(a){return null===a?null:(b(s(a)),a.impl)}function w(a){return a&&s(a)?v(a):a}function x(a){return a&&!s(a)?u(a):a}function y(a,c){null!==c&&(b(t(a)),b(void 0===c||s(c)),a.polymerWrapper_=c)}function z(a,b,c){Object.defineProperty(a.prototype,b,{get:c,configurable:!0,enumerable:!0})}function A(a,b){z(a,b,function(){return u(this.impl[b])})}function B(a,b){a.forEach(function(a){b.forEach(function(b){a.prototype[b]=function(){var a=x(this);return a[b].apply(a,arguments)}})})}var C=new WeakMap,D=new WeakMap,E=Object.create(null),F=!("securityPolicy"in document)||document.securityPolicy.allowsEval;if(F)try{var G=new Function("","return true;");F=G()}catch(H){}Object.getOwnPropertyNames(window);var I=/Firefox/.test(navigator.userAgent),J={get:function(){},set:function(){},configurable:!0,enumerable:!0},K=window.DOMImplementation,L=window.Event,M=window.Node,N=window.Window,O=window.Range,P=window.CanvasRenderingContext2D,Q=window.WebGLRenderingContext;a.assert=b,a.constructorTable=C,a.defineGetter=z,a.defineWrapGetter=A,a.forwardMethodsToWrapper=B,a.isWrapperFor=p,a.mixin=c,a.nativePrototypeTable=D,a.oneOf=e,a.registerObject=q,a.registerWrapper=n,a.rewrap=y,a.unwrap=v,a.unwrapIfNeeded=w,a.wrap=u,a.wrapIfNeeded=x,a.wrappers=E}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a instanceof O.ShadowRoot}function c(a){var b=a.localName;return"content"===b||"shadow"===b}function d(a){return!!a.shadowRoot}function e(a){var b;return a.parentNode||(b=a.defaultView)&&N(b)||null}function f(f,g,h){if(h.length)return h.shift();if(b(f))return j(f)||a.getHostForShadowRoot(f);var i=a.eventParentsTable.get(f);if(i){for(var k=1;k<i.length;k++)h[k-1]=i[k];return i[0]}if(g&&c(f)){var l=f.parentNode;if(l&&d(l))for(var m=a.getShadowTrees(l),n=j(g),k=0;k<m.length;k++)if(m[k].contains(n))return n}return e(f)}function g(a){for(var d=[],e=a,g=[],i=[];e;){var j=null;if(c(e)){j=h(d);var k=d[d.length-1]||e;d.push(k)}else d.length||d.push(e);var l=d[d.length-1];g.push({target:l,currentTarget:e}),b(e)&&d.pop(),e=f(e,j,i)}return g}function h(a){for(var b=a.length-1;b>=0;b--)if(!c(a[b]))return a[b];return null}function i(d,e){for(var g=[];d;){for(var i=[],j=e,l=void 0;j;){var n=null;if(i.length){if(c(j)&&(n=h(i),k(l))){var o=i[i.length-1];i.push(o)}}else i.push(j);if(m(j,d))return i[i.length-1];b(j)&&i.pop(),l=j,j=f(j,n,g)}d=b(d)?a.getHostForShadowRoot(d):d.parentNode}}function j(b){return a.insertionParentTable.get(b)}function k(a){return j(a)}function l(a){for(var b;b=a.parentNode;)a=b;return a}function m(a,b){return l(a)===l(b)}function n(b,c){if(b===c)return!0;if(b instanceof O.ShadowRoot){var d=a.getHostForShadowRoot(b);return n(l(d),c)}return!1}function o(){Z++}function p(){Z--}function q(b){if(!Q.get(b)){if(Q.set(b,!0),b instanceof $){if(Z)return}else a.renderAllPending();var c=N(b.target),d=N(b);return r(d,c)}}function r(a,b){var c=g(b);return"load"===a.type&&2===c.length&&c[0].target instanceof O.Document&&c.shift(),Y.set(a,c),s(a,c)&&t(a,c)&&u(a,c),U.set(a,x.NONE),S.set(a,null),a.defaultPrevented}function s(a,b){for(var c,d=b.length-1;d>0;d--){var e=b[d].target,f=b[d].currentTarget;if(e!==f&&(c=x.CAPTURING_PHASE,!v(b[d],a,c)))return!1}return!0}function t(a,b){var c=x.AT_TARGET;return v(b[0],a,c)}function u(a,b){for(var c,d=a.bubbles,e=1;e<b.length;e++){var f=b[e].target,g=b[e].currentTarget;if(f===g)c=x.AT_TARGET;else{if(!d||W.get(a))continue;c=x.BUBBLING_PHASE}if(!v(b[e],a,c))return}}function v(a,b,c){var d=a.target,e=a.currentTarget,f=P.get(e);if(!f)return!0;if("relatedTarget"in b){var g=M(b);if(g.relatedTarget){var h=N(g.relatedTarget),j=i(e,h);if(j===d)return!0;T.set(b,j)}}U.set(b,c);var k=b.type,l=!1;R.set(b,d),S.set(b,e);for(var m=0;m<f.length;m++){var n=f[m];if(n.removed)l=!0;else if(!(n.type!==k||!n.capture&&c===x.CAPTURING_PHASE||n.capture&&c===x.BUBBLING_PHASE))try{if("function"==typeof n.handler?n.handler.call(e,b):n.handler.handleEvent(b),W.get(b))return!1}catch(o){window.onerror?window.onerror(o.message):console.error(o,o.stack)}}if(l){var p=f.slice();f.length=0;for(var m=0;m<p.length;m++)p[m].removed||f.push(p[m])}return!V.get(b)}function w(a,b,c){this.type=a,this.handler=b,this.capture=Boolean(c)}function x(a,b){return a instanceof _?(this.impl=a,void 0):N(B(_,"Event",a,b))}function y(a){return a&&a.relatedTarget?Object.create(a,{relatedTarget:{value:M(a.relatedTarget)}}):a}function z(a,b,c){var d=window[a],e=function(b,c){return b instanceof d?(this.impl=b,void 0):N(B(d,a,b,c))};return e.prototype=Object.create(b.prototype),c&&K(e.prototype,c),d&&(d.prototype["init"+a]?L(d,e,document.createEvent(a)):L(d,e,new d("temp"))),e}function A(a,b){return function(){arguments[b]=M(arguments[b]);var c=M(this);c[a].apply(c,arguments)}}function B(a,b,c,d){if(jb)return new a(c,y(d));var e=M(document.createEvent(b)),f=ib[b],g=[c];return Object.keys(f).forEach(function(a){var b=null!=d&&a in d?d[a]:f[a];"relatedTarget"===a&&(b=M(b)),g.push(b)}),e["init"+b].apply(e,g),e}function C(a){return"function"==typeof a?!0:a&&a.handleEvent}function D(a){this.impl=a}function E(b){return b instanceof O.ShadowRoot&&(b=a.getHostForShadowRoot(b)),M(b)}function F(a){J(a,mb)}function G(b,c,d,e){a.renderAllPending();for(var f=N(nb.call(c.impl,d,e)),h=g(f,this),i=0;i<h.length;i++){var j=h[i];if(j.currentTarget===b)return j.target}return null}function H(a){return function(){var b=X.get(this);return b&&b[a]&&b[a].value||null}}function I(a){var b=a.slice(2);return function(c){var d=X.get(this);d||(d=Object.create(null),X.set(this,d));var e=d[a];if(e&&this.removeEventListener(b,e.wrapped,!1),"function"==typeof c){var f=function(b){var d=c.call(this,b);d===!1?b.preventDefault():"onbeforeunload"===a&&"string"==typeof d&&(b.returnValue=d)};this.addEventListener(b,f,!1),d[a]={value:c,wrapped:f}}}}var J=a.forwardMethodsToWrapper,K=a.mixin,L=a.registerWrapper,M=a.unwrap,N=a.wrap,O=a.wrappers;new WeakMap;var P=new WeakMap,Q=new WeakMap,R=new WeakMap,S=new WeakMap,T=new WeakMap,U=new WeakMap,V=new WeakMap,W=new WeakMap,X=new WeakMap,Y=new WeakMap,Z=0,$=window.MutationEvent;w.prototype={equals:function(a){return this.handler===a.handler&&this.type===a.type&&this.capture===a.capture},get removed(){return null===this.handler},remove:function(){this.handler=null}};var _=window.Event;x.prototype={get target(){return R.get(this)},get currentTarget(){return S.get(this)},get eventPhase(){return U.get(this)},get path(){var a=new O.NodeList,b=Y.get(this);if(b){for(var c=0,d=b.length-1,e=l(S.get(this)),f=0;d>=f;f++){var g=b[f].currentTarget,h=l(g);n(e,h)&&(f!==d||g instanceof O.Node)&&(a[c++]=g)}a.length=c}return a},stopPropagation:function(){V.set(this,!0)},stopImmediatePropagation:function(){V.set(this,!0),W.set(this,!0)}},L(_,x,document.createEvent("Event"));var ab=z("UIEvent",x),bb=z("CustomEvent",x),cb={get relatedTarget(){return T.get(this)||N(M(this).relatedTarget)}},db=K({initMouseEvent:A("initMouseEvent",14)},cb),eb=K({initFocusEvent:A("initFocusEvent",5)},cb),fb=z("MouseEvent",ab,db),gb=z("FocusEvent",ab,eb),hb=z("MutationEvent",x,{initMutationEvent:A("initMutationEvent",3),get relatedNode(){return N(this.impl.relatedNode)}}),ib=Object.create(null),jb=function(){try{new window.MouseEvent("click")}catch(a){return!1}return!0}();if(!jb){var kb=function(a,b,c){if(c){var d=ib[c];b=K(K({},d),b)}ib[a]=b};kb("Event",{bubbles:!1,cancelable:!1}),kb("CustomEvent",{detail:null},"Event"),kb("UIEvent",{view:null,detail:0},"Event"),kb("MouseEvent",{screenX:0,screenY:0,clientX:0,clientY:0,ctrlKey:!1,altKey:!1,shiftKey:!1,metaKey:!1,button:0,relatedTarget:null},"UIEvent"),kb("FocusEvent",{relatedTarget:null},"UIEvent")}var lb=window.EventTarget,mb=["addEventListener","removeEventListener","dispatchEvent"];[Node,Window].forEach(function(a){var b=a.prototype;mb.forEach(function(a){Object.defineProperty(b,a+"_",{value:b[a]})})}),D.prototype={addEventListener:function(a,b,c){if(C(b)){var d=new w(a,b,c),e=P.get(this);if(e){for(var f=0;f<e.length;f++)if(d.equals(e[f]))return}else e=[],P.set(this,e);e.push(d);var g=E(this);g.addEventListener_(a,q,!0)}},removeEventListener:function(a,b,c){c=Boolean(c);var d=P.get(this);if(d){for(var e=0,f=!1,g=0;g<d.length;g++)d[g].type===a&&d[g].capture===c&&(e++,d[g].handler===b&&(f=!0,d[g].remove()));if(f&&1===e){var h=E(this);h.removeEventListener_(a,q,!0)}}},dispatchEvent:function(a){var b=E(this),c=M(a);return Q.set(c,!1),b.dispatchEvent_(c)}},lb&&L(lb,D);var nb=document.elementFromPoint;a.adjustRelatedTarget=i,a.elementFromPoint=G,a.getEventHandlerGetter=H,a.getEventHandlerSetter=I,a.muteMutationEvents=o,a.unmuteMutationEvents=p,a.wrapEventTargetMethods=F,a.wrappers.CustomEvent=bb,a.wrappers.Event=x,a.wrappers.EventTarget=D,a.wrappers.FocusEvent=gb,a.wrappers.MouseEvent=fb,a.wrappers.MutationEvent=hb,a.wrappers.UIEvent=ab}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a,b){Object.defineProperty(a,b,{enumerable:!1})}function c(){this.length=0,b(this,"length")}function d(a){if(null==a)return a;for(var b=new c,d=0,e=a.length;e>d;d++)b[d]=f(a[d]);return b.length=e,b}function e(a,b){a.prototype[b]=function(){return d(this.impl[b].apply(this.impl,arguments))}}var f=a.wrap;c.prototype={item:function(a){return this[a]}},b(c.prototype,"item"),a.wrappers.NodeList=c,a.addWrapNodeListMethod=e,a.wrapNodeList=d}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){o(a instanceof k)}function c(a,b,c,d){if(!(a instanceof DocumentFragment))return a.parentNode&&a.parentNode.removeChild(a),a.parentNode_=b,a.previousSibling_=c,a.nextSibling_=d,c&&(c.nextSibling_=a),d&&(d.previousSibling_=a),[a];for(var e,f=[];e=a.firstChild;)a.removeChild(e),f.push(e),e.parentNode_=b;for(var g=0;g<f.length;g++)f[g].previousSibling_=f[g-1]||c,f[g].nextSibling_=f[g+1]||d;return c&&(c.nextSibling_=f[0]),d&&(d.previousSibling_=f[f.length-1]),f}function d(a){if(a instanceof DocumentFragment){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}return[a]}function e(a){for(var b=0;b<a.length;b++)a[b].nodeWasAdded_()}function f(a,b){var c=a.nodeType===k.DOCUMENT_NODE?a:a.ownerDocument;c!==b.ownerDocument&&c.adoptNode(b)}function g(b,c){if(c.length){var d=b.ownerDocument;if(d!==c[0].ownerDocument)for(var e=0;e<c.length;e++)a.adoptNodeNoRemove(c[e],d)}}function h(a,b){g(a,b);var c=b.length;if(1===c)return r(b[0]);for(var d=r(a.ownerDocument.createDocumentFragment()),e=0;c>e;e++)d.appendChild(r(b[e]));return d}function i(a){if(a.invalidateShadowRenderer()){for(var b=a.firstChild;b;){o(b.parentNode===a);var c=b.nextSibling,d=r(b),e=d.parentNode;e&&y.call(e,d),b.previousSibling_=b.nextSibling_=b.parentNode_=null,b=c}a.firstChild_=a.lastChild_=null}else for(var c,f=r(a),g=f.firstChild;g;)c=g.nextSibling,y.call(f,g),g=c}function j(a){var b=a.parentNode;return b&&b.invalidateShadowRenderer()}function k(a){o(a instanceof u),l.call(this,a),this.parentNode_=void 0,this.firstChild_=void 0,this.lastChild_=void 0,this.nextSibling_=void 0,this.previousSibling_=void 0}var l=a.wrappers.EventTarget,m=a.wrappers.NodeList,n=a.defineWrapGetter,o=a.assert,p=a.mixin,q=a.registerWrapper,r=a.unwrap,s=a.wrap,t=a.wrapIfNeeded,u=window.Node,v=u.prototype.appendChild,w=u.prototype.insertBefore,x=u.prototype.replaceChild,y=u.prototype.removeChild,z=u.prototype.compareDocumentPosition;k.prototype=Object.create(l.prototype),p(k.prototype,{appendChild:function(a){b(a);var g;if(this.invalidateShadowRenderer()||j(a)){var i=this.lastChild,k=null;g=c(a,this,i,k),this.lastChild_=g[g.length-1],i||(this.firstChild_=g[0]),v.call(this.impl,h(this,g))}else g=d(a),f(this,a),v.call(this.impl,r(a));return e(g),a},insertBefore:function(a,i){if(!i)return this.appendChild(a);b(a),b(i),o(i.parentNode===this);var k;if(this.invalidateShadowRenderer()||j(a)){var l=i.previousSibling,m=i;k=c(a,this,l,m),this.firstChild===i&&(this.firstChild_=k[0]);var n=r(i),p=n.parentNode;p?w.call(p,h(this,k),n):g(this,k)}else k=d(a),f(this,a),w.call(this.impl,r(a),r(i));return e(k),a},removeChild:function(a){if(b(a),a.parentNode!==this)throw new Error("NotFoundError");var c=r(a);if(this.invalidateShadowRenderer()){var d=this.firstChild,e=this.lastChild,f=a.nextSibling,g=a.previousSibling,h=c.parentNode;h&&y.call(h,c),d===a&&(this.firstChild_=f),e===a&&(this.lastChild_=g),g&&(g.nextSibling_=f),f&&(f.previousSibling_=g),a.previousSibling_=a.nextSibling_=a.parentNode_=void 0}else y.call(this.impl,c);return a},replaceChild:function(a,g){if(b(a),b(g),g.parentNode!==this)throw new Error("NotFoundError");var i,k=r(g);if(this.invalidateShadowRenderer()||j(a)){var l=g.previousSibling,m=g.nextSibling;m===a&&(m=a.nextSibling),i=c(a,this,l,m),this.firstChild===g&&(this.firstChild_=i[0]),this.lastChild===g&&(this.lastChild_=i[i.length-1]),g.previousSibling_=g.nextSibling_=g.parentNode_=void 0,k.parentNode&&x.call(k.parentNode,h(this,i),k)}else i=d(a),f(this,a),x.call(this.impl,r(a),k);return e(i),g},nodeWasAdded_:function(){for(var a=this.firstChild;a;a=a.nextSibling)a.nodeWasAdded_()},hasChildNodes:function(){return null!==this.firstChild},get parentNode(){return void 0!==this.parentNode_?this.parentNode_:s(this.impl.parentNode)},get firstChild(){return void 0!==this.firstChild_?this.firstChild_:s(this.impl.firstChild)},get lastChild(){return void 0!==this.lastChild_?this.lastChild_:s(this.impl.lastChild)},get nextSibling(){return void 0!==this.nextSibling_?this.nextSibling_:s(this.impl.nextSibling)},get previousSibling(){return void 0!==this.previousSibling_?this.previousSibling_:s(this.impl.previousSibling)},get parentElement(){for(var a=this.parentNode;a&&a.nodeType!==k.ELEMENT_NODE;)a=a.parentNode;return a},get textContent(){for(var a="",b=this.firstChild;b;b=b.nextSibling)a+=b.textContent;return a},set textContent(a){if(this.invalidateShadowRenderer()){if(i(this),""!==a){var b=this.impl.ownerDocument.createTextNode(a);this.appendChild(b)}}else this.impl.textContent=a},get childNodes(){for(var a=new m,b=0,c=this.firstChild;c;c=c.nextSibling)a[b++]=c;return a.length=b,a},cloneNode:function(a){if(!this.invalidateShadowRenderer())return s(this.impl.cloneNode(a));var b=s(this.impl.cloneNode(!1));if(a)for(var c=this.firstChild;c;c=c.nextSibling)b.appendChild(c.cloneNode(!0));return b},contains:function(a){if(!a)return!1;if(a=t(a),a===this)return!0;var b=a.parentNode;return b?this.contains(b):!1},compareDocumentPosition:function(a){return z.call(this.impl,r(a))}}),n(k,"ownerDocument"),q(u,k,document.createDocumentFragment()),delete k.prototype.querySelector,delete k.prototype.querySelectorAll,k.prototype=p(Object.create(l.prototype),k.prototype),a.wrappers.Node=k}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a,c){for(var d,e=a.firstElementChild;e;){if(e.matches(c))return e;if(d=b(e,c))return d;e=e.nextElementSibling}return null
+}function c(a,b,d){for(var e=a.firstElementChild;e;)e.matches(b)&&(d[d.length++]=e),c(e,b,d),e=e.nextElementSibling;return d}var d={querySelector:function(a){return b(this,a)},querySelectorAll:function(a){return c(this,a,new NodeList)}},e={getElementsByTagName:function(a){return this.querySelectorAll(a)},getElementsByClassName:function(a){return this.querySelectorAll("."+a)},getElementsByTagNameNS:function(a,b){if("*"===a)return this.getElementsByTagName(b);for(var c=new NodeList,d=this.getElementsByTagName(b),e=0,f=0;e<d.length;e++)d[e].namespaceURI===a&&(c[f++]=d[e]);return c.length=f,c}};a.GetElementsByInterface=e,a.SelectorsInterface=d}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.nextSibling;return a}function c(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.previousSibling;return a}var d=a.wrappers.NodeList,e={get firstElementChild(){return b(this.firstChild)},get lastElementChild(){return c(this.lastChild)},get childElementCount(){for(var a=0,b=this.firstElementChild;b;b=b.nextElementSibling)a++;return a},get children(){for(var a=new d,b=0,c=this.firstElementChild;c;c=c.nextElementSibling)a[b++]=c;return a.length=b,a}},f={get nextElementSibling(){return b(this.nextSibling)},get previousElementSibling(){return c(this.previousSibling)}};a.ChildNodeInterface=f,a.ParentNodeInterface=e}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}var c=a.ChildNodeInterface,d=a.wrappers.Node,e=a.mixin,f=a.registerWrapper,g=window.CharacterData;b.prototype=Object.create(d.prototype),e(b.prototype,{get textContent(){return this.data},set textContent(a){this.data=a}}),e(b.prototype,c),f(g,b,document.createTextNode("")),a.wrappers.CharacterData=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(b,c){var d=b.parentNode;if(d&&d.shadowRoot){var e=a.getRendererForHost(d);e.dependsOnAttribute(c)&&e.invalidate()}}function c(a){g.call(this,a)}function d(a,c,d){var e=d||c;Object.defineProperty(a,c,{get:function(){return this.impl[c]},set:function(a){this.impl[c]=a,b(this,e)},configurable:!0,enumerable:!0})}var e=a.ChildNodeInterface,f=a.GetElementsByInterface,g=a.wrappers.Node,h=a.ParentNodeInterface,i=a.SelectorsInterface;a.addWrapNodeListMethod;var j=a.mixin,k=a.oneOf,l=a.registerWrapper,m=a.wrappers,n=window.Element,o=k(n.prototype,["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"]),p=n.prototype[o];c.prototype=Object.create(g.prototype),j(c.prototype,{createShadowRoot:function(){var b=new m.ShadowRoot(this);this.impl.polymerShadowRoot_=b;var c=a.getRendererForHost(this);return c.invalidate(),b},get shadowRoot(){return this.impl.polymerShadowRoot_||null},setAttribute:function(a,c){this.impl.setAttribute(a,c),b(this,a)},removeAttribute:function(a){this.impl.removeAttribute(a),b(this,a)},matches:function(a){return p.call(this.impl,a)}}),c.prototype[o]=function(a){return this.matches(a)},n.prototype.webkitCreateShadowRoot&&(c.prototype.webkitCreateShadowRoot=c.prototype.createShadowRoot),d(c.prototype,"id"),d(c.prototype,"className","class"),j(c.prototype,e),j(c.prototype,f),j(c.prototype,h),j(c.prototype,i),l(n,c),a.matchesName=o,a.wrappers.Element=c}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a){case"&":return"&amp;";case"<":return"&lt;";case'"':return"&quot;"}}function c(a){return a.replace(r,b)}function d(a){switch(a.nodeType){case Node.ELEMENT_NODE:for(var b,d=a.tagName.toLowerCase(),f="<"+d,g=a.attributes,h=0;b=g[h];h++)f+=" "+b.name+'="'+c(b.value)+'"';return f+=">",s[d]?f:f+e(a)+"</"+d+">";case Node.TEXT_NODE:return c(a.nodeValue);case Node.COMMENT_NODE:return"<!--"+c(a.nodeValue)+"-->";default:throw console.error(a),new Error("not implemented")}}function e(a){for(var b="",c=a.firstChild;c;c=c.nextSibling)b+=d(c);return b}function f(a,b,c){var d=c||"div";a.textContent="";var e=p(a.ownerDocument.createElement(d));e.innerHTML=b;for(var f;f=e.firstChild;)a.appendChild(q(f))}function g(a){l.call(this,a)}function h(b){return function(){return a.renderAllPending(),this.impl[b]}}function i(a){m(g,a,h(a))}function j(b){Object.defineProperty(g.prototype,b,{get:h(b),set:function(c){a.renderAllPending(),this.impl[b]=c},configurable:!0,enumerable:!0})}function k(b){Object.defineProperty(g.prototype,b,{value:function(){return a.renderAllPending(),this.impl[b].apply(this.impl,arguments)},configurable:!0,enumerable:!0})}var l=a.wrappers.Element,m=a.defineGetter,n=a.mixin,o=a.registerWrapper,p=a.unwrap,q=a.wrap,r=/&|<|"/g,s={area:!0,base:!0,br:!0,col:!0,command:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0},t=window.HTMLElement;g.prototype=Object.create(l.prototype),n(g.prototype,{get innerHTML(){return e(this)},set innerHTML(a){this.invalidateShadowRenderer()?f(this,a,this.tagName):this.impl.innerHTML=a},get outerHTML(){return d(this)},set outerHTML(a){var b=this.parentNode;b&&(b.invalidateShadowRenderer(),this.impl.outerHTML=a)}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(i),["scrollLeft","scrollTop"].forEach(j),["getBoundingClientRect","getClientRects","scrollIntoView"].forEach(k),o(t,g,document.createElement("b")),a.wrappers.HTMLElement=g,a.getInnerHTML=e,a.setInnerHTML=f}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrap,g=window.HTMLCanvasElement;b.prototype=Object.create(c.prototype),d(b.prototype,{getContext:function(){var a=this.impl.getContext.apply(this.impl,arguments);return a&&f(a)}}),e(g,b),a.wrappers.HTMLCanvasElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLContentElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get select(){return this.getAttribute("select")},set select(a){this.setAttribute("select",a)},setAttribute:function(a,b){c.prototype.setAttribute.call(this,a,b),"select"===String(a).toLowerCase()&&this.invalidateShadowRenderer(!0)}}),f&&e(f,b),a.wrappers.HTMLContentElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLShadowElement;b.prototype=Object.create(c.prototype),d(b.prototype,{}),f&&e(f,b),a.wrappers.HTMLShadowElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){if(!a.defaultView)return a;var b=o.get(a);if(!b){for(b=a.implementation.createHTMLDocument("");b.lastChild;)b.removeChild(b.lastChild);o.set(a,b)}return b}function c(a){var c,d=b(a.ownerDocument),e=l(d.createDocumentFragment());for(h();c=a.firstChild;)e.appendChild(c);return k(),e}function d(a){if(e.call(this,a),!p){var b=c(a);n.set(this,m(b))}}var e=a.wrappers.HTMLElement,f=a.getInnerHTML,g=a.mixin,h=a.muteMutationEvents,i=a.registerWrapper,j=a.setInnerHTML,k=a.unmuteMutationEvents,l=a.unwrap,m=a.wrap,n=new WeakMap,o=new WeakMap,p=window.HTMLTemplateElement;d.prototype=Object.create(e.prototype),g(d.prototype,{get content(){return p?m(this.impl.content):n.get(this)},get innerHTML(){return f(this.content)},set innerHTML(a){j(this.content,a)}}),p&&i(p,d),a.wrappers.HTMLTemplateElement=d}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a.localName){case"content":return new c(a);case"shadow":return new e(a);case"template":return new f(a)}d.call(this,a)}var c=a.wrappers.HTMLContentElement,d=a.wrappers.HTMLElement,e=a.wrappers.HTMLShadowElement,f=a.wrappers.HTMLTemplateElement;a.mixin;var g=a.registerWrapper,h=window.HTMLUnknownElement;b.prototype=Object.create(d.prototype),g(h,b),a.wrappers.HTMLUnknownElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.wrap,g=window.CanvasRenderingContext2D;c(b.prototype,{get canvas(){return f(this.impl.canvas)},drawImage:function(){arguments[0]=e(arguments[0]),this.impl.drawImage.apply(this.impl,arguments)},createPattern:function(){return arguments[0]=e(arguments[0]),this.impl.createPattern.apply(this.impl,arguments)}}),d(g,b),a.wrappers.CanvasRenderingContext2D=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.wrap,g=window.WebGLRenderingContext;g&&(c(b.prototype,{get canvas(){return f(this.impl.canvas)},texImage2D:function(){arguments[5]=e(arguments[5]),this.impl.texImage2D.apply(this.impl,arguments)},texSubImage2D:function(){arguments[6]=e(arguments[6]),this.impl.texSubImage2D.apply(this.impl,arguments)}}),d(g,b),a.wrappers.WebGLRenderingContext=b)}(this.ShadowDOMPolyfill),function(a){"use strict";var b=a.GetElementsByInterface,c=a.ParentNodeInterface,d=a.SelectorsInterface,e=a.mixin,f=a.registerObject,g=f(document.createDocumentFragment());e(g.prototype,c),e(g.prototype,d),e(g.prototype,b);var h=f(document.createTextNode("")),i=f(document.createComment(""));a.wrappers.Comment=i,a.wrappers.DocumentFragment=g,a.wrappers.Text=h}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=i(a.impl.ownerDocument.createDocumentFragment());c.call(this,b),g(b,this);var d=a.shadowRoot;k.set(this,d),j.set(this,a)}var c=a.wrappers.DocumentFragment,d=a.elementFromPoint,e=a.getInnerHTML,f=a.mixin,g=a.rewrap,h=a.setInnerHTML,i=a.unwrap,j=new WeakMap,k=new WeakMap;b.prototype=Object.create(c.prototype),f(b.prototype,{get innerHTML(){return e(this)},set innerHTML(a){h(this,a),this.invalidateShadowRenderer()},get olderShadowRoot(){return k.get(this)||null},invalidateShadowRenderer:function(){return j.get(this).invalidateShadowRenderer()},elementFromPoint:function(a,b){return d(this,this.ownerDocument,a,b)},getElementById:function(a){return this.querySelector("#"+a)}}),a.wrappers.ShadowRoot=b,a.getHostForShadowRoot=function(a){return j.get(a)}}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){a.previousSibling_=a.previousSibling,a.nextSibling_=a.nextSibling,a.parentNode_=a.parentNode}function c(a,c,e){var f=G(a),g=G(c),h=e?G(e):null;if(d(c),b(c),e)a.firstChild===e&&(a.firstChild_=e),e.previousSibling_=e.previousSibling;else{a.lastChild_=a.lastChild,a.lastChild===a.firstChild&&(a.firstChild_=a.firstChild);var i=H(f.lastChild);i&&(i.nextSibling_=i.nextSibling)}f.insertBefore(g,h)}function d(a){var c=G(a),d=c.parentNode;if(d){var e=H(d);b(a),a.previousSibling&&(a.previousSibling.nextSibling_=a),a.nextSibling&&(a.nextSibling.previousSibling_=a),e.lastChild===a&&(e.lastChild_=a),e.firstChild===a&&(e.firstChild_=a),d.removeChild(c)}}function e(a,b){g(b).push(a),x(a,b);var c=J.get(a);c||J.set(a,c=[]),c.push(b)}function f(a){I.set(a,[])}function g(a){return I.get(a)}function h(a){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}function i(a,b,c){for(var d=a.firstChild;d;d=d.nextSibling)if(b(d)){if(c(d)===!1)return}else i(d,b,c)}function j(a,b){var c=b.getAttribute("select");if(!c)return!0;if(c=c.trim(),!c)return!0;if(!(a instanceof y))return!1;if(!M.test(c))return!1;if(":"===c[0]&&!N.test(c))return!1;try{return a.matches(c)}catch(d){return!1}}function k(){for(var a=0;a<P.length;a++)P[a].render();P=[]}function l(){F=null,k()}function m(a){var b=L.get(a);return b||(b=new q(a),L.set(a,b)),b}function n(a){for(;a;a=a.parentNode)if(a instanceof C)return a;return null}function o(a){return m(D(a))}function p(a){this.skip=!1,this.node=a,this.childNodes=[]}function q(a){this.host=a,this.dirty=!1,this.invalidateAttributes(),this.associateNode(a)}function r(a){return a instanceof z}function s(a){return a instanceof z}function t(a){return a instanceof A}function u(a){return a instanceof A}function v(a){return a.shadowRoot}function w(a){for(var b=[],c=a.shadowRoot;c;c=c.olderShadowRoot)b.push(c);return b}function x(a,b){K.set(a,b)}var y=a.wrappers.Element,z=a.wrappers.HTMLContentElement,A=a.wrappers.HTMLShadowElement,B=a.wrappers.Node,C=a.wrappers.ShadowRoot;a.assert;var D=a.getHostForShadowRoot;a.mixin,a.muteMutationEvents;var E=a.oneOf;a.unmuteMutationEvents;var F,G=a.unwrap,H=a.wrap,I=new WeakMap,J=new WeakMap,K=new WeakMap,L=new WeakMap,M=/^[*.:#[a-zA-Z_|]/,N=new RegExp("^:("+["link","visited","target","enabled","disabled","checked","indeterminate","nth-child","nth-last-child","nth-of-type","nth-last-of-type","first-child","last-child","first-of-type","last-of-type","only-of-type"].join("|")+")"),O=E(window,["requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","setTimeout"]),P=[],Q=new ArraySplice;Q.equals=function(a,b){return G(a.node)===b},p.prototype={append:function(a){var b=new p(a);return this.childNodes.push(b),b},sync:function(a){if(!this.skip){for(var b=this.node,e=this.childNodes,f=h(G(b)),g=a||new WeakMap,i=Q.calculateSplices(e,f),j=0,k=0,l=0,m=0;m<i.length;m++){for(var n=i[m];l<n.index;l++)k++,e[j++].sync(g);for(var o=n.removed.length,p=0;o>p;p++){var q=H(f[k++]);g.get(q)||d(q)}for(var r=n.addedCount,s=f[k]&&H(f[k]),p=0;r>p;p++){var t=e[j++],u=t.node;c(b,u,s),g.set(u,!0),t.sync(g)}l+=r}for(var m=l;m<e.length;m++)e[m].sync(g)}}},q.prototype={render:function(a){if(this.dirty){this.invalidateAttributes(),this.treeComposition();var b=this.host,c=b.shadowRoot;this.associateNode(b);for(var d=!e,e=a||new p(b),f=c.firstChild;f;f=f.nextSibling)this.renderNode(c,e,f,!1);d&&e.sync(),this.dirty=!1}},invalidate:function(){if(!this.dirty){if(this.dirty=!0,P.push(this),F)return;F=window[O](l,0)}},renderNode:function(a,b,c,d){if(v(c)){b=b.append(c);var e=m(c);e.dirty=!0,e.render(b)}else r(c)?this.renderInsertionPoint(a,b,c,d):t(c)?this.renderShadowInsertionPoint(a,b,c):this.renderAsAnyDomTree(a,b,c,d)},renderAsAnyDomTree:function(a,b,c,d){if(b=b.append(c),v(c)){var e=m(c);b.skip=!e.dirty,e.render(b)}else for(var f=c.firstChild;f;f=f.nextSibling)this.renderNode(a,b,f,d)},renderInsertionPoint:function(a,b,c,d){var e=g(c);if(e.length){this.associateNode(c);for(var f=0;f<e.length;f++){var h=e[f];r(h)&&d?this.renderInsertionPoint(a,b,h,d):this.renderAsAnyDomTree(a,b,h,d)}}else this.renderFallbackContent(a,b,c);this.associateNode(c.parentNode)},renderShadowInsertionPoint:function(a,b,c){var d=a.olderShadowRoot;if(d){x(d,c),this.associateNode(c.parentNode);for(var e=d.firstChild;e;e=e.nextSibling)this.renderNode(d,b,e,!0)}else this.renderFallbackContent(a,b,c)},renderFallbackContent:function(a,b,c){this.associateNode(c),this.associateNode(c.parentNode);for(var d=c.firstChild;d;d=d.nextSibling)this.renderAsAnyDomTree(a,b,d,!1)},invalidateAttributes:function(){this.attributes=Object.create(null)},updateDependentAttributes:function(a){if(a){var b=this.attributes;/\.\w+/.test(a)&&(b["class"]=!0),/#\w+/.test(a)&&(b.id=!0),a.replace(/\[\s*([^\s=\|~\]]+)/g,function(a,c){b[c]=!0})}},dependsOnAttribute:function(a){return this.attributes[a]},distribute:function(a,b){var c=this;i(a,s,function(a){f(a),c.updateDependentAttributes(a.getAttribute("select"));for(var d=0;d<b.length;d++){var g=b[d];void 0!==g&&j(g,a)&&(e(g,a),b[d]=void 0)}})},treeComposition:function(){for(var a=this.host,b=a.shadowRoot,c=[],d=a.firstChild;d;d=d.nextSibling)if(r(d)){var e=g(d);e&&e.length||(e=h(d)),c.push.apply(c,e)}else c.push(d);for(var f,j;b;){if(f=void 0,i(b,u,function(a){return f=a,!1}),j=f,this.distribute(b,c),j){var k=b.olderShadowRoot;if(k){b=k,x(b,j);continue}break}break}},associateNode:function(a){a.impl.polymerShadowRenderer_=this}},B.prototype.invalidateShadowRenderer=function(){var a=this.impl.polymerShadowRenderer_;return a?(a.invalidate(),!0):!1},z.prototype.getDistributedNodes=function(){return k(),g(this)},A.prototype.nodeWasAdded_=z.prototype.nodeWasAdded_=function(){this.invalidateShadowRenderer();var a,b=n(this);b&&(a=o(b)),this.impl.polymerShadowRenderer_=a,a&&a.invalidate()},a.eventParentsTable=J,a.getRendererForHost=m,a.getShadowTrees=w,a.insertionParentTable=K,a.renderAllPending=k,a.visual={insertBefore:c,remove:d}}(this.ShadowDOMPolyfill),function(a){"use strict";function b(b){if(window[b]){d(!a.wrappers[b]);var i=function(a){c.call(this,a)};i.prototype=Object.create(c.prototype),e(i.prototype,{get form(){return h(g(this).form)}}),f(window[b],i,document.createElement(b.slice(4,-7))),a.wrappers[b]=i}}var c=a.wrappers.HTMLElement,d=a.assert,e=a.mixin,f=a.registerWrapper,g=a.unwrap,h=a.wrap,i=["HTMLButtonElement","HTMLFieldSetElement","HTMLInputElement","HTMLKeygenElement","HTMLLabelElement","HTMLLegendElement","HTMLObjectElement","HTMLOptionElement","HTMLOutputElement","HTMLSelectElement","HTMLTextAreaElement"];i.forEach(b)}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){k.call(this,a)}function c(a){var c=document[a];b.prototype[a]=function(){return v(c.apply(this.impl,arguments))}}function d(a,b){y.call(b.impl,u(a)),e(a,b)}function e(a,b){a.shadowRoot&&b.adoptNode(a.shadowRoot),a instanceof n&&f(a,b);for(var c=a.firstChild;c;c=c.nextSibling)e(c,b)}function f(a,b){var c=a.olderShadowRoot;c&&b.adoptNode(c)}function g(a){this.impl=a}function h(a,b){var c=document.implementation[b];a.prototype[b]=function(){return v(c.apply(this.impl,arguments))}}function i(a,b){var c=document.implementation[b];a.prototype[b]=function(){return c.apply(this.impl,arguments)}}var j=a.GetElementsByInterface,k=a.wrappers.Node,l=a.ParentNodeInterface,m=a.SelectorsInterface,n=a.wrappers.ShadowRoot,o=a.defineWrapGetter,p=a.elementFromPoint,q=a.forwardMethodsToWrapper,r=a.matchesName,s=a.mixin,t=a.registerWrapper,u=a.unwrap,v=a.wrap,w=a.wrapEventTargetMethods;a.wrapNodeList;var x=new WeakMap;b.prototype=Object.create(k.prototype),o(b,"documentElement"),o(b,"body"),o(b,"head"),["createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","getElementById"].forEach(c);var y=document.adoptNode;if(s(b.prototype,{adoptNode:function(a){return a.parentNode&&a.parentNode.removeChild(a),d(a,this),a},elementFromPoint:function(a,b){return p(this,this,a,b)}}),document.register){var z=document.register;b.prototype.register=function(b,c){function d(a){return a?(this.impl=a,void 0):document.createElement(b)}var e=c.prototype;if(a.nativePrototypeTable.get(e))throw new Error("NotSupportedError");for(var f,g=Object.getPrototypeOf(e),h=[];g&&!(f=a.nativePrototypeTable.get(g));)h.push(g),g=Object.getPrototypeOf(g);if(!f)throw new Error("NotSupportedError");for(var i=Object.create(f),j=h.length-1;j>=0;j--)i=Object.create(i);return["createdCallback","enteredViewCallback","leftViewCallback","attributeChangedCallback"].forEach(function(a){var b=e[a];b&&(i[a]=function(){b.apply(v(this),arguments)})}),z.call(u(this),b,{prototype:i}),d.prototype=e,d.prototype.constructor=d,a.constructorTable.set(i,d),a.nativePrototypeTable.set(e,i),d},q([window.HTMLDocument||window.Document],["register"])}q([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild",r]),q([window.HTMLDocument||window.Document],["adoptNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","elementFromPoint","getElementById"]),s(b.prototype,j),s(b.prototype,l),s(b.prototype,m),s(b.prototype,{get implementation(){var a=x.get(this);return a?a:(a=new g(u(this).implementation),x.set(this,a),a)}}),t(window.Document,b,document.implementation.createHTMLDocument("")),window.HTMLDocument&&t(window.HTMLDocument,b),w([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]),h(g,"createDocumentType"),h(g,"createDocument"),h(g,"createHTMLDocument"),i(g,"hasFeature"),t(window.DOMImplementation,g),q([window.DOMImplementation],["createDocumentType","createDocument","createHTMLDocument","hasFeature"]),a.adoptNodeNoRemove=d,a.wrappers.DOMImplementation=g,a.wrappers.Document=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.EventTarget,d=a.mixin,e=a.registerWrapper,f=a.unwrap,g=a.unwrapIfNeeded,h=a.wrap,i=a.renderAllPending,j=window.Window;b.prototype=Object.create(c.prototype);var k=window.getComputedStyle;j.prototype.getComputedStyle=function(a,b){return i(),k.call(this||window,g(a),b)},["addEventListener","removeEventListener","dispatchEvent"].forEach(function(a){j.prototype[a]=function(){var b=h(this||window);return b[a].apply(b,arguments)}}),d(b.prototype,{getComputedStyle:function(a,b){return k.call(f(this),g(a),b)}}),e(j,b),a.wrappers.Window=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}function c(a){return new b(a)}function d(a){return a.map(c)}function e(a){var b=this;this.impl=new k(function(c){a.call(b,d(c),b)})}var f=a.defineGetter,g=a.defineWrapGetter,h=a.registerWrapper,i=a.unwrapIfNeeded,j=a.wrapNodeList;a.wrappers;var k=window.MutationObserver||window.WebKitMutationObserver;if(k){var l=window.MutationRecord;b.prototype={get addedNodes(){return j(this.impl.addedNodes)},get removedNodes(){return j(this.impl.removedNodes)}},["target","previousSibling","nextSibling"].forEach(function(a){g(b,a)}),["type","attributeName","attributeNamespace","oldValue"].forEach(function(a){f(b,a,function(){return this.impl[a]})}),l&&h(l,b),window.Node,e.prototype={observe:function(a,b){this.impl.observe(i(a),b)},disconnect:function(){this.impl.disconnect()},takeRecords:function(){return d(this.impl.takeRecords())}},a.wrappers.MutationObserver=e,a.wrappers.MutationRecord=b}}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.registerWrapper,d=a.unwrap,e=a.unwrapIfNeeded,f=a.wrap,g=window.Range;b.prototype={get startContainer(){return f(this.impl.startContainer)},get endContainer(){return f(this.impl.endContainer)},get commonAncestorContainer(){return f(this.impl.commonAncestorContainer)},setStart:function(a,b){this.impl.setStart(e(a),b)},setEnd:function(a,b){this.impl.setEnd(e(a),b)},setStartBefore:function(a){this.impl.setStartBefore(e(a))},setStartAfter:function(a){this.impl.setStartAfter(e(a))},setEndBefore:function(a){this.impl.setEndBefore(e(a))},setEndAfter:function(a){this.impl.setEndAfter(e(a))},selectNode:function(a){this.impl.selectNode(e(a))},selectNodeContents:function(a){this.impl.selectNodeContents(e(a))},compareBoundaryPoints:function(a,b){return this.impl.compareBoundaryPoints(a,d(b))},extractContents:function(){return f(this.impl.extractContents())},cloneContents:function(){return f(this.impl.cloneContents())},insertNode:function(a){this.impl.insertNode(e(a))},surroundContents:function(a){this.impl.surroundContents(e(a))},cloneRange:function(){return f(this.impl.cloneRange())},isPointInRange:function(a,b){return this.impl.isPointInRange(e(a),b)},comparePoint:function(a,b){return this.impl.comparePoint(e(a),b)},intersectsNode:function(a){return this.impl.intersectsNode(e(a))}},g.prototype.createContextualFragment&&(b.prototype.createContextualFragment=function(a){return f(this.impl.createContextualFragment(a))}),c(window.Range,b),a.wrappers.Range=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=c[a],d=window[b];if(d){var e=document.createElement(a),f=e.constructor;window[b]=f}}a.isWrapperFor;var c={a:"HTMLAnchorElement",applet:"HTMLAppletElement",area:"HTMLAreaElement",audio:"HTMLAudioElement",br:"HTMLBRElement",base:"HTMLBaseElement",body:"HTMLBodyElement",button:"HTMLButtonElement",canvas:"HTMLCanvasElement",dl:"HTMLDListElement",datalist:"HTMLDataListElement",dir:"HTMLDirectoryElement",div:"HTMLDivElement",embed:"HTMLEmbedElement",fieldset:"HTMLFieldSetElement",font:"HTMLFontElement",form:"HTMLFormElement",frame:"HTMLFrameElement",frameset:"HTMLFrameSetElement",hr:"HTMLHRElement",head:"HTMLHeadElement",h1:"HTMLHeadingElement",html:"HTMLHtmlElement",iframe:"HTMLIFrameElement",input:"HTMLInputElement",li:"HTMLLIElement",label:"HTMLLabelElement",legend:"HTMLLegendElement",link:"HTMLLinkElement",map:"HTMLMapElement",menu:"HTMLMenuElement",menuitem:"HTMLMenuItemElement",meta:"HTMLMetaElement",meter:"HTMLMeterElement",del:"HTMLModElement",ol:"HTMLOListElement",object:"HTMLObjectElement",optgroup:"HTMLOptGroupElement",option:"HTMLOptionElement",output:"HTMLOutputElement",p:"HTMLParagraphElement",param:"HTMLParamElement",pre:"HTMLPreElement",progress:"HTMLProgressElement",q:"HTMLQuoteElement",script:"HTMLScriptElement",select:"HTMLSelectElement",source:"HTMLSourceElement",span:"HTMLSpanElement",style:"HTMLStyleElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",table:"HTMLTableElement",tr:"HTMLTableRowElement",thead:"HTMLTableSectionElement",tbody:"HTMLTableSectionElement",textarea:"HTMLTextAreaElement",title:"HTMLTitleElement",ul:"HTMLUListElement",video:"HTMLVideoElement"};Object.keys(c).forEach(b),Object.getOwnPropertyNames(a.wrappers).forEach(function(b){window[b]=a.wrappers[b]}),a.knownElements=c}(this.ShadowDOMPolyfill),function(){var a=window.ShadowDOMPolyfill;a.wrap,Object.defineProperties(HTMLElement.prototype,{webkitShadowRoot:{get:function(){return this.shadowRoot}}}),HTMLElement.prototype.webkitCreateShadowRoot=HTMLElement.prototype.createShadowRoot,window.dartExperimentalFixupGetTag=function(b){function c(a){if(a instanceof d)return"NodeList";if(a instanceof e)return"ShadowRoot";if(window.MutationRecord&&a instanceof MutationRecord)return"MutationRecord";if(window.MutationObserver&&a instanceof MutationObserver)return"MutationObserver";if(a instanceof HTMLTemplateElement)return"HTMLTemplateElement";var c=f(a);if(a!==c){var g=a.constructor;if(g===c.constructor){var h=g._ShadowDOMPolyfill$cacheTag_;return h||(h=Object.prototype.toString.call(c),h=h.substring(8,h.length-1),g._ShadowDOMPolyfill$cacheTag_=h),h}a=c}return b(a)}var d=a.wrappers.NodeList,e=a.wrappers.ShadowRoot,f=a.unwrapIfNeeded;return c}}();var Platform={};!function(a){function b(a,b){var c="";return Array.prototype.forEach.call(a,function(a){c+=a.textContent+"\n\n"}),b||(c=c.replace(n,"")),c}function c(a){var b=document.createElement("style");return b.textContent=a,b}function d(a){var b=c(a);document.head.appendChild(b);var d=b.sheet.cssRules;return b.parentNode.removeChild(b),d}function e(a){for(var b=0,c=[];b<a.length;b++)c.push(a[b].cssText);return c.join("\n\n")}function f(a){a&&g().appendChild(document.createTextNode(a))}function g(){return h||(h=document.createElement("style"),h.setAttribute("ShadowCSSShim","")),h}var h,i={strictStyling:!1,registry:{},shimStyling:function(a,b,d){var e=this.isTypeExtension(d),g=this.registerDefinition(a,b,d);this.strictStyling&&this.applyScopeToContent(a,b),this.insertPolyfillDirectives(g.rootStyles),this.insertPolyfillRules(g.rootStyles);var h=this.stylesToShimmedCssText(g.scopeStyles,b,e);h+=this.extractPolyfillUnscopedRules(g.rootStyles),g.shimmedStyle=c(h),a&&(a.shimmedStyle=g.shimmedStyle);for(var i,j=0,k=g.rootStyles.length;k>j&&(i=g.rootStyles[j]);j++)i.parentNode.removeChild(i);f(h)},registerDefinition:function(a,b,c){var d=this.registry[b]={root:a,name:b,extendsName:c},e=a?a.querySelectorAll("style"):[];e=e?Array.prototype.slice.call(e,0):[],d.rootStyles=e,d.scopeStyles=d.rootStyles;var f=this.registry[d.extendsName];return!f||a&&!a.querySelector("shadow")||(d.scopeStyles=f.scopeStyles.concat(d.scopeStyles)),d},isTypeExtension:function(a){return a&&a.indexOf("-")<0},applyScopeToContent:function(a,b){a&&(Array.prototype.forEach.call(a.querySelectorAll("*"),function(a){a.setAttribute(b,"")}),Array.prototype.forEach.call(a.querySelectorAll("template"),function(a){this.applyScopeToContent(a.content,b)},this))},insertPolyfillDirectives:function(a){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.insertPolyfillDirectivesInCssText(a.textContent)},this)},insertPolyfillDirectivesInCssText:function(a){return a.replace(o,function(a,b){return b.slice(0,-2)+"{"})},insertPolyfillRules:function(a){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.insertPolyfillRulesInCssText(a.textContent)},this)},insertPolyfillRulesInCssText:function(a){return a.replace(p,function(a,b){return b.slice(0,-1)})},extractPolyfillUnscopedRules:function(a){var b="";return a&&Array.prototype.forEach.call(a,function(a){b+=this.extractPolyfillUnscopedRulesFromCssText(a.textContent)+"\n\n"},this),b},extractPolyfillUnscopedRulesFromCssText:function(a){for(var b,c="";b=q.exec(a);)c+=b[1].slice(0,-1)+"\n\n";return c},stylesToShimmedCssText:function(a,b,c){return this.shimAtHost(a,b,c)+this.shimScoping(a,b,c)},shimAtHost:function(a,b,c){return a?this.convertAtHostStyles(a,b,c):void 0},convertAtHostStyles:function(a,c,f){var g=b(a),h=this;return g=g.replace(j,function(a,b){return h.scopeHostCss(b,c,f)}),g=e(this.findAtHostRules(d(g),new RegExp("^"+c+u,"m")))},scopeHostCss:function(a,b,c){var d=this;return a.replace(k,function(a,e,f){return d.scopeHostSelector(e,b,c)+" "+f+"\n	"})},scopeHostSelector:function(a,b,c){var d=[],e=a.split(","),f="[is="+b+"]";return e.forEach(function(a){a=a.trim(),a.match(l)?a=a.replace(l,c?f+"$1$3":b+"$1$3"):a.match(m)&&(a=c?f+a:b+a),d.push(a)},this),d.join(", ")},findAtHostRules:function(a,b){return Array.prototype.filter.call(a,this.isHostRule.bind(this,b))},isHostRule:function(a,b){return b.selectorText&&b.selectorText.match(a)||b.cssRules&&this.findAtHostRules(b.cssRules,a).length||b.type==CSSRule.WEBKIT_KEYFRAMES_RULE},shimScoping:function(a,b,c){return a?this.convertScopedStyles(a,b,c):void 0},convertScopedStyles:function(a,c,e){var f=b(a).replace(j,"");f=this.insertPolyfillHostInCssText(f),f=this.convertColonHost(f),f=this.convertPseudos(f),f=this.convertParts(f),f=this.convertCombinators(f);var g=d(f);return f=this.scopeRules(g,c,e)},convertPseudos:function(a){return a.replace(r," [pseudo=$1]")},convertParts:function(a){return a.replace(s," [part=$1]")},convertColonHost:function(a){return a.replace(t,function(a,b,c,d){return c?y+c+d+", "+c+" "+b+d:b+d})},convertCombinators:function(a){return a.replace("^^"," ").replace("^"," ")},scopeRules:function(a,b,c){var d="";return Array.prototype.forEach.call(a,function(a){a.selectorText&&a.style&&a.style.cssText?(d+=this.scopeSelector(a.selectorText,b,c,this.strictStyling)+" {\n	",d+=this.propertiesFromRule(a)+"\n}\n\n"):a.media?(d+="@media "+a.media.mediaText+" {\n",d+=this.scopeRules(a.cssRules,b),d+="\n}\n\n"):a.cssText&&(d+=a.cssText+"\n\n")},this),d},scopeSelector:function(a,b,c,d){var e=[],f=a.split(",");return f.forEach(function(a){a=a.trim(),this.selectorNeedsScoping(a,b,c)&&(a=d?this.applyStrictSelectorScope(a,b):this.applySimpleSelectorScope(a,b,c)),e.push(a)},this),e.join(", ")},selectorNeedsScoping:function(a,b,c){var d=c?b:"\\[is="+b+"\\]",e=new RegExp("^("+d+")"+u,"m");return!a.match(e)},applySimpleSelectorScope:function(a,b,c){var d=c?"[is="+b+"]":b;return a.match(z)?(a=a.replace(y,d),a.replace(z,d+" ")):d+" "+a},applyStrictSelectorScope:function(a,b){var c=[" ",">","+","~"],d=a,e="["+b+"]";return c.forEach(function(a){var b=d.split(a);d=b.map(function(a){var b=a.trim().replace(z,"");return b&&c.indexOf(b)<0&&b.indexOf(e)<0&&(a=b.replace(/([^:]*)(:*)(.*)/,"$1"+e+"$2$3")),a}).join(a)}),d},insertPolyfillHostInCssText:function(a){return a.replace(v,x).replace(w,x)},propertiesFromRule:function(a){var b=a.style.cssText;return a.style.content&&!a.style.content.match(/['"]+/)&&(b="content: '"+a.style.content+"';\n"+a.style.cssText.replace(/content:[^;]*;/g,"")),b}},j=/@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim,k=/([^{]*)({[\s\S]*?})/gim,l=/(.*)((?:\*)|(?:\:scope))(.*)/,m=/^[.\[:]/,n=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,o=/\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim,p=/\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,q=/\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,r=/::(x-[^\s{,(]*)/gim,s=/::part\(([^)]*)\)/gim,t=/(-host)(?:\(([^)]*)\))?([^,{]*)/gim,u="([>\\s~+[.,{:][\\s\\S]*)?$",v=/@host/gim,w=/\:host/gim,x="-host",y="-host-no-combinator",z=/-host/gim;
+if(window.ShadowDOMPolyfill){f("style { display: none !important; }\n");var A=document.querySelector("head");A.insertBefore(g(),A.childNodes[0])}a.ShadowCSS=i}(window.Platform)}
\ No newline at end of file
diff --git a/pkg/shadow_dom/lib/src/platform/ShadowCSS.js b/pkg/shadow_dom/lib/src/platform/ShadowCSS.js
index 96861a1..49fde56 100644
--- a/pkg/shadow_dom/lib/src/platform/ShadowCSS.js
+++ b/pkg/shadow_dom/lib/src/platform/ShadowCSS.js
@@ -90,6 +90,19 @@
 
     x-foo [pseudo=x-special] { ... }
 
+  * ::part(): These rules are converted to rules that take advantage of the
+  part attribute. For example, a shadowRoot like this inside an x-foo
+
+    <div part="special">Special</div>
+
+  with a rule like this:
+
+    x-foo::part(special) { ... }
+
+  becomes:
+
+    x-foo [part=special] { ... }
+
   Unaddressed ShadowDOM styling features:
 
   * upper/lower bound encapsulation: Styles which are defined outside a
@@ -141,27 +154,37 @@
   // Shim styles for a given root associated with a name and extendsName
   // 1. cache root styles by name
   // 2. optionally tag root nodes with scope name
-  // 3. shim polyfill directives /* @polyfill */
+  // 3. shim polyfill directives /* @polyfill */ and /* @polyfill-rule */
   // 4. shim @host and scoping
   shimStyling: function(root, name, extendsName) {
-    if (root) {
-      // use caching to make working with styles nodes easier and to facilitate
-      // lookup of extendee
-      var def = this.registerDefinition(root, name, extendsName);
-      // find styles and apply shimming...
-      if (this.strictStyling) {
-        this.applyScopeToContent(root, name);
-      }
-      this.shimPolyfillDirectives(def.rootStyles, name);
-      this.applyShimming(def.scopeStyles, name);
+    var typeExtension = this.isTypeExtension(extendsName);
+    // use caching to make working with styles nodes easier and to facilitate
+    // lookup of extendee
+    var def = this.registerDefinition(root, name, extendsName);
+    // find styles and apply shimming...
+    if (this.strictStyling) {
+      this.applyScopeToContent(root, name);
     }
-  },
-  // Shim styles to be placed inside a shadowRoot.
-  // 1. shim polyfill directives /* @polyfill */
-  // 2. shim @host and scoping
-  shimShadowDOMStyling: function(styles, name) {
-    this.shimPolyfillDirectives(styles, name);
-    this.applyShimming(styles, name);
+    // insert @polyfill and @polyfill-rule rules into style elements
+    // scoping process takes care of shimming these
+    this.insertPolyfillDirectives(def.rootStyles);
+    this.insertPolyfillRules(def.rootStyles);
+    var cssText = this.stylesToShimmedCssText(def.scopeStyles, name,
+        typeExtension);
+    // note: we only need to do rootStyles since these are unscoped.
+    cssText += this.extractPolyfillUnscopedRules(def.rootStyles);
+    // provide shimmedStyle for user extensibility
+    def.shimmedStyle = cssTextToStyle(cssText);
+    if (root) {
+      root.shimmedStyle = def.shimmedStyle;
+    }
+    // remove existing style elements
+    for (var i=0, l=def.rootStyles.length, s; (i<l) && (s=def.rootStyles[i]);
+        i++) {
+      s.parentNode.removeChild(s);
+    }
+    // add style to document
+    addCssToDocument(cssText);
   },
   registerDefinition: function(root, name, extendsName) {
     var def = this.registry[name] = {
@@ -169,16 +192,19 @@
       name: name,
       extendsName: extendsName
     }
-    var styles = root.querySelectorAll('style');
+    var styles = root ? root.querySelectorAll('style') : [];
     styles = styles ? Array.prototype.slice.call(styles, 0) : [];
     def.rootStyles = styles;
     def.scopeStyles = def.rootStyles;
     var extendee = this.registry[def.extendsName];
-    if (extendee) {
-      def.scopeStyles = def.scopeStyles.concat(extendee.scopeStyles);
+    if (extendee && (!root || root.querySelector('shadow'))) {
+      def.scopeStyles = extendee.scopeStyles.concat(def.scopeStyles);
     }
     return def;
   },
+  isTypeExtension: function(extendsName) {
+    return extendsName && extendsName.indexOf('-') < 0;
+  },
   applyScopeToContent: function(root, name) {
     if (root) {
       // add the name attribute to each node in root.
@@ -200,78 +226,123 @@
    *
    * For example, we convert this rule:
    *
-   * (comment start) @polyfill @host g-menu-item (comment end)
-   * shadow::-webkit-distributed(g-menu-item) {
+   * (comment start) @polyfill :host menu-item (comment end)
+   * shadow::-webkit-distributed(menu-item) {
    *
    * to this:
    *
-   * scopeName g-menu-item {
+   * scopeName menu-item {
    *
   **/
-  shimPolyfillDirectives: function(styles, name) {
+  insertPolyfillDirectives: function(styles) {
     if (styles) {
       Array.prototype.forEach.call(styles, function(s) {
-        s.textContent = this.convertPolyfillDirectives(s.textContent, name);
+        s.textContent = this.insertPolyfillDirectivesInCssText(s.textContent);
       }, this);
     }
   },
-  convertPolyfillDirectives: function(cssText, name) {
-    var r = '', l = 0, matches, selector;
-    while (matches = cssPolyfillCommentRe.exec(cssText)) {
-      r += cssText.substring(l, matches.index);
-      // remove end comment delimiter (*/)
-      selector = matches[1].slice(0, -2).replace(hostRe, name);
-      r += this.scopeSelector(selector, name) + '{';
-      l = cssPolyfillCommentRe.lastIndex;
+  insertPolyfillDirectivesInCssText: function(cssText) {
+    return cssText.replace(cssPolyfillCommentRe, function(match, p1) {
+      // remove end comment delimiter and add block start
+      return p1.slice(0, -2) + '{';
+    });
+  },
+  /*
+   * Process styles to add rules which will only apply under the polyfill
+   *
+   * For example, we convert this rule:
+   *
+   * (comment start) @polyfill-rule :host menu-item {
+   * ... } (comment end)
+   *
+   * to this:
+   *
+   * scopeName menu-item {...}
+   *
+  **/
+  insertPolyfillRules: function(styles) {
+    if (styles) {
+      Array.prototype.forEach.call(styles, function(s) {
+        s.textContent = this.insertPolyfillRulesInCssText(s.textContent);
+      }, this);
     }
-    r += cssText.substring(l, cssText.length);
+  },
+  insertPolyfillRulesInCssText: function(cssText) {
+    return cssText.replace(cssPolyfillRuleCommentRe, function(match, p1) {
+      // remove end comment delimiter
+      return p1.slice(0, -1);
+    });
+  },
+  /*
+   * Process styles to add rules which will only apply under the polyfill
+   * and do not process via CSSOM. (CSSOM is destructive to rules on rare
+   * occasions, e.g. -webkit-calc on Safari.)
+   * For example, we convert this rule:
+   *
+   * (comment start) @polyfill-unscoped-rule menu-item {
+   * ... } (comment end)
+   *
+   * to this:
+   *
+   * menu-item {...}
+   *
+  **/
+  extractPolyfillUnscopedRules: function(styles) {
+    var cssText = '';
+    if (styles) {
+      Array.prototype.forEach.call(styles, function(s) {
+        cssText += this.extractPolyfillUnscopedRulesFromCssText(
+            s.textContent) + '\n\n';
+      }, this);
+    }
+    return cssText;
+  },
+  extractPolyfillUnscopedRulesFromCssText: function(cssText) {
+    var r = '', matches;
+    while (matches = cssPolyfillUnscopedRuleCommentRe.exec(cssText)) {
+      r += matches[1].slice(0, -1) + '\n\n';
+    }
     return r;
   },
   // apply @host and scope shimming
-  applyShimming: function(styles, name) {
-    var cssText = this.shimAtHost(styles, name);
-    cssText += this.shimScoping(styles, name);
-    addCssToDocument(cssText);
+  stylesToShimmedCssText: function(styles, name, typeExtension) {
+    return this.shimAtHost(styles, name, typeExtension) +
+        this.shimScoping(styles, name, typeExtension);
   },
   // form: @host { .foo { declarations } }
   // becomes: scopeName.foo { declarations }
-  shimAtHost: function(styles, name) {
+  shimAtHost: function(styles, name, typeExtension) {
     if (styles) {
-      return this.convertAtHostStyles(styles, name);
+      return this.convertAtHostStyles(styles, name, typeExtension);
     }
   },
-  convertAtHostStyles: function(styles, name) {
-    var cssText = stylesToCssText(styles);
-    var r = '', l=0, matches;
-    while (matches = hostRuleRe.exec(cssText)) {
-      r += cssText.substring(l, matches.index);
-      r += this.scopeHostCss(matches[1], name);
-      l = hostRuleRe.lastIndex;
-    }
-    r += cssText.substring(l, cssText.length);
-    var re = new RegExp('^' + name + selectorReSuffix, 'm');
-    var cssText = rulesToCss(this.findAtHostRules(cssToRules(r),
-      re));
+  convertAtHostStyles: function(styles, name, typeExtension) {
+    var cssText = stylesToCssText(styles), self = this;
+    cssText = cssText.replace(hostRuleRe, function(m, p1) {
+      return self.scopeHostCss(p1, name, typeExtension);
+    });
+    cssText = rulesToCss(this.findAtHostRules(cssToRules(cssText),
+      new RegExp('^' + name + selectorReSuffix, 'm')));
     return cssText;
   },
-  scopeHostCss: function(cssText, name) {
-    var r = '', matches;
-    while (matches = selectorRe.exec(cssText)) {
-      r += this.scopeHostSelector(matches[1], name) +' ' + matches[2] + '\n\t';
-    }
-    return r;
+  scopeHostCss: function(cssText, name, typeExtension) {
+    var self = this;
+    return cssText.replace(selectorRe, function(m, p1, p2) {
+      return self.scopeHostSelector(p1, name, typeExtension) + ' ' + p2 + '\n\t';
+    });
   },
   // supports scopig by name and  [is=name] syntax
-  scopeHostSelector: function(selector, name) {
+  scopeHostSelector: function(selector, name, typeExtension) {
     var r = [], parts = selector.split(','), is = '[is=' + name + ']';
     parts.forEach(function(p) {
       p = p.trim();
       // selector: *|:scope -> name
       if (p.match(hostElementRe)) {
-        p = p.replace(hostElementRe, name + '$1$3, ' + is + '$1$3');
-      // selector: .foo -> name.foo, [bar] -> name[bar]
+        p = p.replace(hostElementRe, typeExtension ? is + '$1$3' :
+            name + '$1$3');
+      // selector: .foo -> name.foo (OR) [bar] -> name[bar]
       } else if (p.match(hostFixableRe)) {
-        p = name + p + ', ' + is + p;
+        p = typeExtension ? is + p : name + p;
       }
       r.push(p);
     }, this);
@@ -297,32 +368,57 @@
    *
    *  scopeName .foo { ... }
   */
-  shimScoping: function(styles, name) {
+  shimScoping: function(styles, name, typeExtension) {
     if (styles) {
-      return this.convertScopedStyles(styles, name);
+      return this.convertScopedStyles(styles, name, typeExtension);
     }
   },
-  convertScopedStyles: function(styles, name) {
-    Array.prototype.forEach.call(styles, function(s) {
-      if (s.parentNode) {
-        s.parentNode.removeChild(s);
-      }
-    });
+  convertScopedStyles: function(styles, name, typeExtension) {
     var cssText = stylesToCssText(styles).replace(hostRuleRe, '');
+    cssText = this.insertPolyfillHostInCssText(cssText);
+    cssText = this.convertColonHost(cssText);
     cssText = this.convertPseudos(cssText);
+    cssText = this.convertParts(cssText);
+    cssText = this.convertCombinators(cssText);
     var rules = cssToRules(cssText);
-    cssText = this.scopeRules(rules, name);
+    cssText = this.scopeRules(rules, name, typeExtension);
     return cssText;
   },
   convertPseudos: function(cssText) {
     return cssText.replace(cssPseudoRe, ' [pseudo=$1]');
   },
+  convertParts: function(cssText) {
+    return cssText.replace(cssPartRe, ' [part=$1]');
+  },
+  /*
+   * convert a rule like :host(.foo) > .bar { }
+   *
+   * to
+   *
+   * scopeName.foo > .bar, .foo scopeName > .bar { }
+   * TODO(sorvell): file bug since native impl does not do the former yet.
+   * http://jsbin.com/OganOCI/2/edit
+  */
+  convertColonHost: function(cssText) {
+    // p1 = :host, p2 = contents of (), p3 rest of rule
+    return cssText.replace(cssColonHostRe, function(m, p1, p2, p3) {
+      return p2 ? polyfillHostNoCombinator + p2 + p3 + ', '
+          + p2 + ' ' + p1 + p3 :
+          p1 + p3;
+    });
+  },
+  /*
+   * Convert ^ and ^^ combinators by replacing with space.
+  */
+  convertCombinators: function(cssText) {
+    return cssText.replace('^^', ' ').replace('^', ' ');
+  },
   // change a selector like 'div' to 'name div'
-  scopeRules: function(cssRules, name) {
+  scopeRules: function(cssRules, name, typeExtension) {
     var cssText = '';
     Array.prototype.forEach.call(cssRules, function(rule) {
       if (rule.selectorText && (rule.style && rule.style.cssText)) {
-        cssText += this.scopeSelector(rule.selectorText, name,
+        cssText += this.scopeSelector(rule.selectorText, name, typeExtension,
           this.strictStyling) + ' {\n\t';
         cssText += this.propertiesFromRule(rule) + '\n}\n\n';
       } else if (rule.media) {
@@ -335,26 +431,32 @@
     }, this);
     return cssText;
   },
-  scopeSelector: function(selector, name, strict) {
+  scopeSelector: function(selector, name, typeExtension, strict) {
     var r = [], parts = selector.split(',');
     parts.forEach(function(p) {
       p = p.trim();
-      if (this.selectorNeedsScoping(p, name)) {
+      if (this.selectorNeedsScoping(p, name, typeExtension)) {
         p = strict ? this.applyStrictSelectorScope(p, name) :
-          this.applySimpleSelectorScope(p, name);
+          this.applySimpleSelectorScope(p, name, typeExtension);
       }
       r.push(p);
     }, this);
     return r.join(', ');
   },
-  selectorNeedsScoping: function(selector, name) {
-    var matchScope = '(' + name + '|\\[is=' + name + '\\])';
-    var re = new RegExp('^' + matchScope + selectorReSuffix, 'm');
+  selectorNeedsScoping: function(selector, name, typeExtension) {
+    var matchScope = typeExtension ? name : '\\[is=' + name + '\\]';
+    var re = new RegExp('^(' + matchScope + ')' + selectorReSuffix, 'm');
     return !selector.match(re);
   },
   // scope via name and [is=name]
-  applySimpleSelectorScope: function(selector, name) {
-    return name + ' ' + selector + ', ' + '[is=' + name + '] ' + selector;
+  applySimpleSelectorScope: function(selector, name, typeExtension) {
+    var scoper = typeExtension ? '[is=' + name + ']' : name;
+    if (selector.match(polyfillHostRe)) {
+      selector = selector.replace(polyfillHostNoCombinator, scoper);
+      return selector.replace(polyfillHostRe, scoper + ' ');
+    } else {
+      return scoper + ' ' + selector;
+    }
   },
   // return a selector with [name] suffix on each simple selector
   // e.g. .foo.bar > .zot becomes .foo[name].bar[name] > .zot[name]
@@ -365,7 +467,8 @@
     splits.forEach(function(sep) {
       var parts = scoped.split(sep);
       scoped = parts.map(function(p) {
-        var t = p.trim();
+        // remove :host since it should be unnecessary
+        var t = p.trim().replace(polyfillHostRe, '');
         if (t && (splits.indexOf(t) < 0) && (t.indexOf(attrName) < 0)) {
           p = t.replace(/([^:]*)(:*)(.*)/, '$1' + attrName + '$2$3')
         }
@@ -374,6 +477,10 @@
     });
     return scoped;
   },
+  insertPolyfillHostInCssText: function(selector) {
+    return selector.replace(hostRe, polyfillHost).replace(colonHostRe,
+        polyfillHost);
+  },
   propertiesFromRule: function(rule) {
     var properties = rule.style.cssText;
     // TODO(sorvell): Chrome cssom incorrectly removes quotes from the content
@@ -392,9 +499,19 @@
     hostFixableRe = /^[.\[:]/,
     cssCommentRe = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,
     cssPolyfillCommentRe = /\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim,
+    cssPolyfillRuleCommentRe = /\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,
+    cssPolyfillUnscopedRuleCommentRe = /\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,
     cssPseudoRe = /::(x-[^\s{,(]*)/gim,
+    cssPartRe = /::part\(([^)]*)\)/gim,
+    // note: :host pre-processed to -host.
+    cssColonHostRe = /(-host)(?:\(([^)]*)\))?([^,{]*)/gim,
     selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$',
-    hostRe = /@host/gim;
+    hostRe = /@host/gim,
+    colonHostRe = /\:host/gim,
+    polyfillHost = '-host',
+    /* host name without combinator */
+    polyfillHostNoCombinator = '-host-no-combinator',
+    polyfillHostRe = /-host/gim;
 
 function stylesToCssText(styles, preserveComments) {
   var cssText = '';
@@ -408,9 +525,14 @@
   return cssText;
 }
 
-function cssToRules(cssText) {
+function cssTextToStyle(cssText) {
   var style = document.createElement('style');
   style.textContent = cssText;
+  return style;
+}
+
+function cssToRules(cssText) {
+  var style = cssTextToStyle(cssText);
   document.head.appendChild(style);
   var rules = style.sheet.cssRules;
   style.parentNode.removeChild(style);
@@ -449,4 +571,4 @@
 // exports
 scope.ShadowCSS = ShadowCSS;
 
-})(window.Platform);
\ No newline at end of file
+})(window.Platform);
diff --git a/pkg/shadow_dom/lib/src/platform/patches-shadow-css.js b/pkg/shadow_dom/lib/src/platform/patches-shadow-css.js
deleted file mode 100644
index 9525570..0000000
--- a/pkg/shadow_dom/lib/src/platform/patches-shadow-css.js
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-(function(scope) {
-  // TODO(terry): Remove shimShadowDOMStyling2 until wrap/unwrap from a
-  //              dart:html Element to a JS DOM node is available.
-  /**
-   * Given the content of a STYLE tag and the name of a component shim the CSS
-   * and return the new scoped CSS to replace the STYLE's content.  The content
-   * is replaced in Dart's implementation of PolymerElement.
-   */
-  function shimShadowDOMStyling2(styleContent, name) {
-    if (window.ShadowDOMPolyfill) {
-      var content = this.convertPolyfillDirectives(styleContent, name);
-
-      // applyShimming calls shimAtHost and shipScoping
-      // shimAtHost code:
-      var r = '', l=0, matches;
-      while (matches = hostRuleRe.exec(content)) {
-        r += content.substring(l, matches.index);
-        r += this.scopeHostCss(matches[1], name);
-        l = hostRuleRe.lastIndex;
-      }
-      r += content.substring(l, content.length);
-      var re = new RegExp('^' + name + selectorReSuffix, 'm');
-      var atHostCssText = rulesToCss(this.findAtHostRules(cssToRules(r), re));
-
-      // shimScoping code:
-      // strip comments for easier processing
-      content = content.replace(cssCommentRe, '');
-
-      content = this.convertPseudos(content);
-      var rules = cssToRules(content);
-      var cssText = this.scopeRules(rules, name);
-
-      return atHostCssText + cssText;
-    }
-  }
-
-  // Minimal copied code from ShadowCSS, that is not exposed in
-  // PlatForm.ShadowCSS (local code).
-  var hostRuleRe = /@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim,
-    cssCommentRe = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,
-    selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$';
-
-  function cssToRules(cssText) {
-    var style = document.createElement('style');
-    style.textContent = cssText;
-    document.head.appendChild(style);
-    var rules = style.sheet.cssRules;
-    style.parentNode.removeChild(style);
-    return rules;
-  }
-
-  function rulesToCss(cssRules) {
-    for (var i=0, css=[]; i < cssRules.length; i++) {
-      css.push(cssRules[i].cssText);
-    }
-    return css.join('\n\n');
-  }
-
-  // exports
-  scope.ShadowCSS.shimShadowDOMStyling2 = shimShadowDOMStyling2;
-})(window.Platform);
diff --git a/pkg/shadow_dom/tool/build.json b/pkg/shadow_dom/tool/build.json
index 899f6d2..7834f81 100644
--- a/pkg/shadow_dom/tool/build.json
+++ b/pkg/shadow_dom/tool/build.json
@@ -5,6 +5,5 @@
   "../lib/src/platform/patches-shadowdom-polyfill.js",
   "../lib/src/platform/platform-init.js",
   "../lib/src/platform/ShadowCSS.js",
-  "../lib/src/platform/patches-shadow-css.js",
   "build/end-if.js"
 ]
diff --git a/pkg/mdv/lib/src/element.dart b/pkg/template_binding/lib/src/element.dart
similarity index 68%
rename from pkg/mdv/lib/src/element.dart
rename to pkg/template_binding/lib/src/element.dart
index d1f62da..ccb1a28 100644
--- a/pkg/mdv/lib/src/element.dart
+++ b/pkg/template_binding/lib/src/element.dart
@@ -2,21 +2,17 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of mdv;
+part of template_binding;
 
 /** Extensions to the [Element] API. */
-class _ElementExtension extends _NodeExtension {
-  _ElementExtension(Element node) : super(node);
+class _ElementExtension extends NodeBindExtension {
+  _ElementExtension(Element node) : super._(node);
 
   // TODO(jmesserly): should path be optional, and default to empty path?
   // It is used that way in at least one path in JS TemplateElement tests
   // (see "BindImperative" test in original JS code).
   NodeBinding createBinding(String name, model, String path) =>
-      new _AttributeBinding(node, name, model, path);
-
-  // Normally we issue this error in Element._ensureTemplate, but we
-  // avoid calling that from the model getter, so issue the error here.
-  get model => throw new UnsupportedError('$node is not a template.');
+      new _AttributeBinding(_node, name, model, path);
 }
 
 class _AttributeBinding extends NodeBinding {
@@ -28,7 +24,7 @@
   factory _AttributeBinding(Element node, name, model, path) {
     bool conditional = name.endsWith('?');
     if (conditional) {
-      node.xtag.attributes.remove(name);
+      node.attributes.remove(name);
       name = name.substring(0, name.length - 1);
     }
     return new _AttributeBinding._(node, name, model, path, conditional);
@@ -39,14 +35,14 @@
   void boundValueChanged(value) {
     if (conditional) {
       if (_toBoolean(value)) {
-        node.xtag.attributes[property] = '';
+        node.attributes[property] = '';
       } else {
-        node.xtag.attributes.remove(property);
+        node.attributes.remove(property);
       }
     } else {
       // TODO(jmesserly): escape value if needed to protect against XSS.
       // See https://github.com/polymer-project/mdv/issues/58
-      node.xtag.attributes[property] = sanitizeBoundValue(value);
+      node.attributes[property] = sanitizeBoundValue(value);
     }
   }
 }
diff --git a/pkg/mdv/lib/src/input_bindings.dart b/pkg/template_binding/lib/src/input_bindings.dart
similarity index 96%
rename from pkg/mdv/lib/src/input_bindings.dart
rename to pkg/template_binding/lib/src/input_bindings.dart
index fa15841..e00b3a9 100644
--- a/pkg/mdv/lib/src/input_bindings.dart
+++ b/pkg/template_binding/lib/src/input_bindings.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of mdv;
+part of template_binding;
 
 abstract class _InputBinding extends NodeBinding {
   StreamSubscription _eventSub;
@@ -86,7 +86,7 @@
     // CheckedBinding manually.
     if (node is InputElement && node.type == 'radio') {
       for (var r in _getAssociatedRadioButtons(node)) {
-        var checkedBinding = r.bindings['checked'];
+        var checkedBinding = nodeBind(r).bindings['checked'];
         if (checkedBinding != null) {
           // Set the value directly to avoid an infinite call stack.
           checkedBinding.value = false;
@@ -114,7 +114,7 @@
             el.name == element.name;
       });
     } else {
-      var radios = element.document.queryAll(
+      var radios = element.ownerDocument.queryAll(
           'input[type="radio"][name="${element.name}"]');
       return radios.where((el) => el != element && el.form == null);
     }
@@ -124,7 +124,7 @@
   static bool _isNodeInDocument(Node node) {
     // On non-IE this works:
     // return node.ownerDocument.contains(node);
-    var document = node.document;
+    var document = node.ownerDocument;
     if (node == document || node.parentNode == document) return true;
     return document.documentElement.contains(node);
   }
diff --git a/pkg/mdv/lib/src/input_element.dart b/pkg/template_binding/lib/src/input_element.dart
similarity index 72%
rename from pkg/mdv/lib/src/input_element.dart
rename to pkg/template_binding/lib/src/input_element.dart
index 7e4855e..0a6d45a 100644
--- a/pkg/mdv/lib/src/input_element.dart
+++ b/pkg/template_binding/lib/src/input_element.dart
@@ -2,23 +2,23 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of mdv;
+part of template_binding;
 
 /** Extensions to the [InputElement] API. */
 class _InputElementExtension extends _ElementExtension {
   _InputElementExtension(InputElement node) : super(node);
 
-  InputElement get node => super.node;
+  InputElement get _node => super._node;
 
   NodeBinding createBinding(String name, model, String path) {
     if (name == 'value') {
       // TODO(rafaelw): Maybe template should remove all binding instructions.
-      node.attributes.remove(name);
-      return new _ValueBinding(node, model, path);
+      _node.attributes.remove(name);
+      return new _ValueBinding(_node, model, path);
     }
     if (name == 'checked') {
-      node.attributes.remove(name);
-      return new _CheckedBinding(node, model, path);
+      _node.attributes.remove(name);
+      return new _CheckedBinding(_node, model, path);
     }
     return super.createBinding(name, model, path);
   }
diff --git a/pkg/mdv/lib/src/list_diff.dart b/pkg/template_binding/lib/src/list_diff.dart
similarity index 99%
rename from pkg/mdv/lib/src/list_diff.dart
rename to pkg/template_binding/lib/src/list_diff.dart
index 8858c76..ba96d15 100644
--- a/pkg/mdv/lib/src/list_diff.dart
+++ b/pkg/template_binding/lib/src/list_diff.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library mdv.src.list_diff;
+library template_binding.src.list_diff;
 
 import 'dart:math' as math;
 import 'package:observe/observe.dart' show ListChangeRecord;
diff --git a/pkg/template_binding/lib/src/node.dart b/pkg/template_binding/lib/src/node.dart
new file mode 100644
index 0000000..a1bc29c
--- /dev/null
+++ b/pkg/template_binding/lib/src/node.dart
@@ -0,0 +1,247 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of template_binding;
+
+/** Extensions to the [Node] API. */
+class NodeBindExtension {
+  final Node _node;
+  Map<String, NodeBinding> _bindings;
+
+  NodeBindExtension._(this._node);
+
+  /**
+   * Creates a binding to the attribute [name] to the [path] of the [model].
+   *
+   * This can be overridden by custom elements to provide the binding used in
+   * [bind]. This will only create the binding; it will not add
+   * it to [bindings].
+   *
+   * You should not need to call this directly except from [bind].
+   */
+  NodeBinding createBinding(String name, model, String path) => null;
+
+  /**
+   * Binds the attribute [name] to the [path] of the [model].
+   * Path is a String of accessors such as `foo.bar.baz`.
+   * Returns the `NodeBinding` instance.
+   */
+  NodeBinding bind(String name, model, String path) {
+    var binding = bindings[name];
+    if (binding != null) binding.close();
+
+    // Note: dispatch through the node so it can override this.
+    binding = nodeBind(_node).createBinding(name, model, path);
+
+    bindings[name] = binding;
+    if (binding == null) {
+      window.console.error('Unhandled binding to Node: '
+          '$this $name $model $path');
+    }
+    return binding;
+  }
+
+  /** Unbinds the attribute [name]. */
+  void unbind(String name) {
+    if (_bindings == null) return;
+    var binding = bindings.remove(name);
+    if (binding != null) binding.close();
+  }
+
+  /** Unbinds all bound attributes. */
+  void unbindAll() {
+    if (_bindings == null) return;
+    for (var binding in bindings.values) {
+      if (binding != null) binding.close();
+    }
+    _bindings = null;
+  }
+
+  // TODO(jmesserly): we should return a read-only wrapper here.
+  /** Gets the data bindings that are associated with this node. */
+  Map<String, NodeBinding> get bindings {
+    if (_bindings == null) _bindings = new LinkedHashMap<String, NodeBinding>();
+    return _bindings;
+  }
+
+  TemplateInstance _templateInstance;
+
+  /** Gets the template instance that instantiated this node, if any. */
+  TemplateInstance get templateInstance =>
+      _templateInstance != null ? _templateInstance :
+      (_node.parent != null ? _node.parent.templateInstance : null);
+}
+
+
+/** Information about the instantiated template. */
+class TemplateInstance {
+  // TODO(rafaelw): firstNode & lastNode should be read-synchronous
+  // in cases where script has modified the template instance boundary.
+
+  /** The first node of this template instantiation. */
+  final Node firstNode;
+
+  /**
+   * The last node of this template instantiation.
+   * This could be identical to [firstNode] if the template only expanded to a
+   * single node.
+   */
+  final Node lastNode;
+
+  /** The model used to instantiate the template. */
+  final model;
+
+  TemplateInstance(this.firstNode, this.lastNode, this.model);
+}
+
+
+/**
+ * Template Bindings native features enables a wide-range of use cases,
+ * but (by design) don't attempt to implement a wide array of specialized
+ * behaviors.
+ *
+ * Enabling these features is a matter of implementing and registering a
+ * BindingDelegate. A binding delegate is an object which contains one or more
+ * delegation functions which implement specialized behavior. This object is
+ * registered via [TemplateBindExtension.bindingDelegate]:
+ *
+ * HTML:
+ *     <template bind>
+ *       {{ What!Ever('crazy')->thing^^^I+Want(data) }}
+ *     </template>
+ *
+ * Dart:
+ *     class MySyntax extends BindingDelegate {
+ *       getBinding(model, path, name, node) {
+ *         // The magic happens here!
+ *       }
+ *     }
+ *     ...
+ *     templateBind(query('template'))
+ *         ..bindingDelegate = new MySyntax()
+ *         ..model = new MyModel();
+ *
+ * See <https://github.com/polymer-project/mdv/blob/master/docs/syntax.md> for
+ * more information about Custom Syntax.
+ */
+abstract class BindingDelegate {
+  /**
+   * This syntax method allows for a custom interpretation of the contents of
+   * mustaches (`{{` ... `}}`).
+   *
+   * When a template is inserting an instance, it will invoke this method for
+   * each mustache which is encountered. The function is invoked with four
+   * arguments:
+   *
+   * - [model]: The data context for which this instance is being created.
+   * - [path]: The text contents (trimmed of outer whitespace) of the mustache.
+   * - [name]: The context in which the mustache occurs. Within element
+   *   attributes, this will be the name of the attribute. Within text,
+   *   this will be 'text'.
+   * - [node]: A reference to the node to which this binding will be created.
+   *
+   * If the method wishes to handle binding, it is required to return an object
+   * which has at least a `value` property that can be observed. If it does,
+   * then MDV will call [NodeBindExtension.bind] on the node:
+   *
+   *     nodeBind(node).bind(name, retval, 'value');
+   *
+   * If the 'getBinding' does not wish to override the binding, it should return
+   * null.
+   */
+  // TODO(jmesserly): I had to remove type annotations from "name" and "node"
+  // Normally they are String and Node respectively. But sometimes it will pass
+  // (int name, CompoundBinding node). That seems very confusing; we may want
+  // to change this API.
+  getBinding(model, String path, name, node) => null;
+
+  /**
+   * This syntax method allows a syntax to provide an alterate model than the
+   * one the template would otherwise use when producing an instance.
+   *
+   * When a template is about to create an instance, it will invoke this method
+   * The function is invoked with two arguments:
+   *
+   * - [template]: The template element which is about to create and insert an
+   *   instance.
+   * - [model]: The data context for which this instance is being created.
+   *
+   * The template element will always use the return value of `getInstanceModel`
+   * as the model for the new instance. If the syntax does not wish to override
+   * the value, it should simply return the `model` value it was passed.
+   */
+  getInstanceModel(Element template, model) => model;
+}
+
+/**
+ * A data binding on a [Node].
+ * See [NodeBindExtension.bindings] and [NodeBindExtension.bind].
+ */
+abstract class NodeBinding {
+  Node _node;
+  var _model;
+  PathObserver _observer;
+  StreamSubscription _pathSub;
+
+  /** The property of [node] which will be data bound. */
+  final String property;
+
+  /** The property of [node] which will be data bound. */
+  final String path;
+
+  /** The node that has [property] which will be data bound. */
+  Node get node => _node;
+
+  /**
+   * The bound data model.
+   */
+  get model => _model;
+
+  /** True if this binding has been [closed]. */
+  bool get closed => _observer == null;
+
+  /** The value at the [path] on [model]. */
+  get value => _observer.value;
+
+  set value(newValue) {
+    _observer.value = newValue;
+  }
+
+  NodeBinding(this._node, this.property, this._model, this.path) {
+    // Create the path observer
+    _observer = new PathObserver(model, path);
+    _observePath();
+  }
+
+  void _observePath() {
+    _pathSub = _observer.bindSync(boundValueChanged);
+  }
+
+  /** Called when [value] changes to update the [node]. */
+  // TODO(jmesserly): the impl in MDV uses mirrors to set the property,
+  // but that isn't used except for specific known fields like "textContent",
+  // so I'm overridding this in the subclasses instead.
+  void boundValueChanged(newValue);
+
+  /** Called to sanitize the value before it is assigned into the property. */
+  sanitizeBoundValue(value) => value == null ? '' : '$value';
+
+  /**
+   * Called by [NodeBindExtension.unbind] to close this binding and unobserve
+   * the [path].
+   *
+   * This can be overridden in subclasses, but they must call `super.close()`
+   * to free associated resources. They must also check [closed] and return
+   * immediately if already closed.
+   */
+  void close() {
+    if (closed) return;
+
+    if (_pathSub != null) _pathSub.cancel();
+    _pathSub = null;
+    _observer = null;
+    _node = null;
+    _model = null;
+  }
+}
diff --git a/pkg/mdv/lib/src/select_element.dart b/pkg/template_binding/lib/src/select_element.dart
similarity index 79%
rename from pkg/mdv/lib/src/select_element.dart
rename to pkg/template_binding/lib/src/select_element.dart
index 5ae74c8..e1cc143 100644
--- a/pkg/mdv/lib/src/select_element.dart
+++ b/pkg/template_binding/lib/src/select_element.dart
@@ -2,19 +2,19 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of mdv;
+part of template_binding;
 
 /** Extensions to the [SelectElement] API. */
 class _SelectElementExtension extends _ElementExtension {
   _SelectElementExtension(SelectElement node) : super(node);
 
-  SelectElement get node => super.node;
+  SelectElement get _node => super._node;
 
   NodeBinding createBinding(String name, model, String path) {
     if (name.toLowerCase() == 'selectedindex') {
       // TODO(rafaelw): Maybe template should remove all binding instructions.
-      node.attributes.remove(name);
-      return new _SelectedIndexBinding(node, model, path);
+      _node.attributes.remove(name);
+      return new _SelectedIndexBinding(_node, model, path);
     }
     return super.createBinding(name, model, path);
   }
diff --git a/pkg/template_binding/lib/src/template.dart b/pkg/template_binding/lib/src/template.dart
new file mode 100644
index 0000000..ee344f4
--- /dev/null
+++ b/pkg/template_binding/lib/src/template.dart
@@ -0,0 +1,325 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of template_binding;
+
+/** Extensions to [Element]s that behave as templates. */
+class TemplateBindExtension extends _ElementExtension {
+  var _model;
+  BindingDelegate _bindingDelegate;
+  _TemplateIterator _templateIterator;
+  bool _scheduled = false;
+
+  Element _templateInstanceRef;
+
+  // Note: only used if `this is! TemplateElement`
+  DocumentFragment _content;
+  bool _templateIsDecorated;
+
+  TemplateBindExtension._(Element node) : super(node);
+
+  Element get _node => super._node;
+
+  NodeBinding createBinding(String name, model, String path) {
+    switch (name) {
+      case 'bind':
+      case 'repeat':
+      case 'if':
+        if (_templateIterator == null) {
+          _templateIterator = new _TemplateIterator(_node);
+        }
+        // TODO(jmesserly): why do we do this here and nowhere else?
+        if (path == null) path = '';
+        return new _TemplateBinding(this, name, model, path);
+      default:
+        return super.createBinding(name, model, path);
+    }
+  }
+
+  /**
+   * Creates an instance of the template, using the provided model and optional
+   * binding delegate.
+   */
+  DocumentFragment createInstance([model, BindingDelegate delegate]) {
+    var instance = _createDeepCloneAndDecorateTemplates(
+        templateBind(ref).content, delegate);
+
+    _addBindings(instance, model, delegate);
+    _addTemplateInstanceRecord(instance, model);
+    return instance;
+  }
+
+  /** The data model which is inherited through the tree. */
+  get model => _model;
+
+  void set model(value) {
+    _model = value;
+    _ensureSetModelScheduled();
+  }
+
+  /**
+   * The binding delegate which is inherited through the tree. It can be used
+   * to configure custom syntax for `{{bindings}}` inside this template.
+   */
+  BindingDelegate get bindingDelegate => _bindingDelegate;
+
+  void set bindingDelegate(BindingDelegate value) {
+    _bindingDelegate = value;
+    _ensureSetModelScheduled();
+  }
+
+  _ensureSetModelScheduled() {
+    if (_scheduled) return;
+    _decorate();
+    _scheduled = true;
+    scheduleMicrotask(_setModel);
+  }
+
+  void _setModel() {
+    _scheduled = false;
+    _addBindings(_node, _model, _bindingDelegate);
+  }
+
+  /** Gets the template this node refers to. */
+  Element get ref {
+    _decorate();
+
+    Element result = null;
+    var refId = _node.attributes['ref'];
+    if (refId != null) {
+      var treeScope = _node;
+      while (treeScope.parentNode != null) {
+        treeScope = treeScope.parentNode;
+      }
+
+      // Note: JS code tests that getElementById is present. We can't do that
+      // easily, so instead check for the types known to implement it.
+      if (treeScope is Document ||
+          treeScope is ShadowRoot ||
+          treeScope is SvgSvgElement) {
+
+        result = treeScope.getElementById(refId);
+      }
+    }
+
+    if (result == null) {
+      result = _templateInstanceRef;
+      if (result == null) return _node;
+    }
+
+    var nextRef = templateBind(result).ref;
+    return nextRef != null ? nextRef : result;
+  }
+
+  /**
+   * Gets the content of this template.
+   */
+  DocumentFragment get content {
+    _decorate();
+    return _content != null ? _content : (_node as TemplateElement).content;
+  }
+
+  /**
+   * Ensures proper API and content model for template elements.
+   *
+   * [instanceRef] can be used to set the [Element.ref] property of [template],
+   * and use the ref's content will be used as source when createInstance() is
+   * invoked.
+   *
+   * Returns true if this template was just decorated, or false if it was
+   * already decorated.
+   */
+  static bool decorate(Element template, [Element instanceRef]) =>
+      templateBindFallback(template)._decorate(instanceRef);
+
+  bool _decorate([Element instanceRef]) {
+    // == true check because it starts as a null field.
+    if (_templateIsDecorated == true) return false;
+
+    _injectStylesheet();
+
+    var templateElementExt = this;
+    _templateIsDecorated = true;
+    var isNative = _node is TemplateElement;
+    var bootstrapContents = isNative;
+    var liftContents = !isNative;
+    var liftRoot = false;
+
+    if (!isNative && _isAttributeTemplate(_node)) {
+      if (instanceRef != null) {
+        // TODO(jmesserly): this is just an assert in MDV.
+        throw new ArgumentError('instanceRef should not be supplied for '
+            'attribute templates.');
+      }
+      templateElementExt = templateBind(
+          _extractTemplateFromAttributeTemplate(_node));
+      templateElementExt._templateIsDecorated = true;
+      isNative = templateElementExt._node is TemplateElement;
+      liftRoot = true;
+     }
+
+    if (!isNative) {
+      var doc = _getTemplateContentsOwner(
+          templateElementExt._node.ownerDocument);
+      templateElementExt._content = doc.createDocumentFragment();
+    }
+
+    if (instanceRef != null) {
+      // template is contained within an instance, its direct content must be
+      // empty
+      templateElementExt._templateInstanceRef = instanceRef;
+    } else if (liftContents) {
+      _liftNonNativeChildrenIntoContent(templateElementExt, _node, liftRoot);
+    } else if (bootstrapContents) {
+      bootstrap(templateElementExt.content);
+    }
+
+    return true;
+  }
+
+  static final _contentsOwner = new Expando();
+
+  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
+  static Document _getTemplateContentsOwner(HtmlDocument doc) {
+    if (doc.window == null) {
+      return doc;
+    }
+    var d = _contentsOwner[doc];
+    if (d == null) {
+      // TODO(arv): This should either be a Document or HTMLDocument depending
+      // on doc.
+      d = doc.implementation.createHtmlDocument('');
+      while (d.lastChild != null) {
+        d.lastChild.remove();
+      }
+      _contentsOwner[doc] = d;
+    }
+    return d;
+  }
+
+  // For non-template browsers, the parser will disallow <template> in certain
+  // locations, so we allow "attribute templates" which combine the template
+  // element with the top-level container node of the content, e.g.
+  //
+  //   <tr template repeat="{{ foo }}"" class="bar"><td>Bar</td></tr>
+  //
+  // becomes
+  //
+  //   <template repeat="{{ foo }}">
+  //   + #document-fragment
+  //     + <tr class="bar">
+  //       + <td>Bar</td>
+  //
+  static Element _extractTemplateFromAttributeTemplate(Element el) {
+    var template = el.ownerDocument.createElement('template');
+    el.parentNode.insertBefore(template, el);
+
+    for (var name in el.attributes.keys.toList()) {
+      switch (name) {
+        case 'template':
+          el.attributes.remove(name);
+          break;
+        case 'repeat':
+        case 'bind':
+        case 'ref':
+          template.attributes[name] = el.attributes.remove(name);
+          break;
+      }
+    }
+
+    return template;
+  }
+
+  static void _liftNonNativeChildrenIntoContent(TemplateBindExtension template,
+      Element el, bool useRoot) {
+
+    var content = template.content;
+    if (useRoot) {
+      content.append(el);
+      return;
+    }
+
+    var child;
+    while ((child = el.firstChild) != null) {
+      content.append(child);
+    }
+  }
+
+  /**
+   * This used to decorate recursively all templates from a given node.
+   *
+   * By default [decorate] will be called on templates lazily when certain
+   * properties such as [model] are accessed, but it can be run eagerly to
+   * decorate an entire tree recursively.
+   */
+  // TODO(rafaelw): Review whether this is the right public API.
+  static void bootstrap(Node content) {
+    void _bootstrap(template) {
+      if (!TemplateBindExtension.decorate(template)) {
+        bootstrap(templateBind(template).content);
+      }
+    }
+
+    // Need to do this first as the contents may get lifted if |node| is
+    // template.
+    // TODO(jmesserly): content is DocumentFragment or Element
+    var descendents =
+        (content as dynamic).querySelectorAll(_allTemplatesSelectors);
+    if (isSemanticTemplate(content)) {
+      _bootstrap(content);
+    }
+
+    descendents.forEach(_bootstrap);
+  }
+
+  static final String _allTemplatesSelectors =
+      'template, ' +
+      _SEMANTIC_TEMPLATE_TAGS.keys.map((k) => "$k[template]").join(", ");
+
+  static bool _initStyles;
+
+  static void _injectStylesheet() {
+    if (_initStyles == true) return;
+    _initStyles = true;
+
+    var style = new StyleElement();
+    style.text = r'''
+template,
+thead[template],
+tbody[template],
+tfoot[template],
+th[template],
+tr[template],
+td[template],
+caption[template],
+colgroup[template],
+col[template],
+option[template] {
+  display: none;
+}''';
+    document.head.append(style);
+  }
+}
+
+class _TemplateBinding extends NodeBinding {
+  TemplateBindExtension _ext;
+
+  // TODO(jmesserly): MDV uses TemplateIterator as the node, see:
+  // https://github.com/Polymer/mdv/issues/127
+  _TemplateBinding(ext, name, model, path)
+      : _ext = ext, super(ext._node, name, model, path) {
+    _ext._templateIterator.inputs.bind(property, model, path);
+  }
+
+  // These are no-ops because we don't use the underlying PathObserver.
+  void _observePath() {}
+  void boundValueChanged(newValue) {}
+
+  void close() {
+    if (closed) return;
+    var templateIterator = _ext._templateIterator;
+    if (templateIterator != null) templateIterator.inputs.unbind(property);
+    super.close();
+  }
+}
diff --git a/pkg/mdv/lib/src/template_iterator.dart b/pkg/template_binding/lib/src/template_iterator.dart
similarity index 86%
rename from pkg/mdv/lib/src/template_iterator.dart
rename to pkg/template_binding/lib/src/template_iterator.dart
index 8458165..981adf5 100644
--- a/pkg/mdv/lib/src/template_iterator.dart
+++ b/pkg/template_binding/lib/src/template_iterator.dart
@@ -2,25 +2,27 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of mdv;
+part of template_binding;
 
-// This code is a port of Model-Driven-Views:
-// https://github.com/polymer-project/mdv
-// The code mostly comes from src/template_element.js
+// This code is a port of what was formerly known as Model-Driven-Views, now
+// located at:
+//     https://github.com/polymer/TemplateBinding
+//     https://github.com/polymer/NodeBind
 
 // 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
+// everything else is true.
+// See: https://github.com/polymer/TemplateBinding/issues/59
 bool _toBoolean(value) => null != value && false != value;
 
 Node _createDeepCloneAndDecorateTemplates(Node node, BindingDelegate delegate) {
   var clone = node.clone(false); // Shallow clone.
-  if (clone is Element && clone.isTemplate) {
-    TemplateElement.decorate(clone, node);
+  if (isSemanticTemplate(clone)) {
+    TemplateBindExtension.decorate(clone, node);
     if (delegate != null) {
-      _mdv(clone)._bindingDelegate = delegate;
+      templateBindFallback(clone)._bindingDelegate = delegate;
     }
   }
 
@@ -52,7 +54,7 @@
   var bindings = null;
   var ifFound = false;
   var bindFound = false;
-  var isTemplateNode = element.isTemplate;
+  var isTemplateNode = isSemanticTemplate(element);
 
   element.attributes.forEach((name, value) {
     if (isTemplateNode) {
@@ -91,9 +93,6 @@
 void _setupBinding(Node node, String name, List tokens, model,
     BindingDelegate delegate) {
 
-  // If this is a custom element, give the .xtag a change to bind.
-  node = _nodeOrCustom(node);
-
   if (_isSimpleBinding(tokens)) {
     _bindOrDelegate(node, name, model, tokens[1], delegate);
     return;
@@ -129,7 +128,7 @@
 
   replacementBinding.resolve();
 
-  node.bind(name, replacementBinding, 'value');
+  nodeBind(node).bind(name, replacementBinding, 'value');
 }
 
 void _bindOrDelegate(node, name, model, String path,
@@ -143,17 +142,13 @@
     }
   }
 
-  node.bind(name, model, path);
+  if (node is CompoundBinding) {
+    node.bind(name, model, path);
+  } else {
+    nodeBind(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.
-_nodeOrCustom(node) => node is Element ? node.xtag : node;
-
 /** True if and only if [tokens] is of the form `['', path, '']`. */
 bool _isSimpleBinding(List<String> tokens) =>
     tokens.length == 3 && tokens[0].isEmpty && tokens[2].isEmpty;
@@ -201,7 +196,7 @@
 
   var node = instanceRecord.firstNode;
   while (node != null) {
-    _mdv(node)._templateInstance = instanceRecord;
+    nodeBindFallback(node)._templateInstance = instanceRecord;
     node = node.nextNode;
   }
 }
@@ -256,16 +251,16 @@
 
     if (inputs.length == 0) {
       close();
-      _mdv(_templateElement)._templateIterator = null;
+      templateBindFallback(_templateElement)._templateIterator = null;
     }
   }
 
   Node getTerminatorAt(int index) {
     if (index == -1) return _templateElement;
     var terminator = terminators[index];
-    if (terminator is Element && (terminator as Element).isTemplate &&
+    if (isSemanticTemplate(terminator) &&
         !identical(terminator, _templateElement)) {
-      var subIterator = _mdv(terminator)._templateIterator;
+      var subIterator = templateBindFallback(terminator)._templateIterator;
       if (subIterator != null) {
         return subIterator.getTerminatorAt(subIterator.terminators.length - 1);
       }
@@ -325,7 +320,7 @@
   }
 
   DocumentFragment getInstanceFragment(model, BindingDelegate delegate) {
-    return _templateElement.createInstance(model, delegate);
+    return templateBind(_templateElement).createInstance(model, delegate);
   }
 
   void _handleChanges(Iterable<ChangeRecord> splices) {
@@ -334,9 +329,9 @@
     splices = splices.where((s) => s is ListChangeRecord);
 
     var template = _templateElement;
-    var delegate = template.bindingDelegate;
+    var delegate = templateBind(template).bindingDelegate;
 
-    if (template.parentNode == null || template.document.window == null) {
+    if (template.parentNode == null || template.ownerDocument.window == null) {
       close();
       // TODO(jmesserly): MDV calls templateIteratorTable.delete(this) here,
       // but I think that's a no-op because only nodes are used as keys.
@@ -350,7 +345,8 @@
       for (int i = 0; i < splice.removedCount; i++) {
         var instanceNodes = extractInstanceAt(splice.index + removeDelta);
         if (instanceNodes.length == 0) continue;
-        var model = _mdv(instanceNodes.first)._templateInstance.model;
+        var model = nodeBindFallback(instanceNodes.first)
+            ._templateInstance.model;
         instanceCache[model] = instanceNodes;
       }
 
@@ -395,9 +391,9 @@
   }
 
   static void _unbindAllRecursively(Node node) {
-    var nodeExt = _mdv(node);
+    var nodeExt = nodeBindFallback(node);
     nodeExt._templateInstance = null;
-    if (node is Element && (node as Element).isTemplate) {
+    if (isSemanticTemplate(node)) {
       // Make sure we stop observing when we remove an element.
       var templateIterator = nodeExt._templateIterator;
       if (templateIterator != null) {
@@ -406,7 +402,7 @@
       }
     }
 
-    _nodeOrCustom(node).unbindAll();
+    nodeBind(node).unbindAll();
     for (var c = node.firstChild; c != null; c = c.nextNode) {
       _unbindAllRecursively(c);
     }
diff --git a/pkg/mdv/lib/src/text.dart b/pkg/template_binding/lib/src/text.dart
similarity index 75%
rename from pkg/mdv/lib/src/text.dart
rename to pkg/template_binding/lib/src/text.dart
index f17ba2d..8b66752 100644
--- a/pkg/mdv/lib/src/text.dart
+++ b/pkg/template_binding/lib/src/text.dart
@@ -2,14 +2,14 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of mdv;
+part of template_binding;
 
 /** Extensions to the [Text] API. */
-class _TextExtension extends _NodeExtension {
-  _TextExtension(Text node) : super(node);
+class _TextExtension extends NodeBindExtension {
+  _TextExtension(Text node) : super._(node);
 
   NodeBinding createBinding(String name, model, String path) {
-    if (name == 'text') return new _TextBinding(node, model, path);
+    if (name == 'text') return new _TextBinding(_node, model, path);
     return super.createBinding(name, model, path);
   }
 }
diff --git a/pkg/mdv/lib/src/text_area_element.dart b/pkg/template_binding/lib/src/text_area_element.dart
similarity index 79%
rename from pkg/mdv/lib/src/text_area_element.dart
rename to pkg/template_binding/lib/src/text_area_element.dart
index 200cd74..8eec85f 100644
--- a/pkg/mdv/lib/src/text_area_element.dart
+++ b/pkg/template_binding/lib/src/text_area_element.dart
@@ -2,19 +2,19 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of mdv;
+part of template_binding;
 
 /** Extensions to the [TextAreaElement] API. */
 class _TextAreaElementExtension extends _ElementExtension {
   _TextAreaElementExtension(TextAreaElement node) : super(node);
 
-  TextAreaElement get node => super.node;
+  TextAreaElement get _node => super._node;
 
   NodeBinding createBinding(String name, model, String path) {
     if (name == 'value') {
       // TODO(rafaelw): Maybe template should remove all binding instructions.
-      node.attributes.remove(name);
-      return new _ValueBinding(node, model, path);
+      _node.attributes.remove(name);
+      return new _ValueBinding(_node, model, path);
     }
     return super.createBinding(name, model, path);
   }
diff --git a/pkg/template_binding/lib/template_binding.dart b/pkg/template_binding/lib/template_binding.dart
new file mode 100644
index 0000000..72976ac
--- /dev/null
+++ b/pkg/template_binding/lib/template_binding.dart
@@ -0,0 +1,171 @@
+// 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 library provides access to the Polymer project's
+ * [Data Binding](http://www.polymer-project.org/docs/polymer/databinding.html)
+ * Find more information at the
+ * [Polymer.dart homepage](https://www.dartlang.org/polymer-dart/).
+ *
+ * Extends the capabilities of the HTML Template Element by enabling it to
+ * create, manage, and remove instances of content bound to data defined in
+ * Dart.
+ *
+ * Node.bind() is a new method added to all DOM nodes which instructs them to
+ * bind the named property to the data provided. These allows applications to
+ * create a data model in Dart or JavaScript that DOM reacts to.
+ */
+library template_binding;
+
+import 'dart:async';
+import 'dart:collection';
+import 'dart:html';
+import 'dart:svg' show SvgSvgElement;
+import 'package:observe/observe.dart';
+
+import 'src/list_diff.dart' show calculateSplices, ListChangeDelta;
+
+part 'src/element.dart';
+part 'src/input_bindings.dart';
+part 'src/input_element.dart';
+part 'src/node.dart';
+part 'src/select_element.dart';
+part 'src/template.dart';
+part 'src/template_iterator.dart';
+part 'src/text.dart';
+part 'src/text_area_element.dart';
+
+// TODO(jmesserly): ideally we would split TemplateBinding and Node.bind into
+// two packages, but this is not easy when we are faking extension methods.
+// Since TemplateElement needs to override Node.bind, it seems like the
+// Node.bind layer must have some innate knowledge of TemplateBinding.
+
+/**
+ * Provides access to the data binding APIs for the [node]. For example:
+ *
+ *     templateBind(node).model = new MyModel();
+ *
+ * This is equivalent to [nodeBind], but provides access to
+ * [TemplateBindExtension] APIs. [node] should be a [TemplateElement], or
+ * equivalent semantic template such as:
+ *
+ *     <table template repeat="{{row in rows}}">
+ *       <tr template repeat="{{item in row}}">
+ *         <td>{{item}}</td>
+ *       </tr>
+ *     </table>
+ */
+TemplateBindExtension templateBind(Element node) => nodeBind(node);
+
+/**
+ * Like [templateBind], but intended to be used only within a custom element
+ * that implements [TemplateBindExtension]. This method can be used to simulate
+ * a super call. For example:
+ *
+ *     class CoolTemplate extends TemplateElement
+ *         implements TemplateBindExtension {
+ *
+ *       createInstance(model, delegate) {
+ *         // do something cool...
+ *         // otherwise, fall back to superclass
+ *         return templateBindFallback(this).createInstance(model, delegate);
+ *       }
+ *       ...
+ *     }
+ */
+TemplateBindExtension templateBindFallback(Element node) =>
+    nodeBindFallback(node);
+
+/**
+ * Provides access to the data binding APIs for the [node]. For example:
+ *
+ *     nodeBind(node).bind('checked', model, 'path.to.some.value');
+ */
+NodeBindExtension nodeBind(Node node) {
+  return node is NodeBindExtension ? node : nodeBindFallback(node);
+}
+
+/**
+ * Like [nodeBind], but intended to be used only within a custom element that
+ * implements [NodeBindExtension]. This method can be used to simulate a super
+ * call. For example:
+ *
+ *     class FancyButton extends ButtonElement implements NodeBindExtension {
+ *       bind(name, model, path) {
+ *         if (name == 'fancy-prop') ... // do fancy binding
+ *         // otherwise, fall back to superclass
+ *         return nodeBindFallback(this).bind(name, model, path);
+ *       }
+ *       ...
+ *     }
+ */
+NodeBindExtension nodeBindFallback(Node node) {
+  var extension = _expando[node];
+  if (extension != null) return extension;
+
+  if (node is InputElement) {
+    extension = new _InputElementExtension(node);
+  } else if (node is SelectElement) {
+    extension = new _SelectElementExtension(node);
+  } else if (node is TextAreaElement) {
+    extension = new _TextAreaElementExtension(node);
+  } else if (node is Element) {
+    if (isSemanticTemplate(node)) {
+      extension = new TemplateBindExtension._(node);
+    } else {
+      extension = new _ElementExtension(node);
+    }
+  } else if (node is Text) {
+    extension = new _TextExtension(node);
+  } else {
+    extension = new NodeBindExtension._(node);
+  }
+
+  _expando[node] = extension;
+  return extension;
+}
+
+
+bool _isAttributeTemplate(Element n) => n.attributes.containsKey('template') &&
+    _SEMANTIC_TEMPLATE_TAGS.containsKey(n.localName);
+
+/**
+ * Returns true if this node is semantically a template.
+ *
+ * A node is a template if [tagName] is TEMPLATE, or the node has the
+ * 'template' attribute and this tag supports attribute form for backwards
+ * compatibility with existing HTML parsers. The nodes that can use attribute
+ * form are table elments (THEAD, TBODY, TFOOT, TH, TR, TD, CAPTION, COLGROUP
+ * and COL), OPTION, and OPTGROUP.
+ */
+bool isSemanticTemplate(Node n) => n is Element &&
+    ((n as Element).localName == 'template' || _isAttributeTemplate(n));
+
+// TODO(jmesserly): const set would be better
+const _SEMANTIC_TEMPLATE_TAGS = const {
+  'caption': null,
+  'col': null,
+  'colgroup': null,
+  'option': null,
+  'optgroup': null,
+  'tbody': null,
+  'td': null,
+  'tfoot': null,
+  'th': null,
+  'thead': null,
+  'tr': null,
+};
+
+
+// TODO(jmesserly): investigate if expandos give us enough performance.
+
+// The expando for storing our MDV extensions.
+//
+// In general, we need state associated with the nodes. Rather than having a
+// bunch of individual expandos, we keep one per node.
+//
+// Aside from the potentially helping performance, it also keeps things simpler
+// if we decide to integrate MDV into the DOM later, and means less code needs
+// to worry about expandos.
+final Expando _expando = new Expando('template_binding');
diff --git a/pkg/template_binding/pubspec.yaml b/pkg/template_binding/pubspec.yaml
new file mode 100644
index 0000000..62a8a94
--- /dev/null
+++ b/pkg/template_binding/pubspec.yaml
@@ -0,0 +1,12 @@
+name: template_binding
+author: Polymer.dart Team <web-ui-dev@dartlang.org>
+description: >
+  Extends the capabilities of the HTML Template Element by enabling it to
+  create, manage, and remove instances of content bound to data defined in Dart.
+homepage: https://www.dartlang.org/polymer-dart/
+dependencies:
+  logging: any
+  observe: any
+dev_dependencies:
+  custom_element: any
+  unittest: any
diff --git a/pkg/template_binding/test/analyzer_test.dart b/pkg/template_binding/test/analyzer_test.dart
new file mode 100644
index 0000000..5b47d43
--- /dev/null
+++ b/pkg/template_binding/test/analyzer_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library template_binding.test.analyzer_test;
+
+import 'dart:html';
+import 'package:template_binding/template_binding.dart';
+
+// @static-clean
+
+// This test ensures template_binding compiles without errors.
+void main() {
+  // To make analyzer happy about unused imports.
+  nodeBind(document);
+}
diff --git a/pkg/mdv/test/binding_syntax_test.dart b/pkg/template_binding/test/binding_syntax_test.dart
similarity index 91%
rename from pkg/mdv/test/binding_syntax_test.dart
rename to pkg/template_binding/test/binding_syntax_test.dart
index b4d0381..b8b6283 100644
--- a/pkg/mdv/test/binding_syntax_test.dart
+++ b/pkg/template_binding/test/binding_syntax_test.dart
@@ -2,21 +2,20 @@
 // 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 binding_syntax_test;
+library template_binding.test.binding_syntax_test;
 
 import 'dart:collection';
 import 'dart:html';
-import 'package:mdv/mdv.dart' as mdv;
+import 'package:template_binding/template_binding.dart';
 import 'package:observe/observe.dart';
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
-import 'mdv_test_utils.dart';
+import 'utils.dart';
 
 // Note: this file ported from
 // https://github.com/toolkitchen/mdv/blob/master/tests/syntax.js
 
 main() {
-  mdv.initialize();
   useHtmlConfiguration();
 
   group('Syntax FooBarModel', () {
@@ -28,8 +27,6 @@
 }
 
 syntaxTests(FooBarModel fooModel([foo, bar])) {
-  var testDiv;
-
   setUp(() {
     document.body.append(testDiv = new DivElement());
   });
@@ -39,21 +36,8 @@
     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;
-  }
-
   observeTest('Registration', () {
     var model = fooModel('bar');
-
     var testSyntax = new TestBindingSyntax();
     var div = createTestHtml('<template bind>{{ foo }}'
         '<template bind>{{ foo }}</template></template>');
@@ -62,7 +46,6 @@
     expect(div.nodes.length, 4);
     expect(div.nodes.last.text, 'bar');
     expect(div.nodes[2].tagName, 'TEMPLATE');
-
     expect(testSyntax.log, [
       [model, '', 'bind', 'TEMPLATE'],
       [model, 'foo', 'text', null],
@@ -135,7 +118,7 @@
 class TestBindingSyntax extends BindingDelegate {
   var log = [];
 
-  getBinding(model, String path, String name, Node node) {
+  getBinding(model, String path, String name, node) {
     log.add([model, path, name, node is Element ? node.tagName : null]);
   }
 }
@@ -166,7 +149,7 @@
   int removed = 0;
 
   DocumentFragment getInstanceFragment(Element template) {
-    var instance = template.createInstance();
+    var instance = templateBind(template).createInstance();
     var walker = new TreeWalker(instance, NodeFilter.SHOW_TEXT);
 
     var toRemove = [];
diff --git a/pkg/mdv/test/custom_element_bindings_test.dart b/pkg/template_binding/test/custom_element_bindings_test.dart
similarity index 65%
rename from pkg/mdv/test/custom_element_bindings_test.dart
rename to pkg/template_binding/test/custom_element_bindings_test.dart
index 3150a27..1779361 100644
--- a/pkg/mdv/test/custom_element_bindings_test.dart
+++ b/pkg/template_binding/test/custom_element_bindings_test.dart
@@ -2,26 +2,34 @@
 // 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;
+library template_binding.test.custom_element_bindings_test;
 
+import 'dart:async';
 import 'dart:html';
-import 'package:mdv/mdv.dart' as mdv;
+import 'package:custom_element/polyfill.dart';
+import 'package:template_binding/template_binding.dart';
 import 'package:observe/observe.dart' show toObservable;
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
-import 'mdv_test_utils.dart';
+import 'utils.dart';
+
+Future _registered;
 
 main() {
-  mdv.initialize();
   useHtmlConfiguration();
+
+  _registered = loadCustomElementPolyfill().then((_) {
+    document.register('my-custom-element', MyCustomElement);
+    document.register('with-attrs-custom-element', WithAttrsCustomElement);
+  });
+
   group('Custom Element Bindings', customElementBindingsTest);
 }
 
 customElementBindingsTest() {
-  var testDiv;
-
   setUp(() {
     document.body.append(testDiv = new DivElement());
+    return _registered;
   });
 
   tearDown(() {
@@ -29,25 +37,13 @@
     testDiv = null;
   });
 
-  createTestHtml(s) {
-    var div = new DivElement();
-    div.setInnerHtml(s, treeSanitizer: new NullTreeSanitizer());
-    testDiv.append(div);
-
-    for (var node in div.queryAll('*')) {
-      if (node.isTemplate) TemplateElement.decorate(node);
-    }
-
-    return div;
-  }
-
-
   observeTest('override bind/unbind/unbindAll', () {
     var element = new MyCustomElement();
     var model = toObservable({'a': new Point(123, 444), 'b': new Monster(100)});
 
-    element.bind('my-point', model, 'a');
-    element.bind('scary-monster', model, 'b');
+    nodeBind(element)
+        ..bind('my-point', model, 'a')
+        ..bind('scary-monster', model, 'b');
 
     expect(element.attributes, isNot(contains('my-point')));
     expect(element.attributes, isNot(contains('scary-monster')));
@@ -58,7 +54,7 @@
     model['a'] = null;
     performMicrotaskCheckpoint();
     expect(element.myPoint, null);
-    element.unbind('my-point');
+    nodeBind(element).unbind('my-point');
 
     model['a'] = new Point(1, 2);
     model['b'] = new Monster(200);
@@ -66,17 +62,17 @@
     expect(element.scaryMonster, model['b']);
     expect(element.myPoint, null, reason: 'a was unbound');
 
-    element.unbindAll();
+    nodeBind(element).unbindAll();
     model['b'] = null;
     performMicrotaskCheckpoint();
     expect(element.scaryMonster.health, 200);
   });
 
   observeTest('override attribute setter', () {
-    var element = new WithAttrsCustomElement().real;
+    var element = new WithAttrsCustomElement();
     var model = toObservable({'a': 1, 'b': 2});
-    element.bind('hidden?', model, 'a');
-    element.bind('id', model, 'b');
+    nodeBind(element).bind('hidden?', model, 'a');
+    nodeBind(element).bind('id', model, 'b');
 
     expect(element.attributes, contains('hidden'));
     expect(element.attributes['hidden'], '');
@@ -103,7 +99,7 @@
     expect(element.attributes['hidden'], '');
     expect(element.id, 'x');
 
-    expect(element.xtag.attributes.log, [
+    expect(element.attributes.log, [
       ['remove', 'hidden?'],
       ['[]=', 'hidden', ''],
       ['[]=', 'id', '2'],
@@ -117,38 +113,30 @@
   observeTest('template bind uses overridden custom element bind', () {
 
     var model = toObservable({'a': new Point(123, 444), 'b': new Monster(100)});
-
     var div = createTestHtml('<template bind>'
           '<my-custom-element my-point="{{a}}" scary-monster="{{b}}">'
           '</my-custom-element>'
         '</template>');
 
-    callback(fragment) {
-      for (var e in fragment.queryAll('my-custom-element')) {
-        new MyCustomElement.attach(e);
-      }
-    }
-    mdv.instanceCreated.add(callback);
-
-    div.query('template').model = model;
+    templateBind(div.query('template')).model = model;
     performMicrotaskCheckpoint();
 
     var element = div.nodes[1];
 
-    expect(element.xtag is MyCustomElement, true,
-        reason: '${element.xtag} should be a MyCustomElement');
+    expect(element is MyCustomElement, true,
+        reason: '${element} should be a MyCustomElement');
 
-    expect(element.xtag.myPoint, model['a']);
-    expect(element.xtag.scaryMonster, model['b']);
+    expect(element.myPoint, model['a']);
+    expect(element.scaryMonster, model['b']);
 
     expect(element.attributes, isNot(contains('my-point')));
     expect(element.attributes, isNot(contains('scary-monster')));
 
     model['a'] = null;
     performMicrotaskCheckpoint();
-    expect(element.xtag.myPoint, null);
+    expect(element.myPoint, null);
 
-    div.query('template').model = null;
+    templateBind(div.query('template')).model = null;
     performMicrotaskCheckpoint();
 
     expect(element.parentNode, null, reason: 'element was detached');
@@ -157,10 +145,8 @@
     model['b'] = new Monster(200);
     performMicrotaskCheckpoint();
 
-    expect(element.xtag.myPoint, null, reason: 'model was unbound');
-    expect(element.xtag.scaryMonster.health, 100, reason: 'model was unbound');
-
-    mdv.instanceCreated.remove(callback);
+    expect(element.myPoint, null, reason: 'model was unbound');
+    expect(element.scaryMonster.health, 100, reason: 'model was unbound');
   });
 
 }
@@ -171,20 +157,13 @@
 }
 
 /** Demonstrates a custom element overriding bind/unbind/unbindAll. */
-class MyCustomElement implements Element {
-  final Element real;
-
+class MyCustomElement extends HtmlElement implements NodeBindExtension {
   Point myPoint;
   Monster scaryMonster;
 
-  MyCustomElement() : this.attach(new Element.tag('my-custom-element'));
+  factory MyCustomElement() => new Element.tag('my-custom-element');
 
-  MyCustomElement.attach(this.real) {
-    real.xtag = this;
-  }
-
-  get attributes => real.attributes;
-  get bindings => real.bindings;
+  MyCustomElement.created() : super.created();
 
   NodeBinding createBinding(String name, model, String path) {
     switch (name) {
@@ -192,15 +171,15 @@
       case 'scary-monster':
         return new _MyCustomBinding(this, name, model, path);
     }
-    return real.createBinding(name, model, path);
+    return nodeBindFallback(this).createBinding(name, model, path);
   }
 
-  bind(String name, model, String path) => real.bind(name, model, path);
-  void unbind(String name) => real.unbind(name);
-  void unbindAll() => real.unbindAll();
+  bind(name, model, path) => nodeBindFallback(this).bind(name, model, path);
+  unbind(name) => nodeBindFallback(this).unbind(name);
+  unbindAll() => nodeBindFallback(this).unbindAll();
 }
 
-class _MyCustomBinding extends mdv.NodeBinding {
+class _MyCustomBinding extends NodeBinding {
   _MyCustomBinding(MyCustomElement node, property, model, path)
       : super(node, property, model, path) {
 
@@ -220,25 +199,17 @@
  * 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;
+class WithAttrsCustomElement extends HtmlElement {
+  AttributeMapWrapper _attributes;
 
-  factory WithAttrsCustomElement() {
-    var real = new Element.tag('with-attrs-custom-element');
-    var attributes = new AttributeMapWrapper(real.attributes);
-    return new WithAttrsCustomElement._(real, attributes);
+  factory WithAttrsCustomElement() =>
+      new Element.tag('with-attrs-custom-element');
+
+  WithAttrsCustomElement.created() : super.created() {
+    _attributes = new AttributeMapWrapper(super.attributes);
   }
 
-  WithAttrsCustomElement._(this.real, this.attributes) {
-    real.xtag = this;
-  }
-
-  createBinding(String name, model, String path) =>
-      real.createBinding(name, model, path);
-  bind(String name, model, String path) => real.bind(name, model, path);
-  void unbind(String name) => real.unbind(name);
-  void unbindAll() => real.unbindAll();
+  get attributes => _attributes;
 }
 
 // TODO(jmesserly): would be nice to use mocks when mirrors work on dart2js.
@@ -264,6 +235,7 @@
     _map.remove(key);
   }
 
+  void addAll(Map<K, V> other) => _map.addAll(other);
   void clear() => _map.clear();
   void forEach(void f(K key, V value)) => _map.forEach(f);
   Iterable<K> get keys => _map.keys;
@@ -272,10 +244,3 @@
   bool get isEmpty => _map.isEmpty;
   bool get isNotEmpty => _map.isNotEmpty;
 }
-
-/**
- * Sanitizer which does nothing.
- */
-class NullTreeSanitizer implements NodeTreeSanitizer {
-  void sanitizeTree(Node node) {}
-}
diff --git a/pkg/mdv/test/element_bindings_test.dart b/pkg/template_binding/test/element_bindings_test.dart
similarity index 88%
rename from pkg/mdv/test/element_bindings_test.dart
rename to pkg/template_binding/test/element_bindings_test.dart
index 8ffbc5c..56c42c4 100644
--- a/pkg/mdv/test/element_bindings_test.dart
+++ b/pkg/template_binding/test/element_bindings_test.dart
@@ -2,21 +2,19 @@
 // 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 node_bindings_test;
+library template_binding.test.element_bindings_test;
 
-import 'dart:async';
 import 'dart:html';
-import 'package:mdv/mdv.dart' as mdv;
 import 'package:observe/observe.dart';
+import 'package:template_binding/template_binding.dart';
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
-import 'mdv_test_utils.dart';
+import 'utils.dart';
 
 // Note: this file ported from
 // https://github.com/toolkitchen/mdv/blob/master/tests/element_bindings.js
 
 main() {
-  mdv.initialize();
   useHtmlConfiguration();
   group('Element Bindings', elementBindingTests);
 }
@@ -24,8 +22,6 @@
 observePath(obj, path) => new PathObserver(obj, path);
 
 elementBindingTests() {
-  var testDiv;
-
   setUp(() {
     document.body.append(testDiv = new DivElement());
   });
@@ -39,7 +35,7 @@
     var template = new Element.html('<template bind>{{a}} and {{b}}');
     testDiv.append(template);
     var model = toObservable({'a': 1, 'b': 2});
-    template.model = model;
+    templateBind(template).model = model;
     performMicrotaskCheckpoint();
     var text = testDiv.nodes[1];
     expect(text.text, '1 and 2');
@@ -52,7 +48,7 @@
   observeTest('SimpleBinding', () {
     var el = new DivElement();
     var model = toObservable({'a': '1'});
-    el.bind('foo', model, 'a');
+    nodeBind(el).bind('foo', model, 'a');
     performMicrotaskCheckpoint();
     expect(el.attributes['foo'], '1');
 
@@ -76,7 +72,7 @@
   observeTest('SimpleBindingWithDashes', () {
     var el = new DivElement();
     var model = toObservable({'a': '1'});
-    el.bind('foo-bar', model, 'a');
+    nodeBind(el).bind('foo-bar', model, 'a');
     performMicrotaskCheckpoint();
     expect(el.attributes['foo-bar'], '1');
 
@@ -89,7 +85,7 @@
     var el = new DivElement();
     el.innerHtml = '<!-- Comment -->';
     var model = toObservable({'a': '1'});
-    el.bind('foo-bar', model, 'a');
+    nodeBind(el).bind('foo-bar', model, 'a');
     performMicrotaskCheckpoint();
     expect(el.attributes['foo-bar'], '1');
 
@@ -108,9 +104,9 @@
     el.text = 'dummy';
     el.nodes.first.text = 'Hello {{ adj }} {{noun}}!';
     var template = new Element.html('<template bind>');
-    template.content.append(el);
+    templateBind(template).content.append(el);
     testDiv.append(template);
-    template.model = model;
+    templateBind(template).model = model;
 
     performMicrotaskCheckpoint();
     el = testDiv.nodes[1].nodes.first;
@@ -125,7 +121,7 @@
     var model = toObservable({'val': 'ping'});
 
     var el = new InputElement();
-    el.bind('value', model, 'val');
+    nodeBind(el).bind('value', model, 'val');
     performMicrotaskCheckpoint();
     expect(el.value, 'ping');
 
@@ -136,7 +132,7 @@
     // Try a deep path.
     model = toObservable({'a': {'b': {'c': 'ping'}}});
 
-    el.bind('value', model, 'a.b.c');
+    nodeBind(el).bind('value', model, 'a.b.c');
     performMicrotaskCheckpoint();
     expect(el.value, 'ping');
 
@@ -170,7 +166,7 @@
     var el = new InputElement();
     testDiv.append(el);
     el.type = 'checkbox';
-    el.bind('checked', model, 'val');
+    nodeBind(el).bind('checked', model, 'val');
     performMicrotaskCheckpoint();
     expect(el.checked, true);
 
@@ -200,7 +196,7 @@
     var el = new InputElement();
     testDiv.append(el);
     el.type = 'checkbox';
-    el.bind('checked', model, 'val');
+    nodeBind(el).bind('checked', model, 'val');
     performMicrotaskCheckpoint();
     expect(el.checked, true);
 
@@ -217,7 +213,7 @@
     var el = new InputElement();
     testDiv.append(el);
     el.type = 'checkbox';
-    el.bind('checked', model, 'val');
+    nodeBind(el).bind('checked', model, 'val');
     performMicrotaskCheckpoint();
     expect(el.checked, true);
 
@@ -239,25 +235,25 @@
     testDiv.append(el1);
     el1.type = 'radio';
     el1.name = RADIO_GROUP_NAME;
-    el1.bind('checked', model, 'val1');
+    nodeBind(el1).bind('checked', model, 'val1');
 
     var el2 = new InputElement();
     testDiv.append(el2);
     el2.type = 'radio';
     el2.name = RADIO_GROUP_NAME;
-    el2.bind('checked', model, 'val2');
+    nodeBind(el2).bind('checked', model, 'val2');
 
     var el3 = new InputElement();
     testDiv.append(el3);
     el3.type = 'radio';
     el3.name = RADIO_GROUP_NAME;
-    el3.bind('checked', model, 'val3');
+    nodeBind(el3).bind('checked', model, 'val3');
 
     var el4 = new InputElement();
     testDiv.append(el4);
     el4.type = 'radio';
     el4.name = 'othergroup';
-    el4.bind('checked', model, 'val4');
+    nodeBind(el4).bind('checked', model, 'val4');
 
     performMicrotaskCheckpoint();
     expect(el1.checked, true);
@@ -302,25 +298,25 @@
     form1.append(el1);
     el1.type = 'radio';
     el1.name = RADIO_GROUP_NAME;
-    el1.bind('checked', model, 'val1');
+    nodeBind(el1).bind('checked', model, 'val1');
 
     var el2 = new InputElement();
     form1.append(el2);
     el2.type = 'radio';
     el2.name = RADIO_GROUP_NAME;
-    el2.bind('checked', model, 'val2');
+    nodeBind(el2).bind('checked', model, 'val2');
 
     var el3 = new InputElement();
     form2.append(el3);
     el3.type = 'radio';
     el3.name = RADIO_GROUP_NAME;
-    el3.bind('checked', model, 'val3');
+    nodeBind(el3).bind('checked', model, 'val3');
 
     var el4 = new InputElement();
     form2.append(el4);
     el4.type = 'radio';
     el4.name = RADIO_GROUP_NAME;
-    el4.bind('checked', model, 'val4');
+    nodeBind(el4).bind('checked', model, 'val4');
 
     performMicrotaskCheckpoint();
     expect(el1.checked, true);
@@ -357,7 +353,7 @@
     input.type = 'checkbox';
 
     var model = toObservable({'a': {'b': false}});
-    input.bind('checked', model, 'a.b');
+    nodeBind(input).bind('checked', model, 'a.b');
 
     input.click();
     expect(model['a']['b'], true);
@@ -375,7 +371,7 @@
 
     var model = toObservable({'val': 2});
 
-    select.bind('selectedIndex', model, 'val');
+    nodeBind(select).bind('selectedIndex', model, 'val');
     performMicrotaskCheckpoint();
     expect(select.selectedIndex, 2);
 
@@ -387,12 +383,12 @@
   observeTest('MultipleReferences', () {
     var el = new DivElement();
     var template = new Element.html('<template bind>');
-    template.content.append(el);
+    templateBind(template).content.append(el);
     testDiv.append(template);
 
     var model = toObservable({'foo': 'bar'});
     el.attributes['foo'] = '{{foo}} {{foo}}';
-    template.model = model;
+    templateBind(template).model = model;
 
     performMicrotaskCheckpoint();
     el = testDiv.nodes[1];
diff --git a/pkg/mdv/test/node_bindings_test.dart b/pkg/template_binding/test/node_bindings_test.dart
similarity index 86%
rename from pkg/mdv/test/node_bindings_test.dart
rename to pkg/template_binding/test/node_bindings_test.dart
index a12e878..04ef8d4 100644
--- a/pkg/mdv/test/node_bindings_test.dart
+++ b/pkg/template_binding/test/node_bindings_test.dart
@@ -2,27 +2,24 @@
 // 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 node_bindings_test;
+library template_binding.test.node_bindings_test;
 
 import 'dart:html';
-import 'package:mdv/mdv.dart' as mdv;
 import 'package:observe/observe.dart' show toObservable;
+import 'package:template_binding/template_binding.dart';
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
-import 'mdv_test_utils.dart';
+import 'utils.dart';
 
 // Note: this file ported from
 // https://github.com/toolkitchen/mdv/blob/master/tests/node_bindings.js
 
 main() {
-  mdv.initialize();
   useHtmlConfiguration();
   group('Node Bindings', nodeBindingTests);
 }
 
 nodeBindingTests() {
-  var testDiv;
-
   setUp(() {
     document.body.append(testDiv = new DivElement());
   });
@@ -35,14 +32,14 @@
   observeTest('Text', () {
     var text = new Text('hi');
     var model = toObservable({'a': 1});
-    text.bind('text', model, 'a');
+    nodeBind(text).bind('text', model, 'a');
     expect(text.text, '1');
 
     model['a'] = 2;
     performMicrotaskCheckpoint();
     expect(text.text, '2');
 
-    text.unbind('text');
+    nodeBind(text).unbind('text');
     model['a'] = 3;
     performMicrotaskCheckpoint();
     expect(text.text, '2');
@@ -53,8 +50,8 @@
   observeTest('Element', () {
     var element = new DivElement();
     var model = toObservable({'a': 1, 'b': 2});
-    element.bind('hidden?', model, 'a');
-    element.bind('id', model, 'b');
+    nodeBind(element).bind('hidden?', model, 'a');
+    nodeBind(element).bind('id', model, 'b');
 
     expect(element.attributes, contains('hidden'));
     expect(element.attributes['hidden'], '');
@@ -81,7 +78,7 @@
     var el = new Element.tag(tagName);
     testDiv.nodes.add(el);
     var model = toObservable({'x': 42});
-    el.bind('value', model, 'x');
+    nodeBind(el).bind('value', model, 'x');
     expect(el.value, '42');
 
     model['x'] = 'Hi';
@@ -93,13 +90,13 @@
     dispatchEvent('input', el);
     expect(model['x'], 'changed');
 
-    el.unbind('value');
+    nodeBind(el).unbind('value');
 
     el.value = 'changed again';
     dispatchEvent('input', el);
     expect(model['x'], 'changed');
 
-    el.bind('value', model, 'x');
+    nodeBind(el).bind('value', model, 'x');
     model['x'] = null;
     performMicrotaskCheckpoint();
     expect(el.value, '');
@@ -112,7 +109,7 @@
     var input = new InputElement();
     input.type = 'radio';
     var model = toObservable({'x': true});
-    input.bind('checked', model, 'x');
+    nodeBind(input).bind('checked', model, 'x');
     expect(input.checked, true);
 
     model['x'] = false;
@@ -124,7 +121,7 @@
     dispatchEvent('change', input);
     expect(model['x'], true, reason: 'input.checked should set model');
 
-    input.unbind('checked');
+    nodeBind(input).unbind('checked');
 
     input.checked = false;
     dispatchEvent('change', input);
@@ -137,7 +134,7 @@
     testDiv.append(input);
     input.type = 'checkbox';
     var model = toObservable({'x': true});
-    input.bind('checked', model, 'x');
+    nodeBind(input).bind('checked', model, 'x');
     expect(input.checked, true);
 
     model['x'] = false;
diff --git a/pkg/mdv/test/template_element_test.dart b/pkg/template_binding/test/template_element_test.dart
similarity index 93%
rename from pkg/mdv/test/template_element_test.dart
rename to pkg/template_binding/test/template_element_test.dart
index a39ad62..005c137 100644
--- a/pkg/mdv/test/template_element_test.dart
+++ b/pkg/template_binding/test/template_element_test.dart
@@ -2,17 +2,17 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library template_element_test;
+library template_binding.test.template_element_test;
 
 import 'dart:async';
 import 'dart:collection';
 import 'dart:html';
 import 'dart:math' as math;
-import 'package:mdv/mdv.dart' as mdv;
 import 'package:observe/observe.dart';
+import 'package:template_binding/template_binding.dart';
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
-import 'mdv_test_utils.dart';
+import 'utils.dart';
 
 // Note: this file ported from
 // https://github.com/toolkitchen/mdv/blob/master/tests/template_element.js
@@ -21,14 +21,11 @@
 // look for "assertNodesAre".
 
 main() {
-  mdv.initialize();
   useHtmlConfiguration();
   group('Template Element', templateElementTests);
 }
 
 templateElementTests() {
-  var testDiv;
-
   setUp(() {
     document.body.append(testDiv = new DivElement());
   });
@@ -38,31 +35,6 @@
     testDiv = null;
   });
 
-  createTestHtml(s) {
-    var div = new DivElement();
-    div.setInnerHtml(s, treeSanitizer: new NullTreeSanitizer());
-    testDiv.append(div);
-
-    for (var node in div.queryAll('*')) {
-      if (node.isTemplate) TemplateElement.decorate(node);
-    }
-
-    return div;
-  }
-
-  createShadowTestHtml(s) {
-    var div = new DivElement();
-    var root = div.createShadowRoot();
-    root.innerHtml = s;
-    testDiv.append(div);
-
-    for (var node in root.queryAll('*')) {
-      if (node.isTemplate) TemplateElement.decorate(node);
-    }
-
-    return root;
-  }
-
   var expando = new Expando('observeTest');
   void addExpandos(node) {
     while (node != null) {
@@ -417,7 +389,8 @@
   observeTest('Removal from iteration needs to unbind', () {
     var div = createTestHtml(
         '<template repeat="{{}}"><a>{{v}}</a></template>');
-    var model = toObservable([{'v': 0}, {'v': 1}, {'v': 2}, {'v': 3}, {'v': 4}]);
+    var model = toObservable([{'v': 0}, {'v': 1}, {'v': 2}, {'v': 3},
+        {'v': 4}]);
     recursivelySetTemplateModel(div, model);
     deliverChanges(model);
 
@@ -583,7 +556,7 @@
 
   observeTest('DefaultStyles', () {
     var t = new Element.tag('template');
-    TemplateElement.decorate(t);
+    TemplateBindExtension.decorate(t);
 
     document.body.append(t);
     expect(t.getComputedStyle().display, 'none');
@@ -609,14 +582,15 @@
     var t = div.nodes.first;
 
     var model = toObservable({'name': 'Leela'});
-    t.bind('bind', model, '');
+    nodeBind(t).bind('bind', model, '');
 
     deliverChanges(model);
     expect(div.nodes[1].text, 'Hi Leela');
   });
 
   observeTest('BindPlaceHolderHasNewLine', () {
-    var div = createTestHtml('<template bind="{{}}">Hi {{\nname\n}}</template>');
+    var div = createTestHtml(
+        '<template bind="{{}}">Hi {{\nname\n}}</template>');
     var model = toObservable({'name': 'Leela'});
     recursivelySetTemplateModel(div, model);
 
@@ -635,7 +609,7 @@
     var t1 = div.nodes.first;
     var t2 = div.nodes[1];
 
-    expect(t2.ref, t1);
+    expect(templateBind(t2).ref, t1);
 
     var model = toObservable({'name': 'Fry'});
     recursivelySetTemplateModel(div, model);
@@ -662,7 +636,7 @@
     expect(div.nodes.length, 2);
     expect(t.nextNode.text, 'Hi Leela');
 
-    t.bind('bind', model, 'XZ');
+    nodeBind(t).bind('bind', model, 'XZ');
     deliverChanges(model);
 
     expect(div.nodes.length, 2);
@@ -718,7 +692,8 @@
     m['contacts'].replaceRange(0, 1,
         toObservable([{'name': 'Tab'}, {'name': 'Neal'}]));
     deliverChanges(m);
-    assertNodesAre(div, ['Hi Tab', 'Hi Neal', 'Hi Erik', 'Hi Dimitri', 'Hi Alex']);
+    assertNodesAre(div, ['Hi Tab', 'Hi Neal', 'Hi Erik', 'Hi Dimitri',
+        'Hi Alex']);
 
     m['contacts'] = toObservable([{'name': 'Alex'}]);
     deliverChanges(m);
@@ -750,7 +725,8 @@
   });
 
   observeTest('RepeatEmptyPath', () {
-    var div = createTestHtml('<template repeat="{{}}">Hi {{ name }}</template>');
+    var div = createTestHtml(
+        '<template repeat="{{}}">Hi {{ name }}</template>');
     var t = div.nodes.first;
 
     var m = toObservable([
@@ -782,7 +758,8 @@
 
     m.replaceRange(0, 1, toObservable([{'name': 'Tab'}, {'name': 'Neal'}]));
     deliverChanges(m);
-    assertNodesAre(div, ['Hi Tab', 'Hi Neal', 'Hi Erik', 'Hi Dimitri', 'Hi Alex']);
+    assertNodesAre(div, ['Hi Tab', 'Hi Neal', 'Hi Erik', 'Hi Dimitri',
+        'Hi Alex']);
 
     m.length = 0;
     m.add(toObservable({'name': 'Alex'}));
@@ -791,7 +768,8 @@
   });
 
   observeTest('RepeatNullModel', () {
-    var div = createTestHtml('<template repeat="{{}}">Hi {{ name }}</template>');
+    var div = createTestHtml(
+        '<template repeat="{{}}">Hi {{ name }}</template>');
     var t = div.nodes.first;
 
     var m = null;
@@ -808,7 +786,8 @@
   });
 
   observeTest('RepeatReuse', () {
-    var div = createTestHtml('<template repeat="{{}}">Hi {{ name }}</template>');
+    var div = createTestHtml(
+        '<template repeat="{{}}">Hi {{ name }}</template>');
     var t = div.nodes.first;
 
     var m = toObservable([
@@ -860,7 +839,7 @@
     var m = toObservable({
       'a': true
     });
-    t.bind('bind', m, '');
+    nodeBind(t).bind('bind', m, '');
     deliverChanges(m);
 
     var instanceInput = t.nextNode;
@@ -1124,7 +1103,8 @@
       }));
     }));
     expect(select.nodes[0].tagName, 'TEMPLATE');
-    expect(select.nodes[0].ref.content.nodes[0].tagName, 'OPTGROUP');
+    expect((templateBind(templateBind(select.nodes[0]).ref)
+        .content.nodes[0] as Element).tagName, 'OPTGROUP');
 
     var optgroup = select.nodes[1];
     expect(optgroup.nodes[0].tagName, 'TEMPLATE');
@@ -1207,8 +1187,8 @@
     expect(tbody.nodes[2].nodes[1].text, '2');
     expect(tbody.nodes[2].nodes[2].text, '3');
 
-    // Asset the 'class' binding is retained on the semantic template (just check
-    // the last one).
+    // Asset the 'class' binding is retained on the semantic template (just
+    // check the last one).
     expect(tbody.nodes[2].nodes[2].attributes['class'], '3');
   });
 
@@ -1428,7 +1408,7 @@
     observer.observe(div, childList: true);
 
     var template = div.firstChild;
-    template.bind('repeat', toObservable(m.toList()), '');
+    nodeBind(template).bind('repeat', toObservable(m.toList()), '');
     performMicrotaskCheckpoint();
     var records = observer.takeRecords();
     expect(records.length, 0);
@@ -1473,16 +1453,17 @@
     expect(div.nodes.length, 2);
     expect(div.nodes[1].text, '3');
 
-    template.unbind('bind');
-    template.bind('repeat', m, 'a');
+    nodeBind(template)
+        ..unbind('bind')
+        ..bind('repeat', m, 'a');
     deliverChanges(m);
     expect(div.nodes.length, 4);
     expect(div.nodes[1].text, '0');
     expect(div.nodes[2].text, '1');
     expect(div.nodes[3].text, '2');
 
-    template.unbind('repeat');
-    template.bind('bind', m, 'a.1.b');
+    nodeBind(template).unbind('repeat');
+    nodeBind(template).bind('bind', m, 'a.1.b');
 
     deliverChanges(m);
     expect(div.nodes.length, 2);
@@ -1519,8 +1500,8 @@
         '<template><b></b></template>');
     var templateA = div.nodes.first;
     var templateB = div.nodes.last;
-    var contentA = templateA.content;
-    var contentB = templateB.content;
+    var contentA = templateBind(templateA).content;
+    var contentB = templateBind(templateB).content;
     expect(contentA, isNotNull);
 
     expect(templateA.ownerDocument, isNot(equals(contentA.ownerDocument)));
@@ -1548,10 +1529,12 @@
         '<template></template>'
         '</template>');
     var templateA = div.nodes.first;
-    var templateB = templateA.content.nodes.first;
+    var templateB = templateBind(templateA).content.nodes.first;
 
-    expect(templateB.ownerDocument, templateA.content.ownerDocument);
-    expect(templateB.content.ownerDocument, templateA.content.ownerDocument);
+    expect(templateB.ownerDocument, templateBind(templateA)
+        .content.ownerDocument);
+    expect(templateBind(templateB).content.ownerDocument,
+        templateBind(templateA).content.ownerDocument);
   });
 
   observeTest('BindShadowDOM', () {
@@ -1570,7 +1553,7 @@
       var model = toObservable({'name': 'Leela'});
       var template = new Element.html('<template>Hi {{ name }}</template>');
       var root = createShadowTestHtml('');
-      root.nodes.add(template.createInstance(model));
+      root.nodes.add(templateBind(template).createInstance(model));
 
       performMicrotaskCheckpoint();
       expect(root.text, 'Hi Leela');
@@ -1645,12 +1628,13 @@
           '{{ foo }}:{{ replaceme }}'
         '</template>'
       '</template>');
-    var outer = div.nodes.first;
+    var outer = templateBind(div.nodes.first);
     var model = toObservable({'b': {'foo': 'bar'}});
 
     var host = new DivElement();
     var instance = outer.createInstance(model, new TestBindingSyntax());
-    expect(outer.content.nodes.first, instance.nodes.first.ref);
+    expect(outer.content.nodes.first,
+        templateBind(instance.nodes.first).ref);
 
     host.append(instance);
     performMicrotaskCheckpoint();
@@ -1667,10 +1651,10 @@
         '</template>'
       '</template>';
 
-    TemplateElement.bootstrap(div);
-    var template = div.nodes.first;
+    TemplateBindExtension.bootstrap(div);
+    var template = templateBind(div.nodes.first);
     expect(template.content.nodes.length, 2);
-    var template2 = template.content.nodes.first.nextNode;
+    var template2 = templateBind(template.content.nodes.first.nextNode);
     expect(template2.content.nodes.length, 1);
     expect(template2.content.nodes.first.text, 'Hello');
 
@@ -1683,32 +1667,13 @@
         '</template>'
       '</template>';
 
-    TemplateElement.bootstrap(template);
-    template2 = template.content.nodes.first;
+    TemplateBindExtension.bootstrap(template);
+    template2 = templateBind(templateBind(template).content.nodes.first);
     expect(template2.content.nodes.length, 2);
-    var template3 = template2.content.nodes.first.nextNode;
+    var template3 = templateBind(template2.content.nodes.first.nextNode);
     expect(template3.content.nodes.length, 1);
     expect(template3.content.nodes.first.text, 'Hello');
   });
-
-  observeTest('instanceCreated hack', () {
-    var called = false;
-
-    callback(node) {
-      called = true;
-      expect(node.nodeType, Node.DOCUMENT_FRAGMENT_NODE);
-    }
-    mdv.instanceCreated.add(callback);
-
-    var div = createTestHtml('<template bind="{{}}">Foo</template>');
-    expect(called, false);
-
-    recursivelySetTemplateModel(div, null);
-    performMicrotaskCheckpoint();
-    expect(called, true);
-
-    mdv.instanceCreated.remove(callback);
-  });
 }
 
 class TestBindingSyntax extends BindingDelegate {
@@ -1774,10 +1739,3 @@
   }
   return value;
 }
-
-/**
- * Sanitizer which does nothing.
- */
-class NullTreeSanitizer implements NodeTreeSanitizer {
-  void sanitizeTree(Node node) {}
-}
diff --git a/pkg/template_binding/test/utils.dart b/pkg/template_binding/test/utils.dart
new file mode 100644
index 0000000..4aee4b9
--- /dev/null
+++ b/pkg/template_binding/test/utils.dart
@@ -0,0 +1,96 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library template_binding.test.utils;
+
+import 'dart:html';
+import 'package:observe/observe.dart';
+import 'package:template_binding/template_binding.dart';
+import 'package:unittest/unittest.dart';
+
+import 'package:observe/src/microtask.dart';
+export 'package:observe/src/microtask.dart';
+
+final bool parserHasNativeTemplate = () {
+  var div = new DivElement()..innerHtml = '<table><template>';
+  return div.firstChild.firstChild != null &&
+      div.firstChild.firstChild.tagName == 'TEMPLATE';
+}();
+
+recursivelySetTemplateModel(element, model, [delegate]) {
+  for (var node in element.queryAll('*')) {
+    if (isSemanticTemplate(node)) {
+      templateBind(node)
+          ..bindingDelegate = delegate
+          ..model = model;
+    }
+  }
+}
+
+dispatchEvent(type, target) {
+  target.dispatchEvent(new Event(type, cancelable: false));
+}
+
+class FooBarModel extends Observable {
+  @observable var foo;
+  @observable var bar;
+
+  FooBarModel([this.foo, this.bar]);
+}
+
+@reflectable
+class FooBarNotifyModel extends ChangeNotifier implements FooBarModel {
+  var _foo;
+  var _bar;
+
+  FooBarNotifyModel([this._foo, this._bar]);
+
+  get foo => _foo;
+  set foo(value) {
+    _foo = notifyPropertyChange(#foo, _foo, value);
+  }
+
+  get bar => _bar;
+  set bar(value) {
+    _bar = notifyPropertyChange(#bar, _bar, value);
+  }
+}
+
+observeTest(name, testCase) => test(name, wrapMicrotask(testCase));
+
+solo_observeTest(name, testCase) => solo_test(name, wrapMicrotask(testCase));
+
+DivElement testDiv;
+
+createTestHtml(s) {
+  var div = new DivElement();
+  div.setInnerHtml(s, treeSanitizer: new NullTreeSanitizer());
+  testDiv.append(div);
+
+  for (var node in div.queryAll('*')) {
+    if (isSemanticTemplate(node)) TemplateBindExtension.decorate(node);
+  }
+
+  return div;
+}
+
+createShadowTestHtml(s) {
+  var div = new DivElement();
+  var root = div.createShadowRoot();
+  root.setInnerHtml(s, treeSanitizer: new NullTreeSanitizer());
+  testDiv.append(div);
+
+  for (var node in root.querySelectorAll('*')) {
+    if (isSemanticTemplate(node)) TemplateBindExtension.decorate(node);
+  }
+
+  return root;
+}
+
+/**
+ * Sanitizer which does nothing.
+ */
+class NullTreeSanitizer implements NodeTreeSanitizer {
+  void sanitizeTree(Node node) {}
+}
diff --git a/pkg/unittest/lib/test_controller.js b/pkg/unittest/lib/test_controller.js
index 68b83bf..f78fbde 100644
--- a/pkg/unittest/lib/test_controller.js
+++ b/pkg/unittest/lib/test_controller.js
@@ -89,11 +89,14 @@
 }
 
 function processMessage(msg) {
+  if (typeof msg != 'string') return;
   // TODO(ricow): REMOVE, debug info, see issue 13292
   if (!testRunner) {
-    printMessage('processMessage(): ' + msg);
+    // Filter out ShadowDOM polyfill messages which are random floats.
+    if (msg != parseFloat(msg)) {
+      printMessage('processMessage(): ' + msg);
+    }
   }
-  if (typeof msg != 'string') return;
   if (msg == 'unittest-suite-done') {
     notifyDone();
   } else if (msg == 'unittest-suite-wait-for-done') {
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index e7cedb4..8e0f615 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -291,7 +291,7 @@
   if (type == kIsFile) {
     const wchar_t* system_old_path = StringUtils::Utf8ToWide(old_path);
     const wchar_t* system_new_path = StringUtils::Utf8ToWide(new_path);
-    DWORD flags = MOVEFILE_WRITE_THROUGH;
+    DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING;
     int move_status =
         MoveFileExW(system_old_path, system_new_path, flags);
     free(const_cast<wchar_t*>(system_old_path));
@@ -309,7 +309,7 @@
   if (type == kIsLink) {
     const wchar_t* system_old_path = StringUtils::Utf8ToWide(old_path);
     const wchar_t* system_new_path = StringUtils::Utf8ToWide(new_path);
-    DWORD flags = MOVEFILE_WRITE_THROUGH;
+    DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING;
     int move_status =
         MoveFileExW(system_old_path, system_new_path, flags);
     free(const_cast<wchar_t*>(system_old_path));
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 5aa10cb..5824572 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -297,10 +297,6 @@
  */
 DART_EXPORT Dart_Handle Dart_NewUnhandledExceptionError(Dart_Handle exception);
 
-/* Deprecated. */
-/* TODO(turnidge): Remove all uses and delete. */
-DART_EXPORT Dart_Handle Dart_Error(const char* error);
-
 /**
  * Propagates an error.
  *
diff --git a/runtime/lib/collection_patch.dart b/runtime/lib/collection_patch.dart
index d2331c3..cdee5c4 100644
--- a/runtime/lib/collection_patch.dart
+++ b/runtime/lib/collection_patch.dart
@@ -845,7 +845,7 @@
                                      implements EfficientLength {
   LinkedHashMap<dynamic, V> _map;
   _LinkedHashMapValueIterable(this._map);
-  Iterator<K> get iterator => new _LinkedHashMapValueIterator<V>(_map);
+  Iterator<V> get iterator => new _LinkedHashMapValueIterator<V>(_map);
   bool contains(Object value) => _map.containsValue(value);
   bool get isEmpty => _map.isEmpty;
   bool get isNotEmpty => _map.isNotEmpty;
diff --git a/runtime/lib/double.dart b/runtime/lib/double.dart
index 6480f5d..c5b2c38 100644
--- a/runtime/lib/double.dart
+++ b/runtime/lib/double.dart
@@ -96,6 +96,7 @@
   bool get isNegative native "Double_getIsNegative";
   bool get isInfinite native "Double_getIsInfinite";
   bool get isNaN native "Double_getIsNaN";
+  bool get isFinite => !isInfinite && !isNaN;  // Can be optimized.
 
   double abs() {
     // Handle negative 0.0.
diff --git a/runtime/lib/errors.cc b/runtime/lib/errors.cc
index 4912747..3e9137d 100644
--- a/runtime/lib/errors.cc
+++ b/runtime/lib/errors.cc
@@ -35,13 +35,16 @@
   script.GetTokenLocation(assertion_start, &from_line, &from_column);
   intptr_t to_line, to_column;
   script.GetTokenLocation(assertion_end, &to_line, &to_column);
+  // The snippet will extract the correct assertion code even if the source
+  // is generated.
   args.SetAt(0, String::Handle(
       script.GetSnippet(from_line, from_column, to_line, to_column)));
 
   // Initialize location arguments starting at position 1.
+  // Do not set a column if the source has been generated as it will be wrong.
   args.SetAt(1, String::Handle(script.url()));
   args.SetAt(2, Smi::Handle(Smi::New(from_line)));
-  args.SetAt(3, Smi::Handle(Smi::New(from_column)));
+  args.SetAt(3, Smi::Handle(Smi::New(script.HasSource() ? from_column : -1)));
 
   Exceptions::ThrowByType(Exceptions::kAssertion, args);
   UNREACHABLE();
@@ -89,8 +92,8 @@
   iterator.NextFrame();  // Skip native call.
   const Script& script = Script::Handle(Exceptions::GetCallerScript(&iterator));
   args.SetAt(0, String::Handle(script.url()));
-  intptr_t line, column;
-  script.GetTokenLocation(fallthrough_pos, &line, &column);
+  intptr_t line;
+  script.GetTokenLocation(fallthrough_pos, &line, NULL);
   args.SetAt(1, Smi::Handle(Smi::New(line)));
 
   Exceptions::ThrowByType(Exceptions::kFallThrough, args);
@@ -116,8 +119,8 @@
   const Script& script = Script::Handle(Exceptions::GetCallerScript(&iterator));
   args.SetAt(0, class_name);
   args.SetAt(1, String::Handle(script.url()));
-  intptr_t line, column;
-  script.GetTokenLocation(error_pos, &line, &column);
+  intptr_t line;
+  script.GetTokenLocation(error_pos, &line, NULL);
   args.SetAt(2, Smi::Handle(Smi::New(line)));
 
   Exceptions::ThrowByType(Exceptions::kAbstractClassInstantiation, args);
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index 1f3ee3e..8e4ecbe 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -20,7 +20,12 @@
       native "AssertionError_throwNew";
 
   String toString() {
-    return "'$_url': Failed assertion: line $_line pos $_column: "
+    var columnInfo = "";
+    if (_column > 0) {
+      // Only add column information if it is valid.
+      columnInfo = " pos $_column";
+    }
+    return "'$_url': Failed assertion: line $_line$columnInfo: "
         "'$_failedAssertion' is not true.";
   }
   final String _failedAssertion;
@@ -32,23 +37,23 @@
 patch class TypeError extends AssertionError {
   TypeError._create(String url, int line, int column,
                     this._srcType, this._dstType, this._dstName,
-                    this._malformedError)
+                    this._boundError)
       : super._create("is assignable", url, line, column);
 
   static _throwNew(int location,
                    Object src_value,
                    String dst_type_name,
                    String dst_name,
-                   String malformed_error)
+                   String bound_error)
       native "TypeError_throwNew";
 
   String toString() {
-    String str = (_malformedError != null) ? _malformedError : "";
+    String str = (_boundError != null) ? _boundError : "";
     if ((_dstName != null) && (_dstName.length > 0)) {
       str = "${str}type '$_srcType' is not a subtype of "
             "type '$_dstType' of '$_dstName'.";
     } else {
-      str = "${str}malformed type used.";
+      str = "${str}malbounded type used.";
     }
     return str;
   }
@@ -56,19 +61,19 @@
   final String _srcType;
   final String _dstType;
   final String _dstName;
-  final String _malformedError;
+  final String _boundError;
 }
 
 patch class CastError extends Error {
   CastError._create(this._url, this._line, this._column,
                     this._srcType, this._dstType, this._dstName,
-                    this._malformedError);
+                    this._boundError);
 
   // A CastError is allocated by TypeError._throwNew() when dst_name equals
   // Exceptions::kCastErrorDstName.
 
   String toString() {
-    String str = (_malformedError != null) ? _malformedError : "";
+    String str = (_boundError != null) ? _boundError : "";
     str = "${str}type '$_srcType' is not a subtype of "
           "type '$_dstType' in type cast.";
     return str;
@@ -81,7 +86,7 @@
   final String _srcType;
   final String _dstType;
   final String _dstName;
-  final String _malformedError;
+  final String _boundError;
 }
 
 patch class FallThroughError {
@@ -223,6 +228,11 @@
         }
         break;
       }
+      case _InvocationMirror._SUPER: {
+        msg = "Super class of class '${_receiver.runtimeType}' has no instance "
+              "$type_str '$memberName'$args_message.";
+        break;
+      }
       case _InvocationMirror._STATIC: {
         msg = "No static $type_str '$memberName' declared in class "
             "'$_receiver'.";
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc
index dedb88d..8df1396 100644
--- a/runtime/lib/integers.cc
+++ b/runtime/lib/integers.cc
@@ -208,7 +208,7 @@
 
   Scanner scanner(value, Symbols::Empty());
   const Scanner::GrowableTokenStream& tokens = scanner.GetStream();
-  String* int_string;
+  const String* int_string;
   bool is_positive;
   if (Scanner::IsValidLiteral(tokens,
                              Token::kINTEGER,
diff --git a/runtime/lib/integers.dart b/runtime/lib/integers.dart
index c0fb109..cc9a9fc 100644
--- a/runtime/lib/integers.dart
+++ b/runtime/lib/integers.dart
@@ -97,6 +97,7 @@
   bool get isNaN => false;
   bool get isNegative => this < 0;
   bool get isInfinite => false;
+  bool get isFinite => true;
 
   int toUnsigned(int width) {
     return this & ((1 << width) - 1);
diff --git a/runtime/lib/invocation_mirror.h b/runtime/lib/invocation_mirror.h
index af0d24c..6e0a75b 100644
--- a/runtime/lib/invocation_mirror.h
+++ b/runtime/lib/invocation_mirror.h
@@ -27,14 +27,15 @@
   };
 
   enum Call {
-    // These values, except kDynamic, are only used when throwing
+    // These values, except kDynamic and kSuper, are only used when throwing
     // NoSuchMethodError for compile-time resolution failures.
     kDynamic = 0,
-    kStatic  = 1,
-    kConstructor = 2,
-    kTopLevel = 3,
+    kSuper = 1,
+    kStatic  = 2,
+    kConstructor = 3,
+    kTopLevel = 4,
     kCallShift = kTypeBits,
-    kCallBits = 2,
+    kCallBits = 3,
     kCallMask = (1 << kCallBits) - 1
   };
 
diff --git a/runtime/lib/invocation_mirror_patch.dart b/runtime/lib/invocation_mirror_patch.dart
index 9669626..4c2e7e5 100644
--- a/runtime/lib/invocation_mirror_patch.dart
+++ b/runtime/lib/invocation_mirror_patch.dart
@@ -13,20 +13,22 @@
   static const int _TYPE_BITS = 2;
   static const int _TYPE_MASK = (1 << _TYPE_BITS) - 1;
 
-  // These values, except _DYNAMIC, are only used when throwing
+  // These values, except _DYNAMIC and _SUPER, are only used when throwing
   // NoSuchMethodError for compile-time resolution failures.
   static const int _DYNAMIC = 0;
-  static const int _STATIC = 1;
-  static const int _CONSTRUCTOR = 2;
-  static const int _TOP_LEVEL = 3;
+  static const int _SUPER = 1;
+  static const int _STATIC = 2;
+  static const int _CONSTRUCTOR = 3;
+  static const int _TOP_LEVEL = 4;
   static const int _CALL_SHIFT = _TYPE_BITS;
-  static const int _CALL_BITS = 2;
+  static const int _CALL_BITS = 3;
   static const int _CALL_MASK = (1 << _CALL_BITS) - 1;
 
   // Internal representation of the invocation mirror.
   final String _functionName;
   final List _argumentsDescriptor;
   final List _arguments;
+  final bool _isSuperInvocation;
 
   // External representation of the invocation mirror; populated on demand.
   Symbol _memberName;
@@ -45,7 +47,7 @@
           new _collection_dev.Symbol.unvalidated(
               _functionName.substring(4) + "=");
     } else {
-      _type = _METHOD;
+      _type = _isSuperInvocation ? (_SUPER << _CALL_SHIFT) | _METHOD : _METHOD;
       _memberName = new _collection_dev.Symbol.unvalidated(_functionName);
     }
   }
@@ -93,38 +95,43 @@
     if (_type == null) {
       _setMemberNameAndType();
     }
-    return _type == _METHOD;
+    return (_type & _TYPE_MASK) == _METHOD;
   }
 
   bool get isAccessor {
     if (_type == null) {
       _setMemberNameAndType();
     }
-    return _type != _METHOD;
+    return (_type & _TYPE_MASK) != _METHOD;
   }
 
   bool get isGetter {
     if (_type == null) {
       _setMemberNameAndType();
     }
-    return _type == _GETTER;
+    return (_type & _TYPE_MASK) == _GETTER;
   }
 
   bool get isSetter {
     if (_type == null) {
       _setMemberNameAndType();
     }
-    return _type == _SETTER;
+    return (_type & _TYPE_MASK) == _SETTER;
   }
 
   _InvocationMirror(this._functionName,
                     this._argumentsDescriptor,
-                    this._arguments);
+                    this._arguments,
+                    this._isSuperInvocation);
 
   static _allocateInvocationMirror(String functionName,
                                    List argumentsDescriptor,
-                                   List arguments) {
-    return new _InvocationMirror(functionName, argumentsDescriptor, arguments);
+                                   List arguments,
+                                   bool isSuperInvocation) {
+    return new _InvocationMirror(functionName,
+                                 argumentsDescriptor,
+                                 arguments,
+                                 isSuperInvocation);
   }
 
   static _invoke(Object receiver,
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index dc6808b..2522480 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -16,6 +16,10 @@
 
 namespace dart {
 
+DEFINE_FLAG(bool, use_mirrored_compilation_error, false,
+    "Wrap compilation errors that occur during reflective access in a "
+    "MirroredCompilationError, rather than suspending the isolate.");
+
 static RawInstance* CreateMirror(const String& mirror_class_name,
                                  const Array& constructor_arguments) {
   const Library& mirrors_lib = Library::Handle(Library::MirrorsLibrary());
@@ -41,7 +45,7 @@
 
 
 static void ThrowInvokeError(const Error& error) {
-  if (error.IsLanguageError()) {
+  if (FLAG_use_mirrored_compilation_error && error.IsLanguageError()) {
     // A compilation error that was delayed by lazy compilation.
     const LanguageError& compilation_error = LanguageError::Cast(error);
     String& message = String::Handle(compilation_error.message());
@@ -107,7 +111,9 @@
 }
 
 static void EnsureConstructorsAreCompiled(const Function& func) {
-  if (func.kind() != RawFunction::kConstructor) return;
+  // Only generative constructors can have initializing formals.
+  if (!func.IsConstructor()) return;
+
   const Class& cls = Class::Handle(func.Owner());
   const Error& error = Error::Handle(cls.EnsureIsFinalized(Isolate::Current()));
   if (!error.IsNull()) {
@@ -235,11 +241,16 @@
 
 
 static RawInstance* CreateTypedefMirror(const Class& cls,
+                                        const AbstractType& type,
+                                        const Bool& is_declaration,
                                         const Instance& owner_mirror) {
-  const Array& args = Array::Handle(Array::New(3));
+  const Array& args = Array::Handle(Array::New(6));
   args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
-  args.SetAt(1, String::Handle(cls.UserVisibleName()));
-  args.SetAt(2, owner_mirror);
+  args.SetAt(1, type);
+  args.SetAt(2, String::Handle(cls.UserVisibleName()));
+  args.SetAt(3, Bool::Get(cls.NumTypeParameters() != 0));
+  args.SetAt(4, cls.NumTypeParameters() == 0 ? Bool::False() : is_declaration);
+  args.SetAt(5, owner_mirror);
   return CreateMirror(Symbols::_LocalTypedefMirrorImpl(), args);
 }
 
@@ -328,7 +339,7 @@
       return CreateFunctionTypeMirror(cls, type);
     } else {
       // We represent typedefs as non-canonical signature classes.
-      return CreateTypedefMirror(cls, owner_mirror);
+      return CreateTypedefMirror(cls, type, is_declaration, owner_mirror);
     }
   }
 
@@ -828,6 +839,31 @@
 }
 
 
+static RawAbstractType* InstantiateType(const AbstractType& type,
+                                        const AbstractType& instantiator) {
+  ASSERT(type.IsFinalized());
+  ASSERT(instantiator.IsFinalized());
+  ASSERT(!type.IsMalformed());
+  ASSERT(!instantiator.IsMalformed());
+
+  if (type.IsInstantiated()) {
+    return type.Canonicalize();
+  }
+
+  const AbstractTypeArguments& type_args =
+      AbstractTypeArguments::Handle(instantiator.arguments());
+  Error& bound_error = Error::Handle();
+  AbstractType& result =
+      AbstractType::Handle(type.InstantiateFrom(type_args, &bound_error));
+  if (!bound_error.IsNull()) {
+    ThrowInvokeError(bound_error);
+    UNREACHABLE();
+  }
+  ASSERT(result.IsFinalized());
+  return result.Canonicalize();
+}
+
+
 DEFINE_NATIVE_ENTRY(Mirrors_makeLocalMirrorSystem, 0) {
   return CreateMirrorSystem();
 }
@@ -979,6 +1015,7 @@
   return super_type.raw();
 }
 
+
 DEFINE_NATIVE_ENTRY(ClassMirror_supertype_instantiated, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   ASSERT(!type.IsMalformed());
@@ -988,25 +1025,8 @@
     UNREACHABLE();
   }
   const Class& cls = Class::Handle(type.type_class());
-  AbstractType& super_type = AbstractType::Handle(cls.super_type());
-  AbstractType& result = AbstractType::Handle(super_type.raw());
-
-  ASSERT(super_type.IsType());
-  if (!super_type.IsInstantiated()) {
-    AbstractTypeArguments& type_args =
-        AbstractTypeArguments::Handle(type.arguments());
-    Error& bound_error = Error::Handle();
-    result ^= super_type.InstantiateFrom(type_args, &bound_error);
-    if (!bound_error.IsNull()) {
-      ThrowInvokeError(bound_error);
-      UNREACHABLE();
-    }
-    result ^= result.Canonicalize();
-    ASSERT(result.IsType());
-  }
-
-  ASSERT(result.IsFinalized());
-  return result.raw();
+  const AbstractType& super_type = AbstractType::Handle(cls.super_type());
+  return InstantiateType(super_type, type);
 }
 
 
@@ -1041,27 +1061,13 @@
     ThrowInvokeError(error);
   }
 
-  AbstractTypeArguments& type_args =
-      AbstractTypeArguments::Handle(type.arguments());
-  Error& bound_error = Error::Handle();
-
   Array& interfaces = Array::Handle(cls.interfaces());
   Array& interfaces_inst = Array::Handle(Array::New(interfaces.Length()));
   AbstractType& interface = AbstractType::Handle();
 
   for (int i = 0; i < interfaces.Length(); i++) {
     interface ^= interfaces.At(i);
-    ASSERT(interface.IsType());
-    if (!interface.IsInstantiated()) {
-      bound_error ^= Object::null();
-      interface ^= interface.InstantiateFrom(type_args, &bound_error);
-      if (!bound_error.IsNull()) {
-        ThrowInvokeError(bound_error);
-        UNREACHABLE();
-      }
-      interface ^= interface.Canonicalize();
-      ASSERT(interface.IsType());
-    }
+    interface = InstantiateType(interface, type);
     interfaces_inst.SetAt(i, interface);
   }
 
@@ -1100,29 +1106,8 @@
   if (mixin_type.IsNull()) {
     return mixin_type.raw();
   }
-  ASSERT(mixin_type.IsFinalized());
 
-  ASSERT(!instantiator.IsMalformed());
-  ASSERT(instantiator.IsFinalized());
-
-  AbstractType& result = AbstractType::Handle(mixin_type.raw());
-
-  ASSERT(mixin_type.IsType());
-  if (!mixin_type.IsInstantiated()) {
-    AbstractTypeArguments& type_args =
-        AbstractTypeArguments::Handle(instantiator.arguments());
-    Error& bound_error = Error::Handle();
-    result ^= mixin_type.InstantiateFrom(type_args, &bound_error);
-    if (!bound_error.IsNull()) {
-      ThrowInvokeError(bound_error);
-      UNREACHABLE();
-    }
-    result ^= result.Canonicalize();
-    ASSERT(result.IsType());
-  }
-
-  ASSERT(result.IsFinalized());
-  return result.raw();
+  return InstantiateType(mixin_type, instantiator);
 }
 
 
@@ -1319,20 +1304,33 @@
 DEFINE_NATIVE_ENTRY(TypeVariableMirror_instantiate_from, 2) {
   GET_NON_NULL_NATIVE_ARGUMENT(TypeParameter, param, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Type, instantiator, arguments->NativeArgAt(1));
-
   ASSERT(param.parameterized_class() == instantiator.type_class());
-
-  AbstractTypeArguments& type_args =
-      AbstractTypeArguments::Handle(instantiator.arguments());
-  Error& bound_error = Error::Handle();
-  AbstractType& result =
-      AbstractType::Handle(param.InstantiateFrom(type_args, &bound_error));
-  ASSERT(bound_error.IsNull());
-  ASSERT(result.IsFinalized());
-  return result.raw();
+  return InstantiateType(param, instantiator);
 }
 
 
+DEFINE_NATIVE_ENTRY(TypedefMirror_instantiate_from, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Type, instantiator, arguments->NativeArgAt(1));
+  const Class& cls = Class::Handle(type.type_class());
+  // We represent typedefs as non-canonical signature classes.
+  ASSERT(cls.IsSignatureClass() && !cls.IsCanonicalSignatureClass());
+  return InstantiateType(type, instantiator);
+}
+
+
+
+DEFINE_NATIVE_ENTRY(TypedefMirror_declaration, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(0));
+  const Class& cls = Class::Handle(type.type_class());
+  // We represent typedefs as non-canonical signature classes.
+  ASSERT(cls.IsSignatureClass() && !cls.IsCanonicalSignatureClass());
+  return CreateTypedefMirror(cls,
+                             AbstractType::Handle(cls.DeclarationType()),
+                             Bool::True(),  // is_declaration
+                             Object::null_instance());
+}
+
 DEFINE_NATIVE_ENTRY(InstanceMirror_invoke, 5) {
   // Argument 0 is the mirror, which is unused by the native. It exists
   // because this native is an instance method in order to be polymorphic
@@ -1450,6 +1448,12 @@
   GET_NON_NULL_NATIVE_ARGUMENT(Array, lookup_parts, arguments->NativeArgAt(1));
   ASSERT(lookup_parts.Length() >= 1 && lookup_parts.Length() <= 3);
 
+  if (!closure.IsClosure()) {
+    const Array& result_tuple = Array::Handle(Array::New(2));
+    result_tuple.SetAt(0, Bool::False());
+    return result_tuple.raw();
+  }
+
   Function& function = Function::Handle();
   const bool callable = closure.IsCallable(&function, NULL);
   ASSERT(callable);
@@ -1950,11 +1954,15 @@
 
 
 DEFINE_NATIVE_ENTRY(TypedefMirror_referent, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
-  const Class& cls = Class::Handle(ref.GetClassReferent());
+  GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(0));
+  const Class& cls = Class::Handle(type.type_class());
   const Function& sig_func = Function::Handle(cls.signature_function());
   const Class& sig_cls = Class::Handle(sig_func.signature_class());
-  return MirrorReference::New(sig_cls);
+
+  AbstractType& referent_type = AbstractType::Handle(sig_cls.DeclarationType());
+  referent_type = InstantiateType(referent_type, type);
+
+  return CreateFunctionTypeMirror(sig_cls, referent_type);
 }
 
 
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 26688f0..1e79507 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -6,6 +6,49 @@
 
 import "dart:collection";
 
+final emptyList = new UnmodifiableListView([]);
+final emptyMap = new _UnmodifiableMapView({});
+
+// Copied from js_mirrors, in turn copied from the package
+// "unmodifiable_collection".
+// TODO(14314): Move to dart:collection.
+class _UnmodifiableMapView<K, V> implements Map<K, V> {
+   Map<K, V> _source;
+  _UnmodifiableMapView(Map<K, V> source) : _source = source;
+
+ static void _throw() {
+    throw new UnsupportedError("Cannot modify an unmodifiable Map");
+  }
+
+  int get length => _source.length;
+
+  bool get isEmpty => _source.isEmpty;
+
+  bool get isNotEmpty => _source.isNotEmpty;
+
+  V operator [](K key) => _source[key];
+
+  bool containsKey(K key) => _source.containsKey(key);
+
+  bool containsValue(V value) => _source.containsValue(value);
+
+  void forEach(void f(K key, V value)) => _source.forEach(f);
+
+  Iterable<K> get keys => _source.keys;
+
+  Iterable<V> get values => _source.values;
+
+  void operator []=(K key, V value) => _throw();
+
+  V putIfAbsent(K key, V ifAbsent()) { _throw(); }
+
+  void addAll(Map<K, V> other) => _throw();
+
+  V remove(K key) { _throw(); }
+
+  void clear() => _throw();
+}
+
 // These values are allowed to be passed directly over the wire.
 bool _isSimpleValue(var value) {
   return (value == null || value is num || value is String || value is bool);
@@ -18,11 +61,13 @@
       new_map[key] = value;
     }
   });
-  return new_map;
+  return new _UnmodifiableMapView(new_map);
 }
 
-Map _makeMemberMap(List mirrors) => new Map<Symbol, dynamic>.fromIterable(
-    mirrors, key: (e) => e.simpleName);
+Map _makeMemberMap(List mirrors) {
+  return new _UnmodifiableMapView(
+      new Map<Symbol, dynamic>.fromIterable(mirrors, key: (e) => e.simpleName));
+}
 
 String _n(Symbol symbol) => _symbol_dev.Symbol.getName(symbol);
 
@@ -139,10 +184,6 @@
 }
 
 abstract class _LocalMirrorImpl implements Mirror {
-  int get hashCode {
-    throw new UnimplementedError('Mirror.hashCode is not implemented');
-  }
-
   // Local mirrors always return the same MirrorSystem.  This field
   // is more interesting once we implement remote mirrors.
   MirrorSystem get mirrors => _Mirrors.currentMirrorSystem();
@@ -510,8 +551,8 @@
       _superinterfaces = isOriginalDeclaration
           ? _nativeInterfaces(_reflectedType)
           : _nativeInterfacesInstantiated(_reflectedType);
-      _superinterfaces = _superinterfaces
-          .map((i) => reflectType(i)).toList(growable:false);
+      _superinterfaces =
+          new UnmodifiableListView(_superinterfaces.map(reflectType));
     }
     return _superinterfaces;
   }
@@ -621,16 +662,18 @@
   List<TypeVariableMirror> _typeVariables = null;
   List<TypeVariableMirror> get typeVariables {
     if (_typeVariables == null) {
+      if (_isAnonymousMixinApplication) return _typeVariables = emptyList;
       _typeVariables = new List<TypeVariableMirror>();
-      if (_isAnonymousMixinApplication) return _typeVariables;
 
       List params = _ClassMirror_type_variables(_reflectee);
+      ClassMirror owner = originalDeclaration;
       var mirror;
       for (var i = 0; i < params.length; i += 2) {
         mirror = new _LocalTypeVariableMirrorImpl(
-            params[i + 1], params[i], this);
+            params[i + 1], params[i], owner);
         _typeVariables.add(mirror);
       }
+      _typeVariables = new UnmodifiableListView(_typeVariables);
     }
     return _typeVariables;
   }
@@ -639,10 +682,10 @@
   List<TypeMirror> get typeArguments {
     if(_typeArguments == null) {
       if(_isGenericDeclaration || _isAnonymousMixinApplication) {
-        _typeArguments = new List<TypeMirror>();
+        _typeArguments = emptyList;
       } else {
         _typeArguments =
-            new List<TypeMirror>.from(_computeTypeArguments(_reflectedType));
+            new UnmodifiableListView(_computeTypeArguments(_reflectedType));
       }
     }
     return _typeArguments;
@@ -700,7 +743,7 @@
   List<InstanceMirror> get metadata {
     // Get the metadata objects, convert them into InstanceMirrors using
     // reflect() and then make them into a Dart list.
-    return _metadata(_reflectee).map(reflect).toList(growable:false);
+    return new UnmodifiableListView(_metadata(_reflectee).map(reflect));
   }
 
   bool operator ==(other) {
@@ -785,8 +828,8 @@
   TypeMirror _returnType = null;
   TypeMirror get returnType {
     if (_returnType == null) {
-      _returnType =
-          reflectType(_FunctionTypeMirror_return_type(_reflectee));
+      _returnType = reflectType(_FunctionTypeMirror_return_type(_reflectee));
+      _returnType = _returnType._instantiateInContextOf(reflectType(_instantiator));
     }
     return _returnType;
   }
@@ -795,12 +838,21 @@
   List<ParameterMirror> get parameters {
     if (_parameters == null) {
       _parameters = _FunctionTypeMirror_parameters(_reflectee);
+      _parameters.forEach((p) {
+        p._type = p.type._instantiateInContextOf(reflectType(_instantiator));
+      });
+      _parameters = new UnmodifiableListView(_parameters);
     }
     return _parameters;
   }
 
-  Map<Symbol, Mirror> get members => new Map<Symbol,Mirror>();
-  Map<Symbol, MethodMirror> get constructors => new Map<Symbol,MethodMirror>();
+  bool get isOriginalDeclaration => true;
+  get originalDeclaration => this;
+  get typeVariables => emptyList;
+  get typeArguments => emptyList;
+  get metadata => emptyList;
+  Map<Symbol, Mirror> get members => emptyMap;
+  Map<Symbol, MethodMirror> get constructors => emptyMap;
 
   String toString() => "FunctionTypeMirror on '${_n(simpleName)}'";
 
@@ -834,7 +886,7 @@
   List<InstanceMirror> get metadata {
     // Get the metadata objects, convert them into InstanceMirrors using
     // reflect() and then make them into a Dart list.
-    return _metadata(_reflectee).map(reflect).toList(growable:false);
+    return new UnmodifiableListView(_metadata(_reflectee).map(reflect));
   }
 
   bool operator ==(other) {
@@ -855,7 +907,7 @@
   DeclarationMirror _owner;
   DeclarationMirror get owner {
     if (_owner == null) {
-      _owner = _TypeVariableMirror_owner(_reflectee);
+      _owner = _TypeVariableMirror_owner(_reflectee).originalDeclaration;
     }
     return _owner;
   }
@@ -880,8 +932,8 @@
   bool get hasReflectedType => false;
   Type get reflectedType => throw new UnsupportedError() ;
 
-  List<TypeVariableMirror> get typeVariables => new UnmodifiableListView<TypeVariableMirror>();
-  List<TypeMirror> get typeArguments => new UnmodifiableListView<TypeMirror>();
+  List<TypeVariableMirror> get typeVariables => emptyList;
+  List<TypeMirror> get typeArguments => emptyList;
 
   bool get isOriginalDeclaration => true;
   TypeMirror get originalDeclaration => this;
@@ -908,7 +960,8 @@
     var instantiator = declaration;
     while (instantiator is MethodMirror) instantiator = instantiator.owner;
     if (instantiator is LibraryMirror) return this;
-    if (instantiator is! ClassMirror) throw "UNREACHABLE";
+    if (!(instantiator is ClassMirror || instantiator is TypedefMirror))
+      throw "UNREACHABLE";
     if (instantiator.isOriginalDeclaration) return this;
 
     return reflectType(
@@ -921,15 +974,18 @@
 class _LocalTypedefMirrorImpl extends _LocalDeclarationMirrorImpl
     implements TypedefMirror {
   _LocalTypedefMirrorImpl(reflectee,
+                          this._reflectedType,
                           String simpleName,
+                          this._isGeneric,
+                          this._isGenericDeclaration,
                           this._owner)
       : super(reflectee, _s(simpleName));
 
-  final bool isTopLevel = true;
+  final Type _reflectedType;
+  final bool _isGeneric;
+  final bool _isGenericDeclaration;
 
-  // TODO(12282): Deal with generic typedefs.
-  bool get _isGeneric => false;
-
+  bool get isTopLevel => true;
   bool get isPrivate => false;
 
   DeclarationMirror _owner;
@@ -947,20 +1003,72 @@
   TypeMirror _referent = null;
   TypeMirror get referent {
     if (_referent == null) {
-      // TODO(12282): Deal with generic typedef.
-      return new _LocalFunctionTypeMirrorImpl(
-          _TypedefMirror_referent(_reflectee), null);
+      _referent = _nativeReferent(_reflectedType);
+      _referent._instantiator = _reflectedType;
     }
     return _referent;
   }
 
+  bool get isOriginalDeclaration => !_isGeneric || _isGenericDeclaration;
+
+  TypedefMirror get originalDeclaration {
+    if (isOriginalDeclaration) {
+      return this;
+    } else {
+      return _nativeDeclaration(_reflectedType);
+    }
+  }
+
+  List<TypeVariableMirror> _typeVariables = null;
+  List<TypeVariableMirror> get typeVariables {
+    if (_typeVariables == null) {
+      _typeVariables = new List<TypeVariableMirror>();
+      List params = _LocalClassMirrorImpl._ClassMirror_type_variables(_reflectee);
+      TypedefMirror owner = originalDeclaration;
+      var mirror;
+      for (var i = 0; i < params.length; i += 2) {
+        mirror = new _LocalTypeVariableMirrorImpl(
+            params[i + 1], params[i], owner);
+        _typeVariables.add(mirror);
+      }
+    }
+    return _typeVariables;
+  }
+
+  List<TypeMirror> _typeArguments = null;
+  List<TypeMirror> get typeArguments {
+    if(_typeArguments == null) {
+      if(_isGenericDeclaration) {
+        _typeArguments = emptyList;
+      } else {
+        _typeArguments = new UnmodifiableListView(
+            _LocalClassMirrorImpl._computeTypeArguments(_reflectedType));
+      }
+    }
+    return _typeArguments;
+  }
+
+  TypeMirror _instantiateInContextOf(declaration) {
+    var instantiator = declaration;
+    while (instantiator is MethodMirror) instantiator = instantiator.owner;
+    if (instantiator is LibraryMirror) return this;
+    if (!(instantiator is ClassMirror || instantiator is TypedefMirror))
+      throw "UNREACHABLE";
+
+    return reflectType(
+        _nativeInstatniateFrom(_reflectedType, instantiator._reflectedType));
+  }
+
   String toString() => "TypedefMirror on '${_n(simpleName)}'";
 
-  static _TypedefMirror_referent(_reflectee)
+  static _nativeReferent(reflectedType)
       native "TypedefMirror_referent";
 
-  // TODO(12282): This is wrong.
-  TypeMirror _instantiateInContextOf(declaration) => this;
+  static _nativeInstatniateFrom(reflectedType, instantiator)
+      native "TypedefMirror_instantiate_from";
+
+  static _nativeDeclaration(reflectedType)
+      native "TypedefMirror_declaration";
 }
 
 class _LocalLibraryMirrorImpl extends _LocalObjectMirrorImpl
@@ -1011,8 +1119,7 @@
   Map<Symbol, ClassMirror> _classes;
   Map<Symbol, ClassMirror> get classes {
     if (_classes == null) {
-      _classes = _filterMap(members,
-                            (key, value) => (value is ClassMirror));
+      _classes = _filterMap(members, (key, value) => (value is ClassMirror));
     }
     return _classes;
   }
@@ -1053,7 +1160,7 @@
   List<InstanceMirror> get metadata {
     // Get the metadata objects, convert them into InstanceMirrors using
     // reflect() and then make them into a Dart list.
-    return _metadata(_reflectee).map(reflect).toList(growable:false);
+    return new UnmodifiableListView(_metadata(_reflectee).map(reflect));
   }
 
   bool operator ==(other) {
@@ -1145,6 +1252,7 @@
   List<ParameterMirror> get parameters {
     if (_parameters == null) {
       _parameters = _MethodMirror_parameters(_reflectee);
+      _parameters = new UnmodifiableListView(_parameters);
     }
     return _parameters;
   }
@@ -1280,8 +1388,8 @@
   bool get hasDefaultValue => _defaultValueReflectee != null;
 
   List<InstanceMirror> get metadata {
-    if ( _unmirroredMetadata == null) return const [];
-    return _unmirroredMetadata.map(reflect).toList(growable:false);
+    if ( _unmirroredMetadata == null) return emptyList;
+    return new UnmodifiableListView(_unmirroredMetadata.map(reflect));
   }
 
   TypeMirror _type = null;
@@ -1308,7 +1416,7 @@
   final Symbol simpleName;
   final bool isTopLevel = true;
   // Fixed length 0, therefore immutable.
-  final List<InstanceMirror> metadata = new List(0);
+  final List<InstanceMirror> metadata = emptyList;
 
   SourceLocation get location {
     throw new UnimplementedError('TypeMirror.location is not implemented');
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 2417476..493a523 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -4,6 +4,7 @@
 
 #include "vm/bootstrap_natives.h"
 
+#include "lib/invocation_mirror.h"
 #include "vm/exceptions.h"
 #include "vm/heap.h"
 #include "vm/native_entry.h"
@@ -61,7 +62,9 @@
   dart_arguments.SetAt(3, func_args);
   dart_arguments.SetAt(4, func_named_args);
 
-  if (is_method.value()) {
+  if (is_method.value() &&
+      (((invocation_type.Value() >> InvocationMirror::kCallShift) &
+        InvocationMirror::kCallMask) != InvocationMirror::kSuper)) {
     // Report if a function with same name (but different arguments) has been
     // found.
     Function& function = Function::Handle();
@@ -113,10 +116,12 @@
       AbstractType::CheckedHandle(arguments->NativeArgAt(3));
   const Bool& negate = Bool::CheckedHandle(arguments->NativeArgAt(4));
   ASSERT(type.IsFinalized());
-  Error& malformed_error = Error::Handle();
+  ASSERT(!type.IsMalformed());
+  ASSERT(!type.IsMalbounded());
+  Error& bound_error = Error::Handle();
   const bool is_instance_of = instance.IsInstanceOf(type,
                                                     instantiator_type_arguments,
-                                                    &malformed_error);
+                                                    &bound_error);
   if (FLAG_trace_type_checks) {
     const char* result_str = is_instance_of ? "true" : "false";
     OS::Print("Object.instanceOf: result %s\n", result_str);
@@ -124,21 +129,21 @@
     OS::Print("  instance type: %s\n",
               String::Handle(instance_type.Name()).ToCString());
     OS::Print("  test type: %s\n", String::Handle(type.Name()).ToCString());
-    if (!malformed_error.IsNull()) {
-      OS::Print("  malformed error: %s\n", malformed_error.ToErrorCString());
+    if (!bound_error.IsNull()) {
+      OS::Print("  bound error: %s\n", bound_error.ToErrorCString());
     }
   }
-  if (!is_instance_of && !malformed_error.IsNull()) {
+  if (!is_instance_of && !bound_error.IsNull()) {
     // Throw a dynamic type error only if the instanceof test fails.
     DartFrameIterator iterator;
     StackFrame* caller_frame = iterator.NextFrame();
     ASSERT(caller_frame != NULL);
     const intptr_t location = caller_frame->GetTokenPos();
-    String& malformed_error_message = String::Handle(
-        String::New(malformed_error.ToErrorCString()));
+    String& bound_error_message = String::Handle(
+        String::New(bound_error.ToErrorCString()));
     Exceptions::CreateAndThrowTypeError(
         location, Symbols::Empty(), Symbols::Empty(),
-        Symbols::Empty(), malformed_error_message);
+        Symbols::Empty(), bound_error_message);
     UNREACHABLE();
   }
   return Bool::Get(negate.value() ? !is_instance_of : is_instance_of).raw();
@@ -156,13 +161,25 @@
       AbstractType::CheckedHandle(arguments->NativeArgAt(3));
   ASSERT(type.IsFinalized());
   ASSERT(!type.IsMalformed());
-  Error& malformed_error = Error::Handle();
+  ASSERT(!type.IsMalbounded());
+  Error& bound_error = Error::Handle();
   if (instance.IsNull()) {
     return instance.raw();
   }
   const bool is_instance_of = instance.IsInstanceOf(type,
                                                     instantiator_type_arguments,
-                                                    &malformed_error);
+                                                    &bound_error);
+  if (FLAG_trace_type_checks) {
+    const char* result_str = is_instance_of ? "true" : "false";
+    OS::Print("Object.as: result %s\n", result_str);
+    const Type& instance_type = Type::Handle(instance.GetType());
+    OS::Print("  instance type: %s\n",
+              String::Handle(instance_type.Name()).ToCString());
+    OS::Print("  cast type: %s\n", String::Handle(type.Name()).ToCString());
+    if (!bound_error.IsNull()) {
+      OS::Print("  bound error: %s\n", bound_error.ToErrorCString());
+    }
+  }
   if (!is_instance_of) {
     DartFrameIterator iterator;
     StackFrame* caller_frame = iterator.NextFrame();
@@ -182,8 +199,8 @@
     } else {
       type_name = type.UserVisibleName();
     }
-    String& malformed_error_message =  String::Handle();
-    if (malformed_error.IsNull()) {
+    String& bound_error_message =  String::Handle();
+    if (bound_error.IsNull()) {
       const String& dst_name = String::ZoneHandle(
           Symbols::New(Exceptions::kCastErrorDstName));
 
@@ -192,10 +209,10 @@
           dst_name, Object::null_string());
     } else {
       ASSERT(FLAG_enable_type_checks);
-      malformed_error_message = String::New(malformed_error.ToErrorCString());
+      bound_error_message = String::New(bound_error.ToErrorCString());
       Exceptions::CreateAndThrowTypeError(
           location, instance_type_name, Symbols::Empty(),
-          Symbols::Empty(), malformed_error_message);
+          Symbols::Empty(), bound_error_message);
     }
     UNREACHABLE();
   }
diff --git a/runtime/tests/vm/dart/error_stacktrace_test.dart b/runtime/tests/vm/dart/error_stacktrace_test.dart
new file mode 100644
index 0000000..533aed5
--- /dev/null
+++ b/runtime/tests/vm/dart/error_stacktrace_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Test that the full stacktrace in an error object matches the stacktrace
+// handed to the catch clause.
+library test.error_stacktrace;
+
+import "package:expect/expect.dart";
+
+class C {
+  // operator*(o) is missing to trigger a noSuchMethodError when a C object
+  // is used in the multiplication below.
+}
+
+bar(c) => c * 4;
+foo(c) => bar(c);
+
+main() {
+  try {
+    var a = foo(new C());
+  } catch (e, s) {
+    print(e);
+    print("###");
+    print(e.stackTrace);
+    print("###");
+    print(s);
+    print("###");
+    Expect.isTrue(e is NoSuchMethodError);
+    Expect.stringEquals(e.stackTrace.toString(), s.toString());
+  }
+}
diff --git a/runtime/tests/vm/dart/isolate_mirror_local_test.dart b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
index 1576139..4ffcaef 100644
--- a/runtime/tests/vm/dart/isolate_mirror_local_test.dart
+++ b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
@@ -149,8 +149,6 @@
                 'function, '
                 'global_var, '
                 'main, '
-                'methodWithError, '
-                'methodWithException, '
                 'myFunc, '
                 'myVar, '
                 'myVar=, '
@@ -161,7 +159,6 @@
                 'testImplements, '
                 'testIntegerInstanceMirror, '
                 'testLibrariesMap, '
-                'testMirrorErrors, '
                 'testMirrorSystem, '
                 'testNullInstanceMirror, '
                 'testRootLibraryMirror, '
@@ -202,8 +199,6 @@
                 'buildVariableString, '
                 'function, '
                 'main, '
-                'methodWithError, '
-                'methodWithException, '
                 'myVar, '
                 'myVar=, '
                 'sort, '
@@ -213,7 +208,6 @@
                 'testImplements, '
                 'testIntegerInstanceMirror, '
                 'testLibrariesMap, '
-                'testMirrorErrors, '
                 'testMirrorSystem, '
                 'testNullInstanceMirror, '
                 'testRootLibraryMirror, '
@@ -430,7 +424,6 @@
 class MyInterface {
 }
 
-@notDefined
 class MyClass extends MySuperClass implements MyInterface {
   MyClass(this.value) {}
   MyClass.named() {}
@@ -469,9 +462,6 @@
                 cls.owner.simpleName);
   Expect.isTrue(cls.isClass);
   Expect.equals(const Symbol('MyInterface'), cls.superinterfaces[0].simpleName);
-  Expect.throws(() => cls.metadata,
-                (e) => e is MirroredCompilationError,
-                'Bad metadata');
   Expect.equals("ClassMirror on 'MyClass'", cls.toString());
 
   // Invoke mirror.method(1000).
@@ -491,57 +481,6 @@
   String toString() { return 'MyException: $_message'; }
 }
 
-void methodWithException() {
-  throw new MyException("from methodWithException");
-}
-
-void methodWithError() {
-  // We get a parse error when we try to run this function.
-  +++;
-}
-
-void testMirrorErrors(MirrorSystem mirrors) {
-  LibraryMirror lib_mirror = mirrors.isolate.rootLibrary;
-
-  lib_mirror.invokeAsync(const Symbol('methodWithException'), [])
-    .then((InstanceMirror retval) {
-      // Should not reach here.
-      Expect.isTrue(false);
-    })
-    .catchError((error) {
-        Expect.isTrue(error is MyException);
-        Expect.equals('MyException: from methodWithException',
-                      error.toString());
-        testDone('testMirrorErrors1');
-      });
-
-  lib_mirror.invokeAsync(const Symbol('methodWithError'), [])
-    .then((InstanceMirror retval) {
-      // Should not reach here.
-      Expect.isTrue(false);
-    })
-    .catchError((error) {
-      Expect.isTrue(error is MirroredCompilationError);
-      Expect.isTrue(error.message.contains('unexpected token'));
-      testDone('testMirrorErrors2');
-    });
-
-  // TODO(turnidge): When we call a method that doesn't exist, we
-  // should probably call noSuchMethod().  I'm adding this test to
-  // document the current behavior in the meantime.
-  lib_mirror.invokeAsync(const Symbol('methodNotFound'), [])
-    .then((InstanceMirror retval) {
-      // Should not reach here.
-      Expect.isTrue(false);
-    })
-    .catchError((error) {
-      Expect.isTrue(error is NoSuchMethodError);
-      Expect.isTrue(error.toString().contains(
-          "No top-level method 'methodNotFound'"));
-      testDone('testMirrorErrors3');
-    });
-}
-
 void main() {
   // When all of the expected tests complete, the exit_port is closed,
   // allowing the program to terminate.
@@ -553,10 +492,7 @@
                                         'testStringInstanceMirror',
                                         'testBoolInstanceMirror',
                                         'testNullInstanceMirror',
-                                        'testCustomInstanceMirror',
-                                        'testMirrorErrors1',
-                                        'testMirrorErrors2',
-                                        'testMirrorErrors3']);
+                                        'testCustomInstanceMirror']);
 
   // Test that an isolate can reflect on itself.
   mirrorSystemOf(exit_port.toSendPort()).then(testMirrorSystem);
@@ -566,5 +502,4 @@
   testBoolInstanceMirror(reflect(true));
   testNullInstanceMirror(reflect(null));
   testCustomInstanceMirror(reflect(new MyClass(17)));
-  testMirrorErrors(currentMirrorSystem());
 }
diff --git a/runtime/tests/vm/dart/mirrored_compilation_error_test.dart b/runtime/tests/vm/dart/mirrored_compilation_error_test.dart
new file mode 100644
index 0000000..b661afe
--- /dev/null
+++ b/runtime/tests/vm/dart/mirrored_compilation_error_test.dart
@@ -0,0 +1,103 @@
+// 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=--use_mirrored_compilation_error=true
+
+@notDefined
+library mirrored_compilation_error_test;
+
+import 'dart:mirrors';
+import "package:expect/expect.dart";
+
+@notDefined
+class Class<@notDefined T> {
+  @notDefined
+  var field;
+
+  @notDefined
+  method(@notDefined param) {}
+}
+
+class Class2 {
+  method() { +++; }
+  get getter { +++; }
+  set setter(x) { +++; }
+
+  static staticFunction() { +++; }
+  static get staticGetter { +++; }
+  static set staticSetter(x) { +++; }
+
+  Class2() {}
+  Class2.constructor() { +++; }
+}
+
+toplevelFunction() { +++; }
+get toplevelGetter { +++; }
+set toplevelSetter(x) { +++; }
+
+
+class G<A extends int, B extends String> {
+  G();
+  factory G.swap() = G<B,A>;  /// static type warning
+}
+
+raises(closure) {
+  Expect.throws(closure,
+                (e) => e is MirroredCompilationError,
+                'Expected a deferred compilation error');
+}
+
+bool get inCheckedMode {
+  try {
+    var i = 1;
+    String s = i;
+    return false;
+  } catch (e) {
+    return true;
+  }
+}
+
+main() {
+
+  // Metadata.
+
+  raises(() => reflectClass(Class).metadata);
+  raises(() => reflectClass(Class).typeVariables.single.metadata);
+  raises(() => reflectClass(Class).variables[#field].metadata);
+  raises(() => reflectClass(Class).methods[#method].metadata);
+  raises(() => reflectClass(Class).methods[#method].parameters.single.metadata);
+  raises(() => reflectClass(Class).owner.metadata);
+
+
+  // Invocation.
+
+  InstanceMirror im = reflect(new Class2());
+  raises(() => im.invoke(#method, []));
+  raises(() => im.getField(#getter));
+  raises(() => im.setField(#setter, 'some value'));
+  // The implementation is within its right to defer the compilation even
+  // further here, so we apply the tear-off to force compilation.
+  raises(() => im.getField(#method).apply([]));
+
+  ClassMirror cm = reflectClass(Class2);
+  raises(() => cm.invoke(#staticFunction, []));
+  raises(() => cm.getField(#staticGetter));
+  raises(() => cm.setField(#staticSetter, 'some value'));
+  raises(() => cm.getField(#staticFunction).apply([]));
+  raises(() => cm.newInstance(#constructor, []));
+
+  LibraryMirror lm = reflectClass(Class2).owner;
+  raises(() => lm.invoke(#toplevelFunction, []));
+  raises(() => lm.getField(#toplevelGetter));
+  raises(() => lm.setField(#toplevelSetter, 'some value'));
+  raises(() => lm.getField(#toplevelFunction).apply([]));
+
+
+  // Bounds violation.
+
+  if (inCheckedMode) {
+    ClassMirror cm = reflect(new G<int, String>()).type;
+    raises(() => cm.newInstance(#swap, []));
+  }
+}
diff --git a/runtime/tests/vm/dart/redirection_type_shuffling_test.dart b/runtime/tests/vm/dart/redirection_type_shuffling_test.dart
new file mode 100644
index 0000000..c1db64c
--- /dev/null
+++ b/runtime/tests/vm/dart/redirection_type_shuffling_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:mirrors";
+import "package:expect/expect.dart";
+
+class G<A extends int, B extends String> {
+  G();
+  factory G.swap() = G<B,A>;  /// 00: static type warning
+  factory G.retain() = G<A,B>;
+}
+
+main() {
+  ClassMirror cm = reflect(new G<int, String>()).type;
+
+  Expect.isTrue(cm.newInstance(#retain, []).reflectee is G<int,String>);
+
+  Expect.isTrue(cm.newInstance(#swap, []).reflectee is G<String,int>);  /// 00: dynamic type error
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index e6ce377..1c349bf 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -24,10 +24,9 @@
 cc/Dart2JSCompileAll: Skip
 cc/ExternalizeConstantStrings: Skip
 
-[ $runtime == drt ]
-dart/isolate_mirror_local_test: Skip
-
 [ $compiler == dart2js ]
+dart/mirrored_compilation_error_test: Skip # VM-specific flag
+dart/redirection_type_shuffling_test: Skip # Depends on lazy enforcement of type bounds
 dart/isolate_mirror*: Skip # compilers not aware of dart:mirrors
 dart/byte_array_test: Skip # compilers not aware of byte arrays
 dart/byte_array_optimized_test: Skip # compilers not aware of byte arrays
@@ -59,17 +58,15 @@
 cc/Cop1CvtDL: Crash
 cc/Cop1CvtDL_neg: Crash
 
-[ $compiler == dartanalyzer ]
-# has compilation error, as designed
-dart/isolate_mirror_local_test: fail
-
-[ $compiler == dart2analyzer ]
-# has compilation error, as designed
-dart/isolate_mirror_local_test: fail
+[ $compiler == none && $runtime == drt ]
+dart/isolate_mirror_local_test: Skip
+dart/error_stacktrace_test: Skip
 
 [ $compiler == none && $runtime == dartium ]
 dart/isolate_mirror_local_test: Fail # Issue 13719: Please triage this failure.
+dart/error_stacktrace_test: Skip
 
 [ $compiler == none && ($runtime == drt || $runtime == dartium) ]
 dart/isolate_mirror_remote_test: Fail # Issue 13921
 dart/isolate_unhandled_exception_test: Fail # Issue 13921
+dart/mirrored_compilation_error_test: Skip # Can't pass needed VM flag
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index 2d47321..bd80596 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -676,7 +676,7 @@
   void Vreciprocalqs(QRegister qd, QRegister qm);
   void VreciprocalSqrtqs(QRegister qd, QRegister qm);
   // If qm must be preserved, then provide a (non-QTMP) temporary.
-  void Vsqrtqs(QRegister qd, QRegister qm, QRegister temp = kNoQRegister);
+  void Vsqrtqs(QRegister qd, QRegister qm, QRegister temp);
   void Vdivqs(QRegister qd, QRegister qn, QRegister qm);
 
   void SmiTag(Register reg, Condition cond = AL) {
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index a2e629c..cbbcee0 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -21,7 +21,7 @@
     "dart:"#name"-patch", patch }                                              \
 
 typedef struct {
-  intptr_t index_;
+  ObjectStore::BootstrapLibraryId index_;
   const char* uri_;
   const char** source_paths_;
   const char* patch_uri_;
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 104756a..7e1e097 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -297,6 +297,8 @@
   V(MethodMirror_source, 1)                                                    \
   V(ParameterMirror_type, 2)                                                   \
   V(TypedefMirror_referent, 1)                                                 \
+  V(TypedefMirror_instantiate_from, 2)                                         \
+  V(TypedefMirror_declaration, 1)                                              \
   V(VariableMirror_type, 1)                                                    \
   V(GrowableList_allocate, 2)                                                  \
   V(GrowableList_getIndexed, 2)                                                \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index c8e2d2a..12f2319 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -278,12 +278,18 @@
                                                const Function& factory) {
   const Function& target = Function::Handle(factory.RedirectionTarget());
   if (target.IsNull()) {
-    const Type& type = Type::Handle(factory.RedirectionType());
+    Type& type = Type::Handle(factory.RedirectionType());
     if (!type.IsMalformed()) {
       const GrowableObjectArray& visited_factories =
           GrowableObjectArray::Handle(GrowableObjectArray::New());
       ResolveRedirectingFactoryTarget(cls, factory, visited_factories);
     }
+    if (factory.is_const()) {
+      type = factory.RedirectionType();
+      if (type.IsMalformed()) {
+        ReportError(Error::Handle(type.malformed_error()));
+      }
+    }
   }
 }
 
@@ -396,7 +402,7 @@
     const Script& script = Script::Handle(target_class.script());
     ReportError(Error::Handle(),  // No previous error.
                 script, target.token_pos(),
-                "constructor '%s' must be const as required by redirecting"
+                "constructor '%s' must be const as required by redirecting "
                 "const factory '%s'",
                 String::Handle(target.name()).ToCString(),
                 String::Handle(factory.name()).ToCString());
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 1505ae3..82e2561 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -184,20 +184,19 @@
     const AbstractTypeArguments& instantiator =
         AbstractTypeArguments::CheckedHandle(arguments.ArgAt(2));
     ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
-    Error& malformed_error = Error::Handle();
+    Error& bound_error = Error::Handle();
     // Code inlined in the caller should have optimized the case where the
     // instantiator can be reused as type argument vector.
   ASSERT(instantiator.IsNull() || !type_arguments.IsUninstantiatedIdentity());
-    type_arguments = type_arguments.InstantiateFrom(instantiator,
-                                                    &malformed_error);
-    if (!malformed_error.IsNull()) {
+    type_arguments = type_arguments.InstantiateFrom(instantiator, &bound_error);
+    if (!bound_error.IsNull()) {
       // Throw a dynamic type error.
       const intptr_t location = GetCallerLocation();
-      String& malformed_error_message =  String::Handle(
-          String::New(malformed_error.ToErrorCString()));
+      String& bound_error_message =  String::Handle(
+          String::New(bound_error.ToErrorCString()));
       Exceptions::CreateAndThrowTypeError(
           location, Symbols::Empty(), Symbols::Empty(),
-          Symbols::Empty(), malformed_error_message);
+          Symbols::Empty(), bound_error_message);
       UNREACHABLE();
     }
   }
@@ -216,16 +215,16 @@
       AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
   ASSERT(!type.IsNull() && !type.IsInstantiated());
   ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
-  Error& malformed_error = Error::Handle();
-  type = type.InstantiateFrom(instantiator, &malformed_error);
-  if (!malformed_error.IsNull()) {
+  Error& bound_error = Error::Handle();
+  type = type.InstantiateFrom(instantiator, &bound_error);
+  if (!bound_error.IsNull()) {
     // Throw a dynamic type error.
     const intptr_t location = GetCallerLocation();
-    String& malformed_error_message =  String::Handle(
-        String::New(malformed_error.ToErrorCString()));
+    String& bound_error_message =  String::Handle(
+        String::New(bound_error.ToErrorCString()));
     Exceptions::CreateAndThrowTypeError(
         location, Symbols::Empty(), Symbols::Empty(),
-        Symbols::Empty(), malformed_error_message);
+        Symbols::Empty(), bound_error_message);
     UNREACHABLE();
   }
   ASSERT(!type.IsNull() && type.IsInstantiated());
@@ -346,9 +345,9 @@
                  caller_frame->pc());
   } else {
     // Instantiate type before printing.
-    Error& malformed_error = Error::Handle();
+    Error& bound_error = Error::Handle();
     const AbstractType& instantiated_type = AbstractType::Handle(
-        type.InstantiateFrom(instantiator_type_arguments, &malformed_error));
+        type.InstantiateFrom(instantiator_type_arguments, &bound_error));
     OS::PrintErr("%s: '%s' %s '%s' instantiated from '%s' (pc: %#" Px ").\n",
                  message,
                  String::Handle(instance_type.Name()).ToCString(),
@@ -356,8 +355,8 @@
                  String::Handle(instantiated_type.Name()).ToCString(),
                  String::Handle(type.Name()).ToCString(),
                  caller_frame->pc());
-    if (!malformed_error.IsNull()) {
-      OS::Print("  malformed error: %s\n", malformed_error.ToErrorCString());
+    if (!bound_error.IsNull()) {
+      OS::Print("  bound error: %s\n", bound_error.ToErrorCString());
     }
   }
   const Function& function = Function::Handle(
@@ -390,10 +389,10 @@
       uninstantiated =
           instantiated_type_arguments.uninstantiated_type_arguments();
       instantiator = instantiated_type_arguments.instantiator_type_arguments();
-      Error& malformed_error = Error::Handle();
+      Error& bound_error = Error::Handle();
       type_arguments = uninstantiated.InstantiateFrom(instantiator,
-                                                      &malformed_error);
-      ASSERT(malformed_error.IsNull());  // Malformed types are not optimized.
+                                                      &bound_error);
+      ASSERT(bound_error.IsNull());  // Malbounded types are not optimized.
     } while (type_arguments.IsInstantiatedTypeArguments());
     AbstractTypeArguments& new_type_arguments = AbstractTypeArguments::Handle();
     new_type_arguments = type_arguments.Canonicalize();
@@ -496,10 +495,10 @@
   if (FLAG_trace_type_checks) {
     AbstractType& test_type = AbstractType::Handle(type.raw());
     if (!test_type.IsInstantiated()) {
-      Error& malformed_error = Error::Handle();
+      Error& bound_error = Error::Handle();
       test_type = type.InstantiateFrom(instantiator_type_arguments,
-                                       &malformed_error);
-      ASSERT(malformed_error.IsNull());  // Malformed types are not optimized.
+                                       &bound_error);
+      ASSERT(bound_error.IsNull());  // Malbounded types are not optimized.
     }
     OS::PrintErr("  Updated test cache %p ix: %" Pd " with "
         "(cid: %" Pd ", type-args: %p, instantiator: %p, result: %s)\n"
@@ -546,23 +545,23 @@
   const SubtypeTestCache& cache =
       SubtypeTestCache::CheckedHandle(arguments.ArgAt(4));
   ASSERT(type.IsFinalized());
-  Error& malformed_error = Error::Handle();
+  Error& bound_error = Error::Handle();
   const Bool& result =
       Bool::Get(instance.IsInstanceOf(type,
                                       instantiator_type_arguments,
-                                      &malformed_error));
+                                      &bound_error));
   if (FLAG_trace_type_checks) {
     PrintTypeCheck("InstanceOf",
         instance, type, instantiator_type_arguments, result);
   }
-  if (!result.value() && !malformed_error.IsNull()) {
+  if (!result.value() && !bound_error.IsNull()) {
     // Throw a dynamic type error only if the instanceof test fails.
     const intptr_t location = GetCallerLocation();
-    String& malformed_error_message =  String::Handle(
-        String::New(malformed_error.ToErrorCString()));
+    String& bound_error_message =  String::Handle(
+        String::New(bound_error.ToErrorCString()));
     Exceptions::CreateAndThrowTypeError(
         location, Symbols::Empty(), Symbols::Empty(),
-        Symbols::Empty(), malformed_error_message);
+        Symbols::Empty(), bound_error_message);
     UNREACHABLE();
   }
   UpdateTypeTestCache(instance, type, instantiator,
@@ -596,9 +595,9 @@
   ASSERT(!dst_type.IsMalbounded());  // Already checked in code generator.
   ASSERT(!src_instance.IsNull());  // Already checked in inlined code.
 
-  Error& malformed_error = Error::Handle();
+  Error& bound_error = Error::Handle();
   const bool is_instance_of = src_instance.IsInstanceOf(
-      dst_type, instantiator_type_arguments, &malformed_error);
+      dst_type, instantiator_type_arguments, &bound_error);
 
   if (FLAG_trace_type_checks) {
     PrintTypeCheck("TypeCheck",
@@ -615,18 +614,18 @@
       // Instantiate dst_type before reporting the error.
       const AbstractType& instantiated_dst_type = AbstractType::Handle(
           dst_type.InstantiateFrom(instantiator_type_arguments, NULL));
-      // Note that instantiated_dst_type may be malformed.
+      // Note that instantiated_dst_type may be malbounded.
       dst_type_name = instantiated_dst_type.UserVisibleName();
     } else {
       dst_type_name = dst_type.UserVisibleName();
     }
-    String& malformed_error_message =  String::Handle();
-    if (!malformed_error.IsNull()) {
+    String& bound_error_message =  String::Handle();
+    if (!bound_error.IsNull()) {
       ASSERT(FLAG_enable_type_checks);
-      malformed_error_message = String::New(malformed_error.ToErrorCString());
+      bound_error_message = String::New(bound_error.ToErrorCString());
     }
     Exceptions::CreateAndThrowTypeError(location, src_type_name, dst_type_name,
-                                        dst_name, malformed_error_message);
+                                        dst_name, bound_error_message);
     UNREACHABLE();
   }
   UpdateTypeTestCache(src_instance, dst_type,
@@ -648,14 +647,16 @@
   const String& src_type_name = String::Handle(src_type.UserVisibleName());
   const String& bool_type_name =
       String::Handle(bool_interface.UserVisibleName());
-  const String& no_malformed_type_error = String::Handle();
+  const String& no_bound_error = String::Handle();
   Exceptions::CreateAndThrowTypeError(location, src_type_name, bool_type_name,
                                       Symbols::BooleanExpression(),
-                                      no_malformed_type_error);
+                                      no_bound_error);
   UNREACHABLE();
 }
 
 
+// TODO(regis): Is this entry still used for malformed types or just malbounded
+// types? Revisit.
 // Report that the type of the type check is malformed.
 // Arg0: src value.
 // Arg1: name of instance being assigned to.
@@ -665,12 +666,12 @@
   const intptr_t location = GetCallerLocation();
   const Instance& src_value = Instance::CheckedHandle(arguments.ArgAt(0));
   const String& dst_name = String::CheckedHandle(arguments.ArgAt(1));
-  const String& malformed_error = String::CheckedHandle(arguments.ArgAt(2));
+  const String& bound_error = String::CheckedHandle(arguments.ArgAt(2));
   const AbstractType& src_type = AbstractType::Handle(src_value.GetType());
   const String& src_type_name = String::Handle(src_type.UserVisibleName());
   Exceptions::CreateAndThrowTypeError(location, src_type_name,
                                       Symbols::Malformed(),
-                                      dst_name, malformed_error);
+                                      dst_name, bound_error);
   UNREACHABLE();
 }
 
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 7942295..6cbfac4 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -44,7 +44,6 @@
     "Do common subexpression elimination.");
 DEFINE_FLAG(bool, loop_invariant_code_motion, true,
     "Do loop invariant code motion.");
-DEFINE_FLAG(bool, propagate_types, true, "Do static type propagation.");
 DEFINE_FLAG(bool, allocation_sinking, true,
     "Attempt to sink temporary allocations to side exits");
 DEFINE_FLAG(int, deoptimization_counter_threshold, 16,
@@ -349,11 +348,8 @@
           TimerScope timer(FLAG_compiler_stats,
                            &CompilerStats::graphinliner_timer);
           // Propagate types to create more inlining opportunities.
-          if (FLAG_propagate_types) {
-            FlowGraphTypePropagator propagator(flow_graph);
-            propagator.Propagate();
-            DEBUG_ASSERT(flow_graph->VerifyUseLists());
-          }
+          FlowGraphTypePropagator::Propagate(flow_graph);
+          DEBUG_ASSERT(flow_graph->VerifyUseLists());
 
           // Use propagated class-ids to create more inlining opportunities.
           optimizer.ApplyClassIds();
@@ -366,11 +362,8 @@
         }
 
         // Propagate types and eliminate more type tests.
-        if (FLAG_propagate_types) {
-          FlowGraphTypePropagator propagator(flow_graph);
-          propagator.Propagate();
-          DEBUG_ASSERT(flow_graph->VerifyUseLists());
-        }
+        FlowGraphTypePropagator::Propagate(flow_graph);
+        DEBUG_ASSERT(flow_graph->VerifyUseLists());
 
         // Use propagated class-ids to optimize further.
         optimizer.ApplyClassIds();
@@ -399,17 +392,14 @@
         }
 
         // Propagate types and eliminate even more type tests.
-        if (FLAG_propagate_types) {
-          // Recompute types after constant propagation to infer more precise
-          // types for uses that were previously reached by now eliminated phis.
-          FlowGraphTypePropagator propagator(flow_graph);
-          propagator.Propagate();
-          DEBUG_ASSERT(flow_graph->VerifyUseLists());
-        }
+        // Recompute types after constant propagation to infer more precise
+        // types for uses that were previously reached by now eliminated phis.
+        FlowGraphTypePropagator::Propagate(flow_graph);
+        DEBUG_ASSERT(flow_graph->VerifyUseLists());
 
         // Unbox doubles. Performed after constant propagation to minimize
         // interference from phis merging double values and tagged
-        // values comming from dead paths.
+        // values coming from dead paths.
         optimizer.SelectRepresentations();
         DEBUG_ASSERT(flow_graph->VerifyUseLists());
 
@@ -438,13 +428,11 @@
         flow_graph->RemoveRedefinitions();
 
         if (FLAG_range_analysis) {
-          if (FLAG_propagate_types) {
-            // Propagate types after store-load-forwarding. Some phis may have
-            // become smi phis that can be processed by range analysis.
-            FlowGraphTypePropagator propagator(flow_graph);
-            propagator.Propagate();
-            DEBUG_ASSERT(flow_graph->VerifyUseLists());
-          }
+          // Propagate types after store-load-forwarding. Some phis may have
+          // become smi phis that can be processed by range analysis.
+          FlowGraphTypePropagator::Propagate(flow_graph);
+          DEBUG_ASSERT(flow_graph->VerifyUseLists());
+
           // We have to perform range analysis after LICM because it
           // optimistically moves CheckSmi through phis into loop preheaders
           // making some phis smi.
@@ -459,13 +447,10 @@
           DEBUG_ASSERT(flow_graph->VerifyUseLists());
         }
 
-        if (FLAG_propagate_types) {
-          // Recompute types after code movement was done to ensure correct
-          // reaching types for hoisted values.
-          FlowGraphTypePropagator propagator(flow_graph);
-          propagator.Propagate();
-          DEBUG_ASSERT(flow_graph->VerifyUseLists());
-        }
+        // Recompute types after code movement was done to ensure correct
+        // reaching types for hoisted values.
+        FlowGraphTypePropagator::Propagate(flow_graph);
+        DEBUG_ASSERT(flow_graph->VerifyUseLists());
 
         // Optimize try-blocks.
         TryCatchAnalyzer::Optimize(flow_graph);
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 46a159c..0eff97c 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -264,6 +264,9 @@
   NoGCScope no_gc_scope;
   NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
   RawObject* raw_obj = arguments->NativeArgAt(arg_index);
+  if (!raw_obj->IsHeapObject()) {
+    return false;
+  }
   intptr_t cid = raw_obj->GetClassId();
   if (cid == kExternalOneByteStringCid) {
     RawExternalOneByteString* raw_string =
@@ -385,13 +388,6 @@
 }
 
 
-// Deprecated.
-// TODO(turnidge): Remove all uses and delete.
-DART_EXPORT Dart_Handle Dart_Error(const char* error) {
-  return Dart_NewApiError(error);
-}
-
-
 // TODO(turnidge): This clones Api::NewError.  I need to use va_copy to
 // fix this but not sure if it available on all of our builds.
 DART_EXPORT Dart_Handle Dart_NewApiError(const char* error) {
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index cb40979..118f25d 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -127,11 +127,12 @@
                                     function_name,
                                     Resolver::kIsQualified));
   ASSERT(!allocation_function.IsNull());
-  const int kNumAllocationArgs = 3;
+  const int kNumAllocationArgs = 4;
   const Array& allocation_args = Array::Handle(Array::New(kNumAllocationArgs));
   allocation_args.SetAt(0, target_name);
   allocation_args.SetAt(1, arguments_descriptor);
   allocation_args.SetAt(2, arguments);
+  allocation_args.SetAt(3, Bool::False());  // Not a super invocation.
   const Object& invocation_mirror = Object::Handle(
       InvokeFunction(allocation_function, allocation_args));
 
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 5365419..450d251 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -375,7 +375,6 @@
     // Get stacktrace field of class Error.
     const Field& stacktrace_field =
         Field::Handle(isolate, LookupStacktraceField(exception));
-    bool full_stacktrace = !stacktrace_field.IsNull();
     handler_exists = FindExceptionHandler(&handler_pc,
                                           &handler_sp,
                                           &handler_fp,
@@ -383,28 +382,39 @@
     Array& code_array = Array::Handle(isolate, Object::empty_array().raw());
     Array& pc_offset_array =
         Array::Handle(isolate, Object::empty_array().raw());
-    if (handler_needs_stacktrace || full_stacktrace) {
-      RegularStacktraceBuilder frame_builder(full_stacktrace);
-      BuildStackTrace(&frame_builder);
-
-      // Create arrays for function, code and pc_offset triplet of each frame.
-      code_array = Array::MakeArray(frame_builder.code_list());
-      pc_offset_array = Array::MakeArray(frame_builder.pc_offset_list());
-      if (!stacktrace_field.IsNull()) {
+    // If we have an error with a stacktrace field then collect the full stack
+    // trace and store it into the field.
+    if (!stacktrace_field.IsNull()) {
+      if (exception.GetField(stacktrace_field) == Object::null()) {
         // This is an error object and we need to capture the full stack trace
         // here implicitly, so we set up the stack trace. The stack trace field
         // is set only once, it is not overriden.
-        const Array& catch_code_array = Array::Handle(isolate,
+        RegularStacktraceBuilder frame_builder(true);
+        BuildStackTrace(&frame_builder);
+
+        // Create arrays for code and pc_offset tuples of each frame.
+        const Array& full_code_array = Array::Handle(isolate,
+            Array::MakeArray(frame_builder.code_list()));
+        const Array& full_pc_offset_array = Array::Handle(isolate,
+            Array::MakeArray(frame_builder.pc_offset_list()));
+        const Array& full_catch_code_array = Array::Handle(isolate,
             Array::MakeArray(frame_builder.catch_code_list()));
-        const Array& catch_pc_offset_array = Array::Handle(isolate,
+        const Array& full_catch_pc_offset_array = Array::Handle(isolate,
             Array::MakeArray(frame_builder.catch_pc_offset_list()));
-        stacktrace = Stacktrace::New(code_array, pc_offset_array);
-        stacktrace.SetCatchStacktrace(catch_code_array,
-                                      catch_pc_offset_array);
-        if (exception.GetField(stacktrace_field) == Object::null()) {
-          exception.SetField(stacktrace_field, stacktrace);
-        }
-      }  // if stacktrace needed.
+        const Stacktrace& full_stacktrace = Stacktrace::Handle(isolate,
+            Stacktrace::New(full_code_array, full_pc_offset_array));
+        full_stacktrace.SetCatchStacktrace(full_catch_code_array,
+                                           full_catch_pc_offset_array);
+        exception.SetField(stacktrace_field, full_stacktrace);
+      }
+    }
+    if (handler_needs_stacktrace) {
+      RegularStacktraceBuilder frame_builder(false);
+      BuildStackTrace(&frame_builder);
+
+      // Create arrays for code and pc_offset tuples of each frame.
+      code_array = Array::MakeArray(frame_builder.code_list());
+      pc_offset_array = Array::MakeArray(frame_builder.pc_offset_list());
     }
     if (existing_stacktrace.IsNull()) {
       stacktrace = Stacktrace::New(code_array, pc_offset_array);
@@ -491,39 +501,44 @@
 
 
 // Allocate, initialize, and throw a TypeError or CastError.
+// If bound_error is not null, throw a TypeError, even for a type cast.
 void Exceptions::CreateAndThrowTypeError(intptr_t location,
                                          const String& src_type_name,
                                          const String& dst_type_name,
                                          const String& dst_name,
-                                         const String& malformed_error) {
+                                         const String& bound_error) {
   const Array& args = Array::Handle(Array::New(7));
 
   ExceptionType exception_type =
-      dst_name.Equals(kCastErrorDstName) ? kCast : kType;
+      (bound_error.IsNull() && dst_name.Equals(kCastErrorDstName)) ?
+          kCast : kType;
 
   DartFrameIterator iterator;
   const Script& script = Script::Handle(GetCallerScript(&iterator));
-  intptr_t line, column;
-  script.GetTokenLocation(location, &line, &column);
+  intptr_t line;
+  intptr_t column = -1;
+  if (script.HasSource()) {
+    script.GetTokenLocation(location, &line, &column);
+  } else {
+    script.GetTokenLocation(location, &line, NULL);
+  }
   // Initialize '_url', '_line', and '_column' arguments.
   args.SetAt(0, String::Handle(script.url()));
   args.SetAt(1, Smi::Handle(Smi::New(line)));
   args.SetAt(2, Smi::Handle(Smi::New(column)));
 
-  // Initialize '_srcType', '_dstType', '_dstName', and '_malformedError'.
+  // Initialize '_srcType', '_dstType', '_dstName', and '_boundError'.
   args.SetAt(3, src_type_name);
   args.SetAt(4, dst_type_name);
   args.SetAt(5, dst_name);
-  args.SetAt(6, malformed_error);
+  args.SetAt(6, bound_error);
 
   // Type errors in the core library may be difficult to diagnose.
   // Print type error information before throwing the error when debugging.
   if (FLAG_print_stacktrace_at_throw) {
-    if (!malformed_error.IsNull()) {
-      OS::Print("%s\n", malformed_error.ToCString());
+    if (!bound_error.IsNull()) {
+      OS::Print("%s\n", bound_error.ToCString());
     }
-    intptr_t line, column;
-    script.GetTokenLocation(location, &line, &column);
     OS::Print("'%s': Failed type check: line %" Pd " pos %" Pd ": ",
               String::Handle(script.url()).ToCString(), line, column);
     if (!dst_name.IsNull() && (dst_name.Length() > 0)) {
@@ -532,7 +547,7 @@
                 dst_type_name.ToCString(),
                 dst_name.ToCString());
     } else {
-      OS::Print("malformed type used.\n");
+      OS::Print("malbounded type used.\n");
     }
   }
   // Throw TypeError or CastError instance.
@@ -692,10 +707,6 @@
       class_name = &Symbols::AbstractClassInstantiationError();
       constructor_name = &Symbols::DotCreate();
       break;
-    case kMirroredUncaughtExceptionError:
-      library = Library::MirrorsLibrary();
-      class_name = &Symbols::MirroredUncaughtExceptionError();
-      break;
     case kMirroredCompilationError:
       library = Library::MirrorsLibrary();
       class_name = &Symbols::MirroredCompilationError();
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index 46d8120..c49b903 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -37,7 +37,7 @@
                                       const String& src_type_name,
                                       const String& dst_type_name,
                                       const String& dst_name,
-                                      const String& malformed_error);
+                                      const String& bound_error);
 
   enum ExceptionType {
     kNone,
@@ -58,7 +58,6 @@
     kType,
     kFallThrough,
     kAbstractClassInstantiation,
-    kMirroredUncaughtExceptionError,
     kMirroredCompilationError,
   };
 
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 0e0fa78..5a18370 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -2746,7 +2746,8 @@
                                       node->receiver(),
                                       getter_name,
                                       arguments,
-                                      false);  // Don't save last argument.
+                                      false,  // Don't save last argument.
+                                      true);  // Super invocation.
       ReturnDefinition(call);
       return;
     } else {
@@ -2824,7 +2825,8 @@
           node->receiver(),
           setter_name,
           arguments,
-          result_is_needed);  // Save last arg if result is needed.
+          result_is_needed,  // Save last arg if result is needed.
+          true);  // Super invocation.
     } else {
       // Throw a NoSuchMethodError.
       ArgumentListNode* arguments = new ArgumentListNode(node->token_pos());
@@ -3180,7 +3182,8 @@
                                       node->array(),
                                       Symbols::IndexToken(),
                                       arguments,
-                                      false);  // Don't save last arg.
+                                      false,  // Don't save last arg.
+                                      true);  // Super invocation.
       ReturnDefinition(call);
       return;
     }
@@ -3241,7 +3244,8 @@
           node->array(),
           Symbols::AssignIndexToken(),
           arguments,
-          result_is_needed);  // Save last arg if result is needed.
+          result_is_needed,  // Save last arg if result is needed.
+          true);  // Super invocation.
       if (result_is_needed) {
         Do(call);
         // BuildStaticNoSuchMethodCall stores the value in expression_temp.
@@ -3622,7 +3626,8 @@
     AstNode* receiver,
     const String& method_name,
     ArgumentListNode* method_arguments,
-    bool save_last_arg) {
+    bool save_last_arg,
+    bool is_super_invocation) {
   intptr_t args_pos = method_arguments->token_pos();
   LocalVariable* temp = NULL;
   if (save_last_arg) {
@@ -3632,7 +3637,8 @@
       Parser::BuildNoSuchMethodArguments(args_pos,
                                          method_name,
                                          *method_arguments,
-                                         temp);
+                                         temp,
+                                         is_super_invocation);
   const Function& no_such_method_func = Function::ZoneHandle(
       Resolver::ResolveDynamicAnyArgs(target_class, Symbols::NoSuchMethod()));
   // We are guaranteed to find noSuchMethod of class Object.
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h
index d022409..0dfe02e 100644
--- a/runtime/vm/flow_graph_builder.h
+++ b/runtime/vm/flow_graph_builder.h
@@ -364,7 +364,8 @@
       AstNode* receiver,
       const String& method_name,
       ArgumentListNode* method_arguments,
-      bool save_last_arg);
+      bool save_last_arg,
+      bool is_super_invocation);
 
   StaticCallInstr* BuildThrowNoSuchMethodError(
       intptr_t token_pos,
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index dc22d62..eac4aa7 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -363,8 +363,8 @@
   bool CheckInlinedDuplicate(const Function& target);
   bool CheckNonInlinedDuplicate(const Function& target);
 
-  bool TryInlining(const Function& target);
-  bool TryInlineRecognizedMethod(const Function& target);
+  bool TryInlining(intptr_t receiver_cid, const Function& target);
+  bool TryInlineRecognizedMethod(intptr_t receiver_cid, const Function& target);
 
   TargetEntryInstr* BuildDecisionGraph();
 
@@ -1033,7 +1033,8 @@
 //   * JoinEntry: the inlined body is shared and this is a subsequent variant.
 bool PolymorphicInliner::CheckInlinedDuplicate(const Function& target) {
   for (intptr_t i = 0; i < inlined_variants_.length(); ++i) {
-    if (target.raw() == inlined_variants_[i].target->raw()) {
+    if ((target.raw() == inlined_variants_[i].target->raw()) &&
+        !MethodRecognizer::PolymorphicTarget(target)) {
       // The call target is shared with a previous inlined variant.  Share
       // the graph.  This requires a join block at the entry, and edge-split
       // form requires a target for each branch.
@@ -1089,9 +1090,10 @@
 }
 
 
-bool PolymorphicInliner::TryInlining(const Function& target) {
+bool PolymorphicInliner::TryInlining(intptr_t receiver_cid,
+                                     const Function& target) {
   if (!target.is_optimizable()) {
-    if (TryInlineRecognizedMethod(target)) {
+    if (TryInlineRecognizedMethod(receiver_cid, target)) {
       owner_->inlined_ = true;
       return true;
     }
@@ -1157,11 +1159,13 @@
 }
 
 
-bool PolymorphicInliner::TryInlineRecognizedMethod(const Function& target) {
+bool PolymorphicInliner::TryInlineRecognizedMethod(intptr_t receiver_cid,
+                                                   const Function& target) {
   FlowGraphOptimizer optimizer(owner_->caller_graph());
   TargetEntryInstr* entry;
   Definition* last;
-  if (optimizer.TryInlineRecognizedMethod(target,
+  if (optimizer.TryInlineRecognizedMethod(receiver_cid,
+                                          target,
                                           call_,
                                           call_->instance_call()->token_pos(),
                                           *call_->instance_call()->ic_data(),
@@ -1412,6 +1416,7 @@
   FlowGraphCompiler::SortICDataByCount(call_->ic_data(), &variants_);
   for (intptr_t var_idx = 0; var_idx < variants_.length(); ++var_idx) {
     const Function& target = *variants_[var_idx].target;
+    const intptr_t receiver_cid = variants_[var_idx].cid;
 
     // First check if this is the same target as an earlier inlined variant.
     if (CheckInlinedDuplicate(target)) {
@@ -1428,7 +1433,7 @@
     }
 
     // Make an inlining decision.
-    if (TryInlining(target)) {
+    if (TryInlining(receiver_cid, target)) {
       inlined_variants_.Add(variants_[var_idx]);
     } else {
       non_inlined_variants_.Add(variants_[var_idx]);
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 6c60c21..87e4c88 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -829,7 +829,8 @@
   const Function& target = Function::Handle(ic_data.GetTargetAt(0));
   TargetEntryInstr* entry;
   Definition* last;
-  if (!TryInlineRecognizedMethod(target,
+  if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0),
+                                 target,
                                  call,
                                  call->token_pos(),
                                  *call->ic_data(),
@@ -995,7 +996,8 @@
 }
 
 
-bool FlowGraphOptimizer::TryInlineRecognizedMethod(const Function& target,
+bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid,
+                                                   const Function& target,
                                                    Instruction* call,
                                                    intptr_t token_pos,
                                                    const ICData& ic_data,
@@ -1074,6 +1076,45 @@
       value_check = ic_data.AsUnaryClassChecksForArgNr(2);
       return InlineSetIndexed(kind, target, call, token_pos,
                               &ic_data, value_check, entry, last);
+    case MethodRecognizer::kByteArrayBaseGetInt8:
+      return InlineByteArrayViewLoad(call, receiver_cid,
+                                     kTypedDataInt8ArrayCid,
+                                     ic_data, entry, last);
+    case MethodRecognizer::kByteArrayBaseGetUint8:
+      return InlineByteArrayViewLoad(call, receiver_cid,
+                                     kTypedDataUint8ArrayCid,
+                                     ic_data, entry, last);
+    case MethodRecognizer::kByteArrayBaseGetInt16:
+      return InlineByteArrayViewLoad(call, receiver_cid,
+                                     kTypedDataInt16ArrayCid,
+                                     ic_data, entry, last);
+    case MethodRecognizer::kByteArrayBaseGetUint16:
+      return InlineByteArrayViewLoad(call, receiver_cid,
+                                     kTypedDataUint16ArrayCid,
+                                     ic_data, entry, last);
+    case MethodRecognizer::kByteArrayBaseGetInt32:
+      if (!CanUnboxInt32()) return false;
+      return InlineByteArrayViewLoad(call, receiver_cid,
+                                     kTypedDataInt32ArrayCid,
+                                     ic_data, entry, last);
+    case MethodRecognizer::kByteArrayBaseGetUint32:
+      if (!CanUnboxInt32()) return false;
+      return InlineByteArrayViewLoad(call, receiver_cid,
+                                     kTypedDataUint32ArrayCid,
+                                     ic_data, entry, last);
+    case MethodRecognizer::kByteArrayBaseGetFloat32:
+      return InlineByteArrayViewLoad(call, receiver_cid,
+                                     kTypedDataFloat32ArrayCid,
+                                     ic_data, entry, last);
+    case MethodRecognizer::kByteArrayBaseGetFloat64:
+      return InlineByteArrayViewLoad(call, receiver_cid,
+                                     kTypedDataFloat64ArrayCid,
+                                     ic_data, entry, last);
+    case MethodRecognizer::kByteArrayBaseGetFloat32x4:
+      if (!ShouldInlineSimd()) return false;
+      return InlineByteArrayViewLoad(call, receiver_cid,
+                                     kTypedDataFloat32x4ArrayCid,
+                                     ic_data, entry, last);
     default:
       return false;
   }
@@ -1198,7 +1239,8 @@
   const Function& target = Function::Handle(ic_data.GetTargetAt(0));
   TargetEntryInstr* entry;
   Definition* last;
-  if (!TryInlineRecognizedMethod(target,
+  if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0),
+                                 target,
                                  call,
                                  call->token_pos(),
                                  *call->ic_data(),
@@ -2026,32 +2068,23 @@
     switch (recognized_kind) {
       // ByteArray getters.
       case MethodRecognizer::kByteArrayBaseGetInt8:
-        return BuildByteArrayViewLoad(
-            call, class_ids[0], kTypedDataInt8ArrayCid);
+        return BuildByteArrayViewLoad(call, kTypedDataInt8ArrayCid);
       case MethodRecognizer::kByteArrayBaseGetUint8:
-        return BuildByteArrayViewLoad(
-            call, class_ids[0], kTypedDataUint8ArrayCid);
+        return BuildByteArrayViewLoad(call, kTypedDataUint8ArrayCid);
       case MethodRecognizer::kByteArrayBaseGetInt16:
-        return BuildByteArrayViewLoad(
-            call, class_ids[0], kTypedDataInt16ArrayCid);
+        return BuildByteArrayViewLoad(call, kTypedDataInt16ArrayCid);
       case MethodRecognizer::kByteArrayBaseGetUint16:
-        return BuildByteArrayViewLoad(
-            call, class_ids[0], kTypedDataUint16ArrayCid);
+        return BuildByteArrayViewLoad(call, kTypedDataUint16ArrayCid);
       case MethodRecognizer::kByteArrayBaseGetInt32:
-        return BuildByteArrayViewLoad(
-            call, class_ids[0], kTypedDataInt32ArrayCid);
+        return BuildByteArrayViewLoad(call, kTypedDataInt32ArrayCid);
       case MethodRecognizer::kByteArrayBaseGetUint32:
-        return BuildByteArrayViewLoad(
-            call, class_ids[0], kTypedDataUint32ArrayCid);
+        return BuildByteArrayViewLoad(call, kTypedDataUint32ArrayCid);
       case MethodRecognizer::kByteArrayBaseGetFloat32:
-        return BuildByteArrayViewLoad(
-            call, class_ids[0], kTypedDataFloat32ArrayCid);
+        return BuildByteArrayViewLoad(call, kTypedDataFloat32ArrayCid);
       case MethodRecognizer::kByteArrayBaseGetFloat64:
-        return BuildByteArrayViewLoad(
-            call, class_ids[0], kTypedDataFloat64ArrayCid);
+        return BuildByteArrayViewLoad(call, kTypedDataFloat64ArrayCid);
       case MethodRecognizer::kByteArrayBaseGetFloat32x4:
-        return BuildByteArrayViewLoad(
-            call, class_ids[0], kTypedDataFloat32x4ArrayCid);
+        return BuildByteArrayViewLoad(call, kTypedDataFloat32x4ArrayCid);
 
       // ByteArray setters.
       case MethodRecognizer::kByteArrayBaseSetInt8:
@@ -2449,33 +2482,175 @@
 }
 
 
-bool FlowGraphOptimizer::BuildByteArrayViewLoad(
-    InstanceCallInstr* call,
-    intptr_t receiver_cid,
-    intptr_t view_cid) {
+bool FlowGraphOptimizer::InlineByteArrayViewLoad(Instruction* call,
+                                                 intptr_t array_cid,
+                                                 intptr_t view_cid,
+                                                 const ICData& ic_data,
+                                                 TargetEntryInstr** entry,
+                                                 Definition** last) {
+  ASSERT(array_cid != kIllegalCid);
+  Definition* array = call->ArgumentAt(0);
+  Definition* index = call->ArgumentAt(1);
+  *entry = new TargetEntryInstr(flow_graph()->allocate_block_id(),
+                                call->GetBlock()->try_index());
+  (*entry)->InheritDeoptTarget(call);
+  Instruction* cursor = *entry;
+
+  array_cid = PrepareInlineByteArrayViewOp(call,
+                                           array_cid,
+                                           view_cid,
+                                           &array,
+                                           index,
+                                           &cursor);
+
+  intptr_t deopt_id = Isolate::kNoDeoptId;
+  if ((array_cid == kTypedDataInt32ArrayCid) ||
+      (array_cid == kTypedDataUint32ArrayCid)) {
+    // Set deopt_id if we can optimistically assume that the result is Smi.
+    // Assume mixed Mint/Smi if this instruction caused deoptimization once.
+    deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ?
+        call->deopt_id() : Isolate::kNoDeoptId;
+  }
+
+  *last = new LoadIndexedInstr(new Value(array),
+                               new Value(index),
+                               1,
+                               view_cid,
+                               deopt_id);
+  flow_graph()->AppendTo(cursor,
+                         *last,
+                         deopt_id != Isolate::kNoDeoptId ? call->env() : NULL,
+                         Definition::kValue);
+  return true;
+}
+
+
+intptr_t FlowGraphOptimizer::PrepareInlineByteArrayViewOp(
+    Instruction* call,
+    intptr_t array_cid,
+    intptr_t view_cid,
+    Definition** array,
+    Definition* byte_index,
+    Instruction** cursor) {
+  // Insert byte_index smi check.
+  *cursor = flow_graph()->AppendTo(*cursor,
+                                   new CheckSmiInstr(new Value(byte_index),
+                                                     call->deopt_id()),
+                                   call->env(),
+                                   Definition::kEffect);
+
+  const bool is_immutable = true;
+  LoadFieldInstr* length =
+      new LoadFieldInstr(new Value(*array),
+                         CheckArrayBoundInstr::LengthOffsetFor(array_cid),
+                         Type::ZoneHandle(Type::SmiType()),
+                         is_immutable);
+  length->set_result_cid(kSmiCid);
+  length->set_recognized_kind(
+      LoadFieldInstr::RecognizedKindFromArrayCid(array_cid));
+  *cursor = flow_graph()->AppendTo(*cursor,
+                                   length,
+                                   NULL,
+                                   Definition::kValue);
+
+  intptr_t element_size = FlowGraphCompiler::ElementSizeFor(array_cid);
+  ConstantInstr* bytes_per_element =
+      flow_graph()->GetConstant(Smi::Handle(Smi::New(element_size)));
+  BinarySmiOpInstr* len_in_bytes =
+      new BinarySmiOpInstr(Token::kMUL,
+                           new Value(length),
+                           new Value(bytes_per_element),
+                           call->deopt_id());
+  *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(),
+                                   Definition::kValue);
+
+  ConstantInstr* length_adjustment =
+      flow_graph()->GetConstant(Smi::Handle(Smi::New(
+          FlowGraphCompiler::ElementSizeFor(view_cid) - 1)));
+  // adjusted_length = len_in_bytes - (element_size - 1).
+  BinarySmiOpInstr* adjusted_length =
+      new BinarySmiOpInstr(Token::kSUB,
+                           new Value(len_in_bytes),
+                           new Value(length_adjustment),
+                           call->deopt_id());
+  *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(),
+                                   Definition::kValue);
+
+  // Check adjusted_length > 0.
+  ConstantInstr* zero = flow_graph()->GetConstant(Smi::Handle(Smi::New(0)));
+  *cursor = flow_graph()->AppendTo(*cursor,
+                                   new CheckArrayBoundInstr(
+                                       new Value(adjusted_length),
+                                       new Value(zero),
+                                       call->deopt_id()),
+                                   call->env(),
+                                   Definition::kEffect);
+  // Check 0 <= byte_index < adjusted_length.
+  *cursor = flow_graph()->AppendTo(*cursor,
+                                   new CheckArrayBoundInstr(
+                                       new Value(adjusted_length),
+                                       new Value(byte_index),
+                                       call->deopt_id()),
+                                   call->env(),
+                                   Definition::kEffect);
+
+  if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+    LoadUntaggedInstr* elements =
+        new LoadUntaggedInstr(new Value(*array),
+                              ExternalTypedData::data_offset());
+    *cursor = flow_graph()->AppendTo(*cursor,
+                                     elements,
+                                     NULL,
+                                     Definition::kValue);
+    *array = elements;
+  }
+  return array_cid;
+}
+
+
+bool FlowGraphOptimizer::BuildByteArrayViewLoad(InstanceCallInstr* call,
+                                                intptr_t view_cid) {
   if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) {
     return false;
   }
 
-  Definition* array = call->ArgumentAt(0);
-  PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array);
+  ASSERT(call->HasICData());
+  Function& target = Function::Handle();
+  GrowableArray<intptr_t> class_ids;
+  call->ic_data()->GetCheckAt(0, &class_ids, &target);
+  const intptr_t receiver_cid = class_ids[0];
 
-  // Optimistically build a smi-checked load for Int32 and Uint32
-  // loads on ia32 like we do for normal array loads, and only revert to
-  // mint case after deoptimizing here.
-  intptr_t deopt_id = Isolate::kNoDeoptId;
-  if ((view_cid == kTypedDataInt32ArrayCid ||
-       view_cid == kTypedDataUint32ArrayCid) &&
-      call->ic_data()->deopt_reason() == kDeoptUnknown) {
-    deopt_id = call->deopt_id();
+  TargetEntryInstr* entry;
+  Definition* last;
+  if (!TryInlineRecognizedMethod(receiver_cid,
+                                 target,
+                                 call,
+                                 call->token_pos(),
+                                 *call->ic_data(),
+                                 &entry, &last)) {
+    return false;
   }
-  Definition* byte_index = call->ArgumentAt(1);
-  LoadIndexedInstr* array_op = new LoadIndexedInstr(new Value(array),
-                                                    new Value(byte_index),
-                                                    1,  // Index scale.
-                                                    view_cid,
-                                                    deopt_id);
-  ReplaceCall(call, array_op);
+
+  // Insert receiver class check.
+  AddReceiverCheck(call);
+  // Remove the original push arguments.
+  for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
+    PushArgumentInstr* push = call->PushArgumentAt(i);
+    push->ReplaceUsesWith(push->value()->definition());
+    push->RemoveFromGraph();
+  }
+  // Replace all uses of this definition with the result.
+  call->ReplaceUsesWith(last);
+  // Finally insert the sequence other definition in place of this one in the
+  // graph.
+  call->previous()->LinkTo(entry->next());
+  entry->UnuseAllInputs();  // Entry block is not in the graph.
+  last->LinkTo(call);
+  // Remove through the iterator.
+  ASSERT(current_iterator()->Current() == call);
+  current_iterator()->RemoveCurrentFromGraph();
+  call->set_previous(NULL);
+  call->set_next(NULL);
   return true;
 }
 
@@ -2825,7 +3000,15 @@
     return;
   }
 
-  const bool has_one_target = unary_checks.HasOneTarget();
+  bool has_one_target = unary_checks.HasOneTarget();
+
+  if (has_one_target) {
+    // Check if the single target is a polymorphic target, if it is,
+    // we don't have one target.
+    const Function& target = Function::Handle(unary_checks.GetTargetAt(0));
+    const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target);
+    has_one_target = !polymorphic_target;
+  }
 
   if (has_one_target) {
     const bool is_method_extraction =
@@ -4127,6 +4310,7 @@
   Place(const Place& other)
       : ValueObject(),
         kind_(other.kind_),
+        representation_(other.representation_),
         instance_(other.instance_),
         raw_selector_(other.raw_selector_),
         id_(other.id_) {
@@ -4135,10 +4319,15 @@
   // Construct a place from instruction if instruction accesses any place.
   // Otherwise constructs kNone place.
   Place(Instruction* instr, bool* is_load)
-      : kind_(kNone), instance_(NULL), raw_selector_(0), id_(0) {
+      : kind_(kNone),
+        representation_(kNoRepresentation),
+        instance_(NULL),
+        raw_selector_(0),
+        id_(0) {
     switch (instr->tag()) {
       case Instruction::kLoadField: {
         LoadFieldInstr* load_field = instr->AsLoadField();
+        representation_ = load_field->representation();
         instance_ = OriginalDefinition(load_field->instance()->definition());
         if (load_field->field() != NULL) {
           kind_ = kField;
@@ -4155,6 +4344,8 @@
         StoreInstanceFieldInstr* store_instance_field =
             instr->AsStoreInstanceField();
         kind_ = kField;
+        representation_ = store_instance_field->
+            RequiredInputRepresentation(StoreInstanceFieldInstr::kValuePos);
         instance_ =
             OriginalDefinition(store_instance_field->instance()->definition());
         field_ = &store_instance_field->field();
@@ -4164,6 +4355,8 @@
       case Instruction::kStoreVMField: {
         StoreVMFieldInstr* store_vm_field = instr->AsStoreVMField();
         kind_ = kVMField;
+        representation_ = store_vm_field->
+            RequiredInputRepresentation(StoreVMFieldInstr::kValuePos);
         instance_ = OriginalDefinition(store_vm_field->dest()->definition());
         offset_in_bytes_ = store_vm_field->offset_in_bytes();
         break;
@@ -4171,18 +4364,22 @@
 
       case Instruction::kLoadStaticField:
         kind_ = kField;
+        representation_ = instr->AsLoadStaticField()->representation();
         field_ = &instr->AsLoadStaticField()->StaticField();
         *is_load = true;
         break;
 
       case Instruction::kStoreStaticField:
         kind_ = kField;
+        representation_ = instr->AsStoreStaticField()->
+            RequiredInputRepresentation(StoreStaticFieldInstr::kValuePos);
         field_ = &instr->AsStoreStaticField()->field();
         break;
 
       case Instruction::kLoadIndexed: {
         LoadIndexedInstr* load_indexed = instr->AsLoadIndexed();
         kind_ = kIndexed;
+        representation_ = load_indexed->representation();
         instance_ = OriginalDefinition(load_indexed->array()->definition());
         index_ = load_indexed->index()->definition();
         *is_load = true;
@@ -4192,6 +4389,8 @@
       case Instruction::kStoreIndexed: {
         StoreIndexedInstr* store_indexed = instr->AsStoreIndexed();
         kind_ = kIndexed;
+        representation_ = store_indexed->
+            RequiredInputRepresentation(StoreIndexedInstr::kValuePos);
         instance_ = OriginalDefinition(store_indexed->array()->definition());
         index_ = store_indexed->index()->definition();
         break;
@@ -4199,11 +4398,16 @@
 
       case Instruction::kCurrentContext:
         kind_ = kContext;
+        ASSERT(instr->AsCurrentContext()->representation() == kTagged);
+        representation_ = kTagged;
         *is_load = true;
         break;
 
       case Instruction::kStoreContext:
         kind_ = kContext;
+        ASSERT(instr->AsStoreContext()->RequiredInputRepresentation(
+            StoreContextInstr::kValuePos) == kTagged);
+        representation_ = kTagged;
         break;
 
       default:
@@ -4216,6 +4420,8 @@
 
   Kind kind() const { return kind_; }
 
+  Representation representation() const { return representation_; }
+
   Definition* instance() const {
     ASSERT((kind_ == kField) || (kind_ == kVMField) || (kind_ == kIndexed));
     return instance_;
@@ -4281,11 +4487,12 @@
 
   intptr_t Hashcode() const {
     return (kind_ * 63 + reinterpret_cast<intptr_t>(instance_)) * 31 +
-        FieldHashcode();
+        representation_ * 15 + FieldHashcode();
   }
 
   bool Equals(Place* other) const {
     return (kind_ == other->kind_) &&
+        (representation_ == other->representation_) &&
         (instance_ == other->instance_) &&
         SameField(other);
   }
@@ -4295,8 +4502,12 @@
 
  private:
   static Definition* OriginalDefinition(Definition* defn) {
-    while (defn->IsRedefinition()) {
-      defn = defn->AsRedefinition()->value()->definition();
+    while (defn->IsRedefinition() || defn->IsAssertAssignable()) {
+      if (defn->IsRedefinition()) {
+        defn = defn->AsRedefinition()->value()->definition();
+      } else {
+        defn = defn->AsAssertAssignable()->value()->definition();
+      }
     }
     return defn;
   }
@@ -4312,6 +4523,7 @@
   }
 
   Kind kind_;
+  Representation representation_;
   Definition* instance_;
   union {
     intptr_t raw_selector_;
@@ -4513,8 +4725,10 @@
         if (instr->IsPushArgument() ||
             (instr->IsStoreVMField() && (use->use_index() != 1)) ||
             (instr->IsStoreInstanceField() && (use->use_index() != 0)) ||
-            (instr->IsStoreStaticField()) ||
-            (instr->IsPhi())) {
+            instr->IsStoreStaticField() ||
+            instr->IsPhi() ||
+            instr->IsAssertAssignable() ||
+            instr->IsRedefinition()) {
           escapes = true;
           break;
         }
@@ -6196,79 +6410,8 @@
 
 
 void ConstantPropagator::VisitStringInterpolate(StringInterpolateInstr* instr) {
-  // TODO(srdjan): Remove the code below and enable constant folding once
-  // issue resolved.
   SetValue(instr, non_constant_);
   return;
-
-  if (IsNonConstant(instr->constant_value())) {
-    // Do not bother with costly analysis if we already know that the
-    // instruction is not a constant.
-    SetValue(instr, non_constant_);
-    return;
-  }
-  // If all inputs are constant strings, numbers, booleans or null, then
-  // constant fold.
-  // TODO(srdjan): Also constant fold an interval of constant arguments.
-  //   v2 <- CreateArray(v0)
-  //   StoreIndexed(v2, v3, v4)   -- v3:constant index, v4: value.
-  //   ..
-  //   v8 <- StringInterpolate(v2)
-  CreateArrayInstr* create_array =
-      instr->value()->definition()->AsCreateArray();
-  ASSERT(create_array != NULL);
-
-  // Check if the string interpolation has only constant inputs.
-  for (Value::Iterator it(create_array->input_use_list());
-       !it.Done();
-       it.Advance()) {
-    Instruction* curr = it.Current()->instruction();
-    if (curr != instr) {
-      StoreIndexedInstr* store = curr->AsStoreIndexed();
-      ASSERT(store != NULL);
-      const Object& value = store->value()->definition()->constant_value();
-      if (IsNonConstant(value)) {
-        SetValue(instr, non_constant_);
-        return;
-      } else if (IsUnknown(value)) {
-        ASSERT(IsUnknown(instr->constant_value()));
-        return;
-      }
-    }
-  }
-  // Interpolate string at compile time.
-  const Array& value_arr =
-      Array::Handle(Array::New(create_array->num_elements()));
-  // Build array of literal values to interpolate.
-  for (Value::Iterator it(create_array->input_use_list());
-       !it.Done();
-       it.Advance()) {
-    Instruction* curr = it.Current()->instruction();
-    // Skip StringInterpolateInstr.
-    if (curr != instr) {
-      StoreIndexedInstr* store = curr->AsStoreIndexed();
-      ASSERT(store != NULL);
-      Value* index_value = store->index();
-      ASSERT(index_value->BindsToConstant() && index_value->IsSmiValue());
-      const intptr_t ix = Smi::Cast(index_value->BoundConstant()).Value();
-      ASSERT(IsConstant(store->value()->definition()->constant_value()));
-      value_arr.SetAt(ix, store->value()->definition()->constant_value());
-    }
-  }
-  // Build argument array to pass to the interpolation function.
-  const Array& interpolate_arg = Array::Handle(Array::New(1));
-  interpolate_arg.SetAt(0, value_arr);
-  // Call interpolation function.
-  String& concatenated = String::ZoneHandle();
-  concatenated ^=
-      DartEntry::InvokeFunction(instr->CallFunction(), interpolate_arg);
-  if (concatenated.IsUnhandledException()) {
-    SetValue(instr, non_constant_);
-    return;
-  }
-
-  concatenated = Symbols::New(concatenated);
-  SetValue(instr, concatenated);
 }
 
 
@@ -7044,16 +7187,6 @@
         ConstantInstr* constant = graph_->GetConstant(defn->constant_value());
         defn->ReplaceUsesWith(constant);
         i.RemoveCurrentFromGraph();
-        if (defn->IsStringInterpolate()) {
-          CreateArrayInstr* create_array = defn->AsStringInterpolate()->
-              value()->definition()->AsCreateArray();
-          for (Value* use = create_array->input_use_list();
-              use != NULL;
-              use = create_array->input_use_list()) {
-            use->instruction()->RemoveFromGraph();
-          }
-          create_array->RemoveFromGraph();
-        }
       }
     }
 
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h
index 79d6fe3..17fd3cf 100644
--- a/runtime/vm/flow_graph_optimizer.h
+++ b/runtime/vm/flow_graph_optimizer.h
@@ -44,7 +44,8 @@
 
   void AnalyzeTryCatch();
 
-  bool TryInlineRecognizedMethod(const Function& target,
+  bool TryInlineRecognizedMethod(intptr_t receiver_cid,
+                                 const Function& target,
                                  Instruction* call,
                                  intptr_t token_pos,
                                  const ICData& ic_data,
@@ -118,8 +119,21 @@
   LoadIndexedInstr* BuildStringCodeUnitAt(InstanceCallInstr* call,
                                           intptr_t cid);
 
+  bool InlineByteArrayViewLoad(Instruction* call,
+                               intptr_t array_cid,
+                               intptr_t view_cid,
+                               const ICData& ic_data,
+                               TargetEntryInstr** entry,
+                               Definition** last);
+
+  intptr_t PrepareInlineByteArrayViewOp(Instruction* call,
+                                        intptr_t array_cid,
+                                        intptr_t view_cid,
+                                        Definition** array,
+                                        Definition* index,
+                                        Instruction** cursor);
+
   bool BuildByteArrayViewLoad(InstanceCallInstr* call,
-                              intptr_t receiver_cid,
                               intptr_t view_cid);
   bool BuildByteArrayViewStore(InstanceCallInstr* call,
                                intptr_t view_cid);
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index 1915b0c..3883925 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -18,6 +18,12 @@
 DECLARE_FLAG(bool, use_cha);
 
 
+void FlowGraphTypePropagator::Propagate(FlowGraph* flow_graph) {
+  FlowGraphTypePropagator propagator(flow_graph);
+  propagator.Propagate();
+}
+
+
 FlowGraphTypePropagator::FlowGraphTypePropagator(FlowGraph* flow_graph)
     : FlowGraphVisitor(flow_graph->reverse_postorder()),
       flow_graph_(flow_graph),
diff --git a/runtime/vm/flow_graph_type_propagator.h b/runtime/vm/flow_graph_type_propagator.h
index 9b6e02d..4569295 100644
--- a/runtime/vm/flow_graph_type_propagator.h
+++ b/runtime/vm/flow_graph_type_propagator.h
@@ -12,11 +12,13 @@
 
 class FlowGraphTypePropagator : public FlowGraphVisitor {
  public:
+  static void Propagate(FlowGraph* flow_graph);
+
+ private:
   explicit FlowGraphTypePropagator(FlowGraph* flow_graph);
 
   void Propagate();
 
- private:
   void PropagateRecursive(BlockEntryInstr* block);
   void HandleBranchOnNull(BlockEntryInstr* block);
 
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index fdbaa09..185eaf3 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -20,6 +20,8 @@
 #include "vm/stub_code.h"
 #include "vm/symbols.h"
 
+#include "vm/il_printer.h"
+
 namespace dart {
 
 DEFINE_FLAG(int, max_equality_polymorphic_checks, 32,
@@ -407,6 +409,28 @@
 }
 
 
+bool MethodRecognizer::PolymorphicTarget(const Function& function) {
+  const Class& function_class = Class::Handle(function.Owner());
+  const Library& lib = Library::Handle(function_class.library());
+  if (!IsRecognizedLibrary(lib)) {
+    return false;
+  }
+
+  const String& function_name = String::Handle(function.name());
+  const String& class_name = String::Handle(function_class.Name());
+
+#define RECOGNIZE_FUNCTION(test_class_name, test_function_name, enum_name, fp) \
+  if (CompareNames(lib, #test_function_name, function_name) &&                 \
+      CompareNames(lib, #test_class_name, class_name)) {                       \
+    ASSERT(function.CheckSourceFingerprint(fp));                               \
+    return true;                                                               \
+  }
+POLYMORPHC_TARGET_LIST(RECOGNIZE_FUNCTION)
+#undef RECOGNIZE_FUNCTION
+  return false;
+}
+
+
 const char* MethodRecognizer::KindToCString(Kind kind) {
 #define KIND_TO_STRING(class_name, function_name, enum_name, fp)               \
   if (kind == k##enum_name) return #enum_name;
@@ -2697,6 +2721,65 @@
 }
 
 
+// Replace StringInterpolateInstr with a constant string if all inputs are
+// constant of [string, number, boolean, null].
+// Leave the CreateArrayInstr and StoreIndexedInstr in the stream in case
+// deoptimization occurs.
+Definition* StringInterpolateInstr::Canonicalize(FlowGraph* flow_graph) {
+  // The following graph structure is generated by the graph builder:
+  //   v2 <- CreateArray(v0)
+  //   StoreIndexed(v2, v3, v4)   -- v3:constant index, v4: value.
+  //   ..
+  //   v8 <- StringInterpolate(v2)
+  CreateArrayInstr* create_array = value()->definition()->AsCreateArray();
+  ASSERT(create_array != NULL);
+  // Check if the string interpolation has only constant inputs.
+  GrowableArray<ConstantInstr*> constants(create_array->num_elements());
+  for (intptr_t i = 0; i < create_array->num_elements(); i++) {
+    constants.Add(NULL);
+  }
+  for (Value::Iterator it(create_array->input_use_list());
+       !it.Done();
+       it.Advance()) {
+    Instruction* curr = it.Current()->instruction();
+    if (curr != this) {
+      StoreIndexedInstr* store = curr->AsStoreIndexed();
+      ASSERT(store != NULL);
+      if (store->value()->definition()->IsConstant()) {
+        ASSERT(store->index()->BindsToConstant());
+        const Object& obj = store->value()->definition()->AsConstant()->value();
+        if (obj.IsNumber() || obj.IsString() || obj.IsBool() || obj.IsNull()) {
+          constants[Smi::Cast(store->index()->BoundConstant()).Value()] =
+              store->value()->definition()->AsConstant();
+        } else {
+          return this;
+        }
+      } else {
+        return this;
+      }
+    }
+  }
+  // Interpolate string at compile time.
+  const Array& array_argument =
+      Array::Handle(Array::New(create_array->num_elements()));
+  for (intptr_t i = 0; i < constants.length(); i++) {
+    array_argument.SetAt(i, constants[i]->value());
+  }
+  // Build argument array to pass to the interpolation function.
+  const Array& interpolate_arg = Array::Handle(Array::New(1));
+  interpolate_arg.SetAt(0, array_argument);
+  // Call interpolation function.
+  String& concatenated = String::ZoneHandle();
+  concatenated ^=
+      DartEntry::InvokeFunction(CallFunction(), interpolate_arg);
+  if (concatenated.IsUnhandledException()) {
+    return this;
+  }
+  concatenated = Symbols::New(concatenated);
+  return flow_graph->GetConstant(concatenated);
+}
+
+
 InvokeMathCFunctionInstr::InvokeMathCFunctionInstr(
     ZoneGrowableArray<Value*>* inputs,
     intptr_t original_deopt_id,
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 4bfc463..62cd8a6 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -177,8 +177,19 @@
   V(_StringBase, get:length, StringBaseLength, 1483520063)                     \
   V(ListIterator, moveNext, ListIteratorMoveNext, 90930587)                    \
   V(_GrowableList, get:iterator, GrowableArrayIterator, 1305127405)            \
-  V(_GrowableList, forEach, GrowableArrayForEach, 1675430533)
+  V(_GrowableList, forEach, GrowableArrayForEach, 1675430533)                  \
 
+// A list of core functions that internally dispatch based on received id.
+#define POLYMORPHC_TARGET_LIST(V)                                              \
+  V(_TypedList, _getInt8, ByteArrayBaseGetInt8, 272598802)                     \
+  V(_TypedList, _getUint8, ByteArrayBaseGetUint8, 831354841)                   \
+  V(_TypedList, _getInt16, ByteArrayBaseGetInt16, 1832126257)                  \
+  V(_TypedList, _getUint16, ByteArrayBaseGetUint16, 1762714698)                \
+  V(_TypedList, _getInt32, ByteArrayBaseGetInt32, 48785449)                    \
+  V(_TypedList, _getUint32, ByteArrayBaseGetUint32, 1392579206)                \
+  V(_TypedList, _getFloat32, ByteArrayBaseGetFloat32, 185163470)               \
+  V(_TypedList, _getFloat64, ByteArrayBaseGetFloat64, 1356392173)              \
+  V(_TypedList, _getFloat32x4, ByteArrayBaseGetFloat32x4, 1239681356)          \
 
 // Class that recognizes the name and owner of a function and returns the
 // corresponding enum. See RECOGNIZED_LIST above for list of recognizable
@@ -194,6 +205,7 @@
 
   static Kind RecognizeKind(const Function& function);
   static bool AlwaysInline(const Function& function);
+  static bool PolymorphicTarget(const Function& function);
   static const char* KindToCString(Kind kind);
   static void InitializeState();
 };
@@ -2219,14 +2231,18 @@
 class StoreContextInstr : public TemplateInstruction<1> {
  public:
   explicit StoreContextInstr(Value* value) {
-    SetInputAt(0, value);
+    SetInputAt(kValuePos, value);
   }
 
+  enum {
+    kValuePos = 0
+  };
+
   DECLARE_INSTRUCTION(StoreContext)
 
   virtual intptr_t ArgumentCount() const { return 0; }
 
-  Value* value() const { return inputs_[0]; }
+  Value* value() const { return inputs_[kValuePos]; }
 
   virtual bool CanDeoptimize() const { return false; }
 
@@ -3419,17 +3435,24 @@
                           StoreBarrierType emit_store_barrier)
       : field_(field),
         emit_store_barrier_(emit_store_barrier) {
-    SetInputAt(0, instance);
-    SetInputAt(1, value);
+    SetInputAt(kInstancePos, instance);
+    SetInputAt(kValuePos, value);
   }
 
   DECLARE_INSTRUCTION(StoreInstanceField)
+
+  enum {
+    kInstancePos = 0,
+    kValuePos = 1
+  };
+
+  Value* instance() const { return inputs_[kInstancePos]; }
+  Value* value() const { return inputs_[kValuePos]; }
+
   virtual CompileType* ComputeInitialType() const;
 
   const Field& field() const { return field_; }
 
-  Value* instance() const { return inputs_[0]; }
-  Value* value() const { return inputs_[1]; }
   bool ShouldEmitStoreBarrier() const {
     return value()->NeedsStoreBuffer()
         && (emit_store_barrier_ == kEmitStoreBarrier);
@@ -3534,14 +3557,18 @@
   StoreStaticFieldInstr(const Field& field, Value* value)
       : field_(field) {
     ASSERT(field.IsZoneHandle());
-    SetInputAt(0, value);
+    SetInputAt(kValuePos, value);
   }
 
+  enum {
+    kValuePos = 0
+  };
+
   DECLARE_INSTRUCTION(StoreStaticField)
   virtual CompileType* ComputeInitialType() const;
 
   const Field& field() const { return field_; }
-  Value* value() const { return inputs_[0]; }
+  Value* value() const { return inputs_[kValuePos]; }
 
   virtual void PrintOperandsTo(BufferFormatter* f) const;
 
@@ -3674,6 +3701,8 @@
 
   const Function& CallFunction() const;
 
+  virtual Definition* Canonicalize(FlowGraph* flow_graph);
+
   DECLARE_INSTRUCTION(StringInterpolate)
 
  private:
@@ -3696,17 +3725,24 @@
       : emit_store_barrier_(emit_store_barrier),
         index_scale_(index_scale),
         class_id_(class_id) {
-    SetInputAt(0, array);
-    SetInputAt(1, index);
-    SetInputAt(2, value);
+    SetInputAt(kArrayPos, array);
+    SetInputAt(kIndexPos, index);
+    SetInputAt(kValuePos, value);
     deopt_id_ = deopt_id;
   }
 
   DECLARE_INSTRUCTION(StoreIndexed)
 
-  Value* array() const { return inputs_[0]; }
-  Value* index() const { return inputs_[1]; }
-  Value* value() const { return inputs_[2]; }
+  enum {
+    kArrayPos = 0,
+    kIndexPos = 1,
+    kValuePos = 2
+  };
+
+  Value* array() const { return inputs_[kArrayPos]; }
+  Value* index() const { return inputs_[kIndexPos]; }
+  Value* value() const { return inputs_[kValuePos]; }
+
   intptr_t index_scale() const { return index_scale_; }
   intptr_t class_id() const { return class_id_; }
 
@@ -4197,15 +4233,20 @@
                     const AbstractType& type)
       : offset_in_bytes_(offset_in_bytes), type_(type) {
     ASSERT(type.IsZoneHandle());  // May be null if field is not an instance.
-    SetInputAt(0, value);
-    SetInputAt(1, dest);
+    SetInputAt(kValuePos, value);
+    SetInputAt(kDestPos, dest);
   }
 
+  enum {
+    kValuePos = 0,
+    kDestPos = 1
+  };
+
   DECLARE_INSTRUCTION(StoreVMField)
   virtual CompileType* ComputeInitialType() const;
 
-  Value* value() const { return inputs_[0]; }
-  Value* dest() const { return inputs_[1]; }
+  Value* value() const { return inputs_[kValuePos]; }
+  Value* dest() const { return inputs_[kDestPos]; }
   intptr_t offset_in_bytes() const { return offset_in_bytes_; }
   const AbstractType& type() const { return type_; }
 
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 96ffe7a..0ec3129 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -3308,10 +3308,11 @@
 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   QRegister left = locs()->in(0).fpu_reg();
   QRegister result = locs()->out().fpu_reg();
+  QRegister temp = locs()->temp(0).fpu_reg();
 
   switch (op_kind()) {
     case MethodRecognizer::kFloat32x4Sqrt:
-      __ Vsqrtqs(result, left);
+      __ Vsqrtqs(result, left, temp);
       break;
     case MethodRecognizer::kFloat32x4Reciprocal:
       __ Vreciprocalqs(result, left);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index b073679..65fb850 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -330,7 +330,8 @@
       }
       start = i + 1;
     } else if (name.CharAt(i) == '@') {
-      ASSERT(at_pos == -1);  // Only one @ is supported.
+      // Setters should have only one @ so we know where to put the =.
+      ASSERT(!is_setter || (at_pos == -1));
       at_pos = i;
     }
   }
@@ -2788,7 +2789,7 @@
   AbstractType& interface = AbstractType::Handle();
   Class& interface_class = Class::Handle();
   AbstractTypeArguments& interface_args = AbstractTypeArguments::Handle();
-  Error& args_bound_error = Error::Handle();
+  Error& error = Error::Handle();
   for (intptr_t i = 0; i < interfaces.Length(); i++) {
     interface ^= interfaces.At(i);
     if (!interface.IsFinalized()) {
@@ -2796,6 +2797,15 @@
       // unfinalized interface will postpone bound checking to run time.
       continue;
     }
+    error = Error::null();
+    if (interface.IsMalboundedWithError(&error)) {
+      // Return the first bound error to the caller if it requests it.
+      if ((bound_error != NULL) && bound_error->IsNull()) {
+        ASSERT(!error.IsNull());
+        *bound_error = error.raw();
+      }
+      continue;  // Another interface may work better.
+    }
     interface_class = interface.type_class();
     interface_args = interface.arguments();
     if (!interface_args.IsNull() && !interface_args.IsInstantiated()) {
@@ -2807,13 +2817,12 @@
       // parameters of the interface are at the end of the type vector,
       // after the type arguments of the super type of this type.
       // The index of the type parameters is adjusted upon finalization.
-      args_bound_error = Error::null();
-      interface_args = interface_args.InstantiateFrom(type_arguments,
-                                                      &args_bound_error);
-      if (!args_bound_error.IsNull()) {
+      error = Error::null();
+      interface_args = interface_args.InstantiateFrom(type_arguments, &error);
+      if (!error.IsNull()) {
         // Return the first bound error to the caller if it requests it.
         if ((bound_error != NULL) && bound_error->IsNull()) {
-          *bound_error = args_bound_error.raw();
+          *bound_error = error.raw();
         }
         continue;  // Another interface may work better.
       }
@@ -6225,7 +6234,7 @@
 
 
 intptr_t TokenStream::ComputeSourcePosition(intptr_t tok_pos) const {
-  Iterator iterator(*this, 0);
+  Iterator iterator(*this, 0, Iterator::kAllTokens);
   intptr_t src_pos = 0;
   Token::Kind kind = iterator.CurrentTokenKind();
   while (iterator.CurrentPosition() < tok_pos && kind != Token::kEOS) {
@@ -6237,19 +6246,6 @@
 }
 
 
-intptr_t TokenStream::ComputeTokenPosition(intptr_t src_pos) const {
-  Iterator iterator(*this, 0);
-  intptr_t index = 0;
-  Token::Kind kind = iterator.CurrentTokenKind();
-  while (index < src_pos && kind != Token::kEOS) {
-    iterator.Advance();
-    kind = iterator.CurrentTokenKind();
-    index += 1;
-  }
-  return iterator.CurrentPosition();
-}
-
-
 RawTokenStream* TokenStream::New() {
   ASSERT(Object::token_stream_class() != Class::null());
   RawObject* raw = Object::Allocate(TokenStream::kClassId,
@@ -6294,7 +6290,7 @@
   }
 
   // Add an IDENT token into the stream and the token objects array.
-  void AddIdentToken(String* ident) {
+  void AddIdentToken(const String* ident) {
     if (ident != NULL) {
       // If the IDENT token is already in the tokens object array use the
       // same index instead of duplicating it.
@@ -6312,7 +6308,7 @@
   }
 
   // Add a LITERAL token into the stream and the token objects array.
-  void AddLiteralToken(Token::Kind kind, String* literal) {
+  void AddLiteralToken(Token::Kind kind, const String* literal) {
     if (literal != NULL) {
       // If the literal token is already in the tokens object array use the
       // same index instead of duplicating it.
@@ -6347,7 +6343,7 @@
   }
 
  private:
-  intptr_t FindIdentIndex(String* ident) {
+  intptr_t FindIdentIndex(const String* ident) {
     ASSERT(ident != NULL);
     intptr_t hash_value = ident->Hash() % kTableSize;
     GrowableArray<intptr_t>& value = ident_table_[hash_value];
@@ -6365,7 +6361,7 @@
     return -1;
   }
 
-  intptr_t FindLiteralIndex(Token::Kind kind, String* literal) {
+  intptr_t FindLiteralIndex(Token::Kind kind, const String* literal) {
     ASSERT(literal != NULL);
     intptr_t hash_value = literal->Hash() % kTableSize;
     GrowableArray<intptr_t>& value = literal_table_[hash_value];
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 387b734..53c0563 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2218,7 +2218,6 @@
 
   RawString* GenerateSource() const;
   intptr_t ComputeSourcePosition(intptr_t tok_pos) const;
-  intptr_t ComputeTokenPosition(intptr_t src_pos) const;
 
   RawString* PrivateKey() const;
 
@@ -2529,14 +2528,12 @@
   static RawLibrary* CoreLibrary();
   static RawLibrary* CollectionLibrary();
   static RawLibrary* CollectionDevLibrary();
-  static RawLibrary* CryptoLibrary();
   static RawLibrary* IsolateLibrary();
   static RawLibrary* JsonLibrary();
   static RawLibrary* MathLibrary();
   static RawLibrary* MirrorsLibrary();
   static RawLibrary* NativeWrappersLibrary();
   static RawLibrary* TypedDataLibrary();
-  static RawLibrary* UriLibrary();
   static RawLibrary* UtfLibrary();
 
   // Eagerly compile all classes and functions in the library.
@@ -5615,7 +5612,8 @@
   }
 
   void* DataAddr(intptr_t byte_offset) const {
-    ASSERT((byte_offset >= 0) && (byte_offset < LengthInBytes()));
+    ASSERT((byte_offset == 0) ||
+           ((byte_offset > 0) && (byte_offset < LengthInBytes())));
     return reinterpret_cast<void*>(raw_ptr()->data_ + byte_offset);
   }
 
@@ -5747,7 +5745,8 @@
   }
 
   void* DataAddr(intptr_t byte_offset) const {
-    ASSERT((byte_offset >= 0) && (byte_offset < LengthInBytes()));
+    ASSERT((byte_offset == 0) ||
+           ((byte_offset > 0) && (byte_offset < LengthInBytes())));
     return reinterpret_cast<void*>(raw_ptr()->data_ + byte_offset);
   }
 
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 6ccdff9..eb07bf5 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -19,7 +19,7 @@
 // by snapshots eventually.
 class ObjectStore {
  public:
-  enum {
+  enum BootstrapLibraryId {
     kNone = 0,
     kAsync,
     kCore,
@@ -282,7 +282,7 @@
   RawLibrary* mirrors_library() const { return mirrors_library_; }
   RawLibrary* typed_data_library() const { return typed_data_library_; }
   RawLibrary* utf_library() const { return utf_library_; }
-  void set_bootstrap_library(intptr_t index, const Library& value) {
+  void set_bootstrap_library(BootstrapLibraryId index, const Library& value) {
     switch (index) {
       case kAsync:
         async_library_ = value.raw();
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 2cf980e..fbd1068 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -1198,8 +1198,7 @@
   }
 
   if (desc.NamedCount() > 0) {
-    const Array& arg_names =
-        Array::ZoneHandle(Array::New(desc.NamedCount()));
+    const Array& arg_names = Array::ZoneHandle(Array::New(desc.NamedCount()));
     for (intptr_t i = 0; i < arg_names.Length(); ++i) {
       arg_names.SetAt(i, String::Handle(desc.NameAt(i)));
     }
@@ -1207,16 +1206,14 @@
   }
 
   const String& func_name = String::ZoneHandle(func.name());
-  ArgumentListNode* arguments = BuildNoSuchMethodArguments(token_pos,
-                                                           func_name,
-                                                           *func_args);
+  ArgumentListNode* arguments = BuildNoSuchMethodArguments(
+      token_pos, func_name, *func_args, NULL, false);
   const Function& no_such_method = Function::ZoneHandle(
-        Resolver::ResolveDynamicAnyArgs(Class::Handle(func.Owner()),
-                                        Symbols::NoSuchMethod()));
+      Resolver::ResolveDynamicAnyArgs(Class::Handle(func.Owner()),
+                                      Symbols::NoSuchMethod()));
   StaticCallNode* call =
       new StaticCallNode(token_pos, no_such_method, arguments);
 
-
   ReturnNode* return_node = new ReturnNode(token_pos, call);
   current_block_->statements->Add(return_node);
   return CloseBlock();
@@ -1649,7 +1646,8 @@
     intptr_t call_pos,
     const String& function_name,
     const ArgumentListNode& function_args,
-    const LocalVariable* temp_for_last_arg) {
+    const LocalVariable* temp_for_last_arg,
+    bool is_super_invocation) {
   const intptr_t args_pos = function_args.token_pos();
   // Build arguments to the call to the static
   // InvocationMirror._allocateInvocationMirror method.
@@ -1680,6 +1678,7 @@
     }
   }
   arguments->Add(args_array);
+  arguments->Add(new LiteralNode(args_pos, Bool::Get(is_super_invocation)));
   // Lookup the static InvocationMirror._allocateInvocationMirror method.
   const Class& mirror_class =
       Class::Handle(Library::LookupCoreClass(Symbols::InvocationMirror()));
@@ -1696,14 +1695,18 @@
     intptr_t call_pos,
     const String& function_name,
     const ArgumentListNode& function_args,
-    const LocalVariable* temp_for_last_arg) {
+    const LocalVariable* temp_for_last_arg,
+    bool is_super_invocation) {
   ASSERT(function_args.length() >= 1);  // The receiver is the first argument.
   const intptr_t args_pos = function_args.token_pos();
   ArgumentListNode* arguments = new ArgumentListNode(args_pos);
   arguments->Add(function_args.NodeAt(0));
   // The second argument is the invocation mirror.
-  arguments->Add(BuildInvocationMirrorAllocation(
-      call_pos, function_name, function_args, temp_for_last_arg));
+  arguments->Add(BuildInvocationMirrorAllocation(call_pos,
+                                                 function_name,
+                                                 function_args,
+                                                 temp_for_last_arg,
+                                                 is_super_invocation));
   return arguments;
 }
 
@@ -1745,7 +1748,7 @@
   }
   if (is_no_such_method) {
     arguments = BuildNoSuchMethodArguments(
-        supercall_pos, function_name, *arguments);
+        supercall_pos, function_name, *arguments, NULL, true);
   }
   return new StaticCallNode(supercall_pos, super_function, arguments);
 }
@@ -1779,7 +1782,7 @@
                          &is_no_such_method));
     if (is_no_such_method) {
       op_arguments = BuildNoSuchMethodArguments(
-          super_pos, operator_function_name, *op_arguments);
+          super_pos, operator_function_name, *op_arguments, NULL, true);
     }
     super_op = new StaticCallNode(super_pos, super_operator, op_arguments);
   } else {
@@ -1836,7 +1839,7 @@
                          &is_no_such_method));
     if (is_no_such_method) {
       op_arguments = BuildNoSuchMethodArguments(
-          operator_pos, operator_function_name, *op_arguments);
+          operator_pos, operator_function_name, *op_arguments, NULL, true);
     }
     super_op = new StaticCallNode(operator_pos, super_operator, op_arguments);
     if (negate_result) {
@@ -2503,7 +2506,11 @@
   }
 
   SequenceNode* init_statements = CloseBlock();
-  if (init_statements->length() > 0) {
+  if (is_redirecting_constructor) {
+    // A redirecting super constructor simply passes the phase parameter on to
+    // the target which executes the corresponding phase.
+    current_block_->statements->Add(init_statements);
+  } else if (init_statements->length() > 0) {
     // Generate guard around the initializer code.
     LocalVariable* phase_param = LookupPhaseParameter();
     AstNode* phase_value = new LoadLocalNode(TokenPos(), phase_param);
@@ -4792,11 +4799,13 @@
   if (CurrentToken() != Token::kSTRING) {
     ErrorMsg("library url expected");
   }
-  const String& url = *CurrentLiteral();
+  AstNode* url_literal = ParseStringLiteral(false);
+  ASSERT(url_literal->IsLiteralNode());
+  ASSERT(url_literal->AsLiteralNode()->literal().IsString());
+  const String& url = String::Cast(url_literal->AsLiteralNode()->literal());
   if (url.Length() == 0) {
     ErrorMsg("library url expected");
   }
-  ConsumeToken();
   String& prefix = String::Handle();
   if (is_import && (CurrentToken() == Token::kAS)) {
     ConsumeToken();
@@ -4881,8 +4890,10 @@
   if (CurrentToken() != Token::kSTRING) {
     ErrorMsg("url expected");
   }
-  const String& url = *CurrentLiteral();
-  ConsumeToken();
+  AstNode* url_literal = ParseStringLiteral(false);
+  ASSERT(url_literal->IsLiteralNode());
+  ASSERT(url_literal->AsLiteralNode()->literal().IsString());
+  const String& url = String::Cast(url_literal->AsLiteralNode()->literal());
   ExpectSemicolon();
   const String& canon_url = String::CheckedHandle(
       CallLibraryTagHandler(Dart_kCanonicalizeUrl, source_pos, url));
@@ -6017,10 +6028,11 @@
 // or any other class that does not override the == operator.
 // The expressions are compile-time constants and are thus in the form
 // of a LiteralNode.
-void Parser::CheckCaseExpressions(const GrowableArray<LiteralNode*>& values) {
+RawClass* Parser::CheckCaseExpressions(
+    const GrowableArray<LiteralNode*>& values) {
   const intptr_t num_expressions = values.length();
   if (num_expressions == 0) {
-    return;
+    return Object::dynamic_class();
   }
   const Instance& first_value = values[0]->literal();
   for (intptr_t i = 0; i < num_expressions; i++) {
@@ -6055,6 +6067,12 @@
       }
     }
   }
+  if (first_value.IsInteger()) {
+    return Type::Handle(Type::IntType()).type_class();
+  } else if (first_value.IsString()) {
+    return Type::Handle(Type::StringType()).type_class();
+  }
+  return first_value.clazz();
 }
 
 
@@ -6153,11 +6171,18 @@
   OpenBlock();
   current_block_->scope->AddLabel(label);
 
-  // Store switch expression in temporary local variable.
+  // Store switch expression in temporary local variable. The type of the
+  // variable is set to dynamic. It will later be patched to match the
+  // type of the case clause expressions. Therefore, we have to allocate
+  // a new type representing dynamic and can't reuse the canonical
+  // type object for dynamic.
+  const Type& temp_var_type =
+      Type::ZoneHandle(Type::New(Class::Handle(Object::dynamic_class()),
+                                 TypeArguments::Handle(),
+                                 expr_pos));
+  temp_var_type.SetIsFinalized();
   LocalVariable* temp_variable =
-      new LocalVariable(expr_pos,
-                        Symbols::SwitchExpr(),
-                        Type::ZoneHandle(Type::DynamicType()));
+      new LocalVariable(expr_pos,  Symbols::SwitchExpr(), temp_var_type);
   current_block_->scope->AddVariable(temp_variable);
   AstNode* save_switch_expr =
       new StoreLocalNode(expr_pos, temp_variable, switch_expr);
@@ -6210,8 +6235,11 @@
   }
 
   // Check that all expressions in case clauses are of the same class,
-  // or implement int, double or String.
-  CheckCaseExpressions(case_expr_values);
+  // or implement int, double or String. Patch the type of the temporary
+  // variable holding the switch expression to match the type of the
+  // case clause constants.
+  temp_var_type.set_type_class(
+      Class::Handle(CheckCaseExpressions(case_expr_values)));
 
   // Check for unresolved label references.
   SourceLabel* unresolved_label =
@@ -6709,13 +6737,6 @@
       ExpectToken(Token::kRPAREN);
     }
 
-    // If a generic "catch all" statement has already been seen then all
-    // subsequent catch statements are dead. We issue an error for now,
-    // it might make sense to turn this into a warning.
-    if (generic_catch_seen) {
-      ErrorMsg("a generic 'catch all' statement already exists for this "
-               "try block. All subsequent catch statements are dead code");
-    }
     OpenBlock();
     AddCatchParamsToScope(exception_param,
                           stack_trace_param,
@@ -7095,11 +7116,21 @@
     if (token_pos >= 0) {
       intptr_t line, column;
       script.GetTokenLocation(token_pos, &line, &column);
-      result = String::NewFormatted("'%s': %s: line %" Pd " pos %" Pd ": ",
-                                    script_url.ToCString(),
-                                    message_header,
-                                    line,
-                                    column);
+      // Only report the line position if we have the original source. We still
+      // need to get a valid column so that we can report the ^ mark below the
+      // snippet.
+      if (script.HasSource()) {
+        result = String::NewFormatted("'%s': %s: line %" Pd " pos %" Pd ": ",
+                                      script_url.ToCString(),
+                                      message_header,
+                                      line,
+                                      column);
+      } else {
+        result = String::NewFormatted("'%s': %s: line %" Pd ": ",
+                                      script_url.ToCString(),
+                                      message_header,
+                                      line);
+      }
       // Append the formatted error or warning message.
       result = String::Concat(result, msg);
       const String& new_line = String::Handle(String::New("\n"));
@@ -9661,8 +9692,8 @@
 }
 
 
-static const String& BuildConstructorName(const String& type_class_name,
-                                          const String* named_constructor) {
+static String& BuildConstructorName(const String& type_class_name,
+                                    const String* named_constructor) {
   // By convention, the static function implementing a named constructor 'C'
   // for class 'A' is labeled 'A.C', and the static function implementing the
   // unnamed constructor for class 'A' is labeled 'A.'.
@@ -9743,7 +9774,7 @@
 
   // Resolve the type and optional identifier to a constructor or factory.
   Class& type_class = Class::Handle(type.type_class());
-  const String& type_class_name = String::Handle(type_class.Name());
+  String& type_class_name = String::Handle(type_class.Name());
   AbstractTypeArguments& type_arguments =
       AbstractTypeArguments::ZoneHandle(type.arguments());
 
@@ -9757,7 +9788,7 @@
   AbstractType& type_bound = AbstractType::ZoneHandle();
 
   // Make sure that an appropriate constructor exists.
-  const String& constructor_name =
+  String& constructor_name =
       BuildConstructorName(type_class_name, named_constructor);
   Function& constructor = Function::ZoneHandle(
       type_class.LookupConstructor(constructor_name));
@@ -9811,8 +9842,10 @@
       }
       type = redirect_type.raw();
       type_class = type.type_class();
+      type_class_name = type_class.Name();
       type_arguments = type.arguments();
       constructor = constructor.RedirectionTarget();
+      constructor_name = constructor.name();
       ASSERT(!constructor.IsNull());
     }
     if (constructor.IsFactory()) {
@@ -9825,14 +9858,21 @@
   // a dynamic error to instantiate an abstract class.
   ASSERT(!constructor.IsNull());
   if (type_class.is_abstract() && !constructor.IsFactory()) {
-    ArgumentListNode* arguments = new ArgumentListNode(type_pos);
-    arguments->Add(new LiteralNode(
+    // Evaluate arguments before throwing.
+    LetNode* result = new LetNode(call_pos);
+    for (intptr_t i = 0; i < arguments->length(); ++i) {
+      result->AddNode(arguments->NodeAt(i));
+    }
+    ArgumentListNode* error_arguments = new ArgumentListNode(type_pos);
+    error_arguments->Add(new LiteralNode(
         TokenPos(), Integer::ZoneHandle(Integer::New(type_pos))));
-    arguments->Add(new LiteralNode(
+    error_arguments->Add(new LiteralNode(
         TokenPos(), String::ZoneHandle(type_class_name.raw())));
-    return MakeStaticCall(Symbols::AbstractClassInstantiationError(),
-                          Library::PrivateCoreLibName(Symbols::ThrowNew()),
-                          arguments);
+    result->AddNode(
+        MakeStaticCall(Symbols::AbstractClassInstantiationError(),
+                       Library::PrivateCoreLibName(Symbols::ThrowNew()),
+                       error_arguments));
+    return result;
   }
   String& error_message = String::Handle();
   if (!constructor.AreValidArguments(arguments_length,
@@ -9966,7 +10006,7 @@
 // interpol = kINTERPOL_VAR | (kINTERPOL_START expression kINTERPOL_END)
 // In other words, the scanner breaks down interpolated strings so that
 // a string literal always begins and ends with a kSTRING token.
-AstNode* Parser::ParseStringLiteral() {
+AstNode* Parser::ParseStringLiteral(bool allow_interpolation) {
   TRACE_PARSER("ParseStringLiteral");
   AstNode* primary = NULL;
   const intptr_t literal_start = TokenPos();
@@ -9982,6 +10022,7 @@
   }
   // String interpolation needed.
   bool is_compiletime_const = true;
+  bool has_interpolation = false;
   GrowableArray<AstNode*> values_list;
   while (CurrentToken() == Token::kSTRING) {
     if (CurrentLiteral()->Length() > 0) {
@@ -9992,6 +10033,10 @@
     ConsumeToken();
     while ((CurrentToken() == Token::kINTERPOL_VAR) ||
         (CurrentToken() == Token::kINTERPOL_START)) {
+      if (!allow_interpolation) {
+        ErrorMsg("string interpolation not allowed in this context");
+      }
+      has_interpolation = true;
       AstNode* expr = NULL;
       const intptr_t expr_pos = TokenPos();
       if (CurrentToken() == Token::kINTERPOL_VAR) {
@@ -10024,7 +10069,19 @@
     }
   }
   if (is_compiletime_const) {
-    primary = new LiteralNode(literal_start, Interpolate(values_list));
+    if (has_interpolation) {
+      primary = new LiteralNode(literal_start, Interpolate(values_list));
+    } else {
+      const Array& strings = Array::Handle(Array::New(values_list.length()));
+      for (int i = 0; i < values_list.length(); i++) {
+        const Instance& part = values_list[i]->AsLiteralNode()->literal();
+        ASSERT(part.IsString());
+        strings.SetAt(i, String::Cast(part));
+      }
+      String& lit = String::ZoneHandle(String::ConcatAll(strings, Heap::kOld));
+      lit = Symbols::New(lit);
+      primary = new LiteralNode(literal_start, lit);
+    }
   } else {
     ArrayNode* values = new ArrayNode(
         TokenPos(),
@@ -10139,7 +10196,7 @@
     primary = new LiteralNode(TokenPos(), double_value);
     ConsumeToken();
   } else if (CurrentToken() == Token::kSTRING) {
-    primary = ParseStringLiteral();
+    primary = ParseStringLiteral(true);
   } else if (CurrentToken() == Token::kNEW) {
     ConsumeToken();
     primary = ParseNewOperator(Token::kNEW);
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index cd5dc73..60b02be 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -426,14 +426,16 @@
       intptr_t call_pos,
       const String& function_name,
       const ArgumentListNode& function_args,
-      const LocalVariable* temp = NULL);
+      const LocalVariable* temp,
+      bool is_super_invocation);
   // Build arguments for a NoSuchMethodCall. If LocalVariable temp is not NULL,
   // the last argument is stored in temp.
   static ArgumentListNode* BuildNoSuchMethodArguments(
       intptr_t call_pos,
       const String& function_name,
       const ArgumentListNode& function_args,
-      const LocalVariable* temp = NULL);
+      const LocalVariable* temp,
+      bool is_super_invocation);
   RawFunction* GetSuperFunction(intptr_t token_pos,
                                 const String& name,
                                 ArgumentListNode* arguments,
@@ -496,7 +498,7 @@
   AstNode* ParseDoWhileStatement(String* label_name);
   AstNode* ParseForStatement(String* label_name);
   AstNode* ParseForInStatement(intptr_t forin_pos, SourceLabel* label);
-  void CheckCaseExpressions(const GrowableArray<LiteralNode*>& values);
+  RawClass* CheckCaseExpressions(const GrowableArray<LiteralNode*>& values);
   CaseNode* ParseCaseClause(LocalVariable* switch_expr_value,
                             GrowableArray<LiteralNode*>* case_expr_values,
                             SourceLabel* case_label);
@@ -556,7 +558,7 @@
   AstNode* ParseSelectors(AstNode* primary, bool is_cascade);
   AstNode* ParseCascades(AstNode* expr);
   AstNode* ParsePrimary();
-  AstNode* ParseStringLiteral();
+  AstNode* ParseStringLiteral(bool allow_interpolation);
   String* ParseImportStringLiteral();
   AstNode* ParseCompoundLiteral();
   AstNode* ParseSymbolLiteral();
diff --git a/runtime/vm/scanner.cc b/runtime/vm/scanner.cc
index 0b1e637..56e8386 100644
--- a/runtime/vm/scanner.cc
+++ b/runtime/vm/scanner.cc
@@ -42,13 +42,17 @@
 
 
 void Scanner::Reset() {
-  // Non-chaning newline properties.
+  // Non-changing newline properties.
   newline_token_.kind = Token::kNEWLINE;
   newline_token_.literal = NULL;
-  newline_token_.length = 1;
   // We don't preserve the column information.
   newline_token_.position.column = 0;
 
+  // Non-changing empty string token properties.
+  empty_string_token_.kind = Token::kSTRING;
+  empty_string_token_.literal = &Symbols::Empty();
+  empty_string_token_.position.column = 0;
+
   lookahead_pos_ = -1;
   token_start_ = 0;
   c0_ = '\0';
@@ -187,7 +191,7 @@
 bool Scanner::IsValidLiteral(const Scanner::GrowableTokenStream& tokens,
                              Token::Kind literal_kind,
                              bool* is_positive,
-                             String** value) {
+                             const String** value) {
   if ((tokens.length() == 2) &&
       (tokens[0].kind == literal_kind) &&
       (tokens[1].kind == Token::kEOS)) {
@@ -877,7 +881,6 @@
         }
     }
   } while (current_token_.kind == Token::kWHITESP);
-  current_token_.length = lookahead_pos_ - token_start_;
 }
 
 
@@ -886,13 +889,21 @@
   do {
     Scan();
 
+    bool inserted_new_lines = false;
     for (intptr_t diff = current_token_.position.line - prev_token_line_;
          diff > 0;
          diff--) {
       newline_token_.position.line = current_token_.position.line - diff;
       token_stream->Add(newline_token_);
+      inserted_new_lines = true;
     }
 
+    if (inserted_new_lines &&
+        ((current_token_.kind == Token::kINTERPOL_VAR) ||
+         (current_token_.kind == Token::kINTERPOL_START))) {
+      empty_string_token_.position.line = current_token_.position.line;
+      token_stream->Add(empty_string_token_);
+    }
     token_stream->Add(current_token_);
     prev_token_line_ = current_token_.position.line;
   } while (current_token_.kind != Token::kEOS);
@@ -904,7 +915,22 @@
   Reset();
   do {
     Scan();
+
+    bool inserted_new_lines = false;
+    for (intptr_t diff = current_token_.position.line - prev_token_line_;
+         diff > 0;
+         diff--) {
+      index++;  // Advance the index to account for tokens added in ScanAll.
+      inserted_new_lines = true;
+    }
+
+    if (inserted_new_lines &&
+        ((current_token_.kind == Token::kINTERPOL_VAR) ||
+         (current_token_.kind == Token::kINTERPOL_START))) {
+          index++;  // Advance the index to account for tokens added in ScanAll.
+    }
     index++;
+    prev_token_line_ = current_token_.position.line;
   } while ((token_index >= index) && (current_token_.kind != Token::kEOS));
 }
 
diff --git a/runtime/vm/scanner.h b/runtime/vm/scanner.h
index e0d20fc..dbbbfbd 100644
--- a/runtime/vm/scanner.h
+++ b/runtime/vm/scanner.h
@@ -37,9 +37,8 @@
   struct TokenDescriptor {
     Token::Kind kind;
     int offset;               // Offset in source string.
-    int length;               // Length of token in source.
     SourcePosition position;  // Text position in source.
-    String* literal;          // Identifier, number or string literal.
+    const String* literal;    // Identifier, number or string literal.
   };
 
   // Dummy token index reflecting an unknown source position.
@@ -92,7 +91,7 @@
   static bool IsValidLiteral(const Scanner::GrowableTokenStream& tokens,
                              Token::Kind literal_kind,
                              bool* is_positive,
-                             String** value);
+                             const String** value);
 
  private:
   struct ScanContext {
@@ -197,14 +196,15 @@
 
   TokenDescriptor current_token_;  // Current token.
   TokenDescriptor newline_token_;  // Newline token.
+  TokenDescriptor empty_string_token_;  // Token for "".
   const String& source_;           // The source text being tokenized.
-  intptr_t source_length_;     // The length of the source text.
-  intptr_t lookahead_pos_;     // Position of lookahead character
-                               // within source_.
-  intptr_t token_start_;       // Begin of current token in src_.
-  int32_t c0_;                 // Lookahead character.
-  bool newline_seen_;          // Newline before current token.
-  intptr_t prev_token_line_;   // Line number of the previous token.
+  intptr_t source_length_;         // The length of the source text.
+  intptr_t lookahead_pos_;         // Position of lookahead character
+                                   // within source_.
+  intptr_t token_start_;           // Begin of current token in src_.
+  int32_t c0_;                     // Lookahead character.
+  bool newline_seen_;              // Newline before current token.
+  intptr_t prev_token_line_;       // Line number of the previous token.
 
   // The following fields keep track whether we are scanning a string literal
   // and its interpolated expressions.
diff --git a/runtime/vm/scanner_test.cc b/runtime/vm/scanner_test.cc
index 630a272..49b8cc4 100644
--- a/runtime/vm/scanner_test.cc
+++ b/runtime/vm/scanner_test.cc
@@ -10,10 +10,10 @@
 
 namespace dart {
 
-void LogTokenDesc(Scanner::TokenDescriptor token) {
+static void LogTokenDesc(Scanner::TokenDescriptor token) {
   OS::Print("pos %2d:%d-%d token %s  ",
             token.position.line, token.position.column,
-            token.position.column + token.length,
+            token.position.column,
             Token::Name(token.kind));
   if (token.literal != NULL) {
     OS::Print("%s", token.literal->ToCString());
@@ -22,7 +22,7 @@
 }
 
 
-void LogTokenStream(const Scanner::GrowableTokenStream& token_stream) {
+static void LogTokenStream(const Scanner::GrowableTokenStream& token_stream) {
   int token_index = 0;
   EXPECT_GT(token_stream.length(), 0);
   while (token_index < token_stream.length()) {
@@ -35,7 +35,7 @@
 }
 
 
-void CheckKind(const Scanner::GrowableTokenStream &token_stream,
+static void CheckKind(const Scanner::GrowableTokenStream &token_stream,
                int index,
                Token::Kind kind) {
   if (token_stream[index].kind != kind) {
@@ -46,7 +46,7 @@
 }
 
 
-void CheckLiteral(const Scanner::GrowableTokenStream& token_stream,
+static void CheckLiteral(const Scanner::GrowableTokenStream& token_stream,
                  int index,
                  const char* literal) {
   if (token_stream[index].literal == NULL) {
@@ -59,7 +59,7 @@
 }
 
 
-void CheckIdent(const Scanner::GrowableTokenStream& token_stream,
+static void CheckIdent(const Scanner::GrowableTokenStream& token_stream,
                int index,
                const char* literal) {
   CheckKind(token_stream, index, Token::kIDENT);
@@ -67,7 +67,7 @@
 }
 
 
-void CheckInteger(const Scanner::GrowableTokenStream& token_stream,
+static void CheckInteger(const Scanner::GrowableTokenStream& token_stream,
                  int index,
                  const char* literal) {
   CheckKind(token_stream, index, Token::kINTEGER);
@@ -75,7 +75,7 @@
 }
 
 
-void CheckLineNumber(const Scanner::GrowableTokenStream& token_stream,
+static void CheckLineNumber(const Scanner::GrowableTokenStream& token_stream,
                      int index,
                      int line_number) {
   if (token_stream[index].position.line != line_number) {
@@ -85,7 +85,7 @@
 }
 
 
-void CheckNumTokens(const Scanner::GrowableTokenStream& token_stream,
+static void CheckNumTokens(const Scanner::GrowableTokenStream& token_stream,
                     int index) {
   if (token_stream.length() != index) {
     OS::PrintErr("Expected %d tokens but got only %" Pd ".\n",
@@ -94,7 +94,7 @@
 }
 
 
-const Scanner::GrowableTokenStream& Scan(const char* source) {
+static const Scanner::GrowableTokenStream& Scan(const char* source) {
   Scanner scanner(String::Handle(String::New(source)),
                   String::Handle(String::New("")));
 
@@ -105,7 +105,7 @@
 }
 
 
-void BoringTest() {
+static void BoringTest() {
   const Scanner::GrowableTokenStream& tokens = Scan("x = iffy++;");
 
   CheckNumTokens(tokens, 6);
@@ -117,7 +117,7 @@
 }
 
 
-void CommentTest() {
+static void CommentTest() {
   const Scanner::GrowableTokenStream& tokens =
       Scan("Foo( /*block \n"
            "comment*/ 0xff) // line comment;");
@@ -133,7 +133,7 @@
 }
 
 
-void GreedIsGood() {
+static void GreedIsGood() {
   // means i++ + j
   const Scanner::GrowableTokenStream& tokens = Scan("x=i+++j");
 
@@ -147,7 +147,7 @@
 }
 
 
-void StringEscapes() {
+static void StringEscapes() {
   // sss = "\" \\ \n\r\t \'"
   const Scanner::GrowableTokenStream& tokens =
       Scan("sss = \"\\\" \\\\ \\n\\r\\t \\\'\"");
@@ -171,7 +171,7 @@
 }
 
 
-void InvalidStringEscapes() {
+static void InvalidStringEscapes() {
   const Scanner::GrowableTokenStream& high_start_4 =
       Scan("\"\\uD800\"");
   EXPECT_EQ(2, high_start_4.length());
@@ -244,7 +244,7 @@
 }
 
 
-void RawString() {
+static void RawString() {
   // rs = @"\' \\"
   const Scanner::GrowableTokenStream& tokens = Scan("rs = r\"\\\' \\\\\"");
 
@@ -265,7 +265,7 @@
 }
 
 
-void MultilineString() {
+static void MultilineString() {
   // |mls = '''
   // |1' x
   // |2''';
@@ -293,7 +293,7 @@
 }
 
 
-void EmptyString() {
+static void EmptyString() {
   // es = "";
   const Scanner::GrowableTokenStream& tokens = Scan("es = \"\";");
 
@@ -306,7 +306,7 @@
   EXPECT_EQ(0, (tokens)[2].literal->Length());
 }
 
-void EmptyMultilineString() {
+static void EmptyMultilineString() {
   // es = """""";
   const Scanner::GrowableTokenStream& tokens = Scan("es = \"\"\"\"\"\";");
 
@@ -320,7 +320,7 @@
 }
 
 
-void NumberLiteral() {
+static void NumberLiteral() {
   const Scanner::GrowableTokenStream& tokens =
       Scan("5 0x5d 0.3 0.33 1E+12 .42 +5");
 
@@ -336,7 +336,7 @@
 }
 
 
-void ScanLargeText() {
+static void ScanLargeText() {
   const char* dart_source =
       "// This source is not meant to be valid Dart code. The text is used to"
       "// test the Dart scanner."
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 647b802..17264e8 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -875,6 +875,36 @@
       "  static s2() { return 'this is a \"string\" in the source'; }\n"
       "  static s3() { return 'this is a \\\'string\\\' in \"the\" source'; }\n"
       "  static s4() { return 'this \"is\" a \"string\" in \"the\" source'; }\n"
+      "  static ms1() {\n"
+      "    return '''\n"
+      "abc\n"
+      "def\n"
+      "ghi''';\n"
+      "  }\n"
+      "  static ms2() {\n"
+      "    return '''\n"
+      "abc\n"
+      "$def\n"
+      "ghi''';\n"
+      "  }\n"
+      "  static ms3() {\n"
+      "    return '''\n"
+      "a b c\n"
+      "d $d e\n"
+      "g h i''';\n"
+      "  }\n"
+      "  static ms4() {\n"
+      "    return '''\n"
+      "abc\n"
+      "${def}\n"
+      "ghi''';\n"
+      "  }\n"
+      "  static ms5() {\n"
+      "    return '''\n"
+      "a b c\n"
+      "d ${d} e\n"
+      "g h i''';\n"
+      "  }\n"
       "}\n";
 
   String& url = String::Handle(String::New("dart-test:SerializeScript"));
@@ -940,34 +970,29 @@
 static void IterateScripts(const Library& lib) {
   const Array& lib_scripts = Array::Handle(lib.LoadedScripts());
   Script& script = Script::Handle();
+  String& uri = String::Handle();
   for (intptr_t i = 0; i < lib_scripts.Length(); i++) {
     script ^= lib_scripts.At(i);
     EXPECT(!script.IsNull());
+    uri = script.url();
+    OS::Print("Generating source for part: %s\n", uri.ToCString());
     GenerateSourceAndCheck(script);
   }
 }
 
 TEST_CASE(GenerateSource) {
+  Isolate* isolate = Isolate::Current();
+  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
+      isolate, isolate->object_store()->libraries());
   Library& lib = Library::Handle();
-  // Check core lib.
-  lib = Library::CoreLibrary();
-  EXPECT(!lib.IsNull());
-  IterateScripts(lib);
-
-  // Check isolate lib.
-  lib = Library::IsolateLibrary();
-  EXPECT(!lib.IsNull());
-  IterateScripts(lib);
-
-  // Check math lib.
-  lib = Library::MathLibrary();
-  EXPECT(!lib.IsNull());
-  IterateScripts(lib);
-
-  // Check mirrors lib.
-  lib = Library::MirrorsLibrary();
-  EXPECT(!lib.IsNull());
-  IterateScripts(lib);
+  String& uri = String::Handle();
+  for (intptr_t i = 0; i < libs.Length(); i++) {
+    lib ^= libs.At(i);
+    EXPECT(!lib.IsNull());
+    uri = lib.url();
+    OS::Print("Generating source for library: %s\n", uri.ToCString());
+    IterateScripts(lib);
+  }
 }
 
 
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 1f2da7a..60464fb 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -237,7 +237,6 @@
   V(IsolateUnhandledException, "IsolateUnhandledException")                    \
   V(JavascriptIntegerOverflowError, "_JavascriptIntegerOverflowError")         \
   V(MirroredCompilationError, "MirroredCompilationError")                      \
-  V(MirroredUncaughtExceptionError, "MirroredUncaughtExceptionError")          \
   V(_setupFullStackTrace, "_setupFullStackTrace")                              \
   V(BooleanExpression, "boolean expression")                                   \
   V(Malformed, "malformed")                                                    \
diff --git a/sdk/lib/_internal/compiler/implementation/closure.dart b/sdk/lib/_internal/compiler/implementation/closure.dart
index 0bf8280..7f666d3 100644
--- a/sdk/lib/_internal/compiler/implementation/closure.dart
+++ b/sdk/lib/_internal/compiler/implementation/closure.dart
@@ -555,10 +555,9 @@
     Element element = elements[node];
     if (Elements.isLocal(element)) {
       mutatedVariables.add(element);
-    }
-    if (Elements.isLocal(element) &&
-        element.computeType(compiler).containsTypeVariables) {
-      registerNeedsThis();
+      if (compiler.enableTypeAssertions) {
+        analyzeTypeVariables(element.computeType(compiler));
+      }
     }
     super.visitSendSet(node);
   }
@@ -770,18 +769,12 @@
       }
 
       DartType type = element.computeType(compiler);
-      // Compute the function type and check for type variables in return or
-      // parameter types.
-      if (type.containsTypeVariables) {
-        registerNeedsThis();
-      }
-      // Ensure that closure that need runtime type information has access to
-      // this of the enclosing class.
-      if (element is FunctionElement &&
-          closureData.thisElement != null &&
-          type.containsTypeVariables &&
-          compiler.backend.methodNeedsRti(element)) {
-        registerNeedsThis();
+      // If the method needs RTI, or checked mode is set, we need to
+      // escape the potential type variables used in that closure.
+      if (element is FunctionElement
+          && (compiler.backend.methodNeedsRti(element) ||
+              compiler.enableTypeAssertions)) {
+        analyzeTypeVariables(type);
       }
 
       visitChildren();
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index b0e1444..93474dc 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -54,9 +54,6 @@
 
 /// [WorkItem] used exclusively by the [CodegenEnqueuer].
 class CodegenWorkItem extends WorkItem {
-  bool allowSpeculativeOptimization = true;
-  List<HTypeGuard> guards = const <HTypeGuard>[];
-
   CodegenWorkItem(Element element,
                   ItemCompilationContext compilationContext)
       : super(element, compilationContext);
diff --git a/sdk/lib/_internal/compiler/implementation/dart_types.dart b/sdk/lib/_internal/compiler/implementation/dart_types.dart
index 78a6490..ff98bd4 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_types.dart
@@ -669,6 +669,19 @@
     return _findTypeVariableOccurrence(namedParameterTypes);
   }
 
+  void forEachTypeVariable(f(TypeVariableType variable)) {
+    returnType.forEachTypeVariable(f);
+    parameterTypes.forEach((DartType type) {
+      type.forEachTypeVariable(f);
+    });
+    optionalParameterTypes.forEach((DartType type) {
+      type.forEachTypeVariable(f);
+    });
+    namedParameterTypes.forEach((DartType type) {
+      type.forEachTypeVariable(f);
+    });
+  }
+
   accept(DartTypeVisitor visitor, var argument) {
     return visitor.visitFunctionType(this, argument);
   }
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
index 4038a16..e1f31b9 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
@@ -141,16 +141,13 @@
   bool enableLengthTracking = true;
   bool continueAnalyzing = true;
 
-  static const int MAX_ANALYSIS_COUNT = 11;
+  static const int MAX_ANALYSIS_COUNT = 16;
   final Setlet<Element> analyzedElements = new Setlet<Element>();
 
   ContainerTracerVisitor(this.container, inferrer)
       : this.inferrer = inferrer, this.compiler = inferrer.compiler;
 
-  void run() {
-    // Add the assignments found at allocation site.
-    assignments.addAll(container.elementType.assignments);
-
+  List<TypeInformation> run() {
     // Collect the [TypeInformation] where the container can flow in,
     // as well as the operations done on all these [TypeInformation]s.
     List<TypeInformation> workList = <TypeInformation>[];
@@ -179,21 +176,13 @@
       }
     }
 
-    ContainerTypeMask mask = container.type;
-    if (!enableLengthTracking
-        && (mask.forwardTo != compiler.typesTask.fixedListType)) {
-      mask.length = null;
+    if (continueAnalyzing) {
+      if (enableLengthTracking && container.inferredLength == null) {
+        container.inferredLength = container.originalLength;
+      }
+      return assignments;
     }
-
-    TypeMask result = continueAnalyzing
-      ? inferrer.types.computeTypeMask(assignments)
-      : inferrer.types.dynamicType.type;
-
-    mask.elementType = result;
-    if (_VERBOSE) {
-      print('$result and ${mask.length} '
-            'for ${mask.allocationNode} ${mask.allocationElement}');
-    }
+    return null;
   }
 
   void bailout(String reason) {
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
index 801ba63..09ddeb7 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
@@ -223,7 +223,10 @@
   final List<T> positional;
   final Map<String, T> named;
   ArgumentsTypes(this.positional, named)
-    : this.named = (named == null || named.isEmpty) ? const {} : named;
+    : this.named = (named == null || named.isEmpty) ? const {} : named {
+    assert(this.positional.every((T type) => type != null));
+    assert(this.named.values.every((T type) => type != null));
+  }
 
   int get length => positional.length + named.length;
 
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
index 8db325d..8f41971 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
@@ -100,10 +100,7 @@
                              Node node,
                              Element enclosing,
                              [TypeMask elementType, int length]) {
-    ContainerTypeMask mask = new ContainerTypeMask(type, node, enclosing);
-    mask.elementType = elementType;
-    mask.length = length;
-    return mask;
+    return new ContainerTypeMask(type, node, enclosing, elementType, length);
   }
 
   Selector newTypedSelector(TypeMask receiver, Selector selector) {
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
index a9e1734..f621f46 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
@@ -253,18 +253,20 @@
                                     Node node,
                                     Element enclosing,
                                     [TypeInformation elementType, int length]) {
-    ContainerTypeMask mask = new ContainerTypeMask(type.type, node, enclosing);
-    // Set the element type now for const lists, so that the inferrer
-    // can use it.
-    mask.elementType = (type.type == compiler.typesTask.constListType)
-        ? elementType.type
-        : null;
-    mask.length = length;
-    TypeInformation element =
-        new ElementInContainerTypeInformation(elementType, mask);
+    bool isConst = (type.type == compiler.typesTask.constListType);
+    bool isFixed = (type.type == compiler.typesTask.fixedListType) || isConst;
+
+    int inferredLength = isFixed ? length : null;
+    TypeMask elementTypeMask = isConst ? elementType.type : dynamicType.type;
+    ContainerTypeMask mask = new ContainerTypeMask(
+        type.type, node, enclosing, elementTypeMask, inferredLength);
+    ElementInContainerTypeInformation element =
+        new ElementInContainerTypeInformation(elementType);
+    element.inferred = isConst;
+
     allocatedTypes.add(element);
     return allocatedContainers[node] =
-        new ContainerTypeInformation(mask, element);
+        new ContainerTypeInformation(mask, element, length);
   }
 
   Selector newTypedSelector(TypeInformation info, Selector selector) {
@@ -318,9 +320,13 @@
   }
 
   TypeMask computeTypeMask(Iterable<TypeInformation> assignments) {
+    return joinTypeMasks(assignments.map((e) => e.type));
+  }
+
+  TypeMask joinTypeMasks(Iterable<TypeMask> masks) {
     TypeMask newType = const TypeMask.nonNullEmpty();
-    for (var info in assignments) {
-      newType = newType.union(info.type, compiler);
+    for (TypeMask mask in masks) {
+      newType = newType.union(mask, compiler);
     }
     return newType.containsAll(compiler) ? dynamicType.type : newType;
   }
@@ -448,6 +454,42 @@
     buildWorkQueue();
     refine();
 
+    // Try to infer element types of lists.
+    types.allocatedContainers.values.forEach((ContainerTypeInformation info) {
+      if (info.elementType.inferred) return;
+      ContainerTracerVisitor tracer = new ContainerTracerVisitor(info, this);
+      List<TypeInformation> newAssignments = tracer.run();
+      if (newAssignments == null) return;
+
+      info.elementType.inferred = true;
+      newAssignments.forEach(info.elementType.addAssignment);
+      workQueue.add(info);
+      workQueue.add(info.elementType);
+    });
+
+    // Reset all nodes that use lists that have been inferred, as well
+    // as nodes that use elements fetched from these lists. The
+    // workset for a new run of the analysis will be these nodes.
+    Set<TypeInformation> seenTypes = new Set<TypeInformation>();
+    while (!workQueue.isEmpty) {
+      TypeInformation info = workQueue.remove();
+      if (seenTypes.contains(info)) continue;
+      info.reset(this);
+      seenTypes.add(info);
+      workQueue.addAll(info.users);
+    }
+
+    workQueue.addAll(seenTypes);
+    refine();
+
+    if (_VERBOSE) {
+      types.allocatedContainers.values.forEach((ContainerTypeInformation info) {
+        print('${info.type} '
+              'for ${info.originalContainerType.allocationNode} '
+              'at ${info.originalContainerType.allocationElement}');
+      });
+    }
+
     compiler.log('Inferred $overallRefineCount types.');
 
     if (compiler.enableTypeAssertions) {
@@ -469,7 +511,6 @@
     }
 
     processLoopInformation();
-    types.allocatedContainers.values.forEach(analyzeContainer);
   }
 
   void processLoopInformation() {
@@ -508,11 +549,6 @@
     }
   }
 
-  void analyzeContainer(ContainerTypeInformation info) {
-    if (info.elementType.isInConstContainer) return;
-    new ContainerTracerVisitor(info, this).run();
-  }
-
   void buildWorkQueue() {
     workQueue.addAll(types.typeInformations.values);
     workQueue.addAll(types.allocatedTypes);
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
index 9c32288..54602bd 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
@@ -101,6 +101,13 @@
     return true;
   }
 
+  /// Reset the analysis of this node by making its type empty.
+  void reset(TypeGraphInferrerEngine inferrer) {
+    if (abandonInferencing) return;
+    type = const TypeMask.nonNullEmpty();
+    refineCount = 0;
+  }
+
   accept(TypeInformationVisitor visitor);
 
   /// The [Element] where this [TypeInformation] was created. May be
@@ -436,15 +443,19 @@
                                             TypeGraphInferrerEngine inferrer) {
     if (!inferrer.compiler.backend.intImplementation.isResolved) return null;
     TypeMask intType = inferrer.compiler.typesTask.intType;
+    TypeMask nullableIntType = intType.nullable();
     TypeMask emptyType = const TypeMask.nonNullEmpty();
-    if (selector.mask != intType) return null;
+    if (selector.mask != intType && selector.mask != nullableIntType) {
+      return null;
+    }
     if (!selector.isCall() && !selector.isOperator()) return null;
     if (!arguments.named.isEmpty) return null;
     if (arguments.positional.length > 1) return null;
 
     String name = selector.name;
     if (name == '*' || name == '+' || name == '%' || name == 'remainder') {
-      if (hasOnePositionalArgumentWithType(intType)) {
+      if (hasOnePositionalArgumentWithType(intType)
+          || hasOnePositionalArgumentWithType(nullableIntType)) {
         return inferrer.types.intType;
       } else if (hasOnePositionalArgumentWithType(emptyType)) {
         return inferrer.types.nonNullEmptyType;
@@ -453,7 +464,8 @@
       }
     } else if (name == '-') {
       if (arguments.hasNoArguments()) return inferrer.types.intType;
-      if (hasOnePositionalArgumentWithType(intType)) {
+      if (hasOnePositionalArgumentWithType(intType)
+          || hasOnePositionalArgumentWithType(nullableIntType)) {
         return inferrer.types.intType;
       } else if (hasOnePositionalArgumentWithType(emptyType)) {
         return inferrer.types.nonNullEmptyType;
@@ -473,7 +485,7 @@
 
     // Walk over the found targets, and compute the joined union type mask
     // for all these targets.
-    TypeMask newType = inferrer.types.computeTypeMask(targets.map((element) {
+    TypeMask newType = inferrer.types.joinTypeMasks(targets.map((element) {
       if (!oldTargets.contains(element)) {
         ElementTypeInformation callee =
             inferrer.types.getInferredTypeOf(element);
@@ -484,22 +496,13 @@
       }
 
       if (returnsElementType(typedSelector)) {
-        // Find the [ElementInContainerTypeInformation] node and tell
-        // that this node is a user of it. Later, when the element
-        // type changes, this node will be notified.
         ContainerTypeMask mask = receiver.type;
-        ContainerTypeInformation container =
-            inferrer.types.allocatedContainers[mask.allocationNode];
-        ElementInContainerTypeInformation element = container.elementType;
-        if (!element.users.contains(element)) {
-          element.addUser(this);
-        }
-        return element;
+        return mask.elementType;
       } else {
         TypeInformation info =
             handleIntrisifiedSelector(typedSelector, inferrer);
-        if (info != null) return info;
-        return inferrer.typeOfElementWithSelector(element, typedSelector);
+        if (info != null) return info.type;
+        return inferrer.typeOfElementWithSelector(element, typedSelector).type;
       }
     }));
 
@@ -610,6 +613,10 @@
     assert(false);
   }
 
+  void reset(TypeGraphInferrerEngine inferrer) {
+    assert(false);
+  }
+
   String toString() => 'Type $type';
 
   accept(TypeInformationVisitor visitor) {
@@ -661,8 +668,21 @@
 class ContainerTypeInformation extends TypeInformation {
   final ElementInContainerTypeInformation elementType;
 
-  ContainerTypeInformation(containerType, this.elementType) {
-    type = containerType;
+  /** The container type before it is inferred. */
+  final ContainerTypeMask originalContainerType;
+
+  /** The length at the allocation site. */
+  final int originalLength;
+
+  /** The length after the container has been traced. */
+  int inferredLength;
+
+  ContainerTypeInformation(this.originalContainerType,
+                           this.elementType,
+                           this.originalLength) {
+    type = originalContainerType;
+    inferredLength = originalContainerType.length;
+    elementType.addUser(this);
   }
 
   String toString() => 'Container type $type';
@@ -670,6 +690,20 @@
   accept(TypeInformationVisitor visitor) {
     return visitor.visitContainerTypeInformation(this);
   }
+
+  TypeMask refine(TypeGraphInferrerEngine inferrer) {
+    var mask = type;
+    if (!mask.isContainer
+        || mask.elementType != elementType.type
+        || mask.length != inferredLength) {
+      return new ContainerTypeMask(originalContainerType.forwardTo,
+                                   originalContainerType.allocationNode,
+                                   originalContainerType.allocationElement,
+                                   elementType.type,
+                                   inferredLength);
+    }
+    return mask;
+  }
 }
 
 /**
@@ -677,23 +711,18 @@
  * elements in a [ContainerTypeInformation].
  */
 class ElementInContainerTypeInformation extends TypeInformation {
-  final ContainerTypeMask container;
+  /** Whether the element type in that container has been inferred. */
+  bool inferred = false;
 
-  ElementInContainerTypeInformation(elementType, this.container) {
+  ElementInContainerTypeInformation(elementType) {
     if (elementType != null) addAssignment(elementType);
   }
 
-  bool get isInConstContainer {
-    LiteralList literal = container.allocationNode.asLiteralList();
-    return (literal != null) && literal.isConst();
-  }
-
   TypeMask refine(TypeGraphInferrerEngine inferrer) {
-    if (!isInConstContainer) {
+    if (!inferred) {
       return inferrer.types.dynamicType.type;
     }
-    return container.elementType =
-        inferrer.types.computeTypeMask(assignments);
+    return inferrer.types.computeTypeMask(assignments);
   }
 
   String toString() => 'Element in container $type';
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index de44eee..3080e5a 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -163,12 +163,6 @@
     return compiler.enqueuer.codegen.generatedCode;
   }
 
-  /**
-   * The generated code as a js AST for compiled bailout methods.
-   */
-  final Map<Element, jsAst.Expression> generatedBailoutCode =
-      new Map<Element, jsAst.Expression>();
-
   FunctionInlineCache inlineCache = new FunctionInlineCache();
 
   ClassElement jsInterceptorClass;
@@ -1222,14 +1216,7 @@
     }
 
     HGraph graph = builder.build(work);
-    optimizer.optimize(work, graph, false);
-    if (work.allowSpeculativeOptimization
-        && optimizer.trySpeculativeOptimizations(work, graph)) {
-      jsAst.Expression code = generator.generateBailoutMethod(work, graph);
-      generatedBailoutCode[element] = code;
-      optimizer.prepareForSpeculativeOptimizations(work, graph);
-      optimizer.optimize(work, graph, true);
-    }
+    optimizer.optimize(work, graph);
     jsAst.Expression code = generator.generateCode(work, graph);
     generatedCode[element] = code;
   }
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/custom_elements_analysis.dart b/sdk/lib/_internal/compiler/implementation/js_backend/custom_elements_analysis.dart
index 158c626..2a9c15f 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/custom_elements_analysis.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/custom_elements_analysis.dart
@@ -101,7 +101,7 @@
     if (!fetchedTableAccessorMethod) {
       fetchedTableAccessorMethod = true;
       tableAccessorMethod = compiler.findInterceptor(
-          'findIndexForWebComponentType');
+          'findIndexForNativeSubclassType');
     }
     if (element == tableAccessorMethod) {
       joinFor(enqueuer).demanded = true;
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
index 4a0098e..6febc82 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
@@ -243,8 +243,6 @@
   final Map<String, String> operatorNameMap;
   final Map<String, int> popularNameCounters;
 
-  final Map<Element, String> bailoutNames;
-
   final Map<Constant, String> constantNames;
   final Map<Constant, String> constantLongNames;
   ConstantCanonicalHasher constantHasher;
@@ -254,7 +252,6 @@
         CURRENT_ISOLATE = compiler.globalJsName,
         globals = new Map<Element, String>(),
         shortPrivateNameOwners = new Map<String, LibraryElement>(),
-        bailoutNames = new Map<Element, String>(),
         usedGlobalNames = new Set<String>(),
         usedInstanceNames = new Set<String>(),
         instanceNameMap = new Map<String, String>(),
@@ -663,39 +660,6 @@
     }
   }
 
-  String getBailoutName(Element element) {
-    String name = bailoutNames[element];
-    if (name != null) return name;
-    bool global = !element.isInstanceMember();
-    // Despite the name of the variable, this gets the minified name when we
-    // are minifying, but it doesn't really make much difference.  The
-    // important thing is that it is a unique name.  We add $bailout and, if we
-    // are minifying, we minify the minified name and '$bailout'.
-    String unminifiedName = '${getNameX(element)}\$bailout';
-    if (global) {
-      name = getMappedGlobalName(unminifiedName);
-    } else {
-      // Make sure two bailout methods on the same inheritance chain do not have
-      // the same name to prevent a subclass bailout method being accidentally
-      // called from the superclass main method.  Use the count of the number of
-      // elements with the same name on the superclass chain to disambiguate
-      // based on 'level'.
-      int level = 0;
-      ClassElement classElement = element.getEnclosingClass().superclass;
-      while (classElement != null) {
-        if (classElement.localLookup(element.name) != null) level++;
-        classElement = classElement.superclass;
-      }
-      name = unminifiedName;
-      if (level != 0) {
-        name = '$unminifiedName$level';
-      }
-      name = getMappedInstanceName(name);
-    }
-    bailoutNames[element] = name;
-    return name;
-  }
-
   /// Returns the runtime name for [element].  The result is not safe as an id.
   String getRuntimeTypeName(Element element) {
     if (identical(element, compiler.dynamicClass)) return 'dynamic';
@@ -737,7 +701,7 @@
    * guaranteed to be unique.
    *
    * For accessing statics consider calling
-   * [isolateAccess]/[isolateBailoutAccess] or [isolatePropertyAccess] instead.
+   * [isolateAccess] or [isolatePropertyAccess] instead.
    */
   // TODO(ahe): This is an internal method to the Namer (and its subclasses)
   // and should not be call from outside.
@@ -865,11 +829,6 @@
     return "${globalObjectFor(element)}.${getNameX(element)}";
   }
 
-  String isolateBailoutAccess(Element element) {
-    String newName = getMappedGlobalName('${getNameX(element)}\$bailout');
-    return '${globalObjectFor(element)}.$newName';
-  }
-
   String isolateLazyInitializerAccess(Element element) {
     return "${globalObjectFor(element)}.${getLazyInitializerName(element)}";
   }
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
index 24f1ef2..bd143b4 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
@@ -803,31 +803,13 @@
 
     Iterable<Element> elements =
         backend.generatedCode.keys.where(isStaticFunction);
-    Set<Element> pendingElementsWithBailouts =
-        backend.generatedBailoutCode.keys
-            .where(isStaticFunction)
-            .toSet();
 
     for (Element element in Elements.sortedByPosition(elements)) {
-      pendingElementsWithBailouts.remove(element);
       ClassBuilder builder = new ClassBuilder();
       containerBuilder.addMember(element, builder);
       builder.writeOn_DO_NOT_USE(
           bufferForElement(element, eagerBuffer), compiler, ',$n$n');
     }
-
-    if (!pendingElementsWithBailouts.isEmpty) {
-      addComment('pendingElementsWithBailouts', eagerBuffer);
-    }
-    // Is it possible the primary function was inlined but the bailout was not?
-    for (Element element in
-             Elements.sortedByPosition(pendingElementsWithBailouts)) {
-      jsAst.Expression bailoutCode = backend.generatedBailoutCode[element];
-      new ClassBuilder()
-          ..addProperty(namer.getBailoutName(element), bailoutCode)
-          ..writeOn_DO_NOT_USE(
-              bufferForElement(element, eagerBuffer), compiler, ',$n$n');
-    }
   }
 
   void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) {
@@ -857,7 +839,6 @@
     if (!lazyFields.isEmpty) {
       needsLazyInitializer = true;
       for (VariableElement element in Elements.sortedByPosition(lazyFields)) {
-        assert(backend.generatedBailoutCode[element] == null);
         jsAst.Expression code = backend.generatedCode[element];
         // The code is null if we ended up not needing the lazily
         // initialized field after all because of constant folding
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart
index c14f3b1..882e0aa 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart
@@ -625,10 +625,6 @@
         builder.addProperty('*$unmangledName', defaultValues);
       }
     }
-    code = backend.generatedBailoutCode[member];
-    if (code != null) {
-      builder.addProperty(namer.getBailoutName(member), code);
-    }
     if (member.isInstanceMember()) {
       // TODO(ahe): Where is this done for static/top-level methods?
       FunctionSignature parameters = member.computeSignature(compiler);
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 69c82d4..b8d6fa7 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -1627,21 +1627,16 @@
                           Identifier prefixName,
                           Identifier typeName) {
     if (prefixName != null) {
-      Element e = lookupInScope(compiler, prefixName, scope, prefixName.source);
-      if (e != null) {
-        if (identical(e.kind, ElementKind.PREFIX)) {
-          // The receiver is a prefix. Lookup in the imported members.
-          PrefixElement prefix = e;
-          return prefix.lookupLocalMember(typeName.source);
-        } else if (identical(e.kind, ElementKind.CLASS)) {
-          // TODO(johnniwinther): Remove this case.
-          // The receiver is the class part of a named constructor.
-          return e;
-        }
-      } else {
-        // The caller creates the ErroneousElement for the MalformedType.
-        return null;
+      Element element =
+          lookupInScope(compiler, prefixName, scope, prefixName.source);
+      if (element != null && element.isPrefix()) {
+        // The receiver is a prefix. Lookup in the imported members.
+        PrefixElement prefix = element;
+        return prefix.lookupLocalMember(typeName.source);
       }
+      // The caller of this method will create the ErroneousElement for
+      // the MalformedType.
+      return null;
     } else {
       String stringValue = typeName.source;
       if (identical(stringValue, 'void')) {
@@ -1668,7 +1663,6 @@
     }
 
     Element element = resolveTypeName(visitor.scope, prefixName, typeName);
-    DartType type;
 
     DartType reportFailureAndCreateType(DualKind messageKind,
                                         Map messageArguments,
@@ -1701,6 +1695,7 @@
       return type;
     }
 
+    DartType type;
     if (element == null) {
       type = reportFailureAndCreateType(
           MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.typeName});
@@ -2582,13 +2577,13 @@
         // TODO(johnniwinther): Use seen type tests to avoid registration of
         // mutation/access to unpromoted variables.
         DartType type =
-            resolveTypeExpression(node.typeAnnotationFromIsCheckOrCast);
+            resolveTypeAnnotation(node.typeAnnotationFromIsCheckOrCast);
         if (type != null) {
           compiler.enqueuer.resolution.registerIsCheck(type, mapping);
         }
         resolvedArguments = true;
       } else if (identical(operatorString, 'as')) {
-        DartType type = resolveTypeExpression(node.arguments.head);
+        DartType type = resolveTypeAnnotation(node.arguments.head);
         if (type != null) {
           compiler.enqueuer.resolution.registerAsCheck(type, mapping);
         }
@@ -2710,7 +2705,7 @@
       }
     }
 
-    visit(node.argumentsNode);
+    resolveArguments(node.argumentsNode);
 
     // TODO(ngeoffray): Check if the target can be assigned.
     // TODO(ngeoffray): Warn if target is null and the send is
@@ -2857,21 +2852,24 @@
       compiler.reportHint(
           enclosingElement, MessageKind.MISSING_FACTORY_KEYWORD);
     }
-    FunctionElement redirectionTarget = resolveRedirectingFactory(node);
-    useElement(node.expression, redirectionTarget);
     FunctionElement constructor = enclosingElement;
-    if (constructor.modifiers.isConst() &&
-        !redirectionTarget.modifiers.isConst()) {
-      error(node, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
-    }
-    if (redirectionTarget == constructor) {
-      compiler.reportError(node, MessageKind.CYCLIC_REDIRECTING_FACTORY);
-      return;
-    }
+    bool isConstConstructor = constructor.modifiers.isConst();
+    FunctionElement redirectionTarget = resolveRedirectingFactory(
+        node, inConstContext: isConstConstructor);
     constructor.defaultImplementation = redirectionTarget;
+    useElement(node.expression, redirectionTarget);
     if (Elements.isUnresolved(redirectionTarget)) {
       compiler.backend.registerThrowNoSuchMethod(mapping);
       return;
+    } else {
+      if (isConstConstructor &&
+          !redirectionTarget.modifiers.isConst()) {
+        compiler.reportError(node, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
+      }
+      if (redirectionTarget == constructor) {
+        compiler.reportError(node, MessageKind.CYCLIC_REDIRECTING_FACTORY);
+        return;
+      }
     }
 
     // Check that the target constructor is type compatible with the
@@ -2996,7 +2994,7 @@
     InterfaceType type = mapping.getType(node);
     if (node.isConst() && type.containsTypeVariables) {
       compiler.reportError(node.send.selector,
-                               MessageKind.TYPE_VARIABLE_IN_CONSTANT);
+                           MessageKind.TYPE_VARIABLE_IN_CONSTANT);
     }
     world.registerInstantiatedType(type, mapping);
     if (constructor.isFactoryConstructor() && !type.typeArguments.isEmpty) {
@@ -3077,16 +3075,16 @@
     return node.accept(new ConstructorResolver(compiler, this));
   }
 
-  FunctionElement resolveRedirectingFactory(Return node) {
-    return node.accept(new ConstructorResolver(compiler, this));
+  FunctionElement resolveRedirectingFactory(Return node,
+                                            {bool inConstContext: false}) {
+    return node.accept(new ConstructorResolver(compiler, this,
+                                               inConstContext: inConstContext));
   }
 
-  DartType resolveTypeExpression(TypeAnnotation node) {
-    return resolveTypeAnnotation(node);
-  }
-
-  DartType resolveTypeAnnotation(TypeAnnotation node) {
-    DartType type = typeResolver.resolveTypeAnnotation(this, node);
+  DartType resolveTypeAnnotation(TypeAnnotation node,
+                                 {bool malformedIsError: false}) {
+    DartType type = typeResolver.resolveTypeAnnotation(
+        this, node, malformedIsError: malformedIsError);
     if (type == null) return null;
     if (inCheckContext) {
       compiler.enqueuer.resolution.registerIsCheck(type, mapping);
@@ -3109,7 +3107,7 @@
         // The syntax [: <>[] :] is not allowed.
         error(arguments, MessageKind.MISSING_TYPE_ARGUMENT.error);
       } else {
-        typeArgument = resolveTypeExpression(nodes.head);
+        typeArgument = resolveTypeAnnotation(nodes.head);
         for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) {
           warning(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT.warning);
           resolveTypeAnnotation(nodes.head);
@@ -3324,12 +3322,12 @@
         // The syntax [: <>{} :] is not allowed.
         error(arguments, MessageKind.MISSING_TYPE_ARGUMENT.error);
       } else {
-        keyTypeArgument = resolveTypeExpression(nodes.head);
+        keyTypeArgument = resolveTypeAnnotation(nodes.head);
         nodes = nodes.tail;
         if (nodes.isEmpty) {
           warning(arguments, MessageKind.MISSING_TYPE_ARGUMENT.warning);
         } else {
-          valueTypeArgument = resolveTypeExpression(nodes.head);
+          valueTypeArgument = resolveTypeAnnotation(nodes.head);
           for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) {
             warning(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT.warning);
             resolveTypeAnnotation(nodes.head);
@@ -4510,10 +4508,12 @@
 
 class ConstructorResolver extends CommonResolverVisitor<Element> {
   final ResolverVisitor resolver;
-  bool inConstContext = false;
+  bool inConstContext;
   DartType type;
 
-  ConstructorResolver(Compiler compiler, this.resolver) : super(compiler);
+  ConstructorResolver(Compiler compiler, this.resolver,
+                      {bool this.inConstContext: false})
+      : super(compiler);
 
   visitNode(Node node) {
     throw 'not supported';
@@ -4534,9 +4534,9 @@
           new ResolutionWarning(
               kind.warning, arguments, compiler.terseDiagnostics);
       compiler.reportWarning(diagnosticNode, warning);
-      return new ErroneousElementX(
-          kind.error, arguments, targetName, enclosing);
     }
+    return new ErroneousElementX(
+        kind.error, arguments, targetName, enclosing);
   }
 
   Selector createConstructorSelector(String constructorName) {
@@ -4572,101 +4572,107 @@
     return result;
   }
 
-  visitNewExpression(NewExpression node) {
+  Element visitNewExpression(NewExpression node) {
     inConstContext = node.isConst();
     Node selector = node.send.selector;
-    Element e = visit(selector);
-    return finishConstructorReference(e, node.send.selector, node);
+    Element element = visit(selector);
+    assert(invariant(selector, element != null,
+        message: 'No element return for $selector.'));
+    return finishConstructorReference(element, node.send.selector, node);
   }
 
   /// Finishes resolution of a constructor reference and records the
   /// type of the constructed instance on [expression].
-  FunctionElement finishConstructorReference(Element e,
+  FunctionElement finishConstructorReference(Element element,
                                              Node diagnosticNode,
                                              Node expression) {
+    assert(invariant(diagnosticNode, element != null,
+        message: 'No element return for $diagnosticNode.'));
     // Find the unnamed constructor if the reference resolved to a
     // class.
-    if (!Elements.isUnresolved(e) && !e.isConstructor()) {
-      if (e.isClass()) {
-        ClassElement cls = e;
+    if (!Elements.isUnresolved(element) && !element.isConstructor()) {
+      if (element.isClass()) {
+        ClassElement cls = element;
         cls.ensureResolved(compiler);
         // The unnamed constructor may not exist, so [e] may become unresolved.
-        e = lookupConstructor(cls, diagnosticNode, '');
+        element = lookupConstructor(cls, diagnosticNode, '');
       } else {
-        e = failOrReturnErroneousElement(
-              e, diagnosticNode, e.name, MessageKind.NOT_A_TYPE,
-              {'node': diagnosticNode});
+        element = failOrReturnErroneousElement(
+            element, diagnosticNode, element.name, MessageKind.NOT_A_TYPE,
+            {'node': diagnosticNode});
       }
     }
     if (type == null) {
-      if (Elements.isUnresolved(e)) {
+      if (Elements.isUnresolved(element)) {
         type = compiler.types.dynamicType;
       } else {
-        type = e.getEnclosingClass().computeType(compiler).asRaw();
+        type = element.getEnclosingClass().computeType(compiler).asRaw();
       }
     }
     resolver.mapping.setType(expression, type);
-    return e;
+    return element;
   }
 
-  visitTypeAnnotation(TypeAnnotation node) {
+  Element visitTypeAnnotation(TypeAnnotation node) {
     assert(invariant(node, type == null));
-    type = resolver.resolveTypeExpression(node);
+    type = resolver.resolveTypeAnnotation(node,
+                                          malformedIsError: inConstContext);
     compiler.backend.registerRequiredType(type, resolver.enclosingElement);
-    return resolver.mapping[node];
+    return type.element;
   }
 
-  visitSend(Send node) {
-    Element e = visit(node.receiver);
-    if (Elements.isUnresolved(e)) return e;
+  Element visitSend(Send node) {
+    Element element = visit(node.receiver);
+    assert(invariant(node.receiver, element != null,
+        message: 'No element return for $node.receiver.'));
+    if (Elements.isUnresolved(element)) return element;
     Identifier name = node.selector.asIdentifier();
     if (name == null) internalError(node.selector, 'unexpected node');
 
-    if (identical(e.kind, ElementKind.CLASS)) {
-      ClassElement cls = e;
+    if (element.isClass()) {
+      ClassElement cls = element;
       cls.ensureResolved(compiler);
       return lookupConstructor(cls, name, name.source);
-    } else if (identical(e.kind, ElementKind.PREFIX)) {
-      PrefixElement prefix = e;
-      e = prefix.lookupLocalMember(name.source);
-      e = Elements.unwrap(e, compiler, node);
-      if (e == null) {
+    } else if (element.isPrefix()) {
+      PrefixElement prefix = element;
+      element = prefix.lookupLocalMember(name.source);
+      element = Elements.unwrap(element, compiler, node);
+      if (element == null) {
         return failOrReturnErroneousElement(
             resolver.enclosingElement, name,
             name.source,
             MessageKind.CANNOT_RESOLVE,
             {'name': name});
-      } else if (!identical(e.kind, ElementKind.CLASS)) {
+      } else if (!element.isClass()) {
         error(node, MessageKind.NOT_A_TYPE.error, {'node': name});
       }
     } else {
-      internalError(node.receiver, 'unexpected element $e');
+      internalError(node.receiver, 'unexpected element $element');
     }
-    return e;
+    return element;
   }
 
   Element visitIdentifier(Identifier node) {
     String name = node.source;
-    Element e = resolver.reportLookupErrorIfAny(
+    Element element = resolver.reportLookupErrorIfAny(
         lookupInScope(compiler, node, resolver.scope, name), node, name);
     // TODO(johnniwinther): Change errors to warnings, cf. 11.11.1.
-    if (e == null) {
+    if (element == null) {
       return failOrReturnErroneousElement(resolver.enclosingElement, node, name,
                                           MessageKind.CANNOT_RESOLVE,
                                           {'name': name});
-    } else if (e.isErroneous()) {
-      return e;
-    } else if (identical(e.kind, ElementKind.TYPEDEF)) {
+    } else if (element.isErroneous()) {
+      return element;
+    } else if (element.isTypedef()) {
       error(node, MessageKind.CANNOT_INSTANTIATE_TYPEDEF,
             {'typedefName': name});
-    } else if (identical(e.kind, ElementKind.TYPE_VARIABLE)) {
+    } else if (element.isTypeVariable()) {
       error(node, MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE,
             {'typeVariableName': name});
-    } else if (!identical(e.kind, ElementKind.CLASS)
-        && !identical(e.kind, ElementKind.PREFIX)) {
+    } else if (!element.isClass() && !element.isPrefix()) {
       error(node, MessageKind.NOT_A_TYPE.error, {'node': name});
     }
-    return e;
+    return element;
   }
 
   /// Assumed to be called by [resolveRedirectingFactory].
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart b/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart
index 90f2196..e69de29 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart
@@ -1,709 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of ssa;
-
-class BailoutInfo {
-  int instructionId;
-  int bailoutId;
-  BailoutInfo(this.instructionId, this.bailoutId);
-}
-
-/**
- * Keeps track of the execution environment for instructions. An
- * execution environment contains the SSA instructions that are live.
- */
-class Environment {
-  final Set<HInstruction> lives;
-  final List<HBasicBlock> loopMarkers;
-  Environment() : lives = new Set<HInstruction>(),
-                  loopMarkers = new List<HBasicBlock>();
-  Environment.from(Environment other)
-    : lives = new Set<HInstruction>.from(other.lives),
-      loopMarkers = new List<HBasicBlock>.from(other.loopMarkers);
-
-  void remove(HInstruction instruction) {
-    lives.remove(instruction);
-  }
-
-  void add(HInstruction instruction) {
-    // If the instruction is a check, we add its checked input
-    // instead. This allows sharing the same environment between
-    // different type guards.
-    //
-    // Also, we don't need to add code motion invariant instructions
-    // in the live set (because we generate them at use-site), except
-    // for parameters that are not 'this', which is always passed as
-    // the receiver.
-    if (instruction is HCheck) {
-      HCheck check = instruction;
-      add(check.checkedInput);
-    } else if (!instruction.isCodeMotionInvariant()
-               || (instruction is HParameterValue && instruction is !HThis)) {
-      lives.add(instruction);
-    } else {
-      for (int i = 0, len = instruction.inputs.length; i < len; i++) {
-        add(instruction.inputs[i]);
-      }
-    }
-  }
-
-  void addAll(Environment other) {
-    lives.addAll(other.lives);
-  }
-
-  bool get isEmpty => lives.isEmpty && loopMarkers.isEmpty;
-}
-
-
-/**
- * Visits the graph in dominator order and inserts TypeGuards in places where
- * we consider the guard to be of value. This phase also does type
- * propagation to help find valuable type guards.
- */
-class SsaTypeGuardInserter extends SsaNonSpeculativeTypePropagator
-    implements OptimizationPhase {
-  final String name = 'SsaTypeGuardInserter';
-  final CodegenWorkItem work;
-  bool calledInLoop = false;
-  bool isRecursiveMethod = false;
-  bool hasInsertedChecks = false;
-  int stateId = 1;
-  Map<HInstruction, HType> savedTypes = new Map<HInstruction, HType>();
-
-  SsaTypeGuardInserter(compiler, this.work) : super(compiler);
-
-  void visitGraph(HGraph graph) {
-    // Run the speculative type propagator. This does in-place
-    // update of the type of the instructions, and saves the
-    // previous types in the [savedTypes] map.
-    SsaTypePropagator propagator =
-        new SsaSpeculativeTypePropagator(compiler, savedTypes);
-    propagator.visitGraph(graph);
-
-    // Put back the original types in the instructions, and save the
-    // speculated types in [savedTypes].
-    Map<HInstruction, HType> speculativeTypes = new Map<HInstruction, HType>();
-
-    savedTypes.forEach((HInstruction instruction, HType type) {
-      speculativeTypes[instruction] = instruction.instructionType;
-      instruction.instructionType = type;
-    });
-    savedTypes = speculativeTypes;
-
-    // Propagate types again, and insert type guards in the graph.
-    isRecursiveMethod = graph.isRecursiveMethod;
-    calledInLoop = graph.calledInLoop;
-    work.guards = <HTypeGuard>[];
-    visitDominatorTree(graph);
-
-    // We need to disable the guards, and therefore re-run a
-    // non-speculative type propagator that will not use the
-    // speculated types.
-    work.guards.forEach((HTypeGuard guard) { guard.disable(); });
-
-    propagator = new SsaNonSpeculativeTypePropagator(compiler);
-    propagator.visitGraph(graph);
-  }
-
-  // Primitive types that are not null are valuable. These include
-  // indexable arrays.
-  bool typeValuable(HType type) {
-    return type.isPrimitive(compiler) && !type.isNull();
-  }
-
-  bool get hasTypeGuards => work.guards.length != 0;
-
-  bool isUsedWithIncompatibleSelector(HInstruction instruction,
-                                      HType speculativeType) {
-    for (HInstruction user in instruction.usedBy) {
-      if (user is HCheck
-          && isUsedWithIncompatibleSelector(user, speculativeType)) {
-        return true;
-      } else if (user.selector != null
-                 && user.getDartReceiver(compiler) == instruction
-                 && !speculativeType.computeMask(compiler).understands(
-                        user.selector, compiler)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  bool typeGuardWouldBeValuable(HInstruction instruction,
-                                HType speculativeType) {
-    // If the type itself is not valuable, do not generate a guard for it.
-    if (!typeValuable(speculativeType)) return false;
-
-    // Do not insert a type guard if the instruction has a type
-    // annotation that disagrees with the speculated type.
-    Element source = instruction.sourceElement;
-    if (source != null) {
-      DartType sourceType = source.computeType(compiler);
-      if (!sourceType.treatAsDynamic &&
-          sourceType.kind == TypeKind.INTERFACE) {
-        TypeMask sourceMask = new TypeMask.subtype(sourceType.element);
-        TypeMask speculatedMask = speculativeType.computeMask(compiler);
-        if (sourceMask.intersection(speculatedMask, compiler).isEmpty) {
-          return false;
-        }
-      }
-    }
-
-    // Do not insert a type guard if one of the calls on it will hit
-    // [NoSuchMethodError].
-    if (isUsedWithIncompatibleSelector(instruction, speculativeType)) {
-      return false;
-    }
-
-    // Insert type guards for recursive methods.
-    if (isRecursiveMethod) return true;
-
-    // Insert type guards if there are uses in loops.
-    bool isNested(HBasicBlock inner, HBasicBlock outer) {
-      if (identical(inner, outer)) return false;
-      if (outer == null) return true;
-      while (inner != null) {
-        if (identical(inner, outer)) return true;
-        inner = inner.parentLoopHeader;
-      }
-      return false;
-    }
-
-    // If the instruction is not in a loop then the header will be null.
-    HBasicBlock currentLoopHeader = instruction.block.enclosingLoopHeader;
-    for (HInstruction user in instruction.usedBy) {
-      HBasicBlock userLoopHeader = user.block.enclosingLoopHeader;
-      if (isNested(userLoopHeader, currentLoopHeader)) return true;
-    }
-
-    bool isIndexOperatorOnIndexablePrimitive(instruction) {
-      return instruction is HIndex
-          || (instruction is HInvokeDynamicMethod
-              && instruction.isIndexOperatorOnIndexablePrimitive(compiler));
-    }
-
-    // To speed up computations on values loaded from arrays, we
-    // insert type guards for builtin array indexing operations in
-    // nested loops. Since this can blow up code size quite
-    // significantly, we only do it if type guards have already been
-    // inserted for this method. The code size price for an additional
-    // type guard is much smaller than the first one that causes the
-    // generation of a bailout method.
-    if (hasTypeGuards
-        && isIndexOperatorOnIndexablePrimitive(instruction)) {
-      HBasicBlock loopHeader = instruction.block.enclosingLoopHeader;
-      if (loopHeader != null && loopHeader.parentLoopHeader != null) {
-        return true;
-      }
-    }
-
-    // If the instruction is used by a phi where a guard would be
-    // valuable, put the guard on that instruction.
-    for (HInstruction user in instruction.usedBy) {
-      if (user is HPhi
-          && user.block.id > instruction.id
-          && typeGuardWouldBeValuable(user, speculativeType)) {
-        return true;
-      }
-    }
-
-    // Insert type guards if the method is likely to be called in a
-    // loop.
-    return calledInLoop;
-  }
-
-  HInstruction computeFirstDominatingUserWithSelector(
-      HInstruction instruction) {
-    // TODO(ngeoffray): We currently only look at the instruction's
-    // block, so that we know it will be executed. We should lift this
-    // limitation.
-
-    // For a parameter, we look at the first block that contains
-    // user instructions.
-    HBasicBlock userMustBeInBlock = instruction is HParameterValue
-        ? instruction.block.successors[0]
-        : instruction.block;
-
-    HInstruction firstUser;
-    for (HInstruction user in instruction.usedBy) {
-      if (user.block == userMustBeInBlock && user.selector != null) {
-        if (firstUser == null || user.dominates(firstUser)) {
-          firstUser = user;
-        }
-      }
-    }
-    return firstUser;
-  }
-
-  /**
-   * Tries to insert a type conversion instruction for [instruction]
-   * instead of a type guard if we know an user will throw. Returns
-   * whether it succeeded at adding a type conversion instruction.
-   */
-  bool tryTypeConversion(HInstruction instruction, HType speculativeType) {
-    HInstruction firstUser =
-        computeFirstDominatingUserWithSelector(instruction);
-    if (firstUser is !HInvokeDynamic) return false;
-
-    // If we have found a user with a selector, we find out if it
-    // will throw [NoSuchMethodError] or [ArgumentError]. If it does,
-    // then we change just add a [HTypeConversion] instruction and
-    // avoid a bailout.
-    Selector selector = firstUser.selector;
-    if (!selector.isOperator()) return false;
-    HInstruction receiver = firstUser.getDartReceiver(compiler);
-
-    if (instruction == receiver) {
-      // If the instruction on which we're speculating the
-      // type is the receiver of the call, check if it will throw
-      // [NoSuchMethodError] if [instruction] is not of the speculated
-      // type.
-      return checkReceiver(firstUser);
-    } else if (!selector.isUnaryOperator()
-               && instruction == firstUser.inputs[2]) {
-      // If the instruction is a parameter of the call, we check if
-      // the method will throw an [ArgumentError] if [instruction] is
-      // not of the speculated type.
-      return checkArgument(firstUser);
-    }
-    return false;
-  }
-
-  bool updateType(HInstruction instruction) {
-    bool hasChanged = super.updateType(instruction);
-    HType speculativeType = savedTypes[instruction];
-    if (speculativeType == null
-        || !speculativeType.isUseful()
-        || speculativeType == instruction.instructionType) {
-      return hasChanged;
-    }
-
-    if (!tryTypeConversion(instruction, speculativeType)
-        && typeGuardWouldBeValuable(instruction, speculativeType)) {
-      HInstruction insertionPoint;
-      if (instruction is HPhi) {
-        insertionPoint = instruction.block.first;
-      } else if (instruction is HParameterValue) {
-        // We insert the type guard at the end of the entry block
-        // because if a parameter is live, it must be kept in the live
-        // environment. Not doing so would mean we could visit a
-        // parameter and remove it from the environment before
-        // visiting a type guard.
-        insertionPoint = instruction.block.last;
-      } else {
-        insertionPoint = instruction.next;
-      }
-      // If the previous instruction is also a type guard, then both
-      // guards have the same environment, and can therefore share the
-      // same state id.
-      HBailoutTarget target;
-      int state;
-      if (insertionPoint.previous is HTypeGuard) {
-        HTypeGuard other = insertionPoint.previous;
-        target = other.bailoutTarget;
-      } else {
-        state = stateId++;
-        target = new HBailoutTarget(state);
-        insertionPoint.block.addBefore(insertionPoint, target);
-      }
-      HTypeGuard guard = new HTypeGuard(speculativeType, instruction, target);
-      work.guards.add(guard);
-      // By setting the type of the guard to the speculated type, we
-      // help the analysis find valuable type guards. This however
-      // requires to run a non-speculative type propagation again
-      // after this analysis.
-      guard.instructionType = speculativeType;
-      instruction.block.rewrite(instruction, guard);
-      insertionPoint.block.addBefore(insertionPoint, guard);
-    }
-    return hasChanged;
-  }
-}
-
-/**
- * Computes the environment for each SSA instruction: visits the graph
- * in post-dominator order. Removes an instruction from the environment
- * and adds its inputs to the environment at the instruction's
- * definition.
- *
- * At the end of the computation, insert type guards in the graph.
- */
-class SsaEnvironmentBuilder extends HBaseVisitor implements OptimizationPhase {
-  final Compiler compiler;
-  final String name = 'SsaEnvironmentBuilder';
-
-  final Map<HBailoutTarget, Environment> capturedEnvironments;
-  final Map<HBasicBlock, Environment> liveInstructions;
-  Environment environment;
-  /**
-   * The set of current loop headers that dominate the current block.
-   */
-  Set<HBasicBlock> loopMarkers;
-
-  SsaEnvironmentBuilder(Compiler this.compiler)
-    : capturedEnvironments = new Map<HBailoutTarget, Environment>(),
-      liveInstructions = new Map<HBasicBlock, Environment>(),
-      loopMarkers = new Set<HBasicBlock>();
-
-
-  void visitGraph(HGraph graph) {
-    visitPostDominatorTree(graph);
-    if (!liveInstructions[graph.entry].isEmpty) {
-      compiler.internalError('Bailout environment computation',
-          node: compiler.currentElement.parseNode(compiler));
-    }
-    updateLoopMarkers();
-    insertCapturedEnvironments();
-  }
-
-  void updateLoopMarkers() {
-    // If the block is a loop header, we need to merge the loop
-    // header's live instructions into every environment that contains
-    // the loop marker.
-    // For example with the following loop (read the example in
-    // reverse):
-    //
-    // while (true) { <-- (4) update the marker with the environment
-    //   use(x);      <-- (3) environment = {x}
-    //   bailout;     <-- (2) has the marker when computed
-    // }              <-- (1) create a loop marker
-    //
-    // The bailout instruction first captures the marker, but it
-    // will be replaced by the live environment at the loop entry,
-    // in this case {x}.
-    capturedEnvironments.forEach((ignoredInstruction, env) {
-      env.loopMarkers.forEach((HBasicBlock header) {
-        env.addAll(liveInstructions[header]);
-      });
-      env.loopMarkers.clear();
-    });
-  }
-
-  void visitBasicBlock(HBasicBlock block) {
-    environment = new Environment();
-
-    // Add to the environment the live instructions of its successor, as well as
-    // the inputs of the phis of the successor that flow from this block.
-    for (int i = 0; i < block.successors.length; i++) {
-      HBasicBlock successor = block.successors[i];
-      Environment successorEnv = liveInstructions[successor];
-      if (successorEnv != null) {
-        environment.addAll(successorEnv);
-      } else {
-        // If we haven't computed the liveInstructions of that successor, we
-        // know it must be a loop header.
-        assert(successor.isLoopHeader());
-        assert(!block.isLoopHeader());
-        loopMarkers.add(successor);
-      }
-
-      int index = successor.predecessors.indexOf(block);
-      for (HPhi phi = successor.phis.first; phi != null; phi = phi.next) {
-        environment.add(phi.inputs[index]);
-      }
-    }
-
-    if (block.isLoopHeader()) {
-      loopMarkers.remove(block);
-    }
-
-    // If the block is a loop header, we're adding all [loopMarkers]
-    // after removing it from the list of [loopMarkers], because
-    // it will just recompute the loop phis.
-    environment.loopMarkers.addAll(loopMarkers);
-
-    // Iterate over all instructions to remove an instruction from the
-    // environment and add its inputs.
-    HInstruction instruction = block.last;
-    while (instruction != null) {
-      instruction.accept(this);
-      instruction = instruction.previous;
-    }
-
-    // We just remove the phis from the environment. The inputs of the
-    // phis will be put in the environment of the predecessors.
-    for (HPhi phi = block.phis.first; phi != null; phi = phi.next) {
-      environment.remove(phi);
-    }
-
-    // Finally save the liveInstructions of that block.
-    liveInstructions[block] = environment;
-  }
-
-  void visitBailoutTarget(HBailoutTarget target) {
-    visitInstruction(target);
-    capturedEnvironments[target] = new Environment.from(environment);
-  }
-
-  void visitInstruction(HInstruction instruction) {
-    environment.remove(instruction);
-    for (int i = 0, len = instruction.inputs.length; i < len; i++) {
-      environment.add(instruction.inputs[i]);
-    }
-  }
-
-  /**
-   * Stores all live variables in the bailout target and the guards.
-   */
-  void insertCapturedEnvironments() {
-    capturedEnvironments.forEach((HBailoutTarget target, Environment env) {
-      assert(target.inputs.length == 0);
-      target.inputs.addAll(env.lives);
-      // TODO(floitsch): we should add the bailout-target's input variables
-      // as input to the guards only in the optimized version. The
-      // non-optimized version does not use the bailout guards and it is
-      // unnecessary to keep the variables alive until the check.
-      for (HTypeGuard guard in target.usedBy) {
-        // A type-guard initially only has two inputs: the guarded instruction
-        // and the bailout-target. Only after adding the environment is it
-        // allowed to have more inputs.
-        assert(guard.inputs.length == 2);
-        guard.inputs.addAll(env.lives);
-      }
-      for (HInstruction live in env.lives) {
-        live.usedBy.add(target);
-        live.usedBy.addAll(target.usedBy);
-      }
-    });
-  }
-}
-
-/**
- * Propagates bailout information to blocks that need it. This visitor
- * is run before codegen, to know which blocks have to deal with
- * bailouts.
- */
-class SsaBailoutPropagator extends HBaseVisitor {
-  final Compiler compiler;
-  /**
-   * A list to propagate bailout information to blocks that start a
-   * guarded or labeled list of statements. Currently, these blocks
-   * are:
-   *    - first block of a then branch,
-   *    - first block of an else branch,
-   *    - a loop header,
-   *    - labeled block.
-   */
-  final List<HBasicBlock> blocks;
-
-  /**
-   * The current subgraph we are visiting.
-   */
-  SubGraph subGraph;
-
-  /**
-   * The current block information we are visiting.
-   */
-  HBlockInformation currentBlockInformation;
-
-  /**
-   * Max number of arguments to the bailout (not counting the state).
-   */
-  int bailoutArity;
-  /**
-   * A map from variables to their names.  These are the names in the
-   * unoptimized (bailout) version of the function.  Their names could be
-   * different in the optimized version.
-   */
-  VariableNames variableNames;
-  /**
-   * Maps from the variable names to their positions in the argument list of the
-   * bailout instruction.  Because of the way the variable allocator works,
-   * several variables can end up with the same name (if their live ranges do
-   * not overlap), therefore they can have the same position in the bailout
-   * argument list
-   */
-  Map<String, int> parameterNames;
-
-  /**
-   * If set to true, the graph has either multiple bailouts in
-   * different places, or a bailout inside an if or a loop. For such a
-   * graph, the code generator will emit a generic switch.
-   */
-  bool hasComplexBailoutTargets = false;
-
-  /**
-   * The first type guard in the graph.
-   */
-  HBailoutTarget firstBailoutTarget;
-
-  /**
-   * If set, it is the first block in the graph where we generate
-   * code. Blocks before this one are dead code in the bailout
-   * version.
-   */
-
-  SsaBailoutPropagator(this.compiler, this.variableNames)
-      : blocks = <HBasicBlock>[],
-        bailoutArity = 0,
-        parameterNames = new Map<String, int>();
-
-  void visitGraph(HGraph graph) {
-    subGraph = new SubGraph(graph.entry, graph.exit);
-    visitBasicBlock(graph.entry);
-    if (!blocks.isEmpty) {
-      compiler.internalError('Bailout propagation',
-          node: compiler.currentElement.parseNode(compiler));
-    }
-  }
-
-  /**
-   * Returns true if we can visit the given [blockFlow]. False
-   * otherwise. Currently, try/catch and switch are not in bailout
-   * methods, so this method only deals with loops and labeled blocks.
-   * If [blockFlow] is a labeled block or a loop, we also visit the
-   * continuation of the block flow.
-   */
-  bool handleBlockFlow(HBlockFlow blockFlow) {
-    HBlockInformation body = blockFlow.body;
-
-    // We reach here again when starting to visit a subgraph. Just
-    // return to visiting the block.
-    if (currentBlockInformation == body) return false;
-
-    HBlockInformation oldInformation = currentBlockInformation;
-    if (body is HLabeledBlockInformation) {
-      currentBlockInformation = body;
-      HLabeledBlockInformation info = body;
-      visitStatements(info.body, newFlow: true);
-    } else if (body is HLoopBlockInformation) {
-      currentBlockInformation = body;
-      HLoopBlockInformation info = body;
-      if (info.initializer != null) {
-        visitExpression(info.initializer);
-      }
-      blocks.add(info.loopHeader);
-      if (!info.isDoWhile()) {
-        visitExpression(info.condition);
-      }
-      visitStatements(info.body, newFlow: false);
-      if (info.isDoWhile()) {
-        visitExpression(info.condition);
-      }
-      if (info.updates != null) {
-        visitExpression(info.updates);
-      }
-      blocks.removeLast();
-    } else {
-      assert(body is! HTryBlockInformation);
-      assert(body is! HSwitchBlockInformation);
-      // [HIfBlockInformation] is handled by visitIf.
-      return false;
-    }
-
-    currentBlockInformation = oldInformation;
-    if (blockFlow.continuation != null) {
-      visitBasicBlock(blockFlow.continuation);
-    }
-    return true;
-  }
-
-  void visitBasicBlock(HBasicBlock block) {
-    // Abort traversal if we are leaving the currently active sub-graph.
-    if (!subGraph.contains(block)) return;
-
-    HBlockFlow blockFlow = block.blockFlow;
-    if (blockFlow != null && handleBlockFlow(blockFlow)) return;
-
-    HInstruction instruction = block.first;
-    while (instruction != null) {
-      instruction.accept(this);
-      instruction = instruction.next;
-    }
-  }
-
-  void visitExpression(HSubExpressionBlockInformation info) {
-    visitSubGraph(info.subExpression);
-  }
-
-  /**
-   * Visit the statements in [info]. If [newFlow] is true, we add the
-   * first block of [statements] to the list of [blocks].
-   */
-  void visitStatements(HSubGraphBlockInformation info, {bool newFlow}) {
-    SubGraph graph = info.subGraph;
-    if (newFlow) blocks.add(graph.start);
-    visitSubGraph(graph);
-    if (newFlow) blocks.removeLast();
-  }
-
-  void visitSubGraph(SubGraph graph) {
-    SubGraph oldSubGraph = subGraph;
-    subGraph = graph;
-    visitBasicBlock(graph.start);
-    subGraph = oldSubGraph;
-  }
-
-  void visitIf(HIf instruction) {
-    int preVisitedBlocks = 0;
-    HIfBlockInformation info = instruction.blockInformation.body;
-    visitStatements(info.thenGraph, newFlow: true);
-    preVisitedBlocks++;
-    visitStatements(info.elseGraph, newFlow: true);
-    preVisitedBlocks++;
-
-    HBasicBlock joinBlock = instruction.joinBlock;
-    if (joinBlock != null
-        && !identical(joinBlock.dominator, instruction.block)) {
-      // The join block is dominated by a block in one of the branches.
-      // The subgraph traversal never reached it, so we visit it here
-      // instead.
-      visitBasicBlock(joinBlock);
-    }
-
-    // Visit all the dominated blocks that are not part of the then or else
-    // branches, and is not the join block.
-    // Depending on how the then/else branches terminate
-    // (e.g., return/throw/break) there can be any number of these.
-    List<HBasicBlock> dominated = instruction.block.dominatedBlocks;
-    int dominatedCount = dominated.length;
-    for (int i = preVisitedBlocks; i < dominatedCount; i++) {
-      HBasicBlock dominatedBlock = dominated[i];
-      visitBasicBlock(dominatedBlock);
-    }
-  }
-
-  void visitGoto(HGoto goto) {
-    HBasicBlock block = goto.block;
-    HBasicBlock successor = block.successors[0];
-    if (identical(successor.dominator, block)) {
-      visitBasicBlock(block.successors[0]);
-    }
-  }
-
-  void visitLoopBranch(HLoopBranch branch) {
-    // For a do-while loop, the body has already been visited.
-    if (!branch.isDoWhile()) {
-      visitBasicBlock(branch.block.dominatedBlocks[0]);
-    }
-  }
-
-  visitBailoutTarget(HBailoutTarget target) {
-    int inputLength = target.inputs.length;
-    for (HInstruction input in target.inputs) {
-      String inputName = variableNames.getName(input);
-      int position = parameterNames[inputName];
-      if (position == null) {
-        position = parameterNames[inputName] = bailoutArity++;
-      }
-    }
-
-    if (blocks.isEmpty) {
-      // If [currentBlockInformation] is not null, we are in the
-      // middle of a loop/labeled block and this is too complex to handle for
-      // now.
-      if (firstBailoutTarget == null && currentBlockInformation == null) {
-        firstBailoutTarget = target;
-      } else {
-        hasComplexBailoutTargets = true;
-      }
-    } else {
-      hasComplexBailoutTargets = true;
-      blocks.forEach((HBasicBlock block) {
-        block.bailoutTargets.add(target);
-      });
-    }
-  }
-}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 6cd0139..a0df363 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -274,6 +274,11 @@
     // classes, or the same as [:this:] for non-intercepted classes.
     ClassElement cls = element.getEnclosingClass();
     JavaScriptBackend backend = compiler.backend;
+
+    // When the class extends a native class, the instance is pre-constructed
+    // and passed to the generative constructor factory function as a parameter.
+    // Instead of allocating and initializing the object, the constructor
+    // 'upgrades' the native subclass object by initializing the Dart fields.
     bool isNativeUpgradeFactory = element.isGenerativeConstructor()
         && Elements.isNativeOrExtendsNative(cls);
     if (backend.isInterceptedMethod(element)) {
@@ -291,7 +296,6 @@
       }
       value.instructionType = builder.getTypeOfThis();
     } else if (isNativeUpgradeFactory) {
-      bool isInterceptorClass = backend.isInterceptorClass(cls.declaration);
       Element parameter = new InterceptedElement(
           cls.computeType(compiler), 'receiver', element);
       HParameterValue value = new HParameterValue(parameter);
@@ -1613,8 +1617,7 @@
               // Unassigned fields of native classes are not initialized to
               // prevent overwriting pre-initialized native properties.
               if (!Elements.isNativeOrExtendsNative(classElement)) {
-                HInstruction value = graph.addConstantNull(compiler);
-                fieldValues[member] = value;
+                fieldValues[member] = graph.addConstantNull(compiler);
               }
             } else {
               Node right = assignment.arguments.head;
@@ -1626,8 +1629,7 @@
                   member, node, elements);
               inlinedFrom(member, () => right.accept(this));
               elements = savedElements;
-              HInstruction value = pop();
-              fieldValues[member] = value;
+              fieldValues[member] = pop();
             }
           });
         });
@@ -1890,7 +1892,8 @@
       if (type.containsTypeVariables) {
         bool contextIsTypeArguments = false;
         HInstruction context;
-        if (currentElement.isInstanceMember()) {
+        if (!currentElement.enclosingElement.isClosure()
+            && currentElement.isInstanceMember()) {
           context = localsHandler.readThis();
         } else {
           ClassElement contextClass = Types.getClassContext(type);
@@ -2934,7 +2937,8 @@
         contextName = graph.addConstantString(
             new DartString.literal(backend.namer.getNameOfClass(contextClass)),
             node, compiler);
-        if (currentElement.isInstanceMember()) {
+        if (!currentElement.enclosingElement.isClosure()
+            && currentElement.isInstanceMember()) {
           context = localsHandler.readThis();
           typeArguments = graph.addConstantNull(compiler);
         } else {
@@ -3116,7 +3120,8 @@
 
     HType ssaType = new HType.fromNativeBehavior(nativeBehavior, compiler);
     push(new HForeign(nativeBehavior.codeAst, ssaType, inputs,
-                      effects: nativeBehavior.sideEffects));
+                      effects: nativeBehavior.sideEffects,
+                      nativeBehavior: nativeBehavior));
     return;
   }
 
@@ -4832,8 +4837,6 @@
                     void buildSwitchCase(SwitchCase switchCase)) {
     Map<CaseMatch, Constant> constants = new Map<CaseMatch, Constant>();
 
-    // TODO(ngeoffray): Handle switch-instruction in bailout code.
-    work.allowSpeculativeOptimization = false;
     HBasicBlock expressionStart = openNewBlock();
     HInstruction expression = buildExpression();
     if (switchCases.isEmpty) {
@@ -4966,7 +4969,6 @@
   }
 
   visitTryStatement(TryStatement node) {
-    work.allowSpeculativeOptimization = false;
     // Save the current locals. The catch block and the finally block
     // must not reuse the existing locals handler. None of the variables
     // that have been defined in the body-block will be used, but for
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index 8c3fe05..8c3783a 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -71,8 +71,7 @@
   js.Expression generateLazyInitializer(work, graph) {
     return measure(() {
       compiler.tracer.traceGraph("codegen", graph);
-      SsaOptimizedCodeGenerator codegen =
-          new SsaOptimizedCodeGenerator(backend, work);
+      SsaCodeGenerator codegen = new SsaCodeGenerator(backend, work);
       codegen.visitGraph(graph);
       return new js.Fun(codegen.parameters,
           attachPosition(codegen.body, work.element));
@@ -82,35 +81,17 @@
   js.Expression generateMethod(CodegenWorkItem work, HGraph graph) {
     return measure(() {
       compiler.tracer.traceGraph("codegen", graph);
-      SsaOptimizedCodeGenerator codegen =
-          new SsaOptimizedCodeGenerator(backend, work);
+      SsaCodeGenerator codegen = new SsaCodeGenerator(backend, work);
       codegen.visitGraph(graph);
-
       FunctionElement element = work.element;
       return buildJavaScriptFunction(element, codegen.parameters, codegen.body);
     });
   }
-
-  js.Expression generateBailoutMethod(CodegenWorkItem work, HGraph graph) {
-    return measure(() {
-      compiler.tracer.traceGraph("codegen-bailout", graph);
-
-      SsaUnoptimizedCodeGenerator codegen =
-          new SsaUnoptimizedCodeGenerator(backend, work);
-      codegen.visitGraph(graph);
-
-      js.Block body = new js.Block(<js.Statement>[]);
-      body.statements.add(codegen.body);
-      js.Fun fun =
-          buildJavaScriptFunction(work.element, codegen.newParameters, body);
-      return fun;
-    });
-  }
 }
 
 typedef void ElementAction(Element element);
 
-abstract class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
+class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
   /**
    * Returned by [expressionType] to tell how code can be generated for
    * a subgraph.
@@ -297,16 +278,9 @@
     return jsNode;
   }
 
-  visitTypeGuard(HTypeGuard node);
-  visitBailoutTarget(HBailoutTarget node);
-
   beginGraph(HGraph graph);
   endGraph(HGraph graph);
 
-  preLabeledBlock(HLabeledBlockInformation labeledBlockInfo);
-  startLabeledBlock(HLabeledBlockInformation labeledBlockInfo);
-  endLabeledBlock(HLabeledBlockInformation labeledBlockInfo);
-
   void preGenerateMethod(HGraph graph) {
     new SsaInstructionMerger(generateAtUseSite, compiler).visitGraph(graph);
     new SsaConditionMerger(
@@ -370,10 +344,8 @@
     currentGraph = graph;
     indent++;  // We are already inside a function.
     subGraph = new SubGraph(graph.entry, graph.exit);
-    HBasicBlock start = beginGraph(graph);
-    visitBasicBlock(start);
+    visitBasicBlock(graph.entry);
     handleDelayedVariableDeclarations();
-    endGraph(graph);
   }
 
   void visitSubGraph(SubGraph newSubGraph) {
@@ -405,14 +377,13 @@
     // counter-example, we degrade our assumption to either expression or
     // statement, and in the latter case, we can return immediately since
     // it can't get any worse. E.g., a function call where the return value
-    // isn't used can't be in a declaration. A bailout can't be in an
-    // expression.
+    // isn't used can't be in a declaration.
     int result = TYPE_DECLARATION;
     HBasicBlock basicBlock = limits.start;
     do {
       HInstruction current = basicBlock.first;
       while (current != basicBlock.last) {
-        // E.g, type guards.
+        // E.g, bounds check.
         if (current.isControlFlow()) {
           return TYPE_STATEMENT;
         }
@@ -962,7 +933,6 @@
   }
 
   bool visitLabeledBlockInfo(HLabeledBlockInformation labeledBlockInfo) {
-    preLabeledBlock(labeledBlockInfo);
     Link<Element> continueOverrides = const Link<Element>();
 
     js.Block oldContainer = currentContainer;
@@ -1011,9 +981,7 @@
     }
 
     currentContainer = body;
-    startLabeledBlock(labeledBlockInfo);
     generateStatements(labeledBlockInfo.body);
-    endLabeledBlock(labeledBlockInfo);
 
     if (labeledBlockInfo.isContinue) {
       while (!continueOverrides.isEmpty) {
@@ -1208,9 +1176,7 @@
   void iterateBasicBlock(HBasicBlock node) {
     HInstruction instruction = node.first;
     while (!identical(instruction, node.last)) {
-      if (instruction is HTypeGuard || instruction is HBailoutTarget) {
-        visit(instruction);
-      } else if (!isGenerateAtUseSite(instruction)) {
+      if (!isGenerateAtUseSite(instruction)) {
         define(instruction);
       }
       instruction = instruction.next;
@@ -1408,8 +1374,7 @@
 
   visitTry(HTry node) {
     // We should never get here. Try/catch/finally is always handled using block
-    // information in [visitTryInfo], or not at all, in the case of the bailout
-    // generator.
+    // information in [visitTryInfo].
     compiler.internalError('visitTry should not be called', instruction: node);
   }
 
@@ -1796,8 +1761,7 @@
     List<js.Expression> arguments = visitArguments(node.inputs, start: 0);
     // TODO(floitsch): jsClassReference is an Access. We shouldn't treat it
     // as if it was a string.
-    js.Expression constructor = new js.VariableUse(jsClassReference);
-    push(new js.New(constructor, arguments), node);
+    push(new js.New(new js.VariableUse(jsClassReference), arguments), node);
     registerForeignTypes(node);
     if (node.instantiatedTypes == null) {
       return;
@@ -2614,433 +2578,6 @@
   }
 }
 
-class SsaOptimizedCodeGenerator extends SsaCodeGenerator {
-  SsaOptimizedCodeGenerator(backend, work) : super(backend, work);
-
-  HBasicBlock beginGraph(HGraph graph) {
-    return graph.entry;
-  }
-
-  void endGraph(HGraph graph) {}
-
-  // Called by visitTypeGuard to generate the actual bailout call, something
-  // like "return $.foo$bailout(t0, t1);"
-  js.Statement bailout(HTypeGuard guard) {
-    HBailoutTarget target = guard.bailoutTarget;
-    List<js.Expression> arguments = <js.Expression>[];
-    arguments.add(new js.LiteralNumber("${guard.state}"));
-
-    for (int i = 0; i < target.inputs.length; i++) {
-      HInstruction parameter = target.inputs[i];
-      for (int pad = target.padding[i]; pad != 0; pad--) {
-        // This argument will not be used by the bailout function, because
-        // of the control flow (controlled by the state argument passed
-        // above).  We need to pass it to get later arguments in the right
-        // position.
-        arguments.add(new js.LiteralNumber('0'));
-      }
-      use(parameter);
-      arguments.add(pop());
-    }
-    // Don't bother emitting the rest of the pending nulls.  Doing so might make
-    // the function invocation a little faster by having the call site and
-    // function defintion have the same number of arguments, but it would be
-    // more verbose and we don't expect the calls to bailout functions to be
-    // hot.
-
-    Element method = work.element;
-    js.Expression bailoutTarget;  // Receiver of the bailout call.
-    Namer namer = backend.namer;
-    if (method.isInstanceMember()) {
-      String bailoutName = namer.getBailoutName(method);
-      bailoutTarget = new js.PropertyAccess.field(new js.This(), bailoutName);
-    } else {
-      assert(!method.isField());
-      bailoutTarget = new js.VariableUse(namer.isolateBailoutAccess(method));
-    }
-    js.Call call = new js.Call(bailoutTarget, arguments);
-    attachLocation(call, guard);
-    return new js.Return(call);
-  }
-
-  // Generate a type guard, something like "if (typeof t0 == 'number')" and the
-  // corresponding bailout call, something like "return $.foo$bailout(t0, t1);"
-  void visitTypeGuard(HTypeGuard node) {
-    js.Expression test = generateTest(node);
-    pushStatement(new js.If.noElse(test, bailout(node)), node);
-  }
-
-  void visitBailoutTarget(HBailoutTarget target) {
-    // Do nothing. Bailout targets are only used in the non-optimized version.
-  }
-
-  void preLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
-  }
-
-  void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
-  }
-
-  void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
-  }
-}
-
-class SsaUnoptimizedCodeGenerator extends SsaCodeGenerator {
-
-  js.Switch currentBailoutSwitch;
-  final List<js.Switch> oldBailoutSwitches;
-  final List<js.Parameter> newParameters;
-  final List<String> labels;
-  int labelId = 0;
-  /**
-   * Keeps track if a bailout switch already used its [:default::] clause. New
-   * bailout-switches just push [:false:] on the stack and replace it when
-   * they used the [:default::] clause.
-   */
-  final List<bool> defaultClauseUsedInBailoutStack;
-
-  SsaBailoutPropagator propagator;
-  HInstruction savedFirstInstruction;
-
-  SsaUnoptimizedCodeGenerator(backend, work)
-    : super(backend, work),
-      oldBailoutSwitches = <js.Switch>[],
-      newParameters = <js.Parameter>[],
-      labels = <String>[],
-      defaultClauseUsedInBailoutStack = <bool>[];
-
-  String pushLabel() {
-    String label = 'L${labelId++}';
-    labels.add(label);
-    return label;
-  }
-
-  String popLabel() {
-    return labels.removeLast();
-  }
-
-  String currentLabel() {
-    return labels.last;
-  }
-
-  js.VariableUse generateStateUse()
-      => new js.VariableUse(variableNames.stateName);
-
-  HBasicBlock beginGraph(HGraph graph) {
-    propagator = new SsaBailoutPropagator(compiler, variableNames);
-    propagator.visitGraph(graph);
-    // TODO(ngeoffray): We could avoid generating the state at the
-    // call site for non-complex bailout methods.
-    newParameters.add(new js.Parameter(variableNames.stateName));
-
-    List<String> names = new List<String>(propagator.bailoutArity);
-    for (String variable in propagator.parameterNames.keys) {
-      int index = propagator.parameterNames[variable];
-      assert(names[index] == null);
-      names[index] = variable;
-    }
-    for (int i = 0; i < names.length; i++) {
-      declaredLocals.add(names[i]);
-      newParameters.add(new js.Parameter(names[i]));
-    }
-
-    if (propagator.hasComplexBailoutTargets) {
-      startBailoutSwitch();
-
-      return graph.entry;
-    } else {
-      // We change the first instruction of the first guard to be the
-      // bailout target. We will change it back in the call to [endGraph].
-      HBasicBlock block = propagator.firstBailoutTarget.block;
-      savedFirstInstruction = block.first;
-      block.first = propagator.firstBailoutTarget;
-      return block;
-    }
-  }
-
-  // If argument is a [HCheck] and it does not have a name, we try to
-  // find the name of its checked input. Note that there must be a
-  // name, otherwise the instruction would not be in the live
-  // environment.
-  HInstruction unwrap(var argument) {
-    while (argument is HCheck && !variableNames.hasName(argument)) {
-      argument = argument.checkedInput;
-    }
-    assert(variableNames.hasName(argument));
-    return argument;
-  }
-
-  void endGraph(HGraph graph) {
-    if (propagator.hasComplexBailoutTargets) {
-      endBailoutSwitch();
-    } else {
-      // Put back the original first instruction of the block.
-      propagator.firstBailoutTarget.block.first = savedFirstInstruction;
-    }
-  }
-
-  visitParameterValue(HParameterValue node) {
-    // Nothing to do, parameters are dealt with specially in a bailout
-    // method.
-  }
-
-  bool visitAndOrInfo(HAndOrBlockInformation info) => false;
-
-  visitLoopBranch(HLoopBranch node) {
-    if (node.computeLoopHeader().hasBailoutTargets()) {
-      // The graph visitor in [visitLoopInfo] does not handle the
-      // condition. We must instead manually emit it here.
-      handleLoopCondition(node);
-      // We must also visit the body from here.
-      // For a do while loop, the body has already been visited.
-      if (!node.isDoWhile()) {
-        visitBasicBlock(node.block.dominatedBlocks[0]);
-      }
-    } else {
-      super.visitLoopBranch(node);
-    }
-  }
-
-
-  bool visitIfInfo(HIfBlockInformation info) {
-    if (info.thenGraph.start.hasBailoutTargets()) return false;
-    if (info.elseGraph.start.hasBailoutTargets()) return false;
-    return super.visitIfInfo(info);
-  }
-
-  bool visitLoopInfo(HLoopBlockInformation info) {
-    // Always emit with block flow traversal.
-    if (info.loopHeader.hasBailoutTargets()) {
-      // If there are any bailout targets in the loop, we cannot use
-      // the pretty [SsaCodeGenerator.visitLoopInfo] printer.
-      if (info.initializer != null) {
-        generateStatements(info.initializer);
-      }
-      beginLoop(info.loopHeader);
-      if (!info.isDoWhile()) {
-        generateStatements(info.condition);
-      }
-      generateStatements(info.body);
-      if (info.isDoWhile()) {
-        generateStatements(info.condition);
-      }
-      if (info.updates != null) {
-        generateStatements(info.updates);
-      }
-      endLoop(info.end);
-      return true;
-    }
-    return super.visitLoopInfo(info);
-  }
-
-  bool visitTryInfo(HTryBlockInformation info) => false;
-  bool visitSequenceInfo(HStatementSequenceInformation info) => false;
-
-  void visitTypeGuard(HTypeGuard node) {
-    // Do nothing. Type guards are only used in the optimized version.
-  }
-
-  void visitBailoutTarget(HBailoutTarget node) {
-    if (propagator.hasComplexBailoutTargets) {
-      js.Block nextBlock = new js.Block.empty();
-      js.Case clause = new js.Case(new js.LiteralNumber('${node.state}'),
-                                   nextBlock);
-      currentBailoutSwitch.cases.add(clause);
-      currentContainer = nextBlock;
-      pushExpressionAsStatement(new js.Assignment(generateStateUse(),
-                                                  new js.LiteralNumber('0')));
-    }
-    // Here we need to rearrange the inputs of the bailout target, so that they
-    // are output in the correct order, perhaps with interspersed nulls, to
-    // match the order in the bailout function, which is of course common to all
-    // the bailout points.
-    var newInputs = new List<HInstruction>(propagator.bailoutArity);
-    for (HInstruction input in node.inputs) {
-      int index = propagator.parameterNames[variableNames.getName(input)];
-      newInputs[index] = input;
-    }
-    // We record the count of unused arguments instead of just filling in the
-    // inputs list with dummy arguments because it is useful to be able easily
-    // to distinguish between a dummy argument (eg 0 or null) and a real
-    // argument that happens to have the same value.  The dummy arguments are
-    // not going to be accessed by the bailout function due to the control flow
-    // implied by the state argument, so we can put anything there, including
-    // just not emitting enough arguments and letting the JS engine insert
-    // undefined for the trailing arguments.
-    node.padding = new List<int>(node.inputs.length);
-    int j = 0;
-    int pendingUnusedArguments = 0;
-    for (int i = 0; i < newInputs.length; i++) {
-      HInstruction input = newInputs[i];
-      if (input == null) {
-        pendingUnusedArguments++;
-      } else {
-        node.padding[j] = pendingUnusedArguments;
-        pendingUnusedArguments = 0;
-        node.updateInput(j, input);
-        j++;
-      }
-    }
-    assert(j == node.inputs.length);
-  }
-
-  void startBailoutCase(List<HBailoutTarget> bailouts1,
-                        [List<HBailoutTarget> bailouts2 = const []]) {
-    if (!defaultClauseUsedInBailoutStack.last &&
-        bailouts1.length + bailouts2.length >= 2) {
-      currentContainer = new js.Block.empty();
-      currentBailoutSwitch.cases.add(new js.Default(currentContainer));
-      int len = defaultClauseUsedInBailoutStack.length;
-      defaultClauseUsedInBailoutStack[len - 1] = true;
-    } else {
-      _handleBailoutCase(bailouts1);
-      _handleBailoutCase(bailouts2);
-      currentContainer = currentBailoutSwitch.cases.last.body;
-    }
-  }
-
-  void _handleBailoutCase(List<HBailoutTarget> targets) {
-    for (int i = 0, len = targets.length; i < len; i++) {
-      js.LiteralNumber expr = new js.LiteralNumber('${targets[i].state}');
-      currentBailoutSwitch.cases.add(new js.Case(expr, new js.Block.empty()));
-    }
-  }
-
-  void startBailoutSwitch() {
-    defaultClauseUsedInBailoutStack.add(false);
-    oldBailoutSwitches.add(currentBailoutSwitch);
-    List<js.SwitchClause> cases = <js.SwitchClause>[];
-    js.Block firstBlock = new js.Block.empty();
-    cases.add(new js.Case(new js.LiteralNumber("0"), firstBlock));
-    currentBailoutSwitch = new js.Switch(generateStateUse(), cases);
-    pushStatement(currentBailoutSwitch);
-    oldContainerStack.add(currentContainer);
-    currentContainer = firstBlock;
-  }
-
-  js.Switch endBailoutSwitch() {
-    js.Switch result = currentBailoutSwitch;
-    currentBailoutSwitch = oldBailoutSwitches.removeLast();
-    defaultClauseUsedInBailoutStack.removeLast();
-    currentContainer = oldContainerStack.removeLast();
-    return result;
-  }
-
-  void beginLoop(HBasicBlock block) {
-    String loopLabel = pushLabel();
-    if (block.hasBailoutTargets()) {
-      startBailoutCase(block.bailoutTargets);
-    }
-    oldContainerStack.add(currentContainer);
-    currentContainer = new js.Block.empty();
-    if (block.hasBailoutTargets()) {
-      startBailoutSwitch();
-      HLoopInformation loopInformation = block.loopInformation;
-      if (loopInformation.target != null) {
-        breakAction[loopInformation.target] = (TargetElement target) {
-          pushStatement(new js.Break(loopLabel));
-        };
-      }
-    }
-  }
-
-  void endLoop(HBasicBlock block) {
-    String loopLabel = popLabel();
-
-    HBasicBlock header = block.isLoopHeader() ? block : block.parentLoopHeader;
-    HLoopInformation info = header.loopInformation;
-    if (header.hasBailoutTargets()) {
-      endBailoutSwitch();
-      if (info.target != null) breakAction.remove(info.target);
-    }
-
-    js.Statement body = unwrapStatement(currentContainer);
-    currentContainer = oldContainerStack.removeLast();
-
-    js.Statement result = new js.While(newLiteralBool(true), body);
-    attachLocationRange(result,
-                        info.loopBlockInformation.sourcePosition,
-                        info.loopBlockInformation.endSourcePosition);
-    result = new js.LabeledStatement(loopLabel, result);
-    result = wrapIntoLabels(result, info.labels);
-    pushStatement(result);
-  }
-
-  void handleLoopCondition(HLoopBranch node) {
-    use(node.inputs[0]);
-    js.Expression test = new js.Prefix('!', pop());
-    js.Statement then = new js.Break(currentLabel());
-    pushStatement(new js.If.noElse(test, then), node);
-  }
-
-  void generateIf(HIf node, HIfBlockInformation info) {
-    HStatementInformation thenGraph = info.thenGraph;
-    HStatementInformation elseGraph = info.elseGraph;
-    bool thenHasGuards = thenGraph.start.hasBailoutTargets();
-    bool elseHasGuards = elseGraph.start.hasBailoutTargets();
-    bool hasGuards = thenHasGuards || elseHasGuards;
-    if (!hasGuards) {
-      super.generateIf(node, info);
-      return;
-    }
-
-    startBailoutCase(thenGraph.start.bailoutTargets,
-                     elseGraph.start.bailoutTargets);
-
-    use(node.inputs[0]);
-    js.Binary stateEquals0 =
-        new js.Binary('===', generateStateUse(), new js.LiteralNumber('0'));
-    js.Expression condition = new js.Binary('&&', stateEquals0, pop());
-    // TODO(ngeoffray): Put the condition initialization in the
-    // arguments?
-    List<HBailoutTarget> targets = node.thenBlock.bailoutTargets;
-    for (int i = 0, len = targets.length; i < len; i++) {
-      js.VariableUse stateRef = generateStateUse();
-      js.Expression targetState = new js.LiteralNumber('${targets[i].state}');
-      js.Binary stateTest = new js.Binary('===', stateRef, targetState);
-      condition = new js.Binary('||', stateTest, condition);
-    }
-
-    js.Statement thenBody = new js.Block.empty();
-    js.Block oldContainer = currentContainer;
-    currentContainer = thenBody;
-    if (thenHasGuards) startBailoutSwitch();
-    generateStatements(thenGraph);
-    if (thenHasGuards) endBailoutSwitch();
-    thenBody = unwrapStatement(thenBody);
-
-    js.Statement elseBody = null;
-    elseBody = new js.Block.empty();
-    currentContainer = elseBody;
-    if (elseHasGuards) startBailoutSwitch();
-    generateStatements(elseGraph);
-    if (elseHasGuards) endBailoutSwitch();
-    elseBody = unwrapStatement(elseBody);
-
-    currentContainer = oldContainer;
-    pushStatement(new js.If(condition, thenBody, elseBody), node);
-  }
-
-  void preLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
-    if (labeledBlockInfo.body.start.hasBailoutTargets()) {
-      indent--;
-      startBailoutCase(labeledBlockInfo.body.start.bailoutTargets);
-      indent++;
-    }
-  }
-
-  void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
-    if (labeledBlockInfo.body.start.hasBailoutTargets()) {
-      startBailoutSwitch();
-    }
-  }
-
-  void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
-    if (labeledBlockInfo.body.start.hasBailoutTargets()) {
-      endBailoutSwitch();
-    }
-  }
-}
-
 String singleIdentityComparison(HInstruction left,
                                 HInstruction right,
                                 Compiler compiler) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
index 1a0ca9a..a476a1e 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
@@ -95,10 +95,6 @@
     analyzeInputs(instruction, 1);
   }
 
-  // A type guard should not generate its input at use site, otherwise
-  // they would not be alive.
-  void visitTypeGuard(HTypeGuard instruction) {}
-
   // An identity operation must only have its inputs generated at use site if
   // does not require an expression with multiple uses (because of null /
   // undefined).
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
index d80e5a8..ae9f7e3 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
@@ -230,13 +230,6 @@
       return false;
     }
 
-    if (node.usedBy.every((e) => e is HBailoutTarget || e is HTypeGuard)) {
-      // The interceptor is only used by the bailout version. We don't
-      // remove it because the bailout version will use it.
-      node.interceptedClasses = backend.interceptedClasses;
-      return false;
-    }
-
     node.interceptedClasses = interceptedClasses;
 
     // Try creating a one-shot interceptor.
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 a9da46b..67768a8 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
@@ -13,12 +13,6 @@
 class InvokeDynamicSpecializer {
   const InvokeDynamicSpecializer();
 
-  HType computeDesiredTypeForInput(HInvokeDynamic instruction,
-                                   HInstruction input,
-                                   Compiler compiler) {
-    return HType.UNKNOWN;
-  }
-
   HType computeTypeFromInputTypes(HInvokeDynamic instruction,
                                   Compiler compiler) {
     HType receiverType = instruction.getDartReceiver(compiler).instructionType;
@@ -93,22 +87,6 @@
 class IndexAssignSpecializer extends InvokeDynamicSpecializer {
   const IndexAssignSpecializer();
 
-  HType computeDesiredTypeForInput(HInvokeDynamic instruction,
-                                   HInstruction input,
-                                   Compiler compiler) {
-    HInstruction index = instruction.inputs[2];
-    if (input == instruction.inputs[1] &&
-        index.instructionType.canBePrimitiveNumber(compiler)) {
-      JavaScriptBackend backend = compiler.backend;
-      return backend.mutableArrayType;
-    }
-    // The index should be an int when the receiver is a string or array.
-    // However it turns out that inserting an integer check in the optimized
-    // version is cheaper than having another bailout case. This is true,
-    // because the integer check will simply throw if it fails.
-    return HType.UNKNOWN;
-  }
-
   HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
                                    Compiler compiler) {
     if (instruction.inputs[1].isMutableIndexable(compiler)) {
@@ -128,22 +106,6 @@
 class IndexSpecializer extends InvokeDynamicSpecializer {
   const IndexSpecializer();
 
-  HType computeDesiredTypeForInput(HInvokeDynamic instruction,
-                                   HInstruction input,
-                                   Compiler compiler) {
-    HInstruction index = instruction.inputs[2];
-    if (input == instruction.inputs[1] &&
-        index.instructionType.canBePrimitiveNumber(compiler)) {
-      JavaScriptBackend backend = compiler.backend;
-      return backend.indexablePrimitiveType;
-    }
-    // The index should be an int when the receiver is a string or array.
-    // However it turns out that inserting an integer check in the optimized
-    // version is cheaper than having another bailout case. This is true,
-    // because the integer check will simply throw if it fails.
-    return HType.UNKNOWN;
-  }
-
   HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
                                    Compiler compiler) {
     if (!instruction.inputs[1].isIndexable(compiler)) return null;
@@ -168,18 +130,6 @@
     return constantSystem.bitNot;
   }
 
-  HType computeDesiredTypeForInput(HInvokeDynamic instruction,
-                                   HInstruction input,
-                                   Compiler compiler) {
-    if (input == instruction.inputs[1]) {
-      HType propagatedType = instruction.instructionType;
-      if (propagatedType.canBePrimitiveNumber(compiler)) {
-        return HType.INTEGER;
-      }
-    }
-    return HType.UNKNOWN;
-  }
-
   HType computeTypeFromInputTypes(HInvokeDynamic instruction,
                                   Compiler compiler) {
     // All bitwise operations on primitive types either produce an
@@ -203,20 +153,6 @@
     return constantSystem.negate;
   }
 
-  HType computeDesiredTypeForInput(HInvokeDynamic instruction,
-                                   HInstruction input,
-                                   Compiler compiler) {
-    if (input == instruction.inputs[1]) {
-      HType propagatedType = instruction.instructionType;
-      // If the outgoing type should be a number (integer, double or both) we
-      // want the outgoing type to be the input too.
-      // If we don't know the outgoing type we try to make it a number.
-      if (propagatedType.isNumber()) return propagatedType;
-      if (propagatedType.canBePrimitiveNumber(compiler)) return HType.NUMBER;
-    }
-    return HType.UNKNOWN;
-  }
-
   HType computeTypeFromInputTypes(HInvokeDynamic instruction,
                                   Compiler compiler) {
     HType operandType = instruction.inputs[1].instructionType;
@@ -247,34 +183,6 @@
     return super.computeTypeFromInputTypes(instruction, compiler);
   }
 
-  HType computeDesiredTypeForInput(HInvokeDynamic instruction,
-                                   HInstruction input,
-                                   Compiler compiler) {
-    if (input == instruction.inputs[0]) return HType.UNKNOWN;
-
-    HType propagatedType = instruction.instructionType;
-    // If the desired output type should be an integer we want to get two
-    // integers as arguments.
-    if (propagatedType.isInteger()) return HType.INTEGER;
-    // If the outgoing type should be a number we can get that if both inputs
-    // are numbers. If we don't know the outgoing type we try to make it a
-    // number.
-    if (propagatedType.canBePrimitiveNumber(compiler)) {
-      return HType.NUMBER;
-    }
-    // Even if the desired outgoing type is not a number we still want the
-    // second argument to be a number if the first one is a number. This will
-    // not help for the outgoing type, but at least the binary arithmetic
-    // operation will not have type problems.
-    // TODO(floitsch): normally we shouldn't request a number, but simply
-    // throw an ArgumentError if it isn't. This would be similar
-    // to the array case.
-    HInstruction left = instruction.inputs[1];
-    HInstruction right = instruction.inputs[2];
-    if (input == right && left.isNumber()) return HType.NUMBER;
-    return HType.UNKNOWN;
-  }
-
   bool isBuiltin(HInvokeDynamic instruction) {
     return instruction.inputs[1].isNumber()
         && instruction.inputs[2].isNumber();
@@ -325,16 +233,6 @@
     return super.computeTypeFromInputTypes(instruction, compiler);
   }
 
-  HType computeDesiredTypeForInput(HInstruction instruction,
-                                   HInstruction input,
-                                   Compiler compiler) {
-    if (input == instruction.inputs[0]) return HType.UNKNOWN;
-    // A division can never return an integer. So don't ask for integer inputs.
-    if (instruction.isInteger()) return HType.UNKNOWN;
-    return super.computeDesiredTypeForInput(
-        instruction, input, compiler);
-  }
-
   HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
     return new HDivide(
         instruction.inputs[1], instruction.inputs[2], instruction.selector);
@@ -404,20 +302,6 @@
     if (left.isPrimitiveOrNull(compiler)) return HType.INTEGER;
     return super.computeTypeFromInputTypes(instruction, compiler);
   }
-
-  HType computeDesiredTypeForInput(HInvokeDynamic instruction,
-                                   HInstruction input,
-                                   Compiler compiler) {
-    if (input == instruction.inputs[0]) return HType.UNKNOWN;
-    // We match the implementation of bit operations on the
-    // [:JSNumber:] class by requesting a number if the receiver can
-    // be a number.
-    HInstruction left = instruction.inputs[1];
-    if (left.instructionType.canBePrimitiveNumber(compiler)) {
-      return HType.NUMBER;
-    }
-    return HType.UNKNOWN;
-  }
 }
 
 class ShiftLeftSpecializer extends BinaryBitOpSpecializer {
@@ -515,23 +399,6 @@
     return super.computeTypeFromInputTypes(instruction, compiler);
   }
 
-  HType computeDesiredTypeForInput(HInvokeDynamic instruction,
-                                   HInstruction input,
-                                   Compiler compiler) {
-    if (input == instruction.inputs[0]) return HType.UNKNOWN;
-    HType propagatedType = instruction.instructionType;
-    // For all relational operations except HIdentity, we expect to get numbers
-    // only. With numbers the outgoing type is a boolean. If something else
-    // is desired, then numbers are incorrect, though.
-    if (propagatedType.canBePrimitiveBoolean(compiler)) {
-      HInstruction left = instruction.inputs[1];
-      if (left.instructionType.canBePrimitiveNumber(compiler)) {
-        return HType.NUMBER;
-      }
-    }
-    return HType.UNKNOWN;
-  }
-
   HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
                                    Compiler compiler) {
     HInstruction left = instruction.inputs[1];
@@ -548,33 +415,6 @@
 class EqualsSpecializer extends RelationalSpecializer {
   const EqualsSpecializer();
 
-  HType computeDesiredTypeForInput(HInvokeDynamic instruction,
-                                   HInstruction input,
-                                   Compiler compiler) {
-    HInstruction left = instruction.inputs[1];
-    HInstruction right = instruction.inputs[2];
-    if (input == left && right.instructionType.isUseful()) {
-      // All our useful types have 'identical' semantics. But we don't want to
-      // speculatively test for all possible types. Therefore we try to match
-      // the two types. That is, if we see x == 3, then we speculatively test
-      // if x is a number and bailout if it isn't.
-      // If right is a number we don't need more than a number (no need to match
-      // the exact type of right).
-      if (right.isNumber()) return HType.NUMBER;
-      return right.instructionType;
-    }
-    // String equality testing is much more common than array equality testing.
-    JavaScriptBackend backend = compiler.backend;
-    if (input == left && left.isIndexablePrimitive(compiler)) {
-      return backend.readableArrayType;
-    }
-    // String equality testing is much more common than array equality testing.
-    if (input == right && right.isIndexablePrimitive(compiler)) {
-      return backend.stringType;
-    }
-    return HType.UNKNOWN;
-  }
-
   HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
                                    Compiler compiler) {
     HInstruction left = instruction.inputs[1];
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index e05bc81..7b76168 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -6,7 +6,6 @@
 
 abstract class HVisitor<R> {
   R visitAdd(HAdd node);
-  R visitBailoutTarget(HBailoutTarget node);
   R visitBitAnd(HBitAnd node);
   R visitBitNot(HBitNot node);
   R visitBitOr(HBitOr node);
@@ -66,7 +65,6 @@
   R visitThrow(HThrow node);
   R visitThrowExpression(HThrowExpression node);
   R visitTry(HTry node);
-  R visitTypeGuard(HTypeGuard node);
   R visitTypeConversion(HTypeConversion node);
   R visitTypeKnown(HTypeKnown node);
 }
@@ -279,7 +277,6 @@
   visitRelational(HRelational node) => visitInvokeBinary(node);
 
   visitAdd(HAdd node) => visitBinaryArithmetic(node);
-  visitBailoutTarget(HBailoutTarget node) => visitInstruction(node);
   visitBitAnd(HBitAnd node) => visitBinaryBitOp(node);
   visitBitNot(HBitNot node) => visitInvokeUnary(node);
   visitBitOr(HBitOr node) => visitBinaryBitOp(node);
@@ -346,7 +343,6 @@
   visitThrow(HThrow node) => visitControlFlow(node);
   visitThrowExpression(HThrowExpression node) => visitInstruction(node);
   visitTry(HTry node) => visitControlFlow(node);
-  visitTypeGuard(HTypeGuard node) => visitCheck(node);
   visitIs(HIs node) => visitInstruction(node);
   visitTypeConversion(HTypeConversion node) => visitCheck(node);
   visitTypeKnown(HTypeKnown node) => visitCheck(node);
@@ -467,7 +463,6 @@
   HLoopInformation loopInformation = null;
   HBlockFlow blockFlow = null;
   HBasicBlock parentLoopHeader = null;
-  List<HBailoutTarget> bailoutTargets;
   bool isLive = true;
 
   final List<HBasicBlock> predecessors;
@@ -481,8 +476,7 @@
       : phis = new HInstructionList(),
         predecessors = <HBasicBlock>[],
         successors = const <HBasicBlock>[],
-        dominatedBlocks = <HBasicBlock>[],
-        bailoutTargets = <HBailoutTarget>[];
+        dominatedBlocks = <HBasicBlock>[];
 
   int get hashCode => id;
 
@@ -507,8 +501,6 @@
     return parentLoopHeader;
   }
 
-  bool hasBailoutTargets() => !bailoutTargets.isEmpty;
-
   void open() {
     assert(isNew());
     status = STATUS_OPEN;
@@ -803,11 +795,10 @@
   static const int FIELD_GET_TYPECODE = 23;
   static const int TYPE_CONVERSION_TYPECODE = 24;
   static const int TYPE_KNOWN_TYPECODE = 25;
-  static const int BAILOUT_TARGET_TYPECODE = 26;
-  static const int INVOKE_STATIC_TYPECODE = 27;
-  static const int INDEX_TYPECODE = 28;
-  static const int IS_TYPECODE = 29;
-  static const int INVOKE_DYNAMIC_TYPECODE = 30;
+  static const int INVOKE_STATIC_TYPECODE = 26;
+  static const int INDEX_TYPECODE = 27;
+  static const int IS_TYPECODE = 28;
+  static const int INVOKE_DYNAMIC_TYPECODE = 29;
 
   HInstruction(this.inputs) : id = idCounter++, usedBy = <HInstruction>[] {
     assert(inputs.every((e) => e != null));
@@ -1099,11 +1090,6 @@
     return validator.isValid;
   }
 
-  /**
-   * The code for computing a bailout environment, and the code
-   * generation must agree on what does not need to be captured,
-   * so should always be generated at use site.
-   */
   bool isCodeMotionInvariant() => false;
 
   bool isJsStatement() => false;
@@ -1185,68 +1171,6 @@
   HInstruction nonCheck() => checkedInput.nonCheck();
 }
 
-class HBailoutTarget extends HInstruction {
-  final int state;
-  bool isEnabled = true;
-  // For each argument we record how many dummy (unused) arguments should
-  // precede it, to make sure it lands in the correctly named parameter in the
-  // bailout function.
-  List<int> padding;
-  HBailoutTarget(this.state) : super(<HInstruction>[]) {
-    setUseGvn();
-  }
-
-  void disable() {
-    isEnabled = false;
-  }
-
-  bool isControlFlow() => isEnabled;
-  bool isJsStatement() => isEnabled;
-
-  accept(HVisitor visitor) => visitor.visitBailoutTarget(this);
-  int typeCode() => HInstruction.BAILOUT_TARGET_TYPECODE;
-  bool typeEquals(other) => other is HBailoutTarget;
-  bool dataEquals(HBailoutTarget other) => other.state == state;
-}
-
-class HTypeGuard extends HCheck {
-  HType guardedType;
-  bool isEnabled = false;
-
-  HTypeGuard(this.guardedType, HInstruction guarded, HInstruction bailoutTarget)
-      : super(<HInstruction>[guarded, bailoutTarget]);
-
-  HInstruction get guarded => inputs[0];
-  HInstruction get checkedInput => guarded;
-  HBailoutTarget get bailoutTarget => inputs[1];
-  int get state => bailoutTarget.state;
-
-  void enable() {
-    isEnabled = true;
-    instructionType = guardedType;
-  }
-
-  void disable() {
-    isEnabled = false;
-    instructionType = guarded.instructionType;
-  }
-
-  bool isControlFlow() => true;
-  bool isJsStatement() => isEnabled;
-  bool canThrow() => isEnabled;
-
-  // A [HTypeGuard] cannot be moved anywhere in the graph, otherwise
-  // instructions that have side effects could end up before the guard
-  // in the optimized version, and after the guard in a bailout
-  // version.
-  bool isPure() => false;
-
-  accept(HVisitor visitor) => visitor.visitTypeGuard(this);
-  int typeCode() => HInstruction.TYPE_GUARD_TYPECODE;
-  bool typeEquals(other) => other is HTypeGuard;
-  bool dataEquals(HTypeGuard other) => guardedType == other.guardedType;
-}
-
 class HBoundsCheck extends HCheck {
   static const int ALWAYS_FALSE = 0;
   static const int FULL_CHECK = 1;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index ccbd6a52..3424ca0 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -29,7 +29,7 @@
     assert(graph.isValid());
   }
 
-  void optimize(CodegenWorkItem work, HGraph graph, bool speculative) {
+  void optimize(CodegenWorkItem work, HGraph graph) {
     ConstantSystem constantSystem = compiler.backend.constantSystem;
     JavaScriptItemCompilationContext context = work.compilationContext;
     measure(() {
@@ -39,7 +39,7 @@
           // some patterns useful for type conversion.
           new SsaInstructionSimplifier(constantSystem, backend, work),
           new SsaTypeConversionInserter(compiler),
-          new SsaNonSpeculativeTypePropagator(compiler),
+          new SsaTypePropagator(compiler),
           // After type propagation, more instructions can be
           // simplified.
           new SsaInstructionSimplifier(constantSystem, backend, work),
@@ -47,7 +47,8 @@
           new SsaRedundantPhiEliminator(),
           new SsaDeadPhiEliminator(),
           new SsaInstructionSimplifier(constantSystem, backend, work),
-          new SsaNonSpeculativeTypePropagator(compiler),
+          new SsaCheckInserter(backend, work, context.boundsChecked),
+          new SsaTypePropagator(compiler),
           // Run a dead code eliminator before LICM because dead
           // interceptors are often in the way of LICM'able instructions.
           new SsaDeadCodeEliminator(compiler),
@@ -57,6 +58,7 @@
           // Previous optimizations may have generated new
           // opportunities for instruction simplification.
           new SsaInstructionSimplifier(constantSystem, backend, work),
+          new SsaCheckInserter(backend, work, context.boundsChecked),
           new SsaSimplifyInterceptors(compiler, constantSystem, work),
           dce = new SsaDeadCodeEliminator(compiler)];
       runPhases(graph, phases);
@@ -66,63 +68,12 @@
           new SsaCodeMotion(),
           new SsaValueRangeAnalyzer(compiler, constantSystem, work),
           new SsaInstructionSimplifier(constantSystem, backend, work),
+          new SsaCheckInserter(backend, work, context.boundsChecked),
           new SsaSimplifyInterceptors(compiler, constantSystem, work),
           new SsaDeadCodeEliminator(compiler)];
       runPhases(graph, phases);
     });
   }
-
-  bool trySpeculativeOptimizations(CodegenWorkItem work, HGraph graph) {
-    if (work.element.isField()) {
-      // Lazy initializers may not have bailout methods.
-      return false;
-    }
-    JavaScriptItemCompilationContext context = work.compilationContext;
-    ConstantSystem constantSystem = compiler.backend.constantSystem;
-    return measure(() {
-      SsaTypeGuardInserter inserter = new SsaTypeGuardInserter(compiler, work);
-
-      // Run the phases that will generate type guards.
-      List<OptimizationPhase> phases = <OptimizationPhase>[
-          inserter,
-          new SsaEnvironmentBuilder(compiler),
-          // Then run the [SsaCheckInserter] because the type propagator also
-          // propagated types non-speculatively. For example, it might have
-          // propagated the type array for a call to the List constructor.
-          new SsaCheckInserter(backend, work, context.boundsChecked)];
-      runPhases(graph, phases);
-
-      if (work.guards.isEmpty && inserter.hasInsertedChecks) {
-        // If there is no guard, and we have inserted type checks
-        // instead, we can do the optimizations right away and avoid
-        // the bailout method.
-        optimize(work, graph, false);
-      }
-      return !work.guards.isEmpty;
-    });
-  }
-
-  void prepareForSpeculativeOptimizations(CodegenWorkItem work, HGraph graph) {
-    JavaScriptItemCompilationContext context = work.compilationContext;
-    measure(() {
-      // In order to generate correct code for the bailout version, we did not
-      // propagate types from the instruction to the type guard. We do it
-      // now to be able to optimize further.
-      work.guards.forEach((HTypeGuard guard) {
-        guard.bailoutTarget.disable();
-        guard.enable();
-      });
-      // We also need to insert range and integer checks for the type
-      // guards. Now that they claim to have a certain type, some
-      // depending instructions might become builtin (like native array
-      // accesses) and need to be checked.
-      // Also run the type propagator, to please the codegen in case
-      // no other optimization is run.
-      runPhases(graph, <OptimizationPhase>[
-          new SsaCheckInserter(backend, work, context.boundsChecked),
-          new SsaNonSpeculativeTypePropagator(compiler)]);
-    });
-  }
 }
 
 /**
@@ -532,16 +483,6 @@
     return newInstruction == null ? super.visitIdentity(node) : newInstruction;
   }
 
-  HInstruction visitTypeGuard(HTypeGuard node) {
-    HInstruction value = node.guarded;
-    // If the intersection of the types is still the incoming type then
-    // the incoming type was a subtype of the guarded type, and no check
-    // is required.
-    HType combinedType =
-        value.instructionType.intersection(node.guardedType, compiler);
-    return (combinedType == value.instructionType) ? value : node;
-  }
-
   void simplifyCondition(HBasicBlock block,
                          HInstruction condition,
                          bool value) {
@@ -987,7 +928,6 @@
       return true;
     }
     return !instruction.canThrow()
-           && instruction is !HTypeGuard
            && instruction is !HParameterValue
            && instruction is !HLocalSet;
   }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/ssa.dart b/sdk/lib/_internal/compiler/implementation/ssa/ssa.dart
index 95b020f..5b0cc17 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/ssa.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/ssa.dart
@@ -29,7 +29,6 @@
 
 import '../js_emitter/js_emitter.dart' show CodeEmitterTask;
 
-part 'bailout.dart';
 part 'builder.dart';
 part 'codegen.dart';
 part 'codegen_helpers.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
index eab3ed8..7b1a34c 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
@@ -211,16 +211,6 @@
     return "$prefix${instruction.id}";
   }
 
-  String visitBailoutTarget(HBailoutTarget node) {
-    StringBuffer envBuffer = new StringBuffer();
-    List<HInstruction> inputs = node.inputs;
-    for (int i = 0; i < inputs.length; i++) {
-      envBuffer.write(" ${temporaryId(inputs[i])}");
-    }
-    String on = node.isEnabled ? "enabled" : "disabled";
-    return "BailoutTarget($on): id: ${node.state} env: $envBuffer";
-  }
-
   String visitBoolify(HBoolify node) {
     return "Boolify: ${temporaryId(node.inputs[0])}";
   }
@@ -506,49 +496,6 @@
         "Join: B${successors.last.id}";
   }
 
-  String visitTypeGuard(HTypeGuard node) {
-    String type;
-    HType guardedType = node.guardedType;
-    if (guardedType.isExtendableArray(compiler)) {
-      type = "extendable_array";
-    } else if (guardedType.isMutableArray(compiler)) {
-      type = "mutable_array";
-    } else if (guardedType.isReadableArray(compiler)) {
-      type = "readable_array";
-    } else if (guardedType == HType.BOOLEAN) {
-      type = "bool";
-    } else if (guardedType == HType.INTEGER) {
-      type = "integer";
-    } else if (guardedType == HType.DOUBLE) {
-      type = "double";
-    } else if (guardedType == HType.NUMBER) {
-      type = "number";
-    } else if (guardedType.isString(compiler)) {
-      type = "string";
-    } else if (guardedType.isIndexable(compiler)) {
-      type = "string_or_array";
-    } else if (guardedType == HType.UNKNOWN) {
-      type = 'unknown';
-    } else {
-      throw new CompilerCancelledException('Unexpected type guard: $type');
-    }
-    HInstruction guarded = node.guarded;
-    HInstruction bailoutTarget = node.bailoutTarget;
-    StringBuffer envBuffer = new StringBuffer();
-    List<HInstruction> inputs = node.inputs;
-    assert(inputs.length >= 2);
-    assert(inputs[0] == guarded);
-    assert(inputs[1] == bailoutTarget);
-    for (int i = 2; i < inputs.length; i++) {
-      envBuffer.write(" ${temporaryId(inputs[i])}");
-    }
-    String on = node.isEnabled ? "enabled" : "disabled";
-    String guardedId = temporaryId(node.guarded);
-    String bailoutId = temporaryId(node.bailoutTarget);
-    return "TypeGuard($on): $guardedId is $type bailout: $bailoutId "
-           "env: $envBuffer";
-  }
-
   String visitIs(HIs node) {
     String type = node.typeExpression.toString();
     return "TypeTest: ${temporaryId(node.expression)} is $type";
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
index d861e34..e3a107b 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
@@ -4,9 +4,7 @@
 
 part of ssa;
 
-abstract class SsaTypePropagator extends HBaseVisitor
-    implements OptimizationPhase {
-
+class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
   final Map<int, HInstruction> workmap = new Map<int, HInstruction>();
   final List<int> worklist = new List<int>();
   final Map<HInstruction, Function> pendingOptimizations =
@@ -109,8 +107,6 @@
   }
 
 
-  void addDependentInstructionsToWorkList(HInstruction instruction) {}
-
   void addToWorkList(HInstruction instruction) {
     final int id = instruction.id;
 
@@ -120,11 +116,6 @@
     }
   }
 
-  HType visitInvokeDynamic(HInvokeDynamic instruction) {
-    return instruction.specializer.computeTypeFromInputTypes(
-        instruction, compiler);
-  }
-
   HType visitBinaryArithmetic(HBinaryArithmetic instruction) {
     HInstruction left = instruction.left;
     HInstruction right = instruction.right;
@@ -241,15 +232,6 @@
     HInstruction left = instruction.inputs[1];
     HType receiverType = left.instructionType;
 
-    // A [HTypeGuard] holds the speculated type when it is being
-    // inserted, so we go find the real receiver type.
-    if (left is HTypeGuard) {
-      var guard = left;
-      while (guard is HTypeGuard && !guard.isEnabled) {
-        guard = guard.checkedInput;
-      }
-      receiverType = guard.instructionType;
-    }
     HInstruction right = instruction.inputs[2];
     Selector selector = instruction.selector;
     if (selector.isOperator() && receiverType.isNumber()) {
@@ -272,16 +254,10 @@
     pendingOptimizations.forEach((instruction, action) => action());
     pendingOptimizations.clear();
   }
-}
-
-class SsaNonSpeculativeTypePropagator extends SsaTypePropagator {
-  final String name = 'non speculative type propagator';
-  DesiredTypeVisitor desiredTypeVisitor;
-  SsaNonSpeculativeTypePropagator(Compiler compiler) : super(compiler);
 
   void addDependentInstructionsToWorkList(HInstruction instruction) {
     for (int i = 0, length = instruction.usedBy.length; i < length; i++) {
-      // The non-speculative type propagator only propagates types forward. We
+      // The type propagator only propagates types forward. We
       // thus only need to add the users of the [instruction] to the list.
       addToWorkList(instruction.usedBy[i]);
     }
@@ -311,179 +287,7 @@
         }
       });
     }
-    return super.visitInvokeDynamic(instruction);
-  }
-}
-
-/**
- * Visitor whose methods return the desired type for the input of an
- * instruction.
- */
-class DesiredTypeVisitor extends HBaseVisitor {
-  final Compiler compiler;
-  final SsaTypePropagator propagator;
-  HInstruction input;
-
-  DesiredTypeVisitor(this.compiler, this.propagator);
-
-  HType visitInstruction(HInstruction instruction) {
-    return HType.UNKNOWN;
-  }
-
-  HType visitCheck(HCheck check) {
-    // If the desired type of the input is already a number, we want
-    // to specialize it to an integer.
-    if (input == check.checkedInput
-        && check.isInteger()
-        && check.checkedInput.isNumberOrNull()) {
-      return HType.INTEGER;
-    }
-    return HType.UNKNOWN;
-  }
-
-  HType visitTypeConversion(HTypeConversion check) {
-    return HType.UNKNOWN;
-  }
-
-  HType visitTypeKnown(HTypeKnown check) {
-    return HType.UNKNOWN;
-  }
-
-  HType visitInvokeDynamic(HInvokeDynamic instruction) {
-    return instruction.specializer.computeDesiredTypeForInput(
-        instruction, input, compiler);
-  }
-
-  HType visitPhi(HPhi phi) {
-    // Best case scenario for a phi is, when all inputs have the same type. If
-    // there is no desired outgoing type we therefore try to unify the input
-    // types (which is basically the [likelyType]).
-    HType propagatedType = phi.instructionType;
-
-    // If the incoming type of a phi is an integer, we don't want to
-    // be too restrictive for the back edge and desire an integer
-    // too. Therefore we only return integer if the phi is used by a
-    // bounds check, which includes an integer check.
-    if (propagatedType.isInteger()) {
-      if (phi.usedBy.any((user) => user is HBoundsCheck && user.index == phi)) {
-        return propagatedType;
-      }
-      return HType.NUMBER;
-    }
-    if (propagatedType.isUnknown()) return computeLikelyType(phi);
-    // When the desired outgoing type is conflicting we don't need to give any
-    // requirements on the inputs.
-    if (propagatedType.isConflicting()) return HType.UNKNOWN;
-    // Otherwise the input type must match the desired outgoing type.
-    return propagatedType;
-  }
-
-  HType computeLikelyType(HPhi phi) {
-    HType agreedType = propagator.computeInputsType(phi, true);
-    if (agreedType.isConflicting()) return HType.UNKNOWN;
-    // Don't be too restrictive. If the agreed type is integer or double just
-    // say that the likely type is number. If more is expected the type will be
-    // propagated back.
-    if (agreedType.isNumber()) return HType.NUMBER;
-    return agreedType;
-  }
-
-  HType visitInterceptor(HInterceptor instruction) {
-    if (instruction.interceptedClasses.length != 1) return HType.UNKNOWN;
-    // If the only class being intercepted is of type number, we
-    // make this interceptor call say it wants that class as input.
-    Element interceptor = instruction.interceptedClasses.toList()[0];
-    JavaScriptBackend backend = compiler.backend;
-    if (interceptor == backend.jsNumberClass) {
-      return HType.NUMBER;
-    } else if (interceptor == backend.jsIntClass) {
-      return HType.INTEGER;
-    } else if (interceptor == backend.jsDoubleClass) {
-      return HType.DOUBLE;
-    }
-    return HType.UNKNOWN;
-  }
-
-  HType computeDesiredTypeForInput(HInstruction user, HInstruction input) {
-    this.input = input;
-    // We simplify the desired type to avoid requesting the type of an
-    // instantiation node, for example [ContainerTypeMask].
-    HType desired = user.accept(this).simplify(compiler);
-    assert(!desired.computeMask(compiler).isContainer);
-    this.input = null;
-    return desired;
-  }
-}
-
-class SsaSpeculativeTypePropagator extends SsaTypePropagator {
-  final String name = 'speculative type propagator';
-  DesiredTypeVisitor desiredTypeVisitor;
-  final Map<HInstruction, HType> savedTypes;
-  SsaSpeculativeTypePropagator(Compiler compiler, this.savedTypes)
-      : super(compiler) {
-    desiredTypeVisitor = new DesiredTypeVisitor(compiler, this);
-  }
-
-  void addDependentInstructionsToWorkList(HInstruction instruction) {
-    // The speculative type propagator propagates types forward and backward.
-    // Not only do we need to add the users of the [instruction] to the list.
-    // We also need to add the inputs fo the [instruction], since they might
-    // want to propagate the desired outgoing type.
-    for (int i = 0, length = instruction.usedBy.length; i < length; i++) {
-      addToWorkList(instruction.usedBy[i]);
-    }
-    for (int i = 0, length = instruction.inputs.length; i < length; i++) {
-      addToWorkList(instruction.inputs[i]);
-    }
-  }
-
-  HType computeDesiredType(HInstruction instruction) {
-    HType desiredType = instruction.instructionType;
-    for (final user in instruction.usedBy) {
-      HType userDesiredType =  desiredTypeVisitor.computeDesiredTypeForInput(
-          user, instruction);
-      desiredType = desiredType.intersection(userDesiredType, compiler);
-      // No need to continue if two users disagree on the type.
-      if (desiredType.isConflicting()) break;
-    }
-    return desiredType;
-  }
-
-  bool hasBeenSpeculativelyOptimized(HInstruction instruction) {
-    return savedTypes.containsKey(instruction);
-  }
-
-  HType computeType(HInstruction instruction) {
-    // Once we are in a conflicting state don't update the type anymore.
-    HType oldType = instruction.instructionType;
-    if (oldType.isConflicting()) return oldType;
-
-    HType newType = super.computeType(instruction);
-    if (oldType != newType && !hasBeenSpeculativelyOptimized(instruction)) {
-      savedTypes[instruction] = oldType;
-    }
-    // [computeDesiredType] goes to all usedBys and lets them compute their
-    // desired type. By setting the [newType] here we give them more context to
-    // work with.
-    instruction.instructionType = newType;
-    HType desiredType = computeDesiredType(instruction);
-    // If the desired type is conflicting just return the computed type.
-    if (desiredType.isConflicting()) return newType;
-    if (desiredType.isUnknown() && hasBeenSpeculativelyOptimized(instruction)) {
-      // If we ever change our decision for a desired type to unknown,
-      // we stop the computation on this instruction.
-      return HType.CONFLICTING;
-    }
-    // TODO(ngeoffray): Allow speculative optimizations on
-    // non-primitive types?
-    if (!desiredType.isPrimitive(compiler)) return newType;
-    // It's not worth having a bailout method just because we want a
-    // boolean. Comparing to true is enough.
-    if (desiredType.isBooleanOrNull()) return newType;
-    desiredType = newType.intersection(desiredType, compiler);
-    if (desiredType != newType && !hasBeenSpeculativelyOptimized(instruction)) {
-      savedTypes[instruction] = oldType;
-    }
-    return desiredType;
+    return instruction.specializer.computeTypeFromInputTypes(
+        instruction, compiler);
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart b/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart
index ec2cede..6d1ef73 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart
@@ -415,11 +415,6 @@
    * anywhere by reserving it when we allocate names for instructions.
    */
   final String swapTemp;
-  /**
-   * Name that is used in bailout code. We make sure this name is not being used
-   * anywhere by reserving it when we allocate names for instructions.
-   */
-  final String stateName;
 
   String getSwapTemp() {
     allUsedNames.add(swapTemp);
@@ -430,8 +425,7 @@
     : ownName = new Map<HInstruction, String>(),
       copyHandlers = new Map<HBasicBlock, CopyHandler>(),
       allUsedNames = new Set<String>(),
-      swapTemp = computeFreshWithPrefix("t"),
-      stateName = computeFreshWithPrefix("state");
+      swapTemp = computeFreshWithPrefix("t");
 
   int get numberOfVariables => allUsedNames.length;
 
@@ -488,12 +482,6 @@
     // [VariableNames.swapTemp] is used when there is a cycle in a copy handler.
     // Therefore we make sure no one uses it.
     usedNames.add(names.swapTemp);
-    // [VariableNames.stateName] is being used throughout a bailout function.
-    // Whenever a bailout-target is reached we set the state-variable to 0. We
-    // must therefore not have any local variable that could clash with the
-    // state variable.
-    // Therefore we make sure no one uses it at any time.
-    usedNames.add(names.stateName);
 
     // All liveIns instructions must have a name at this point, so we
     // add them to the list of used names.
diff --git a/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
index 79281c0..f65de47 100644
--- a/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
@@ -4,24 +4,11 @@
 
 part of types;
 
-/// A holder for an element type. We define a special class for it so
-/// that nullable ContainerTypeMask and non-nullable ContainerTypeMask
-/// share the same [ElementTypeHolder].
-class ElementTypeHolder {
-  // These fields will be set after global analysis.
-  TypeMask elementType;
-  int length;
-
-  int get hashCode => elementType.hashCode;
-}
-
 /// A [ContainerTypeMask] is a [TypeMask] for a specific allocation
 /// site of a container (currently only List) that will get specialized
-/// once the [ListTracer] phase finds an element type for it.
+/// once the [TypeGraphInferrer] phase finds an element type for it.
 class ContainerTypeMask extends ForwardingTypeMask {
-  // The flat version of a [ContainerTypeMask] is the container type
-  // (for example List).
-  final FlatTypeMask forwardTo;
+  final TypeMask forwardTo;
 
   // The [Node] where this type mask was created.
   final Node allocationNode;
@@ -29,24 +16,17 @@
   // The [Element] where this type mask was created.
   final Element allocationElement;
 
-  // A holder for the element type. Shared between all
-  // [ContainerTypeMask] for the same node.
-  final ElementTypeHolder holder;
+  // The element type of this container.
+  final TypeMask elementType;
 
-  TypeMask get elementType => holder.elementType;
-  void set elementType(TypeMask mask) {
-    holder.elementType = mask;
-  }
-  int get length => holder.length;
-  void set length(int length) {
-    holder.length = length;
-  }
+  // The length of the container.
+  final int length;
 
   ContainerTypeMask(this.forwardTo,
                     this.allocationNode,
                     this.allocationElement,
-                    [holder])
-      : this.holder = (holder == null) ? new ElementTypeHolder() : holder;
+                    this.elementType,
+                    this.length);
 
   TypeMask nullable() {
     return isNullable
@@ -54,7 +34,8 @@
         : new ContainerTypeMask(forwardTo.nullable(),
                                 allocationNode,
                                 allocationElement,
-                                holder);
+                                elementType,
+                                length);
   }
 
   TypeMask nonNullable() {
@@ -62,7 +43,8 @@
         ? new ContainerTypeMask(forwardTo.nonNullable(),
                                 allocationNode,
                                 allocationElement,
-                                holder)
+                                elementType,
+                                length)
         : this;
   }
 
@@ -71,7 +53,9 @@
 
   bool equalsDisregardNull(other) {
     if (other is! ContainerTypeMask) return false;
-    return allocationNode == other.allocationNode;
+    return allocationNode == other.allocationNode
+        && elementType == other.elementType
+        && length == other.length;
   }
 
   TypeMask intersection(TypeMask other, Compiler compiler) {
@@ -82,13 +66,38 @@
         : nonNullable();
   }
 
+  TypeMask union(other, Compiler compiler) {
+    if (this == other) {
+      return this;
+    } else if (equalsDisregardNull(other)) {
+      return other.isNullable ? other : this;
+    } else if (other.isEmpty) {
+      return other.isNullable ? this.nullable() : this;
+    } else if (other.isContainer
+               && elementType != null
+               && other.elementType != null) {
+      TypeMask newElementType =
+          elementType.union(other.elementType, compiler);
+      int newLength = (length == other.length) ? length : null;
+      TypeMask newForwardTo = forwardTo.union(other.forwardTo, compiler);
+      return new ContainerTypeMask(
+          newForwardTo, null, null, newElementType, newLength);
+    } else {
+      return forwardTo.union(other, compiler);
+    }
+  }
+
   bool operator==(other) {
     if (other is! ContainerTypeMask) return false;
     return allocationNode == other.allocationNode
-        && isNullable == other.isNullable;
+        && isNullable == other.isNullable
+        && elementType == other.elementType
+        && length == other.length;
   }
 
-  int get hashCode => computeHashCode(allocationNode, isNullable);
+  int get hashCode {
+    return computeHashCode(allocationNode, isNullable, elementType, length);
+  }
 
   String toString() {
     return 'Container mask: $elementType';
diff --git a/sdk/lib/_internal/compiler/implementation/util/expensive_set.dart b/sdk/lib/_internal/compiler/implementation/util/expensive_set.dart
index 4fb3949..2daa9c9 100644
--- a/sdk/lib/_internal/compiler/implementation/util/expensive_set.dart
+++ b/sdk/lib/_internal/compiler/implementation/util/expensive_set.dart
@@ -33,10 +33,12 @@
     _sets[0].forEach(action);
   }
 
-  void add(E element) {
-    for (int i = 0; i < _sets.length; i++) {
+  bool add(E element) {
+    bool result = _sets[0].add(element);
+    for (int i = 1; i < _sets.length; i++) {
       _sets[i].add(element);
     }
+    return result;
   }
 
   void addAll(Iterable<E> objects) {
diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart
index 45803c19..fb33d49 100644
--- a/sdk/lib/_internal/compiler/implementation/warnings.dart
+++ b/sdk/lib/_internal/compiler/implementation/warnings.dart
@@ -527,7 +527,20 @@
           "within a static member."));
 
   static const MessageKind TYPE_VARIABLE_IN_CONSTANT = const MessageKind(
-      "Error: Cannot refer to type variable in constant.");
+      "Error: Constant expressions can't refer to type variables.",
+      howToFix: "Try removing the type variable or replacing it with a "
+                "concrete type.",
+      examples: const ["""
+class C<T> {
+  const C();
+
+  m(T t) => const C<T>();
+}
+
+void main() => new C().m(null);  
+"""
+]);
+
 
   static const MessageKind INVALID_TYPE_VARIABLE_BOUND = const MessageKind(
       "Warning: '#{typeArgument}' is not a subtype of bound '#{bound}' for "
diff --git a/sdk/lib/_internal/lib/interceptors.dart b/sdk/lib/_internal/lib/interceptors.dart
index 151fc3d..e87ce4f 100644
--- a/sdk/lib/_internal/lib/interceptors.dart
+++ b/sdk/lib/_internal/lib/interceptors.dart
@@ -16,6 +16,8 @@
                               checkString,
                               defineProperty,
                               getRuntimeType,
+                              initNativeDispatch,
+                              initNativeDispatchFlag,
                               regExpGetNative,
                               stringContainsUnchecked,
                               stringLastIndexOfUnchecked,
@@ -115,6 +117,13 @@
 getNativeInterceptor(object) {
   var record = getDispatchProperty(object);
 
+  if (record == null) {
+    if (initNativeDispatchFlag == null) {
+      initNativeDispatch();
+      record = getDispatchProperty(object);
+    }
+  }
+
   if (record != null) {
     var proto = dispatchRecordProto(record);
     if (false == proto) return dispatchRecordInterceptor(record);
@@ -142,7 +151,6 @@
   return getNativeInterceptor(object);
 }
 
-
 /**
  * If [JSInvocationMirror._invokeOn] is being used, this variable
  * contains a JavaScript array with the names of methods that are
@@ -168,7 +176,7 @@
 // TODO(sra): Mark this as initialized to a constant with unknown value.
 var mapTypeToInterceptor;
 
-int findIndexForWebComponentType(Type type) {
+int findIndexForNativeSubclassType(Type type) {
   JS_EFFECT((_){ mapTypeToInterceptor = _; });
   if (mapTypeToInterceptor == null) return null;
   List map = JS('JSFixedArray', '#', mapTypeToInterceptor);
@@ -181,7 +189,7 @@
 }
 
 findInterceptorConstructorForType(Type type) {
-  var index = findIndexForWebComponentType(type);
+  var index = findIndexForNativeSubclassType(type);
   if (index == null) return null;
   List map = JS('JSFixedArray', '#', mapTypeToInterceptor);
   return mapTypeToInterceptor[index + 1];
@@ -193,8 +201,8 @@
  *
  * The returned function takes one argument, the web component object.
  */
-findConstructorForWebComponentType(Type type, String name) {
-  var index = findIndexForWebComponentType(type);
+findConstructorForNativeSubclassType(Type type, String name) {
+  var index = findIndexForNativeSubclassType(type);
   if (index == null) return null;
   List map = JS('JSFixedArray', '#', mapTypeToInterceptor);
   var constructorMap = mapTypeToInterceptor[index + 2];
diff --git a/sdk/lib/_internal/lib/isolate_helper.dart b/sdk/lib/_internal/lib/isolate_helper.dart
index 8b0ad62..7d9e722 100644
--- a/sdk/lib/_internal/lib/isolate_helper.dart
+++ b/sdk/lib/_internal/lib/isolate_helper.dart
@@ -600,7 +600,7 @@
     // TODO(floitsch): support precompiled version of dart2js output.
     if (uri != null && uri.endsWith(".dart")) uri += ".js";
 
-    Completer<SendPort> completer = new Completer.sync<SendPort>();
+    Completer<SendPort> completer = new Completer<SendPort>.sync();
     ReceivePort port = new ReceivePort();
     port.receive((msg, SendPort replyPort) {
       port.close();
diff --git a/sdk/lib/_internal/lib/js_mirrors.dart b/sdk/lib/_internal/lib/js_mirrors.dart
index 1c4c70b..e5d73b0 100644
--- a/sdk/lib/_internal/lib/js_mirrors.dart
+++ b/sdk/lib/_internal/lib/js_mirrors.dart
@@ -826,54 +826,63 @@
    * brackets. Then, when get typeArguments is called the first time, the string
    * is parsed into the actual list of TypeMirrors, and the field is overridden
    * with this value.
+   *
+   * If an integer is encountered as a type argument, it represents the type
+   * variable at the corresponding entry in [emitter.globalMetadata].
    */
-  var _typeArgs;
+  var _typeArguments;
 
-  JsTypeBoundClassMirror(this._class, this._typeArgs);
+  JsTypeBoundClassMirror(this._class, this._typeArguments);
 
   List<TypeVariableMirror> get typeVariables => _class.typeVariables;
 
   List<TypeMirror> get typeArguments {
-    if (_typeArgs is! String) return _typeArgs;
+    if (_typeArguments is! String) return _typeArguments;
     List result = new List();
 
-    if (_typeArgs.indexOf('<') == -1) {
-      for (String s in _typeArgs.split(',')) {
-        result.add(reflectClassByMangledName(s.trim()));
+    addTypeArgument(String typeArgument) {
+      int parsedIndex = int.parse(typeArgument, onError: (_) => -1);
+      if (parsedIndex == -1) {
+        result.add(reflectClassByMangledName(typeArgument.trim()));
+      } else {
+        TypeVariable typeVariable = JS('', 'init.metadata[#]', parsedIndex);
+        TypeMirror owner = reflectClass(typeVariable.owner);
+        TypeVariableMirror typeMirror =
+            new JsTypeVariableMirror(typeVariable, owner);
+        result.add(typeMirror);
       }
+    }
+
+    if (_typeArguments.indexOf('<') == -1) {
+      _typeArguments.split(',').forEach((t) => addTypeArgument(t));
     } else {
       int level = 0;
-      StringBuffer currentTypeArg = new StringBuffer();
+      String currentTypeArgument = '';
 
-      addCurrentTypeArg() {
-        var classMirror = reflectClassByMangledName(currentTypeArg.toString());
-        result.add(classMirror);
-        currentTypeArg.clear();
-      }
-
-      for (int i = 0; i < _typeArgs.length; i++) {
-        var character = _typeArgs[i];
+      for (int i = 0; i < _typeArguments.length; i++) {
+        var character = _typeArguments[i];
         if (character == ' ') {
           continue;
         } else if (character == '<') {
-          currentTypeArg.write(character);
+          currentTypeArgument += character;
           level++;
         } else if (character == '>') {
-          currentTypeArg.write(character);
+          currentTypeArgument += character;
           level--;
         } else if (character == ',') {
           if (level > 0) {
-            currentTypeArg.write(character);
+            currentTypeArgument += character;
           } else {
-            addCurrentTypeArg();
+            addTypeArgument(currentTypeArgument);
+            currentTypeArgument = '';
           }
         } else {
-          currentTypeArg.write(character);
+          currentTypeArgument += character;
         }
       }
-      addCurrentTypeArg();
+      addTypeArgument(currentTypeArgument);
     }
-    return _typeArgs = new UnmodifiableListView(result);
+    return _typeArguments = new UnmodifiableListView(result);
   }
 
   Map<Symbol, MethodMirror> get constructors => _class.constructors;
@@ -1813,7 +1822,7 @@
   if (type == null) return JsMirrorSystem._dynamicType;
   String representation = runtimeTypeToString(type);
   if (representation == null) return reflectClass(Function);
-  return reflectClass(createRuntimeType(representation));
+  return reflectType(createRuntimeType(representation));
 }
 
 Symbol computeQualifiedName(DeclarationMirror owner, Symbol simpleName) {
@@ -1908,7 +1917,7 @@
 }
 
 // Copied from package "unmodifiable_collection".
-// TODO(ahe): Lobby to get it added to dart:collection.
+// TODO(14314): Move to dart:collection.
 class UnmodifiableMapView<K, V> implements Map<K, V> {
   Map<K, V> _source;
   UnmodifiableMapView(Map<K, V> source) : _source = source;
diff --git a/sdk/lib/_internal/lib/js_number.dart b/sdk/lib/_internal/lib/js_number.dart
index b5591fb..de6986e 100644
--- a/sdk/lib/_internal/lib/js_number.dart
+++ b/sdk/lib/_internal/lib/js_number.dart
@@ -49,6 +49,8 @@
         || JS('bool', r'# == -Infinity', this);
   }
 
+  bool get isFinite => JS('bool', r'isFinite(#)', this);
+
   num remainder(num b) {
     checkNull(b); // TODO(ngeoffray): This is not specified but co19 tests it.
     if (b is! num) throw new ArgumentError(b);
@@ -190,9 +192,19 @@
     }
   }
 
+  bool _isInt32(value) => JS('bool', '(# | 0) === #', value, value);
+
   num operator ~/(num other) {
+    if (_isInt32(this) && _isInt32(other) && 0 != other && -1 != other) {
+      return JS('num', r'(# / #) | 0', this, other);
+    } else {
+      return _slowTdiv(other);
+    }
+  }
+
+  num _slowTdiv(num other) {
     if (other is !num) throw new ArgumentError(other);
-    return (JS('num', r'# / #', this, other)).truncate();
+    return (JS('num', r'# / #', this, other)).toInt();
   }
 
   // TODO(ngeoffray): Move the bit operations below to [JSInt] and
@@ -289,7 +301,7 @@
   }
 
   int get bitLength {
-    int nonneg = this < 0 ? -this-1 : this;
+    int nonneg = this < 0 ? -this - 1 : this;
     if (nonneg >= 0x100000000) {
       nonneg = nonneg ~/ 0x100000000;
       return _bitCount(_spread(nonneg)) + 32;
diff --git a/sdk/lib/_internal/lib/js_rti.dart b/sdk/lib/_internal/lib/js_rti.dart
index d7c28e0..aea2fc3 100644
--- a/sdk/lib/_internal/lib/js_rti.dart
+++ b/sdk/lib/_internal/lib/js_rti.dart
@@ -158,6 +158,8 @@
   } else if (isJsFunction(type)) {
     // A reference to the constructor.
     return getConstructorName(type);
+  } else if (type is int) {
+    return type.toString();
   } else {
     return null;
   }
diff --git a/sdk/lib/_internal/lib/native_helper.dart b/sdk/lib/_internal/lib/native_helper.dart
index bbee3a5..b5f24ff 100644
--- a/sdk/lib/_internal/lib/native_helper.dart
+++ b/sdk/lib/_internal/lib/native_helper.dart
@@ -285,8 +285,7 @@
     return null;
   }
   var interceptor = JS('', '#.prototype', interceptorClass);
-  var isLeaf =
-      (leafTags != null) && JS('bool', '(#[#]) === true', leafTags, tag);
+  var isLeaf = JS('bool', '(#[#]) === true', leafTags, tag);
   if (isLeaf) {
     return makeLeafDispatchRecord(interceptor);
   } else {
@@ -301,6 +300,46 @@
   return makeDispatchRecord(interceptor, false, null, indexability);
 }
 
+makeDefaultDispatchRecord(tag, interceptorClass, proto) {
+  var interceptor = JS('', '#.prototype', interceptorClass);
+  var isLeaf = JS('bool', '(#[#]) === true', leafTags, tag);
+  if (isLeaf) {
+    return makeLeafDispatchRecord(interceptor);
+  } else {
+    return makeDispatchRecord(interceptor, proto, null, null);
+  }
+}
+
+var initNativeDispatchFlag;  // null or true
+
+void initNativeDispatch() {
+  initNativeDispatchFlag = true;
+
+  // Try to pro-actively patch prototypes of DOM objects.  For each of our known
+  // tags `TAG`, if `window.TAG` is a (constructor) function, set the dispatch
+  // property if the function's prototype to a dispatch record.
+  if (JS('bool', 'typeof window != "undefined"')) {
+    var context = JS('=Object', 'window');
+    var map = interceptorsByTag;
+    var tags = JS('JSMutableArray', 'Object.getOwnPropertyNames(#)', map);
+    for (int i = 0; i < tags.length; i++) {
+      var tag = tags[i];
+      if (JS('bool', 'typeof (#[#]) == "function"', context, tag)) {
+        var constructor = JS('', '#[#]', context, tag);
+        var proto = JS('', '#.prototype', constructor);
+        if (proto != null) {  // E.g. window.mozRTCIceCandidate.prototype
+          var interceptorClass = JS('', '#[#]', map, tag);
+          var record = makeDefaultDispatchRecord(tag, interceptorClass, proto);
+          if (record != null) {
+            setDispatchProperty(proto, record);
+          }
+        }
+      }
+    }
+  }
+}
+
+
 /**
  * [proto] should have no shadowing prototypes that are not also assigned a
  * dispatch rescord.
diff --git a/sdk/lib/_internal/pub/lib/src/barback.dart b/sdk/lib/_internal/pub/lib/src/barback.dart
index 823833c..a78f7b8 100644
--- a/sdk/lib/_internal/pub/lib/src/barback.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback.dart
@@ -20,18 +20,48 @@
 /// An identifier for a transformer and the configuration that will be passed to
 /// it.
 ///
-/// It's possible that [asset] defines multiple transformers. If so,
-/// [configuration] will be passed to all of them.
+/// It's possible that the library identified by [this] defines multiple
+/// transformers. If so, [configuration] will be passed to all of them.
 class TransformerId {
-  /// The asset containing the transformer.
-  final AssetId asset;
+  /// The package containing the library that this transformer identifies.
+  final String package;
+
+  /// The `/`-separated path identifying the library that contains this
+  /// transformer.
+  ///
+  /// This is relative to the `lib/` directory in [package], and doesn't end in
+  /// `.dart`.
+  ///
+  /// This can be null; if so, it indicates that the transformer(s) should be
+  /// loaded from `lib/transformer.dart` if that exists, and `lib/$package.dart`
+  /// otherwise.
+  final String path;
 
   /// The configuration to pass to the transformer.
   ///
   /// This will be null if no configuration was provided.
   final Map configuration;
 
-  TransformerId(this.asset, this.configuration) {
+  /// Parses a transformer identifier.
+  ///
+  /// A transformer identifier is a string of the form "package_name" or
+  /// "package_name/path/to/library". It does not have a trailing extension. If
+  /// it just has a package name, it expands to lib/transformer.dart if that
+  /// exists, or lib/${package}.dart otherwise. Otherwise, it expands to
+  /// lib/${path}.dart. In either case it's located in the given package.
+  factory TransformerId.parse(String identifier, Map configuration) {
+    if (identifier.isEmpty) {
+      throw new FormatException('Invalid library identifier: "".');
+    }
+
+    var parts = split1(identifier, "/");
+    if (parts.length == 1) {
+      return new TransformerId(parts.single, null, configuration);
+    }
+    return new TransformerId(parts.first, parts.last, configuration);
+  }
+
+  TransformerId(this.package, this.path, this.configuration) {
     if (configuration == null) return;
     for (var reserved in ['include', 'exclude']) {
       if (!configuration.containsKey(reserved)) continue;
@@ -42,10 +72,27 @@
 
   // TODO(nweiz): support deep equality on [configuration] as well.
   bool operator==(other) => other is TransformerId &&
-      other.asset == asset &&
+      other.package == package &&
+      other.path == path &&
       other.configuration == configuration;
 
-  int get hashCode => asset.hashCode ^ configuration.hashCode;
+  int get hashCode => package.hashCode ^ path.hashCode ^ configuration.hashCode;
+
+  String toString() => path == null ? package : '$package/$path';
+
+  /// Returns the asset id for the library identified by this transformer id.
+  ///
+  /// If `path` is null, this will determine which library to load.
+  Future<AssetId> getAssetId(Barback barback) {
+    if (path != null) {
+      return new Future.value(new AssetId(package, 'lib/$path.dart'));
+    }
+
+    var transformerAsset = new AssetId(package, 'lib/transformer.dart');
+    return barback.getAssetById(transformerAsset).then((_) => transformerAsset)
+        .catchError((e) => new AssetId(package, 'lib/$package.dart'),
+            test: (e) => e is AssetNotFoundException);
+  }
 }
 
 /// Creates a [BarbackServer] serving on [host] and [port].
@@ -97,47 +144,6 @@
   });
 }
 
-/// Parses a library identifier to an asset id.
-///
-/// A library identifier is a string of the form "package_name" or
-/// "package_name/path/to/library". It does not have a trailing extension. If it
-/// just has a package name, it expands to lib/${package}.dart in that package.
-/// Otherwise, it expands to lib/${path}.dart in that package.
-AssetId libraryIdentifierToId(String identifier) {
-  if (identifier.isEmpty) {
-    throw new FormatException('Invalid library identifier: "".');
-  }
-
-  // Convert the concise asset name in the pubspec (of the form "package"
-  // or "package/library") to an AssetId that points to an actual dart
-  // file ("package/lib/package.dart" or "package/lib/library.dart",
-  // respectively).
-  var parts = split1(identifier, "/");
-  if (parts.length == 1) parts.add(parts.single);
-  return new AssetId(parts.first, 'lib/' + parts.last + '.dart');
-}
-
-final _libraryPathRegExp = new RegExp(r"^lib/(.*)\.dart$");
-
-/// Converts [id] to a library identifier.
-///
-/// A library identifier is a string of the form "package_name" or
-/// "package_name/path/to/library". It does not have a trailing extension. If it
-/// just has a package name, it expands to lib/${package}.dart in that package.
-/// Otherwise, it expands to lib/${path}.dart in that package.
-///
-/// This will throw an [ArgumentError] if [id] doesn't represent a library in
-/// `lib/`.
-String idToLibraryIdentifier(AssetId id) {
-  var match = _libraryPathRegExp.firstMatch(id.path);
-  if (match == null) {
-    throw new ArgumentError("Asset id $id doesn't identify a library.");
-  }
-
-  if (match[1] == id.package) return id.package;
-  return '${id.package}/${match[1]}';
-}
-
 /// Converts [id] to a "package:" URI.
 ///
 /// This will throw an [ArgumentError] if [id] doesn't represent a library in
diff --git a/sdk/lib/_internal/pub/lib/src/barback/load_all_transformers.dart b/sdk/lib/_internal/pub/lib/src/barback/load_all_transformers.dart
index ac4ec09..ff9f1ac 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/load_all_transformers.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/load_all_transformers.dart
@@ -90,7 +90,7 @@
       var transformers = [[rewrite]];
       return Future.forEach(graph.packages[package].pubspec.transformers,
           (phase) {
-        return Future.wait(phase.where((id) => id.asset.package == package)
+        return Future.wait(phase.where((id) => id.package == package)
             .map(loader.load)).then((_) {
           transformers.add(unionAll(phase.map(
               (id) => loader.transformersFor(id))));
@@ -157,7 +157,7 @@
 /// Returns the set of transformer dependencies for [package].
 Set<String> _transformerDeps(PackageGraph graph, String package) =>
   unionAll(graph.packages[package].pubspec.transformers)
-      .map((id) => id.asset.package).toSet();
+      .map((id) => id.package).toSet();
 
 /// Returns an [ApplicationException] describing an ordering dependency cycle
 /// detected in [graph].
@@ -176,8 +176,8 @@
   return new ApplicationException("Transformer cycle detected:\n" +
       pairs(path).map((pair) {
     var transformers = unionAll(graph.packages[pair.first].pubspec.transformers)
-        .where((id) => id.asset.package == pair.last)
-        .map((id) => idToLibraryIdentifier(id.asset)).toList();
+        .where((id) => id.package == pair.last)
+        .map((id) => id.toString()).toList();
     if (transformers.isEmpty) {
       return "  ${pair.first} depends on ${pair.last}";
     } else {
@@ -195,7 +195,7 @@
   for (var package in graph.packages.values) {
     for (var phase in package.pubspec.transformers) {
       for (var id in phase) {
-        packageTransformers[id.asset.package].add(id);
+        packageTransformers[id.package].add(id);
       }
     }
   }
@@ -213,12 +213,13 @@
   /// The packages that use each transformer asset id.
   ///
   /// Used for error reporting.
-  final _transformerUsers = new Map<AssetId, Set<String>>();
+  final _transformerUsers = new Map<Pair<String, String>, Set<String>>();
 
   _TransformerLoader(this._server, PackageGraph graph) {
     for (var package in graph.packages.values) {
       for (var id in unionAll(package.pubspec.transformers)) {
-        _transformerUsers.putIfAbsent(id.asset, () => new Set<String>())
+        _transformerUsers.putIfAbsent(
+            new Pair(id.package, id.path), () => new Set<String>())
             .add(package.name);
       }
     }
@@ -244,9 +245,19 @@
       if (id.configuration != null) {
         message += " that accept configuration";
       }
+
+      var location;
+      if (id.path == null) {
+        location = 'package:${id.package}/transformer.dart or '
+          'package:${id.package}/${id.package}.dart';
+      } else {
+        location = 'package:$id.dart';
+      }
+      var pair = new Pair(id.package, id.path);
+
       throw new ApplicationException(
-          "$message were defined in ${idToPackageUri(id.asset)},\n"
-          "required by ${ordered(_transformerUsers[id.asset]).join(', ')}.");
+          "$message were defined in $location,\n"
+          "required by ${ordered(_transformerUsers[pair]).join(', ')}.");
     });
   }
 
diff --git a/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart b/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart
index 141d83b..5481a50 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart
@@ -27,6 +27,8 @@
 import 'dart:convert';
 import 'dart:mirrors';
 
+import 'http://<<HOST_AND_PORT>>/packages/source_maps/span.dart';
+import 'http://<<HOST_AND_PORT>>/packages/stack_trace/stack_trace.dart';
 import 'http://<<HOST_AND_PORT>>/packages/barback/barback.dart';
 
 /// Sets up the initial communication with the host isolate.
@@ -367,36 +369,40 @@
 ///
 /// [server] is used to serve any Dart files needed to load the transformers.
 Future<Set> loadTransformers(BarbackServer server, TransformerId id) {
-  var path = id.asset.path.replaceFirst('lib/', '');
-  // TODO(nweiz): load from a "package:" URI when issue 12474 is fixed.
-  var hostAndPort = '${server.address.address}:${server.port}';
-  var uri = 'http://$hostAndPort/packages/${id.asset.package}/$path';
-  var code = 'import "$uri";' +
-      _TRANSFORMER_ISOLATE.replaceAll('<<HOST_AND_PORT>>', hostAndPort);
-  log.fine("Loading transformers from ${id.asset}");
-  return dart.runInIsolate(code).then((sendPort) {
-    return _receiveFuture(sendPort.call({
-      'library': uri,
-      // TODO(nweiz): support non-JSON-encodable configuration maps.
-      'configuration': JSON.encode(id.configuration)
-    })).then((transformers) {
-      transformers = transformers.map(_deserializeTransformerOrGroup).toSet();
-      log.fine("Transformers from ${id.asset}: $transformers");
-      return transformers;
-    });
-  }).catchError((error) {
-    if (error is! dart.CrossIsolateException) throw error;
-    if (error.type != 'IsolateSpawnException') throw error;
-    // TODO(nweiz): don't parse this as a string once issues 12617 and 12689 are
-    // fixed.
-    if (!error.message.split('\n')[1].startsWith('import "$uri";')) {
-      throw error;
-    }
+  return id.getAssetId(server.barback).then((assetId) {
+    var path = assetId.path.replaceFirst('lib/', '');
+    // TODO(nweiz): load from a "package:" URI when issue 12474 is fixed.
+    var hostAndPort = '${server.address.address}:${server.port}';
+    var uri = 'http://$hostAndPort/packages/${id.package}/$path';
+    var code = 'import "$uri";' +
+        _TRANSFORMER_ISOLATE.replaceAll('<<HOST_AND_PORT>>', hostAndPort);
+    log.fine("Loading transformers from $assetId");
 
-    // If there was an IsolateSpawnException and the import that actually failed
-    // was the one we were loading transformers from, throw an application
-    // exception with a more user-friendly message.
-    fail('Transformer library "package:${id.asset.package}/$path" not found.');
+    return dart.runInIsolate(code).then((sendPort) {
+      return _receiveFuture(sendPort.call({
+        'library': uri,
+        // TODO(nweiz): support non-JSON-encodable configuration maps.
+        'configuration': JSON.encode(id.configuration)
+      })).then((transformers) {
+        transformers = transformers.map(_deserializeTransformerOrGroup).toSet();
+        log.fine("Transformers from $assetId: $transformers");
+        return transformers;
+      });
+    }).catchError((error) {
+      if (error is! dart.CrossIsolateException) throw error;
+      if (error.type != 'IsolateSpawnException') throw error;
+      // TODO(nweiz): don't parse this as a string once issues 12617 and 12689
+      // are fixed.
+      if (!error.message.split('\n')[1].startsWith('import "$uri";')) {
+        throw error;
+      }
+
+      // If there was an IsolateSpawnException and the import that actually
+      // failed was the one we were loading transformers from, throw an
+      // application exception with a more user-friendly message.
+      fail('Transformer library "package:${id.package}/$path" not '
+          'found.');
+    });
   });
 }
 
diff --git a/sdk/lib/_internal/pub/lib/src/pubspec.dart b/sdk/lib/_internal/pub/lib/src/pubspec.dart
index a8d1195..ee91067 100644
--- a/sdk/lib/_internal/pub/lib/src/pubspec.dart
+++ b/sdk/lib/_internal/pub/lib/src/pubspec.dart
@@ -131,37 +131,38 @@
               '"$transformer".');
         }
 
-        var id;
+        var library;
         var configuration;
         if (transformer is String) {
-          id = _wrapFormatException('library identifier', field,
-              () => libraryIdentifierToId(transformer));
+          library = transformer;
         } else {
           if (transformer.length != 1) {
-            _error('"$field" must have a single key: the library identifier.');
+            _error('"$field" must have a single key: the transformer '
+                'identifier.');
           } else if (transformer.keys.single is! String) {
-            _error('"$field" library identifier must be a string, but was '
-                '"$id".');
+            _error('"$field" transformer identifier must be a string, but was '
+                '"$library".');
           }
 
-          id = _wrapFormatException('library identifier', field,
-              () => libraryIdentifierToId(transformer.keys.single));
+          library = transformer.keys.single;
           configuration = transformer.values.single;
           if (configuration is! Map) {
-            _error('"$field.${idToLibraryIdentifier(id)}" field must be a map, '
-                'but was "$configuration".');
+            _error('"$field.$library" field must be a map, but was '
+                '"$configuration".');
           }
         }
 
+        var id = _wrapFormatException("transformer identifier",
+            "$field.$library",
+            () => new TransformerId.parse(library, configuration));
+
         if (id.package != name &&
             !dependencies.any((ref) => ref.name == id.package)) {
-          _error('"$field.${idToLibraryIdentifier(id)}" refers to a package '
-              'that\'s not listed in "dependencies".');
+          _error('"$field.$library" refers to a package that\'s not listed in '
+              '"dependencies".');
         }
 
-        return _wrapFormatException("transformer identifier",
-            "$field.${idToLibraryIdentifier(id)}",
-            () => new TransformerId(id, configuration));
+        return id;
       }).toSet();
     }).toList();
     return _transformers;
diff --git a/sdk/lib/_internal/pub/pub.status b/sdk/lib/_internal/pub/pub.status
index 7867409..fd1e29c 100644
--- a/sdk/lib/_internal/pub/pub.status
+++ b/sdk/lib/_internal/pub/pub.status
@@ -4,6 +4,8 @@
 
 test/serve/missing_file_test: Pass, Fail # Issue 12570
 
+test/hosted/version_negotiation_test: Pass, Timeout # Issue 14346
+
 [ $runtime == vm && $system == windows ]
 test/serve/watch_removed_file_test: Pass, Fail # Issue 13026
 
diff --git a/sdk/lib/_internal/pub/test/transformer/prefers_transformer_to_library_name_test.dart b/sdk/lib/_internal/pub/test/transformer/prefers_transformer_to_library_name_test.dart
new file mode 100644
index 0000000..1019a6e
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/transformer/prefers_transformer_to_library_name_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library pub_tests;
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import '../serve/utils.dart';
+
+const WRONG_TRANSFORMER = """
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+
+class RewriteTransformer extends Transformer {
+  RewriteTransformer.asPlugin();
+
+  String get allowedExtensions => '.txt';
+
+  Future apply(Transform transform) {
+    return transform.primaryInput.readAsString().then((contents) {
+      var id = transform.primaryInput.id.changeExtension(".wrong");
+      transform.addOutput(new Asset.fromString(id, "\$contents.wrong"));
+    });
+  }
+}
+""";
+
+main() {
+  initConfig();
+  integration("prefers transformer.dart to <package name>.dart", () {
+    d.dir(appPath, [
+      d.pubspec({
+        "name": "myapp",
+        "transformers": ["myapp"]
+      }),
+      d.dir("lib", [
+        d.file("transformer.dart", REWRITE_TRANSFORMER),
+        d.file("myapp.dart", WRONG_TRANSFORMER)
+      ]),
+      d.dir("web", [
+        d.file("foo.txt", "foo")
+      ])
+    ]).create();
+
+    createLockFile('myapp', pkg: ['barback']);
+
+    startPubServe();
+    requestShouldSucceed("foo.out", "foo.out");
+    requestShould404("foo.wrong");
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index ab31d16..6672f47 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -336,7 +336,7 @@
         if (seenFirst) {
           _runUserCode(() => combine(value, element),
                        (T newValue) { value = newValue; },
-                       _cancelAndError(subscription, result));
+                       _cancelAndErrorClosure(subscription, result));
         } else {
           value = element;
           seenFirst = true;
@@ -365,7 +365,7 @@
         _runUserCode(
           () => combine(value, element),
           (newValue) { value = newValue; },
-          _cancelAndError(subscription, result)
+          _cancelAndErrorClosure(subscription, result)
         );
       },
       onError: (e, st) {
@@ -402,8 +402,7 @@
         try {
           buffer.write(element);
         } catch (e, s) {
-          subscription.cancel();
-          result._completeError(_asyncError(e, s));
+          _cancelAndError(subscription, result, _asyncError(e, s), s);
         }
       },
       onError: (e) {
@@ -431,11 +430,10 @@
             () => (element == needle),
             (bool isMatch) {
               if (isMatch) {
-                subscription.cancel();
-                future._complete(true);
+                _cancelAndValue(subscription, future, true);
               }
             },
-            _cancelAndError(subscription, future)
+            _cancelAndErrorClosure(subscription, future)
           );
         },
         onError: future._completeError,
@@ -461,7 +459,7 @@
           _runUserCode(
             () => action(element),
             (_) {},
-            _cancelAndError(subscription, future)
+            _cancelAndErrorClosure(subscription, future)
           );
         },
         onError: future._completeError,
@@ -487,11 +485,10 @@
             () => test(element),
             (bool isMatch) {
               if (!isMatch) {
-                subscription.cancel();
-                future._complete(false);
+                _cancelAndValue(subscription, future, false);
               }
             },
-            _cancelAndError(subscription, future)
+            _cancelAndErrorClosure(subscription, future)
           );
         },
         onError: future._completeError,
@@ -517,11 +514,10 @@
             () => test(element),
             (bool isMatch) {
               if (isMatch) {
-                subscription.cancel();
-                future._complete(true);
+                _cancelAndValue(subscription, future, true);
               }
             },
-            _cancelAndError(subscription, future)
+            _cancelAndErrorClosure(subscription, future)
           );
         },
         onError: future._completeError,
@@ -553,8 +549,7 @@
     StreamSubscription subscription;
     subscription = this.listen(
       (_) {
-        subscription.cancel();
-        future._complete(false);
+        _cancelAndValue(subscription, future, false);
       },
       onError: future._completeError,
       onDone: () {
@@ -686,9 +681,7 @@
     StreamSubscription subscription;
     subscription = this.listen(
       (T value) {
-        subscription.cancel();
-        future._complete(value);
-        return;
+        _cancelAndValue(subscription, future, value);
       },
       onError: future._completeError,
       onDone: () {
@@ -742,10 +735,9 @@
     subscription = this.listen(
       (T value) {
         if (foundResult) {
-          subscription.cancel();
           // This is the second element we get.
           Error error = new StateError("More than one element");
-          future._completeError(error);
+          _cancelAndError(subscription, future, error, null);
           return;
         }
         foundResult = true;
@@ -786,11 +778,10 @@
           () => test(value),
           (bool isMatch) {
             if (isMatch) {
-              subscription.cancel();
-              future._complete(value);
+              _cancelAndValue(subscription, future, value);
             }
           },
-          _cancelAndError(subscription, future)
+          _cancelAndErrorClosure(subscription, future)
         );
       },
       onError: future._completeError,
@@ -827,7 +818,7 @@
               result = value;
             }
           },
-          _cancelAndError(subscription, future)
+          _cancelAndErrorClosure(subscription, future)
         );
       },
       onError: future._completeError,
@@ -864,16 +855,18 @@
           (bool isMatch) {
             if (isMatch) {
               if (foundResult) {
-                subscription.cancel();
-                future._completeError(
-                    new StateError('Multiple matches for "single"'));
+                _cancelAndError(
+                    subscription,
+                    future,
+                    new StateError('Multiple matches for "single"'),
+                    null);
                 return;
               }
               foundResult = true;
               result = value;
             }
           },
-          _cancelAndError(subscription, future)
+          _cancelAndErrorClosure(subscription, future)
         );
       },
       onError: future._completeError,
@@ -906,8 +899,7 @@
     subscription = this.listen(
       (T value) {
         if (index == 0) {
-          subscription.cancel();
-          future._complete(value);
+          _cancelAndValue(subscription, future, value);
           return;
         }
         index -= 1;
@@ -935,8 +927,11 @@
    *
    * If an event is currently firing, this unsubscription will only
    * take effect after all subscribers have received the current event.
+   *
+   * Returns a future if the cancel-operation is not completed synchronously.
+   * Otherwise returns `null`.
    */
-  void cancel();
+  Future cancel();
 
   /** Set or override the data event handler of this subscription. */
   void onData(void handleData(T data));
@@ -1220,6 +1215,9 @@
    * If you need to stop listening for values before the stream iterator is
    * automatically closed, you must call [cancel] to ensure that the stream
    * is properly closed.
+   *
+   * Returns a future if the cancel-operation is not completed synchronously.
+   * Otherwise returns `null`.
    */
-  void cancel();
+  Future cancel();
 }
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index f5b487e..0d82c72 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -66,7 +66,9 @@
    *
    * The [onListen] callback is called when the stream
    * receives its listener and [onCancel] when the listener ends
-   * its subscription.
+   * its subscription. If [onCancel] needs to perform an asynchronous operation,
+   * [onCancel] should return a future that completes when the cancel operation
+   * is done.
    *
    * If the stream is canceled before the controller needs new data the
    * [onResume] call might not be executed.
@@ -74,7 +76,7 @@
   factory StreamController({void onListen(),
                             void onPause(),
                             void onResume(),
-                            void onCancel(),
+                            onCancel(),
                             bool sync: false}) {
     if (onListen == null && onPause == null &&
         onResume == null && onCancel == null) {
@@ -172,7 +174,7 @@
   StreamSubscription<T> _subscribe(bool cancelOnError);
   void _recordPause(StreamSubscription<T> subscription) {}
   void _recordResume(StreamSubscription<T> subscription) {}
-  void _recordCancel(StreamSubscription<T> subscription) {}
+  Future _recordCancel(StreamSubscription<T> subscription) => null;
 }
 
 /**
@@ -463,7 +465,7 @@
     return subscription;
   }
 
-  void _recordCancel(StreamSubscription<T> subscription) {
+  Future _recordCancel(StreamSubscription<T> subscription) {
     if (_isAddingStream) {
       _StreamControllerAddStreamState addState = _varData;
       addState.cancel();
@@ -471,10 +473,18 @@
     _varData = null;
     _state =
         (_state & ~(_STATE_SUBSCRIBED | _STATE_ADDSTREAM)) | _STATE_CANCELED;
-    _runGuarded(_onCancel);
-    if (_doneFuture != null && _doneFuture._mayComplete) {
-      _doneFuture._asyncComplete(null);
+    void complete() {
+      if (_doneFuture != null && _doneFuture._mayComplete) {
+        _doneFuture._asyncComplete(null);
+      }
     }
+    Future future = _runGuarded(_onCancel);
+    if (future != null) {
+      future = future.whenComplete(complete);
+    } else {
+      complete();
+    }
+    return future;
   }
 
   void _recordPause(StreamSubscription<T> subscription) {
@@ -537,7 +547,7 @@
   _AsyncStreamController(void this._onListen(),
                          void this._onPause(),
                          void this._onResume(),
-                         void this._onCancel());
+                         this._onCancel());
 }
 
 class _SyncStreamController<T> extends _StreamController<T>
@@ -550,7 +560,7 @@
   _SyncStreamController(void this._onListen(),
                         void this._onPause(),
                         void this._onResume(),
-                        void this._onCancel());
+                        this._onCancel());
 }
 
 abstract class _NoCallbacks {
@@ -566,12 +576,14 @@
 class _NoCallbackSyncStreamController/*<T>*/ = _StreamController/*<T>*/
        with _SyncStreamControllerDispatch/*<T>*/, _NoCallbacks;
 
-typedef void _NotificationHandler();
+typedef _NotificationHandler();
 
-void _runGuarded(_NotificationHandler notificationHandler) {
-  if (notificationHandler == null) return;
+Future _runGuarded(_NotificationHandler notificationHandler) {
+  if (notificationHandler == null) return null;
   try {
-    notificationHandler();
+    var result = notificationHandler();
+    if (result is Future) return result;
+    return null;
   } catch (e, s) {
     Zone.current.handleUncaughtError(_asyncError(e, s), s);
   }
@@ -605,8 +617,8 @@
   _ControllerSubscription(this._controller, bool cancelOnError)
       : super(cancelOnError);
 
-  void _onCancel() {
-    _controller._recordCancel(this);
+  Future _onCancel() {
+    return _controller._recordCancel(this);
   }
 
   void _onPause() {
@@ -636,7 +648,7 @@
  * Object containing the state used to handle [StreamController.addStream].
  */
 class _AddStreamState<T> {
-  // [_FutureImpl] returned by call to addStream.
+  // [_Future] returned by call to addStream.
   _Future addStreamFuture;
 
   // Subscription on stream argument to addStream.
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index 7f128ed..bf7c8f0 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -73,10 +73,20 @@
    * when `cancelOnError` is true.
    */
   static const int _STATE_CANCELED = 8;
-  static const int _STATE_IN_CALLBACK = 16;
-  static const int _STATE_HAS_PENDING = 32;
-  static const int _STATE_PAUSE_COUNT = 64;
-  static const int _STATE_PAUSE_COUNT_SHIFT = 6;
+  /**
+   * Set when either:
+   *
+   *   * an error is sent, and [cancelOnError] is true, or
+   *   * a done event is sent.
+   *
+   * If the subscription is canceled while _STATE_WAIT_FOR_CANCEL is set, the
+   * state is unset, and no furher events must be delivered.
+   */
+  static const int _STATE_WAIT_FOR_CANCEL = 16;
+  static const int _STATE_IN_CALLBACK = 32;
+  static const int _STATE_HAS_PENDING = 64;
+  static const int _STATE_PAUSE_COUNT = 128;
+  static const int _STATE_PAUSE_COUNT_SHIFT = 7;
 
   /* Event handlers provided in constructor. */
   _DataHandler<T> _onData;
@@ -87,6 +97,10 @@
   /** Bit vector based on state-constants above. */
   int _state;
 
+  // TODO(floitsch): reuse another field
+  /** The future [_onCancel] may return. */
+  Future _cancelFuture;
+
   /**
    * Queue of pending events.
    *
@@ -171,16 +185,14 @@
     }
   }
 
-  void cancel() {
-    if (_isCanceled) return;
+  Future cancel() {
+    // The user doesn't want to receive any further events. If there is an
+    // error or done event pending (waiting for the cancel to be done) discard
+    // that event.
+    _state &= ~_STATE_WAIT_FOR_CANCEL;
+    if (_isCanceled) return _cancelFuture;
     _cancel();
-    if (!_inCallback) {
-      // otherwise checkState will be called after firing or callback completes.
-      _state |= _STATE_IN_CALLBACK;
-      _onCancel();
-      _pending = null;
-      _state &= ~_STATE_IN_CALLBACK;
-    }
+    return _cancelFuture;
   }
 
   Future asFuture([var futureValue]) {
@@ -201,6 +213,7 @@
   bool get _isInputPaused => (_state & _STATE_INPUT_PAUSED) != 0;
   bool get _isClosed => (_state & _STATE_CLOSED) != 0;
   bool get _isCanceled => (_state & _STATE_CANCELED) != 0;
+  bool get _waitsForCancel => (_state & _STATE_WAIT_FOR_CANCEL) != 0;
   bool get _inCallback => (_state & _STATE_IN_CALLBACK) != 0;
   bool get _hasPending => (_state & _STATE_HAS_PENDING) != 0;
   bool get _isPaused => _state >= _STATE_PAUSE_COUNT;
@@ -216,6 +229,8 @@
     if (_hasPending) {
       _pending.cancelSchedule();
     }
+    if (!_inCallback) _pending = null;
+    _cancelFuture = _onCancel();
   }
 
   /**
@@ -283,7 +298,7 @@
     assert(!_isInputPaused);
   }
 
-  void _onCancel() {
+  Future _onCancel() {
     assert(_isCanceled);
   }
 
@@ -325,30 +340,59 @@
     assert(!_isPaused);
     assert(!_inCallback);
     bool wasInputPaused = _isInputPaused;
-    _state |= _STATE_IN_CALLBACK;
-    if (!_zone.inSameErrorZone(Zone.current)) {
-      // Errors are not allowed to traverse zone boundaries.
-      Zone.current.handleUncaughtError(error, stackTrace);
-    } else if (_onError is ZoneBinaryCallback) {
-      _zone.runBinaryGuarded(_onError, error, stackTrace);
-    } else {
-      _zone.runUnaryGuarded(_onError, error);
+
+    void sendError() {
+      // If the subscription has been canceled while waiting for the cancel
+      // future to finish we must not report the error.
+      if (_isCanceled && !_waitsForCancel) return;
+      _state |= _STATE_IN_CALLBACK;
+      if (!_zone.inSameErrorZone(Zone.current)) {
+        // Errors are not allowed to traverse zone boundaries.
+        Zone.current.handleUncaughtError(error, stackTrace);
+      } else if (_onError is ZoneBinaryCallback) {
+        _zone.runBinaryGuarded(_onError, error, stackTrace);
+      } else {
+        _zone.runUnaryGuarded(_onError, error);
+      }
+      _state &= ~_STATE_IN_CALLBACK;
     }
-    _state &= ~_STATE_IN_CALLBACK;
+
     if (_cancelOnError) {
+      _state |= _STATE_WAIT_FOR_CANCEL;
       _cancel();
+      if (_cancelFuture is Future) {
+        _cancelFuture.whenComplete(sendError);
+      } else {
+        sendError();
+      }
+    } else {
+      sendError();
+      // Only check state if not cancelOnError.
+      _checkState(wasInputPaused);
     }
-    _checkState(wasInputPaused);
   }
 
   void _sendDone() {
     assert(!_isCanceled);
     assert(!_isPaused);
     assert(!_inCallback);
-    _state |= (_STATE_CANCELED | _STATE_CLOSED | _STATE_IN_CALLBACK);
-    _zone.runGuarded(_onDone);
-    _onCancel();  // No checkState after cancel, it is always the last event.
-    _state &= ~_STATE_IN_CALLBACK;
+
+    void sendDone() {
+      // If the subscription has been canceled while waiting for the cancel
+      // future to finish we must not report the done event.
+      if (!_waitsForCancel) return;
+      _state |= (_STATE_CANCELED | _STATE_CLOSED | _STATE_IN_CALLBACK);
+      _zone.runGuarded(_onDone);
+      _state &= ~_STATE_IN_CALLBACK;
+    }
+
+    _cancel();
+    _state |= _STATE_WAIT_FOR_CANCEL;
+    if (_cancelFuture is Future) {
+      _cancelFuture.whenComplete(sendDone);
+    } else {
+      sendDone();
+    }
   }
 
   /**
@@ -389,7 +433,6 @@
     // make a new state-change callback. Loop until the state didn't change.
     while (true) {
       if (_isCanceled) {
-        _onCancel();
         _pending = null;
         return;
       }
@@ -699,7 +742,7 @@
   void resume() {
     if (_pauseCounter > 0) _pauseCounter--;
   }
-  void cancel() {}
+  Future cancel() => null;
   bool get isPaused => _pauseCounter > 0;
 
   Future asFuture([futureValue]) => new _Future();
@@ -823,8 +866,9 @@
     _stream._resumeSubscription();
   }
 
-  void cancel() {
+  Future cancel() {
     _stream._cancelSubscription();
+    return null;
   }
 
   bool get isPaused {
@@ -935,7 +979,7 @@
     _state = _STATE_DONE;
   }
 
-  void cancel() {
+  Future cancel() {
     StreamSubscription subscription = _subscription;
     if (_state == _STATE_MOVING) {
       _Future<bool> hasNext = _futureOrPrefetch;
@@ -944,7 +988,7 @@
     } else {
       _clear();
     }
-    subscription.cancel();
+    return subscription.cancel();
   }
 
   void _onData(T data) {
diff --git a/sdk/lib/async/stream_pipe.dart b/sdk/lib/async/stream_pipe.dart
index cc0127e..692deea8 100644
--- a/sdk/lib/async/stream_pipe.dart
+++ b/sdk/lib/async/stream_pipe.dart
@@ -26,12 +26,35 @@
   }
 }
 
-/** Helper function to make an onError argument to [_runUserCode]. */
-_cancelAndError(StreamSubscription subscription, _Future future) =>
-  (error, StackTrace stackTrace) {
-    subscription.cancel();
+/** Helper function to cancel a subscription and wait for the potential future,
+  before completing with an error. */
+void _cancelAndError(StreamSubscription subscription,
+                     _Future future,
+                     error,
+                     StackTrace stackTrace) {
+  var cancelFuture = subscription.cancel();
+  if (cancelFuture is Future) {
+    cancelFuture.whenComplete(() => future._completeError(error, stackTrace));
+  } else {
     future._completeError(error, stackTrace);
-  };
+  }
+}
+
+/** Helper function to make an onError argument to [_runUserCode]. */
+_cancelAndErrorClosure(StreamSubscription subscription, _Future future) =>
+  ((error, StackTrace stackTrace) => _cancelAndError(
+      subscription, future, error, stackTrace));
+
+/** Helper function to cancel a subscription and wait for the potential future,
+  before completing with a value. */
+void _cancelAndValue(StreamSubscription subscription, _Future future, value) {
+  var cancelFuture = subscription.cancel();
+  if (cancelFuture is Future) {
+    cancelFuture.whenComplete(() => future._complete(value));
+  } else {
+    future._complete(value);
+  }
+}
 
 
 /**
diff --git a/sdk/lib/collection/iterable.dart b/sdk/lib/collection/iterable.dart
index ddc2269..d74448a 100644
--- a/sdk/lib/collection/iterable.dart
+++ b/sdk/lib/collection/iterable.dart
@@ -404,110 +404,122 @@
 }
 
 String _iterableToString(Iterable iterable) {
-  const int LENGTH_LIMIT = 80;
-  const int MIN_COUNT = 3;  // Always at least this many elements at the start.
-  const int MAX_COUNT = 100;
-  // Per entry length overhead for ", " (or for "(" and ")" for initial entry)
-  const int OVERHEAD = 2;
-  const int ELLIPSIS_SIZE = 3;  // "...".length.
   if (_toStringVisiting.contains(iterable)) return "(...)";
   _toStringVisiting.add(iterable);
-  List result = [];
+  List parts = [];
   try {
-    building: {  // Break this block to complete the toString.
-      int length = 0;
-      int count = 0;
-      Iterator it = iterable.iterator;
-      // Initial run of elements, at least MIN_COUNT, and then continue until
-      // passing at most LENGTH_LIMIT characters.
-      while (count < MIN_COUNT || length < LENGTH_LIMIT) {
-        if (!it.moveNext()) break building;
-        String next = "${it.current}";
-        result.add(next);
-        length += next.length + OVERHEAD;  // Includes ")" for the first entry.
-        count++;
-      }
-      String penultimateString;
-      String ultimateString;
-
-      // Find last two elements. One or more of them may already be in the
-      // result array. Include their length in `length`.
-      var penultimate = null;
-      var ultimate = null;
-      if (!it.moveNext()) {
-        if (count <= MIN_COUNT + 2) break building;
-        ultimateString = result.removeLast();
-        penultimateString = result.removeLast();
-      } else {
-        penultimate = it.current;
-        count++;
-        if (!it.moveNext()) {
-          if (count <= MIN_COUNT + 1) {
-            result.add("$penultimate");
-            break building;
-          }
-          ultimateString = "$penultimate";
-          penultimateString = result.removeLast();
-          length += ultimateString.length + OVERHEAD;
-        } else {
-          ultimate = it.current;
-          count++;
-          // Then keep looping, keeping the last two elements in variables.
-          assert(count < MAX_COUNT);
-          while (it.moveNext()) {
-            penultimate = ultimate;
-            ultimate = it.current;
-            count++;
-            if (count > MAX_COUNT) {
-              // If we haven't found the end before MAX_COUNT, give up.
-              // This cannot happen before because each count increases
-              // length by at least two, so there is no way to see more
-              // than ~40 elements before this loop.
-
-              // Remove any surplus elements until length including ", ...)"
-              // is at most LENGTH_LIMIT.
-              while (length > LENGTH_LIMIT - ELLIPSIS_SIZE - OVERHEAD &&
-                     count > MIN_COUNT) {
-                length -= result.removeLast().length + OVERHEAD;
-                count--;
-              }
-              result.add("...");
-              break building;
-            }
-          }
-          penultimateString = "$penultimate";
-          ultimateString = "$ultimate";
-          length +=
-              ultimateString.length + penultimateString.length + 2 * OVERHEAD;
-        }
-      }
-
-      // If there is a gap between the initial run and the last two,
-      // prepare to add an ellipsis.
-      String elision = null;
-      if (count > result.length + 2) {
-        elision = "...";
-        length += ELLIPSIS_SIZE + OVERHEAD;
-      }
-
-      // If the last two elements were very long, and we have more than
-      // MIN_COUNT elements in the initial run, drop some to make room for
-      // the last two.
-      while (length > LENGTH_LIMIT && result.length > MIN_COUNT) {
-        length -= result.removeLast().length + OVERHEAD;
-        if (elision == null) {
-          elision = "...";
-          length += ELLIPSIS_SIZE + OVERHEAD;
-        }
-      }
-      if (elision != null) {
-        result.add(elision);
-      }
-      result.add(penultimateString);
-      result.add(ultimateString);
-    }
+    _iterablePartsToStrings(iterable, parts);
   } finally {
     _toStringVisiting.remove(iterable);
   }
-  return (new StringBuffer("(")..writeAll(result, ", ")..write(")")).toString();
+  return (new StringBuffer("(")..writeAll(parts, ", ")..write(")")).toString();
+}
+
+/** Convert elments of [iterable] to strings and store them in [parts]. */
+void _iterablePartsToStrings(Iterable iterable, List parts) {
+  /// Try to stay below this many characters.
+  const int LENGTH_LIMIT = 80;
+  /// Always at least this many elements at the start.
+  const int HEAD_COUNT = 3;
+  /// Always at least this many elements at the end.
+  const int TAIL_COUNT = 2;
+  /// Stop iterating after this many elements. Iterables can be infinite.
+  const int MAX_COUNT = 100;
+  // Per entry length overhead. It's for ", " for all after the first entry,
+  // and for "(" and ")" for the initial entry. By pure luck, that's the same
+  // number.
+  const int OVERHEAD = 2;
+  const int ELLIPSIS_SIZE = 3;  // "...".length.
+
+  int length = 0;
+  int count = 0;
+  Iterator it = iterable.iterator;
+  // Initial run of elements, at least HEAD_COUNT, and then continue until
+  // passing at most LENGTH_LIMIT characters.
+  while (length < LENGTH_LIMIT || count < HEAD_COUNT) {
+    if (!it.moveNext()) return;
+    String next = "${it.current}";
+    parts.add(next);
+    length += next.length + OVERHEAD;
+    count++;
+  }
+
+  String penultimateString;
+  String ultimateString;
+
+  // Find last two elements. One or more of them may already be in the
+  // parts array. Include their length in `length`.
+  var penultimate = null;
+  var ultimate = null;
+  if (!it.moveNext()) {
+    if (count <= HEAD_COUNT + TAIL_COUNT) return;
+    ultimateString = parts.removeLast();
+    penultimateString = parts.removeLast();
+  } else {
+    penultimate = it.current;
+    count++;
+    if (!it.moveNext()) {
+      if (count <= HEAD_COUNT + 1) {
+        parts.add("$penultimate");
+        return;
+      }
+      ultimateString = "$penultimate";
+      penultimateString = parts.removeLast();
+      length += ultimateString.length + OVERHEAD;
+    } else {
+      ultimate = it.current;
+      count++;
+      // Then keep looping, keeping the last two elements in variables.
+      assert(count < MAX_COUNT);
+      while (it.moveNext()) {
+        penultimate = ultimate;
+        ultimate = it.current;
+        count++;
+        if (count > MAX_COUNT) {
+          // If we haven't found the end before MAX_COUNT, give up.
+          // This cannot happen in the code above because each entry
+          // increases length by at least two, so there is no way to
+          // visit more than ~40 elements before this loop.
+
+          // Remove any surplus elements until length, including ", ...)",
+          // is at most LENGTH_LIMIT.
+          while (length > LENGTH_LIMIT - ELLIPSIS_SIZE - OVERHEAD &&
+                 count > HEAD_COUNT) {
+            length -= parts.removeLast().length + OVERHEAD;
+            count--;
+          }
+          parts.add("...");
+          return;
+        }
+      }
+      penultimateString = "$penultimate";
+      ultimateString = "$ultimate";
+      length +=
+          ultimateString.length + penultimateString.length + 2 * OVERHEAD;
+    }
+  }
+
+  // If there is a gap between the initial run and the last two,
+  // prepare to add an ellipsis.
+  String elision = null;
+  if (count > parts.length + TAIL_COUNT) {
+    elision = "...";
+    length += ELLIPSIS_SIZE + OVERHEAD;
+  }
+
+  // If the last two elements were very long, and we have more than
+  // HEAD_COUNT elements in the initial run, drop some to make room for
+  // the last two.
+  while (length > LENGTH_LIMIT && parts.length > HEAD_COUNT) {
+    length -= parts.removeLast().length + OVERHEAD;
+    if (elision == null) {
+      elision = "...";
+      length += ELLIPSIS_SIZE + OVERHEAD;
+    }
+  }
+  if (elision != null) {
+    parts.add(elision);
+  }
+  parts.add(penultimateString);
+  parts.add(ultimateString);
 }
diff --git a/sdk/lib/core/num.dart b/sdk/lib/core/num.dart
index 1ef0e16..674ab2a 100644
--- a/sdk/lib/core/num.dart
+++ b/sdk/lib/core/num.dart
@@ -142,12 +142,30 @@
   /** Relational greater than or equal operator. */
   bool operator >=(num other);
 
+  /** True if the number is the double Not-a-Number value; otherwise, false. */
   bool get isNaN;
 
+  /**
+   * True if the number is negative; otherwise, false.
+   *
+   * Negative numbers are those less than zero, and the double `-0.0`.
+   */
   bool get isNegative;
 
+  /**
+   * True if the number is positive infinity or negative infinity; otherwise,
+   * false.
+   */
   bool get isInfinite;
 
+  /**
+   * True if the number is finite; otherwise, false.
+   *
+   * The only non-finite numbers are NaN, positive infinitity and
+   * negative infinity.
+   */
+  bool get isFinite;
+
   /** Returns the absolute value of this [num]. */
   num abs();
 
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index ec9e4c4..eef7e97 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -56,7 +56,7 @@
     makeLeafDispatchRecord;
 import 'dart:_interceptors' show
     Interceptor, JSExtendableArray, findInterceptorConstructorForType,
-    findConstructorForWebComponentType, getNativeInterceptor,
+    findConstructorForNativeSubclassType, getNativeInterceptor,
     setDispatchProperty, findInterceptorForType;
 
 export 'dart:math' show Rectangle, Point;
@@ -234,28 +234,10 @@
   @DocsEditable()
   String hreflang;
 
-  @DomName('HTMLAnchorElement.name')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLAnchorElement-partial
-  @deprecated // deprecated
-  String name;
-
-  @DomName('HTMLAnchorElement.origin')
-  @DocsEditable()
-  // WebKit only
-  @deprecated // nonstandard
-  final String origin;
-
   @DomName('HTMLAnchorElement.pathname')
   @DocsEditable()
   String pathname;
 
-  @DomName('HTMLAnchorElement.ping')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element
-  @deprecated // deprecated
-  String ping;
-
   @DomName('HTMLAnchorElement.port')
   @DocsEditable()
   String port;
@@ -489,12 +471,6 @@
   @DocsEditable()
   final String pathname;
 
-  @DomName('HTMLAreaElement.ping')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLAreaElement-partial
-  @deprecated // deprecated
-  String ping;
-
   @DomName('HTMLAreaElement.port')
   @DocsEditable()
   final String port;
@@ -648,6 +624,18 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
+@DocsEditable()
+@DomName('BeforeUnloadEvent')
+@Experimental() // untriaged
+class BeforeUnloadEvent extends Event native "BeforeUnloadEvent" {
+  // To suppress missing implicit constructor warnings.
+  factory BeforeUnloadEvent._() { throw new UnsupportedError("Not supported"); }
+}
+// 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.
+
+
 @DomName('Blob')
 class Blob extends Interceptor native "Blob" {
   // To suppress missing implicit constructor warnings.
@@ -1002,9 +990,6 @@
   CanvasRenderingContext2D get context2D =>
       JS('Null|CanvasRenderingContext2D', '#.getContext(#)', this, '2d');
 
-  @deprecated
-  CanvasRenderingContext2D get context2d => this.context2D;
-
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.FIREFOX)
   @Experimental()
@@ -1357,6 +1342,11 @@
   @Experimental() // untriaged
   void drawSystemFocusRing(Element element) native;
 
+  @DomName('CanvasRenderingContext2D.ellipse')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void ellipse(num x, num y, num radiusX, num radiusY, num rotation, num startAngle, num endAngle, bool anticlockwise) native;
+
   @DomName('CanvasRenderingContext2D.fill')
   @DocsEditable()
   void fill([String winding]) native;
@@ -1365,10 +1355,6 @@
   @DocsEditable()
   void fillRect(num x, num y, num width, num height) native;
 
-  @DomName('CanvasRenderingContext2D.fillText')
-  @DocsEditable()
-  void fillText(String text, num x, num y, [num maxWidth]) native;
-
   @DomName('CanvasRenderingContext2D.getContextAttributes')
   @DocsEditable()
   // http://wiki.whatwg.org/wiki/CanvasOpaque#Suggested_IDL
@@ -1387,9 +1373,10 @@
   @Creates('ImageData|=Object')
   _getImageData_1(sx, sy, sw, sh) native;
 
+  @JSName('getLineDash')
   @DomName('CanvasRenderingContext2D.getLineDash')
   @DocsEditable()
-  List<num> getLineDash() native;
+  List<num> _getLineDash() native;
 
   @DomName('CanvasRenderingContext2D.isPointInPath')
   @DocsEditable()
@@ -1443,6 +1430,11 @@
   @DocsEditable()
   void rect(num x, num y, num width, num height) native;
 
+  @DomName('CanvasRenderingContext2D.resetTransform')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void resetTransform() native;
+
   @DomName('CanvasRenderingContext2D.restore')
   @DocsEditable()
   void restore() native;
@@ -1459,10 +1451,6 @@
   @DocsEditable()
   void scale(num sx, num sy) native;
 
-  @DomName('CanvasRenderingContext2D.setLineDash')
-  @DocsEditable()
-  void setLineDash(List<num> dash) native;
-
   @DomName('CanvasRenderingContext2D.setTransform')
   @DocsEditable()
   void setTransform(num m11, num m12, num m21, num m22, num dx, num dy) native;
@@ -1742,14 +1730,80 @@
       num sourceX, num sourceY, num sourceWidth, num sourceHeight,
       num destX, num destY, num destWidth, num destHeight) native;
 
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @SupportedBrowser(SupportedBrowser.IE, '11')
+  @Unstable()
   @DomName('CanvasRenderingContext2D.lineDashOffset')
+  // TODO(14316): Firefox has this functionality with mozDashOffset, but it
+  // needs to be polyfilled.
   num get lineDashOffset => JS('num',
       '#.lineDashOffset || #.webkitLineDashOffset', this, this);
 
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @SupportedBrowser(SupportedBrowser.IE, '11')
+  @Unstable()
   @DomName('CanvasRenderingContext2D.lineDashOffset')
+  // TODO(14316): Firefox has this functionality with mozDashOffset, but it
+  // needs to be polyfilled.
   void set lineDashOffset(num value) => JS('void',
       'typeof #.lineDashOffset != "undefined" ? #.lineDashOffset = # : '
       '#.webkitLineDashOffset = #', this, this, value, this, value);
+
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @SupportedBrowser(SupportedBrowser.IE, '11')
+  @Unstable()
+  @DomName('CanvasRenderingContext2D.getLineDash')
+  List<num> getLineDash() {
+    // TODO(14316): Firefox has this functionality with mozDash, but it's a bit
+    // different.
+    if (JS('bool', '!!#.getLineDash', this)) {
+      return JS('List<num>', '#.getLineDash()', this);
+    } else if (JS('bool', '!!#.webkitLineDash', this)) {
+      return JS('List<num>', '#.webkitLineDash', this);
+    } 
+  }
+
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @SupportedBrowser(SupportedBrowser.IE, '11')
+  @Unstable()
+  @DomName('CanvasRenderingContext2D.setLineDash')
+  void setLineDash(List<num> dash) {
+    // TODO(14316): Firefox has this functionality with mozDash, but it's a bit
+    // different.
+    if (JS('bool', '!!#.setLineDash', this)) {
+      JS('void', '#.setLineDash(#)', this, dash);
+    } else if (JS('bool', '!!#.webkitLineDash', this)) {
+      JS('void', '#.webkitLineDash = #', this, dash);
+    }
+  }
+
+
+  /**
+   * Draws text to the canvas.
+   *
+   * The text is drawn starting at coordinates ([x], [y]).
+   * If [maxWidth] is provided and the [text] is computed to be wider than
+   * [maxWidth], then the drawn text is scaled down horizontally to fit.
+   *
+   * The text uses the current [CanvasRenderingContext2D.font] property for font
+   * options, such as typeface and size, and the current
+   * [CanvasRenderingContext2D.fillStyle] for style options such as color.
+   * The current [CanvasRenderingContext2D.textAlign] and
+   * [CanvasRenderingContext2D.textBaseLine] properties are also applied to the
+   * drawn text.
+   */
+  @DomName('CanvasRenderingContext2D.fillText')
+  void fillText(String text, num x, num y, [num maxWidth]) {
+    if (maxWidth != null) {
+      JS('void', '#.fillText(#, #, #, #)', this, text, x, y, maxWidth);
+    } else {
+      JS('void', '#.fillText(#, #, #)', this, text, x, y);
+    }
+  }
 }
 
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -2039,6 +2093,16 @@
 class ConsoleBase extends Interceptor native "ConsoleBase" {
   // To suppress missing implicit constructor warnings.
   factory ConsoleBase._() { throw new UnsupportedError("Not supported"); }
+
+  @DomName('ConsoleBase.timeline')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void timeline(String title) native;
+
+  @DomName('ConsoleBase.timelineEnd')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void timelineEnd(String title) native;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -2324,13 +2388,10 @@
   // To suppress missing implicit constructor warnings.
   factory CssFontFaceLoadEvent._() { throw new UnsupportedError("Not supported"); }
 
-  @DomName('CSSFontFaceLoadEvent.error')
+  @DomName('CSSFontFaceLoadEvent.fontfaces')
   @DocsEditable()
-  final DomError error;
-
-  @DomName('CSSFontFaceLoadEvent.fontface')
-  @DocsEditable()
-  final CssFontFaceRule fontface;
+  @Experimental() // untriaged
+  final List<FontFace> fontfaces;
 }
 // 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
@@ -2763,12 +2824,6 @@
   @DocsEditable()
   static const int SUPPORTS_RULE = 12;
 
-  @DomName('CSSRule.UNKNOWN_RULE')
-  @DocsEditable()
-  // http://dev.w3.org/csswg/cssom/#changes-from-dom2
-  @deprecated // deprecated
-  static const int UNKNOWN_RULE = 0;
-
   @DomName('CSSRule.VIEWPORT_RULE')
   @DocsEditable()
   @Experimental() // untriaged
@@ -7171,11 +7226,6 @@
   @DocsEditable()
   HtmlElement _body;
 
-  @DomName('Document.charset')
-  @DocsEditable()
-  @deprecated // nonstandard
-  String charset;
-
   @DomName('Document.cookie')
   @DocsEditable()
   String cookie;
@@ -7207,11 +7257,10 @@
   @DocsEditable()
   final String domain;
 
-  @DomName('Document.fontloader')
+  @DomName('Document.fonts')
   @DocsEditable()
-  // http://www.w3.org/TR/css3-fonts/#document-fontloader
-  @Experimental()
-  final FontLoader fontloader;
+  @Experimental() // untriaged
+  final FontFaceSet fonts;
 
   @JSName('head')
   @DomName('Document.head')
@@ -7291,16 +7340,6 @@
   // https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/PageVisibility/Overview.html#document
   final bool _webkitHidden;
 
-  @JSName('webkitIsFullScreen')
-  @DomName('Document.webkitIsFullScreen')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html
-  @deprecated // deprecated
-  final bool _webkitIsFullScreen;
-
   @JSName('webkitPointerLockElement')
   @DomName('Document.webkitPointerLockElement')
   @DocsEditable()
@@ -7330,13 +7369,6 @@
   @Experimental()
   Range _caretRangeFromPoint(int x, int y) native;
 
-  @JSName('createCDATASection')
-  @DomName('Document.createCDATASection')
-  @DocsEditable()
-  // http://dom.spec.whatwg.org/#dom-document-createcdatasection
-  @deprecated // deprecated
-  CDataSection createCDataSection(String data) native;
-
   @DomName('Document.createDocumentFragment')
   @DocsEditable()
   DocumentFragment createDocumentFragment() native;
@@ -7385,13 +7417,6 @@
   @Experimental()
   Touch _createTouch_1(Window window, target, identifier, pageX, pageY, screenX, screenY, webkitRadiusX, webkitRadiusY, webkitRotationAngle, webkitForce) native;
 
-  @JSName('createTouchList')
-  @DomName('Document.createTouchList')
-  @DocsEditable()
-  // http://www.w3.org/TR/touch-events/, http://www.chromestatus.com/features
-  @Experimental()
-  TouchList _createTouchList() native;
-
   @JSName('createTreeWalker')
   @DomName('Document.createTreeWalker')
   @DocsEditable()
@@ -7486,16 +7511,6 @@
   @Creates('NodeList')
   List<Node> _querySelectorAll(String selectors) native;
 
-  @JSName('webkitCancelFullScreen')
-  @DomName('Document.webkitCancelFullScreen')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html
-  @deprecated // deprecated
-  void _webkitCancelFullScreen() native;
-
   @JSName('webkitExitFullscreen')
   @DomName('Document.webkitExitFullscreen')
   @DocsEditable()
@@ -9669,15 +9684,6 @@
     return false;
   }
 
-  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
-  Element _templateInstanceRef;
-
-  // Note: only used if `this is! TemplateElement`
-  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
-  DocumentFragment _templateContent;
-
-  bool _templateIsDecorated;
-
   @DomName('Element.createShadowRoot')
   @SupportedBrowser(SupportedBrowser.CHROME, '25')
   @Experimental()
@@ -9693,133 +9699,6 @@
   ShadowRoot get shadowRoot =>
       JS('ShadowRoot|Null', '#.shadowRoot || #.webkitShadowRoot', this, this);
 
-
-  /**
-   * Gets the template this node refers to.
-   * This is only supported if [isTemplate] is true.
-   */
-  @Experimental()
-  Element get ref {
-    _ensureTemplate();
-
-    Element result = null;
-    var refId = attributes['ref'];
-    if (refId != null) {
-      var treeScope = this;
-      while (treeScope.parentNode != null) {
-        treeScope = treeScope.parentNode;
-      }
-
-      // Note: JS code tests that getElementById is present. We can't do that
-      // easily, so instead check for the types known to implement it.
-      if (treeScope is Document ||
-          treeScope is ShadowRoot ||
-          treeScope is svg.SvgSvgElement) {
-
-        result = treeScope.getElementById(refId);
-      }
-    }
-
-    if (result == null) {
-      result = _templateInstanceRef;
-      if (result == null) return this;
-    }
-
-    var nextRef = result.ref;
-    return nextRef != null ? nextRef : result;
-  }
-
-  /**
-   * Gets the content of this template.
-   * This is only supported if [isTemplate] is true.
-   */
-  @Experimental()
-  DocumentFragment get content {
-    _ensureTemplate();
-    return _templateContent;
-  }
-
-  /**
-   * Creates an instance of the template, using the provided model and optional
-   * binding delegate.
-   *
-   * This is only supported if [isTemplate] is true.
-   */
-  @Experimental()
-  DocumentFragment createInstance(model, [BindingDelegate delegate]) {
-    _ensureTemplate();
-    return TemplateElement.mdvPackage(this).createInstance(model, delegate);
-  }
-
-  /**
-   * The data model which is inherited through the tree.
-   * This is only supported if [isTemplate] is true.
-   */
-  @Experimental()
-  get model => TemplateElement.mdvPackage(this).model;
-
-  @Experimental()
-  void set model(value) {
-    _ensureTemplate();
-    TemplateElement.mdvPackage(this).model = value;
-  }
-
-  /**
-   * The binding delegate which is inherited through the tree. It can be used
-   * to configure custom syntax for `{{bindings}}` inside this template.
-   *
-   * This is only supported if [isTemplate] is true.
-   */
-  @Experimental()
-  BindingDelegate get bindingDelegate =>
-      TemplateElement.mdvPackage(this).bindingDelegate;
-
-  @Experimental()
-  void set bindingDelegate(BindingDelegate value) {
-    _ensureTemplate();
-    TemplateElement.mdvPackage(this).bindingDelegate = value;
-  }
-
-  // TODO(jmesserly): const set would be better
-  static const _TABLE_TAGS = const {
-    'caption': null,
-    'col': null,
-    'colgroup': null,
-    'tbody': null,
-    'td': null,
-    'tfoot': null,
-    'th': null,
-    'thead': null,
-    'tr': null,
-  };
-
-  bool get _isAttributeTemplate => attributes.containsKey('template') &&
-      (localName == 'option' || localName == 'optgroup' ||
-       _TABLE_TAGS.containsKey(localName));
-
-  /**
-   * Returns true if this node is a template.
-   *
-   * A node is a template if [tagName] is TEMPLATE, or the node has the
-   * 'template' attribute and this tag supports attribute form for backwards
-   * compatibility with existing HTML parsers. The nodes that can use attribute
-   * form are table elments (THEAD, TBODY, TFOOT, TH, TR, TD, CAPTION, COLGROUP
-   * and COL), OPTION, and OPTGROUP.
-   */
-  // TODO(jmesserly): this is not a public MDV API, but it seems like a useful
-  // place to document which tags our polyfill considers to be templates.
-  // Otherwise I'd be repeating it in several other places.
-  // See if we can replace this with a TemplateMixin.
-  @Experimental()
-  bool get isTemplate => tagName == 'TEMPLATE' || _isAttributeTemplate;
-
-  void _ensureTemplate() {
-    if (!isTemplate) {
-      throw new UnsupportedError('$this is not a template.');
-    }
-    TemplateElement.decorate(this);
-  }
-
   /**
    * Access this element's content position.
    *
@@ -9901,6 +9780,7 @@
    * This method is the Dart equivalent to jQuery's
    * [offset](http://api.jquery.com/offset/) method.
    */
+  @Experimental()
   Point get documentOffset => offsetTo(document.documentElement);
 
   /**
@@ -9914,6 +9794,7 @@
    * element is _not_ an offset parent or transitive offset parent to this
    * element, an [ArgumentError] is thrown.
    */
+  @Experimental()
   Point offsetTo(Element parent) {
     return Element._offsetToHelper(this, parent);
   }
@@ -10058,15 +9939,6 @@
   String get innerHtml => _innerHtml;
 
   /**
-   * For use while transitioning to the safe [innerHtml] or [setInnerHtml].
-   * Unsafe because it opens the app to cross-site scripting vulnerabilities.
-   */
-  @deprecated
-  void set unsafeInnerHtml(String html) {
-    _innerHtml = html;
-  }
-
-  /**
    * This is an ease-of-use accessor for event streams which should only be
    * used when an explicit accessor is not available.
    */
@@ -10364,12 +10236,6 @@
   @DocsEditable()
   void click() native;
 
-  @DomName('Element.ALLOW_KEYBOARD_INPUT')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#dom-element-requestfullscreen
-  @deprecated // deprecated
-  static const int ALLOW_KEYBOARD_INPUT = 1;
-
   @JSName('attributes')
   @DomName('Element.attributes')
   @DocsEditable()
@@ -10473,12 +10339,12 @@
 
   @DomName('Element.getAttribute')
   @DocsEditable()
-  @deprecated
+  @Experimental() // untriaged
   String getAttribute(String name) native;
 
   @DomName('Element.getAttributeNS')
   @DocsEditable()
-  @deprecated
+  @Experimental() // untriaged
   String getAttributeNS(String namespaceURI, String localName) native;
 
   @DomName('Element.getBoundingClientRect')
@@ -10581,12 +10447,10 @@
 
   @DomName('Element.setAttribute')
   @DocsEditable()
-  @deprecated
   void setAttribute(String name, String value) native;
 
   @DomName('Element.setAttributeNS')
   @DocsEditable()
-  @deprecated
   void setAttributeNS(String namespaceURI, String qualifiedName, String value) native;
 
   @JSName('webkitGetRegionFlowRanges')
@@ -10600,16 +10464,6 @@
   @Returns('JSExtendableArray')
   List<Range> getRegionFlowRanges() native;
 
-  @JSName('webkitRequestFullScreen')
-  @DomName('Element.webkitRequestFullScreen')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#dom-element-requestfullscreen
-  @deprecated // deprecated
-  void requestFullScreen(int flags) native;
-
   @JSName('webkitRequestFullscreen')
   @DomName('Element.webkitRequestFullscreen')
   @DocsEditable()
@@ -10954,12 +10808,6 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => Element.isTagSupported('embed');
 
-  @DomName('HTMLEmbedElement.align')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLEmbedElement-partial
-  @deprecated // deprecated
-  String align;
-
   @DomName('HTMLEmbedElement.height')
   @DocsEditable()
   String height;
@@ -11241,12 +11089,6 @@
   @DocsEditable()
   static const int AT_TARGET = 2;
 
-  @DomName('Event.BLUR')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int BLUR = 8192;
-
   @DomName('Event.BUBBLING_PHASE')
   @DocsEditable()
   static const int BUBBLING_PHASE = 3;
@@ -11255,112 +11097,10 @@
   @DocsEditable()
   static const int CAPTURING_PHASE = 1;
 
-  @DomName('Event.CHANGE')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int CHANGE = 32768;
-
-  @DomName('Event.CLICK')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int CLICK = 64;
-
-  @DomName('Event.DBLCLICK')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int DBLCLICK = 128;
-
-  @DomName('Event.DRAGDROP')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int DRAGDROP = 2048;
-
-  @DomName('Event.FOCUS')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int FOCUS = 4096;
-
-  @DomName('Event.KEYDOWN')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int KEYDOWN = 256;
-
-  @DomName('Event.KEYPRESS')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int KEYPRESS = 1024;
-
-  @DomName('Event.KEYUP')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int KEYUP = 512;
-
-  @DomName('Event.MOUSEDOWN')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int MOUSEDOWN = 1;
-
-  @DomName('Event.MOUSEDRAG')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int MOUSEDRAG = 32;
-
-  @DomName('Event.MOUSEMOVE')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int MOUSEMOVE = 16;
-
-  @DomName('Event.MOUSEOUT')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int MOUSEOUT = 8;
-
-  @DomName('Event.MOUSEOVER')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int MOUSEOVER = 4;
-
-  @DomName('Event.MOUSEUP')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int MOUSEUP = 2;
-
-  @DomName('Event.NONE')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int NONE = 0;
-
-  @DomName('Event.SELECT')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int SELECT = 16384;
-
   @DomName('Event.bubbles')
   @DocsEditable()
   final bool bubbles;
 
-  @DomName('Event.cancelBubble')
-  @DocsEditable()
-  // http://www.w3.org/TR/DOM-Level-3-Events/#events-event-type-stopPropagation
-  @deprecated // deprecated
-  bool cancelBubble;
-
   @DomName('Event.cancelable')
   @DocsEditable()
   final bool cancelable;
@@ -11573,10 +11313,32 @@
 class ElementEvents extends Events {
   /* Raw event target. */
   final Element _ptr;
+  static final webkitEvents = {
+    'animationend' : 'webkitAnimationEnd', 
+    'animationiteration' : 'webkitAnimationIteration', 
+    'animationstart' : 'webkitAnimationStart', 
+    'fullscreenchange' : 'webkitfullscreenchange', 
+    'fullscreenerror' : 'webkitfullscreenerror',
+    'keyadded' : 'webkitkeyadded', 
+    'keyerror' : 'webkitkeyerror', 
+    'keymessage' : 'webkitkeymessage', 
+    'needkey' : 'webkitneedkey', 
+    'pointerlockchange' : 'webkitpointerlockchange', 
+    'pointerlockerror' : 'webkitpointerlockerror', 
+    'resourcetimingbufferfull' : 'webkitresourcetimingbufferfull', 
+    'transitionend': 'webkitTransitionEnd',
+    'speechchange' : 'webkitSpeechChange'
+  };
 
   ElementEvents(Element ptr) : this._ptr = ptr, super(ptr);
 
   Stream operator [](String type) {
+    if (webkitEvents.keys.contains(type.toLowerCase())) {
+      if (Device.isWebKit) {
+        return new _ElementEventStreamImpl(
+            _ptr, webkitEvents[type.toLowerCase()], false);
+      }
+    }
     return new _ElementEventStreamImpl(_ptr, type, false);
   }
 }
@@ -11584,8 +11346,7 @@
 /**
  * Base class for all browser objects that support events.
  *
- * Use the [on] property to add, and remove events (rather than
- * [$dom_addEventListener] and [$dom_removeEventListener]
+ * Use the [on] property to add, and remove events
  * for compile-time type checks and a more concise API.
  */
 @DomName('EventTarget')
@@ -11602,21 +11363,17 @@
   // To suppress missing implicit constructor warnings.
   factory EventTarget._() { throw new UnsupportedError("Not supported"); }
 
-  @JSName('addEventListener')
   @DomName('EventTarget.addEventListener')
   @DocsEditable()
-  @deprecated
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native;
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native;
 
   @DomName('EventTarget.dispatchEvent')
   @DocsEditable()
   bool dispatchEvent(Event event) native;
 
-  @JSName('removeEventListener')
   @DomName('EventTarget.removeEventListener')
   @DocsEditable()
-  @deprecated
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native;
 
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -11973,12 +11730,6 @@
   @DocsEditable()
   void readAsArrayBuffer(Blob blob) native;
 
-  @DomName('FileReader.readAsBinaryString')
-  @DocsEditable()
-  // http://blog.whatwg.org/weekly-stream-autocomplete
-  @deprecated // deprecated
-  void readAsBinaryString(Blob blob) native;
-
   @JSName('readAsDataURL')
   @DomName('FileReader.readAsDataURL')
   @DocsEditable()
@@ -12207,87 +11958,85 @@
 
 
 @DocsEditable()
-@DomName('FontLoader')
-// http://www.w3.org/TR/css3-fonts/#document-fontloader
-@Experimental()
-class FontLoader extends EventTarget native "FontLoader" {
+@DomName('FontFace')
+@Experimental() // untriaged
+class FontFace extends Interceptor native "FontFace" {
   // To suppress missing implicit constructor warnings.
-  factory FontLoader._() { throw new UnsupportedError("Not supported"); }
+  factory FontFace._() { throw new UnsupportedError("Not supported"); }
 
-  @DomName('FontLoader.errorEvent')
+  @DomName('FontFace.FontFace')
   @DocsEditable()
-  static const EventStreamProvider<Event> errorEvent = const EventStreamProvider<Event>('error');
-
-  @DomName('FontLoader.loadEvent')
-  @DocsEditable()
-  static const EventStreamProvider<CssFontFaceLoadEvent> loadEvent = const EventStreamProvider<CssFontFaceLoadEvent>('load');
-
-  @DomName('FontLoader.loadingEvent')
-  @DocsEditable()
-  static const EventStreamProvider<CssFontFaceLoadEvent> loadingEvent = const EventStreamProvider<CssFontFaceLoadEvent>('loading');
-
-  @DomName('FontLoader.loadingdoneEvent')
-  @DocsEditable()
-  static const EventStreamProvider<CssFontFaceLoadEvent> loadingDoneEvent = const EventStreamProvider<CssFontFaceLoadEvent>('loadingdone');
-
-  @DomName('FontLoader.loadstartEvent')
-  @DocsEditable()
-  static const EventStreamProvider<CssFontFaceLoadEvent> loadStartEvent = const EventStreamProvider<CssFontFaceLoadEvent>('loadstart');
-
-  @DomName('FontLoader.loading')
-  @DocsEditable()
-  final bool loading;
-
-  @DomName('FontLoader.checkFont')
-  @DocsEditable()
-  bool checkFont(String font, String text) native;
-
-  @DomName('FontLoader.loadFont')
-  @DocsEditable()
-  void loadFont(Map params) {
-    var params_1 = convertDartToNative_Dictionary(params);
-    _loadFont_1(params_1);
-    return;
+  factory FontFace(String family, String source, Map descriptors) {
+    return FontFace._create_1(family, source, descriptors);
   }
-  @JSName('loadFont')
-  @DomName('FontLoader.loadFont')
-  @DocsEditable()
-  void _loadFont_1(params) native;
+  static FontFace _create_1(family, source, descriptors) => JS('FontFace', 'new FontFace(#,#,#)', family, source, descriptors);
 
-  @JSName('notifyWhenFontsReady')
-  @DomName('FontLoader.notifyWhenFontsReady')
+  @DomName('FontFace.family')
   @DocsEditable()
-  void _notifyWhenFontsReady(VoidCallback callback) native;
+  @Experimental() // untriaged
+  String family;
 
-  @JSName('notifyWhenFontsReady')
-  @DomName('FontLoader.notifyWhenFontsReady')
+  @DomName('FontFace.featureSettings')
   @DocsEditable()
-  Future notifyWhenFontsReady() {
-    var completer = new Completer();
-    _notifyWhenFontsReady(
-        () { completer.complete(); });
-    return completer.future;
-  }
+  @Experimental() // untriaged
+  String featureSettings;
 
-  @DomName('FontLoader.onerror')
+  @DomName('FontFace.status')
   @DocsEditable()
-  Stream<Event> get onError => errorEvent.forTarget(this);
+  @Experimental() // untriaged
+  final String status;
 
-  @DomName('FontLoader.onload')
+  @DomName('FontFace.stretch')
   @DocsEditable()
-  Stream<CssFontFaceLoadEvent> get onLoad => loadEvent.forTarget(this);
+  @Experimental() // untriaged
+  String stretch;
 
-  @DomName('FontLoader.onloading')
+  @DomName('FontFace.style')
   @DocsEditable()
-  Stream<CssFontFaceLoadEvent> get onLoading => loadingEvent.forTarget(this);
+  @Experimental() // untriaged
+  String style;
 
-  @DomName('FontLoader.onloadingdone')
+  @DomName('FontFace.unicodeRange')
   @DocsEditable()
-  Stream<CssFontFaceLoadEvent> get onLoadingDone => loadingDoneEvent.forTarget(this);
+  @Experimental() // untriaged
+  String unicodeRange;
 
-  @DomName('FontLoader.onloadstart')
+  @DomName('FontFace.variant')
   @DocsEditable()
-  Stream<CssFontFaceLoadEvent> get onLoadStart => loadStartEvent.forTarget(this);
+  @Experimental() // untriaged
+  String variant;
+
+  @DomName('FontFace.weight')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String weight;
+}
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+
+@DocsEditable()
+@DomName('FontFaceSet')
+@Experimental() // untriaged
+class FontFaceSet extends EventTarget native "FontFaceSet" {
+  // To suppress missing implicit constructor warnings.
+  factory FontFaceSet._() { throw new UnsupportedError("Not supported"); }
+
+  @DomName('FontFaceSet.status')
+  @DocsEditable()
+  @Experimental() // untriaged
+  final String status;
+
+  @DomName('FontFaceSet.check')
+  @DocsEditable()
+  @Experimental() // untriaged
+  bool check(String font, String text) native;
+
+  @DomName('FontFaceSet.match')
+  @DocsEditable()
+  @Experimental() // untriaged
+  List<FontFace> match(String font, String text) native;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -13003,18 +12752,6 @@
   @DocsEditable()
   final Element activeElement;
 
-  @DomName('HTMLDocument.captureEvents')
-  @DocsEditable()
-  // http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture
-  @deprecated // deprecated
-  void captureEvents() native;
-
-  @DomName('HTMLDocument.releaseEvents')
-  @DocsEditable()
-  // http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture
-  @deprecated // deprecated
-  void releaseEvents() native;
-
 
   @DomName('Document.body')
   BodyElement body;
@@ -13098,14 +12835,6 @@
     _title = value;
   }
 
-  @DomName('Document.webkitCancelFullScreen')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  void cancelFullScreen() {
-    _webkitCancelFullScreen();
-  }
-
   @DomName('Document.webkitExitFullscreen')
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.SAFARI)
@@ -13140,12 +12869,6 @@
   @Experimental()
   bool get hidden => _webkitHidden;
 
-  @DomName('Document.webkitIsFullScreen')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  bool get isFullScreen => _webkitIsFullScreen;
-
   @DomName('Document.webkitPointerLockElement')
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.SAFARI)
@@ -13162,7 +12885,7 @@
     '(#.visibilityState || #.mozVisibilityState || #.msVisibilityState ||'
       '#.webkitVisibilityState)', this, this, this, this);
 
-  @Experimental
+  @Experimental()
   /**
    * Register a custom subclass of Element to be instantiatable by the DOM.
    *
@@ -13235,10 +12958,6 @@
         extendsTag);
   }
 
-  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
-  // Note: used to polyfill <template>
-  Document _templateContentsOwner;
-
   @DomName('Document.visibilityChange')
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.FIREFOX)
@@ -14043,11 +13762,6 @@
   @DocsEditable()
   String alt;
 
-  @DomName('HTMLImageElement.border')
-  @DocsEditable()
-  @deprecated // deprecated
-  String border;
-
   @DomName('HTMLImageElement.complete')
   @DocsEditable()
   final bool complete;
@@ -14064,11 +13778,6 @@
   @DocsEditable()
   bool isMap;
 
-  @DomName('HTMLImageElement.lowsrc')
-  @DocsEditable()
-  @deprecated // deprecated
-  String lowsrc;
-
   @DomName('HTMLImageElement.naturalHeight')
   @DocsEditable()
   final int naturalHeight;
@@ -14081,6 +13790,11 @@
   @DocsEditable()
   String src;
 
+  @DomName('HTMLImageElement.srcset')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String srcset;
+
   @DomName('HTMLImageElement.useMap')
   @DocsEditable()
   String useMap;
@@ -14089,16 +13803,6 @@
   @DocsEditable()
   int width;
 
-  @DomName('HTMLImageElement.x')
-  @DocsEditable()
-  @deprecated // deprecated
-  final int x;
-
-  @DomName('HTMLImageElement.y')
-  @DocsEditable()
-  @deprecated // deprecated
-  final int y;
-
 }
 // 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
@@ -14317,12 +14021,6 @@
   @DocsEditable()
   String type;
 
-  @DomName('HTMLInputElement.useMap')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLInputElement-partial
-  @deprecated // deprecated
-  String useMap;
-
   @DomName('HTMLInputElement.validationMessage')
   @DocsEditable()
   final String validationMessage;
@@ -15035,6 +14733,28 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
+@DocsEditable()
+@DomName('KeyPair')
+@Experimental() // untriaged
+class KeyPair extends Interceptor native "KeyPair" {
+  // To suppress missing implicit constructor warnings.
+  factory KeyPair._() { throw new UnsupportedError("Not supported"); }
+
+  @DomName('KeyPair.privateKey')
+  @DocsEditable()
+  @Experimental() // untriaged
+  final CryptoKey privateKey;
+
+  @DomName('KeyPair.publicKey')
+  @DocsEditable()
+  @Experimental() // untriaged
+  final CryptoKey publicKey;
+}
+// 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.
+
+
 /**
  * An event that describes user interaction with the keyboard.
  *
@@ -15266,12 +14986,6 @@
    */
   LIElement.created() : super.created();
 
-  @DomName('HTMLLIElement.type')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLLIElement-partial
-  @deprecated // deprecated
-  String type;
-
   @DomName('HTMLLIElement.value')
   @DocsEditable()
   int value;
@@ -16832,12 +16546,6 @@
   @DocsEditable()
   final String origin;
 
-  @DomName('MessageEvent.ports')
-  @DocsEditable()
-  @Unstable()
-  @Creates('JSExtendableArray')
-  final List<MessagePort> ports;
-
   @DomName('MessageEvent.source')
   @DocsEditable()
   EventTarget get source => _convertNativeToDart_EventTarget(this._get_source);
@@ -17448,23 +17156,6 @@
   void _initMouseEvent_1(type, canBubble, cancelable, Window view, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget) native;
 
 
-  @deprecated
-  int get clientX => client.x;
-  @deprecated
-  int get clientY => client.y;
-  @deprecated
-  int get offsetX => offset.x;
-  @deprecated
-  int get offsetY => offset.y;
-  @deprecated
-  int get movementX => movement.x;
-  @deprecated
-  int get movementY => movement.y;
-  @deprecated
-  int get screenX => screen.x;
-  @deprecated
-  int get screenY => screen.y;
-
   @DomName('MouseEvent.clientX')
   @DomName('MouseEvent.clientY')
   Point get client => new Point(_clientX, _clientY);
@@ -17883,11 +17574,6 @@
   // To suppress missing implicit constructor warnings.
   factory Navigator._() { throw new UnsupportedError("Not supported"); }
 
-  @DomName('Navigator.appCodeName')
-  @DocsEditable()
-  @Experimental() // non-standard
-  final String appCodeName;
-
   @DomName('Navigator.cookieEnabled')
   @DocsEditable()
   @Unstable()
@@ -17909,16 +17595,6 @@
   @Experimental() // nonstandard
   final MimeTypeArray mimeTypes;
 
-  @DomName('Navigator.plugins')
-  @DocsEditable()
-  @deprecated // nonstandard
-  final PluginArray plugins;
-
-  @DomName('Navigator.product')
-  @DocsEditable()
-  @Unstable()
-  final String product;
-
   @DomName('Navigator.productSub')
   @DocsEditable()
   @Unstable()
@@ -17958,11 +17634,6 @@
   @Experimental()
   void getStorageUpdates() native;
 
-  @DomName('Navigator.javaEnabled')
-  @DocsEditable()
-  @deprecated // nonstandard
-  bool javaEnabled() native;
-
   @DomName('Navigator.registerProtocolHandler')
   @DocsEditable()
   @Unstable()
@@ -18002,6 +17673,11 @@
 
   // From NavigatorID
 
+  @DomName('Navigator.appCodeName')
+  @DocsEditable()
+  @Experimental() // non-standard
+  final String appCodeName;
+
   @DomName('Navigator.appName')
   @DocsEditable()
   final String appName;
@@ -18014,6 +17690,11 @@
   @DocsEditable()
   final String platform;
 
+  @DomName('Navigator.product')
+  @DocsEditable()
+  @Unstable()
+  final String product;
+
   @DomName('Navigator.userAgent')
   @DocsEditable()
   final String userAgent;
@@ -18038,12 +17719,16 @@
   // To suppress missing implicit constructor warnings.
   factory NavigatorID._() { throw new UnsupportedError("Not supported"); }
 
+  String appCodeName;
+
   String appName;
 
   String appVersion;
 
   String platform;
 
+  String product;
+
   String userAgent;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -18271,27 +17956,6 @@
   Node operator[](int index) => _this.childNodes[index];
 }
 
-/** Information about the instantiated template. */
-class TemplateInstance {
-  // TODO(rafaelw): firstNode & lastNode should be read-synchronous
-  // in cases where script has modified the template instance boundary.
-
-  /** The first node of this template instantiation. */
-  final Node firstNode;
-
-  /**
-   * The last node of this template instantiation.
-   * This could be identical to [firstNode] if the template only expanded to a
-   * single node.
-   */
-  final Node lastNode;
-
-  /** The model used to instantiate the template. */
-  final model;
-
-  TemplateInstance(this.firstNode, this.lastNode, this.model);
-}
-
 
 @DomName('Node')
 class Node extends EventTarget native "Node" {
@@ -18370,52 +18034,6 @@
    */
   String toString() => nodeValue == null ? super.toString() : nodeValue;
 
-
-  /**
-   * Creates a binding to the attribute [name] to the [path] of the [model].
-   *
-   * This can be overridden by custom elements to provide the binding used in
-   * [Node.bind]. This will only create the binding; it will not add it to
-   * [bindings].
-   *
-   * You should not need to call this directly except from [Node.bind].
-   */
-  @Experimental()
-  createBinding(String name, model, String path) =>
-      TemplateElement.mdvPackage(this).createBinding(name, model, path);
-
-  /**
-   * Binds the attribute [name] to the [path] of the [model].
-   * Path is a String of accessors such as `foo.bar.baz`.
-   * Returns the `NodeBinding` instance.
-   */
-  @Experimental()
-  bind(String name, model, String path) =>
-      TemplateElement.mdvPackage(this).bind(name, model, path);
-
-  /** Unbinds the attribute [name]. */
-  @Experimental()
-  void unbind(String name) {
-    TemplateElement.mdvPackage(this).unbind(name);
-  }
-
-  /** Unbinds all bound attributes. */
-  @Experimental()
-  void unbindAll() {
-    TemplateElement.mdvPackage(this).unbindAll();
-  }
-
-  /** Gets the data bindings that are associated with this node. */
-  @Experimental()
-  Map<String, dynamic> get bindings =>
-      TemplateElement.mdvPackage(this).bindings;
-
-  /** Gets the template instance that instantiated this node, if any. */
-  @Experimental()
-  TemplateInstance get templateInstance =>
-      TemplateElement.mdvPackage(this).templateInstance;
-
-
   /**
    * Use ownerDocument instead.
    */
@@ -18480,7 +18098,6 @@
 
   @DomName('Node.childNodes')
   @DocsEditable()
-  @deprecated
   @Returns('NodeList')
   @Creates('NodeList')
   final List<Node> childNodes;
@@ -18496,15 +18113,11 @@
   @JSName('localName')
   @DomName('Node.localName')
   @DocsEditable()
-  // http://dom.spec.whatwg.org/#dom-node-localname
-  @deprecated // deprecated
   final String _localName;
 
   @JSName('namespaceURI')
   @DomName('Node.namespaceURI')
   @DocsEditable()
-  // http://dom.spec.whatwg.org/#dom-node-namespaceuri
-  @deprecated // deprecated
   final String _namespaceUri;
 
   @JSName('nextSibling')
@@ -18617,16 +18230,6 @@
   @DocsEditable()
   static const int SHOW_ALL = 0xFFFFFFFF;
 
-  @DomName('NodeFilter.SHOW_ATTRIBUTE')
-  @DocsEditable()
-  @deprecated // deprecated
-  static const int SHOW_ATTRIBUTE = 0x00000002;
-
-  @DomName('NodeFilter.SHOW_CDATA_SECTION')
-  @DocsEditable()
-  @deprecated // deprecated
-  static const int SHOW_CDATA_SECTION = 0x00000008;
-
   @DomName('NodeFilter.SHOW_COMMENT')
   @DocsEditable()
   static const int SHOW_COMMENT = 0x00000080;
@@ -18647,21 +18250,6 @@
   @DocsEditable()
   static const int SHOW_ELEMENT = 0x00000001;
 
-  @DomName('NodeFilter.SHOW_ENTITY')
-  @DocsEditable()
-  @deprecated // deprecated
-  static const int SHOW_ENTITY = 0x00000020;
-
-  @DomName('NodeFilter.SHOW_ENTITY_REFERENCE')
-  @DocsEditable()
-  @deprecated // deprecated
-  static const int SHOW_ENTITY_REFERENCE = 0x00000010;
-
-  @DomName('NodeFilter.SHOW_NOTATION')
-  @DocsEditable()
-  @deprecated // deprecated
-  static const int SHOW_NOTATION = 0x00000800;
-
   @DomName('NodeFilter.SHOW_PROCESSING_INSTRUCTION')
   @DocsEditable()
   static const int SHOW_PROCESSING_INSTRUCTION = 0x00000040;
@@ -18789,14 +18377,6 @@
 class Notation extends Node native "Notation" {
   // To suppress missing implicit constructor warnings.
   factory Notation._() { throw new UnsupportedError("Not supported"); }
-
-  @DomName('Notation.publicId')
-  @DocsEditable()
-  final String publicId;
-
-  @DomName('Notation.systemId')
-  @DocsEditable()
-  final String systemId;
 }
 // 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
@@ -19039,12 +18619,6 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => Element.isTagSupported('object');
 
-  @DomName('HTMLObjectElement.code')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLObjectElement-partial
-  @deprecated // deprecated
-  String code;
-
   @DomName('HTMLObjectElement.data')
   @DocsEditable()
   String data;
@@ -20036,11 +19610,6 @@
    * This can only be called by subclasses from their created constructor.
    */
   PreElement.created() : super.created();
-
-  @DomName('HTMLPreElement.wrap')
-  @DocsEditable()
-  @deprecated // deprecated
-  bool wrap;
 }
 // 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
@@ -20155,11 +19724,6 @@
   @Experimental() // untriaged
   static Promise every(Object values) native;
 
-  @DomName('Promise.fulfill')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static Promise fulfill(Object value) native;
-
   @DomName('Promise.reject')
   @DocsEditable()
   @Experimental() // untriaged
@@ -20169,38 +19733,6 @@
   @DocsEditable()
   @Experimental() // untriaged
   static Promise resolve(Object value) native;
-
-  @DomName('Promise.some')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static Promise some(Object values) native;
-}
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-
-@DocsEditable()
-@DomName('PromiseResolver')
-@Experimental() // untriaged
-class PromiseResolver extends Interceptor native "PromiseResolver" {
-  // To suppress missing implicit constructor warnings.
-  factory PromiseResolver._() { throw new UnsupportedError("Not supported"); }
-
-  @DomName('PromiseResolver.fulfill')
-  @DocsEditable()
-  @Experimental() // untriaged
-  void fulfill([Object value]) native;
-
-  @DomName('PromiseResolver.reject')
-  @DocsEditable()
-  @Experimental() // untriaged
-  void reject([Object value]) native;
-
-  @DomName('PromiseResolver.resolve')
-  @DocsEditable()
-  @Experimental() // untriaged
-  void resolve([Object value]) native;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -20349,11 +19881,6 @@
   @DocsEditable()
   void collapse(bool toStart) native;
 
-  @DomName('Range.compareNode')
-  @DocsEditable()
-  @deprecated // deprecated
-  int compareNode(Node refNode) native;
-
   @DomName('Range.comparePoint')
   @DocsEditable()
   int comparePoint(Node refNode, int offset) native;
@@ -20393,11 +19920,6 @@
   @DocsEditable()
   void insertNode(Node newNode) native;
 
-  @DomName('Range.intersectsNode')
-  @DocsEditable()
-  @deprecated // deprecated
-  bool intersectsNode(Node refNode) native;
-
   @DomName('Range.isPointInRange')
   @DocsEditable()
   bool isPointInRange(Node refNode, int offset) native;
@@ -20889,7 +20411,7 @@
 
   @DomName('RTCPeerConnection.addIceCandidate')
   @DocsEditable()
-  void addIceCandidate(RtcIceCandidate candidate) native;
+  void addIceCandidate(RtcIceCandidate candidate, VoidCallback successCallback, _RtcErrorCallback failureCallback) native;
 
   @DomName('RTCPeerConnection.addStream')
   @DocsEditable()
@@ -21289,18 +20811,6 @@
   @DocsEditable()
   bool defer;
 
-  @DomName('HTMLScriptElement.event')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLScriptElement-partial
-  @deprecated // deprecated
-  String event;
-
-  @DomName('HTMLScriptElement.htmlFor')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLScriptElement-partial
-  @deprecated // deprecated
-  String htmlFor;
-
   @DomName('HTMLScriptElement.nonce')
   @DocsEditable()
   // https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html#interaction-with-the-script-src-directive
@@ -21699,6 +21209,18 @@
 
 
 @DocsEditable()
+@DomName('ServiceWorker')
+@Experimental() // untriaged
+class ServiceWorker extends Interceptor native "ServiceWorker" {
+  // To suppress missing implicit constructor warnings.
+  factory ServiceWorker._() { throw new UnsupportedError("Not supported"); }
+}
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+
+@DocsEditable()
 @DomName('HTMLShadowElement')
 @SupportedBrowser(SupportedBrowser.CHROME, '26')
 @Experimental()
@@ -21869,11 +21391,16 @@
   @Experimental() // untriaged
   void appendBuffer(ByteBuffer data) native;
 
+  @DomName('SourceBuffer.appendStream')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void appendStream(FileStream stream, [int maxSize]) native;
+
   @JSName('appendBuffer')
   @DomName('SourceBuffer.appendBuffer')
   @DocsEditable()
   @Experimental() // untriaged
-  void appendBufferView(TypedData data) native;
+  void appendTypedData(TypedData data) native;
 
   @DomName('SourceBuffer.remove')
   @DocsEditable()
@@ -23199,12 +22726,6 @@
    */
   TableElement.created() : super.created();
 
-  @DomName('HTMLTableElement.border')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLTableElement-partial
-  @deprecated // deprecated
-  String border;
-
   @DomName('HTMLTableElement.caption')
   @DocsEditable()
   TableCaptionElement caption;
@@ -23395,88 +22916,6 @@
 // WARNING: Do not edit - generated code.
 
 
-/**
- * Model-Driven Views (MDV)'s native features enables a wide-range of use cases,
- * but (by design) don't attempt to implement a wide array of specialized
- * behaviors.
- *
- * Enabling these features in MDV is a matter of implementing and registering an
- * MDV Custom Syntax. A Custom Syntax is an object which contains one or more
- * delegation functions which implement specialized behavior. This object is
- * registered with MDV via [Element.bindingDelegate]:
- *
- *
- * HTML:
- *     <template bind>
- *       {{ What!Ever('crazy')->thing^^^I+Want(data) }}
- *     </template>
- *
- * Dart:
- *     class MySyntax extends BindingDelegate {
- *       getBinding(model, path, name, node) {
- *         // The magic happens here!
- *       }
- *     }
- *     ...
- *     query('template').bindingDelegate = new MySyntax();
- *     query('template').model = new MyModel();
- *
- * See <https://github.com/polymer-project/mdv/blob/master/docs/syntax.md> for
- * more information about Custom Syntax.
- */
-// TODO(jmesserly): move this type to the MDV package? Two issues: we'd lose
-// type annotation on [Element.bindingDelegate], and "mdv" is normally imported
-// with a prefix.
-@Experimental()
-abstract class BindingDelegate {
-  /**
-   * This syntax method allows for a custom interpretation of the contents of
-   * mustaches (`{{` ... `}}`).
-   *
-   * When a template is inserting an instance, it will invoke this method for
-   * each mustache which is encountered. The function is invoked with four
-   * arguments:
-   *
-   * - [model]: The data context for which this instance is being created.
-   * - [path]: The text contents (trimmed of outer whitespace) of the mustache.
-   * - [name]: The context in which the mustache occurs. Within element
-   *   attributes, this will be the name of the attribute. Within text,
-   *   this will be 'text'.
-   * - [node]: A reference to the node to which this binding will be created.
-   *
-   * If the method wishes to handle binding, it is required to return an object
-   * which has at least a `value` property that can be observed. If it does,
-   * then MDV will call [Node.bind on the node:
-   *
-   *     node.bind(name, retval, 'value');
-   *
-   * If the 'getBinding' does not wish to override the binding, it should return
-   * null.
-   */
-  // TODO(jmesserly): I had to remove type annotations from "name" and "node"
-  // Normally they are String and Node respectively. But sometimes it will pass
-  // (int name, CompoundBinding node). That seems very confusing; we may want
-  // to change this API.
-  getBinding(model, String path, name, node) => null;
-
-  /**
-   * This syntax method allows a syntax to provide an alterate model than the
-   * one the template would otherwise use when producing an instance.
-   *
-   * When a template is about to create an instance, it will invoke this method
-   * The function is invoked with two arguments:
-   *
-   * - [template]: The template element which is about to create and insert an
-   *   instance.
-   * - [model]: The data context for which this instance is being created.
-   *
-   * The template element will always use the return value of `getInstanceModel`
-   * as the model for the new instance. If the syntax does not wish to override
-   * the value, it should simply return the `model` value it was passed.
-   */
-  getInstanceModel(Element template, model) => model;
-}
-
 @Experimental()
 @DomName('HTMLTemplateElement')
 @SupportedBrowser(SupportedBrowser.CHROME)
@@ -23499,211 +22938,11 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => Element.isTagSupported('template');
 
-  @JSName('content')
   @DomName('HTMLTemplateElement.content')
   @DocsEditable()
-  final DocumentFragment _content;
+  final DocumentFragment content;
 
 
-  // For real TemplateElement use the actual DOM .content field instead of
-  // our polyfilled expando.
-  @Experimental()
-  DocumentFragment get content => _content;
-
-
-  /**
-   * The MDV package, if available.
-   *
-   * This can be used to initialize MDV support via:
-   *
-   *     import 'dart:html';
-   *     import 'package:mdv/mdv.dart' as mdv;
-   *     main() {
-   *       mdv.initialize();
-   *     }
-   */
-  static Function mdvPackage = (node) {
-    throw new UnsupportedError("The MDV package is not available. "
-        "You can enable it with `import 'package:mdv/mdv.dart' as mdv;` and "
-        "`mdv.initialize()`");
-  };
-
-  /**
-   * Ensures proper API and content model for template elements.
-   *
-   * [instanceRef] can be used to set the [Element.ref] property of [template],
-   * and use the ref's content will be used as source when createInstance() is
-   * invoked.
-   *
-   * Returns true if this template was just decorated, or false if it was
-   * already decorated.
-   */
-  @Experimental()
-  static bool decorate(Element template, [Element instanceRef]) {
-    // == true check because it starts as a null field.
-    if (template._templateIsDecorated == true) return false;
-
-    _injectStylesheet();
-
-    var templateElement = template;
-    templateElement._templateIsDecorated = true;
-    var isNative = templateElement is TemplateElement;
-    var bootstrapContents = isNative;
-    var liftContents = !isNative;
-    var liftRoot = false;
-
-    if (!isNative && templateElement._isAttributeTemplate) {
-      if (instanceRef != null) {
-        // TODO(jmesserly): this is just an assert in MDV.
-        throw new ArgumentError('instanceRef should not be supplied for '
-            'attribute templates.');
-      }
-      templateElement = _extractTemplateFromAttributeTemplate(template);
-      templateElement._templateIsDecorated = true;
-      isNative = templateElement is TemplateElement;
-      liftRoot = true;
-     }
-
-    if (!isNative) {
-      var doc = _getTemplateContentsOwner(templateElement.document);
-      templateElement._templateContent = doc.createDocumentFragment();
-    }
-
-    if (instanceRef != null) {
-      // template is contained within an instance, its direct content must be
-      // empty
-      templateElement._templateInstanceRef = instanceRef;
-    } else if (liftContents) {
-      _liftNonNativeChildrenIntoContent(templateElement, template, liftRoot);
-    } else if (bootstrapContents) {
-      bootstrap(templateElement.content);
-    }
-
-    return true;
-  }
-
-  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
-  static Document _getTemplateContentsOwner(HtmlDocument 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.lastChild != null) {
-        d.lastChild.remove();
-      }
-      doc._templateContentsOwner = d;
-    }
-    return d;
-  }
-
-  // For non-template browsers, the parser will disallow <template> in certain
-  // locations, so we allow "attribute templates" which combine the template
-  // element with the top-level container node of the content, e.g.
-  //
-  //   <tr template repeat="{{ foo }}"" class="bar"><td>Bar</td></tr>
-  //
-  // becomes
-  //
-  //   <template repeat="{{ foo }}">
-  //   + #document-fragment
-  //     + <tr class="bar">
-  //       + <td>Bar</td>
-  //
-  static Element _extractTemplateFromAttributeTemplate(Element el) {
-    var template = el.document.createElement('template');
-    el.parentNode.insertBefore(template, el);
-
-    for (var name in el.attributes.keys.toList()) {
-      switch (name) {
-        case 'template':
-          el.attributes.remove(name);
-          break;
-        case 'repeat':
-        case 'bind':
-        case 'ref':
-          template.attributes[name] = el.attributes.remove(name);
-          break;
-      }
-    }
-
-    return template;
-  }
-
-  static void _liftNonNativeChildrenIntoContent(Element template, Element el,
-      bool useRoot) {
-
-    var content = template.content;
-    if (useRoot) {
-      content.append(el);
-      return;
-    }
-
-    var child;
-    while ((child = el.firstChild) != null) {
-      content.append(child);
-    }
-  }
-
-  /**
-   * This used to decorate recursively all templates from a given node.
-   *
-   * By default [decorate] will be called on templates lazily when certain
-   * properties such as [model] are accessed, but it can be run eagerly to
-   * decorate an entire tree recursively.
-   */
-  // TODO(rafaelw): Review whether this is the right public API.
-  @Experimental()
-  static void bootstrap(Node content) {
-    void _bootstrap(template) {
-      if (!TemplateElement.decorate(template)) {
-        bootstrap(template.content);
-      }
-    }
-
-    // Need to do this first as the contents may get lifted if |node| is
-    // template.
-    // TODO(jmesserly): content is DocumentFragment or Element
-    var descendents =
-        (content as dynamic).querySelectorAll(_allTemplatesSelectors);
-    if (content is Element && (content as Element).isTemplate) {
-      _bootstrap(content);
-    }
-
-    descendents.forEach(_bootstrap);
-  }
-
-  static final String _allTemplatesSelectors =
-      'template, option[template], optgroup[template], ' +
-      Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", ");
-
-  static bool _initStyles;
-
-  static void _injectStylesheet() {
-    if (_initStyles == true) return;
-    _initStyles = true;
-
-    var style = new StyleElement();
-    style.text = r'''
-template,
-thead[template],
-tbody[template],
-tfoot[template],
-th[template],
-tr[template],
-td[template],
-caption[template],
-colgroup[template],
-col[template],
-option[template] {
-  display: none;
-}''';
-    document.head.append(style);
-  }
-
   /**
    * An override to place the contents into content rather than as child nodes.
    *
@@ -23744,12 +22983,6 @@
   @Creates('NodeList')
   List<Node> getDestinationInsertionPoints() native;
 
-  @DomName('Text.replaceWholeText')
-  @DocsEditable()
-  // http://dom.spec.whatwg.org/#dom-text-replacewholetext
-  @deprecated // deprecated
-  Text replaceWholeText(String content) native;
-
   @DomName('Text.splitText')
   @DocsEditable()
   Text splitText(int offset) native;
@@ -24483,7 +23716,8 @@
   /// 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.
-  factory TouchList() => document._createTouchList();
+  // TODO(5760): createTouchList now uses varargs.
+  factory TouchList() => null;//document._createTouchList();
   // To suppress missing implicit constructor warnings.
   factory TouchList._() { throw new UnsupportedError("Not supported"); }
 
@@ -24675,12 +23909,6 @@
   @DocsEditable()
   Node currentNode;
 
-  @DomName('TreeWalker.expandEntityReferences')
-  @DocsEditable()
-  // http://dom.spec.whatwg.org/#dom-traversal
-  @deprecated // deprecated
-  final bool expandEntityReferences;
-
   @DomName('TreeWalker.filter')
   @DocsEditable()
   final NodeFilter filter;
@@ -24815,16 +24043,6 @@
   void _initUIEvent(String type, bool canBubble, bool cancelable, Window view, int detail) native;
 
 
-  @deprecated
-  int get layerX => layer.x;
-  @deprecated
-  int get layerY => layer.y;
-
-  @deprecated
-  int get pageX => page.x;
-  @deprecated
-  int get pageY => page.y;
-
   @DomName('UIEvent.layerX')
   @DomName('UIEvent.layerY')
   Point get layer => new Point(_layerX, _layerY);
@@ -25000,16 +24218,6 @@
   @Experimental()
   final int decodedFrameCount;
 
-  @JSName('webkitDisplayingFullscreen')
-  @DomName('HTMLVideoElement.webkitDisplayingFullscreen')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html
-  @deprecated // deprecated
-  final bool displayingFullscreen;
-
   @JSName('webkitDroppedFrameCount')
   @DomName('HTMLVideoElement.webkitDroppedFrameCount')
   @DocsEditable()
@@ -25018,30 +24226,10 @@
   @Experimental()
   final int droppedFrameCount;
 
-  @JSName('webkitSupportsFullscreen')
-  @DomName('HTMLVideoElement.webkitSupportsFullscreen')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html
-  @deprecated // deprecated
-  final bool supportsFullscreen;
-
   @DomName('HTMLVideoElement.width')
   @DocsEditable()
   int width;
 
-  @JSName('webkitEnterFullScreen')
-  @DomName('HTMLVideoElement.webkitEnterFullScreen')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html
-  @deprecated // deprecated
-  void enterFullScreen() native;
-
   @JSName('webkitEnterFullscreen')
   @DomName('HTMLVideoElement.webkitEnterFullscreen')
   @DocsEditable()
@@ -25051,16 +24239,6 @@
   // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html
   void enterFullscreen() native;
 
-  @JSName('webkitExitFullScreen')
-  @DomName('HTMLVideoElement.webkitExitFullScreen')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#dom-document-exitfullscreen
-  @deprecated // deprecated
-  void exitFullScreen() native;
-
   @JSName('webkitExitFullscreen')
   @DomName('HTMLVideoElement.webkitExitFullscreen')
   @DocsEditable()
@@ -25185,12 +24363,6 @@
   @DocsEditable()
   static const int OPEN = 1;
 
-  @JSName('URL')
-  @DomName('WebSocket.URL')
-  @DocsEditable()
-  @deprecated // deprecated
-  final String Url;
-
   @DomName('WebSocket.binaryType')
   @DocsEditable()
   String binaryType;
@@ -25921,11 +25093,6 @@
   @Experimental() // non-standard
   final double devicePixelRatio;
 
-  @DomName('Window.event')
-  @DocsEditable()
-  @deprecated // deprecated
-  final Event event;
-
   @DomName('Window.history')
   @DocsEditable()
   final History history;
@@ -26006,12 +25173,6 @@
   @SupportedBrowser(SupportedBrowser.IE)
   final Performance performance;
 
-  @DomName('Window.personalbar')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.personalbar
-  @deprecated // deprecated
-  final BarProp personalbar;
-
   @DomName('Window.screen')
   @DocsEditable()
   final Screen screen;
@@ -26084,26 +25245,6 @@
   @Returns('Window|=Object')
   final dynamic _get_top;
 
-  @JSName('webkitNotifications')
-  @DomName('Window.webkitNotifications')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  // https://plus.sandbox.google.com/u/0/+GoogleChromeDevelopers/posts/8vWo8hq4pDm?e=Showroom
-  @deprecated // deprecated
-  final NotificationCenter notifications;
-
-  @JSName('webkitStorageInfo')
-  @DomName('Window.webkitStorageInfo')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  // http://www.w3.org/TR/file-system-api/
-  @deprecated // deprecated
-  final StorageInfo storageInfo;
-
   @DomName('Window.window')
   @DocsEditable()
   WindowBase get window => _convertNativeToDart_Window(this._get_window);
@@ -26144,12 +25285,6 @@
   @DocsEditable()
   void alert(String message) native;
 
-  @DomName('Window.captureEvents')
-  @DocsEditable()
-  // http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture
-  @deprecated // deprecated
-  void captureEvents() native;
-
   @DomName('Window.close')
   @DocsEditable()
   void close() native;
@@ -26158,12 +25293,6 @@
   @DocsEditable()
   bool confirm(String message) native;
 
-  @JSName('createImageBitmap')
-  @DomName('Window.createImageBitmap')
-  @DocsEditable()
-  @Experimental() // untriaged
-  Object _createImageBitmap(canvas_OR_context_OR_image_OR_video, [int sx, int sy, int sw, int sh]) native;
-
   @DomName('Window.find')
   @DocsEditable()
   @Experimental() // non-standard
@@ -26234,12 +25363,6 @@
   @DocsEditable()
   void print() native;
 
-  @DomName('Window.releaseEvents')
-  @DocsEditable()
-  // http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture
-  @deprecated // deprecated
-  void releaseEvents() native;
-
   @DomName('Window.resizeBy')
   @DocsEditable()
   void resizeBy(num x, num y) native;
@@ -26626,21 +25749,6 @@
       '#.scrollY', this) : document.documentElement.scrollTop;
 }
 
-/**
- * Event object that is fired before the window is closed.
- *
- * The standard window close behavior can be prevented by setting the
- * [returnValue]. This will display a dialog to the user confirming that they
- * want to close the page.
- */
-abstract class BeforeUnloadEvent implements Event {
-  /**
-   * If set to a non-null value, a dialog will be presented to the user
-   * confirming that they want to close the page.
-   */
-  String returnValue;
-}
-
 class _BeforeUnloadEvent extends _WrappedEvent implements BeforeUnloadEvent {
   String _returnValue;
 
@@ -27328,16 +26436,6 @@
   // Use implementation from Node.
   // final String _namespaceUri;
 
-  @DomName('Attr.ownerElement')
-  @DocsEditable()
-  @deprecated // deprecated
-  final Element ownerElement;
-
-  @DomName('Attr.specified')
-  @DocsEditable()
-  @deprecated // deprecated
-  final bool specified;
-
   @DomName('Attr.value')
   @DocsEditable()
   String value;
@@ -27835,18 +26933,6 @@
 class _Entity extends Node native "Entity" {
   // To suppress missing implicit constructor warnings.
   factory _Entity._() { throw new UnsupportedError("Not supported"); }
-
-  @DomName('Entity.notationName')
-  @DocsEditable()
-  final String notationName;
-
-  @DomName('Entity.publicId')
-  @DocsEditable()
-  final String publicId;
-
-  @DomName('Entity.systemId')
-  @DocsEditable()
-  final String systemId;
 }
 // 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
@@ -29807,13 +28893,13 @@
 
   void _tryResume() {
     if (_onData != null && !isPaused) {
-      _target.$dom_addEventListener(_eventType, _onData, _useCapture);
+      _target.addEventListener(_eventType, _onData, _useCapture);
     }
   }
 
   void _unlisten() {
     if (_onData != null) {
-      _target.$dom_removeEventListener(_eventType, _onData, _useCapture);
+      _target.removeEventListener(_eventType, _onData, _useCapture);
     }
   }
 
@@ -32565,11 +31651,6 @@
 
   bool get bubbles => wrapped.bubbles;
 
-  bool get cancelBubble => wrapped.bubbles;
-  void set cancelBubble(bool value) {
-    wrapped.cancelBubble = value;
-  }
-
   bool get cancelable => wrapped.cancelable;
 
   DataTransfer get clipboardData => wrapped.clipboardData;
@@ -32817,8 +31898,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
-_callConstructor(constructor) {
+_callConstructor(constructor, interceptor) {
   return (receiver) {
+    setNativeSubclassDispatchRecord(receiver, interceptor);
+
     return JS('', '#(#)', constructor, receiver);
   };
 }
@@ -32875,7 +31958,9 @@
     throw new ArgumentError(type);
   }
 
-  var constructor = findConstructorForWebComponentType(type, 'created');
+  var interceptor = JS('=Object', '#.prototype', interceptorClass);
+
+  var constructor = findConstructorForNativeSubclassType(type, 'created');
   if (constructor == null) {
     throw new ArgumentError("$type has no constructor called 'created'");
   }
@@ -32888,7 +31973,18 @@
   if (baseClassName == null) {
     throw new ArgumentError(type);
   }
-  if (baseClassName == 'Element') baseClassName = 'HTMLElement';
+
+  if (extendsTagName == null) {
+    if (baseClassName != 'HTMLElement') {
+      throw new UnsupportedError('Class must provide extendsTag if base '
+          'native class is not HTMLElement');
+    }
+  } else {
+    if (!JS('bool', '(#.createElement(#) instanceof window[#])',
+        document, extendsTagName, baseClassName)) {
+      throw new UnsupportedError('extendsTag does not match base native class');
+    }
+  }
 
   var baseConstructor = JS('=Object', '#[#]', context, baseClassName);
 
@@ -32896,7 +31992,7 @@
 
   JS('void', '#.createdCallback = #', properties,
       JS('=Object', '{value: #}',
-          _makeCallbackMethod(_callConstructor(constructor))));
+          _makeCallbackMethod(_callConstructor(constructor, interceptor))));
   JS('void', '#.enteredViewCallback = #', properties,
       JS('=Object', '{value: #}', _makeCallbackMethod(_callEnteredView)));
   JS('void', '#.leftViewCallback = #', properties,
@@ -32913,8 +32009,6 @@
   var baseProto = JS('=Object', '#.prototype', baseConstructor);
   var proto = JS('=Object', 'Object.create(#, #)', baseProto, properties);
 
-  var interceptor = JS('=Object', '#.prototype', interceptorClass);
-
   setNativeSubclassDispatchRecord(proto, interceptor);
 
   var options = JS('=Object', '{prototype: #}', proto);
@@ -33352,19 +32446,6 @@
    * error.
    */
   static final supportsSimd = false;
-
-  /**
-   * Upgrade all custom elements in the subtree which have not been upgraded.
-   *
-   * This is needed to cover timing scenarios which the custom element polyfill
-   * does not cover.
-   */
-  static void upgradeCustomElements(Node node) {
-    if (JS('bool', '(#.CustomElements && #.CustomElements.upgradeAll)',
-        window, window)) {
-      JS('', '#.CustomElements.upgradeAll(#)', window, node);
-    }
-  }
 }
 // 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
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index adc5b0e..a13b5a7 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -265,24 +265,6 @@
   @DocsEditable()
   void set hreflang(String value) native "HTMLAnchorElement_hreflang_Setter";
 
-  @DomName('HTMLAnchorElement.name')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLAnchorElement-partial
-  @deprecated // deprecated
-  String get name native "HTMLAnchorElement_name_Getter";
-
-  @DomName('HTMLAnchorElement.name')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLAnchorElement-partial
-  @deprecated // deprecated
-  void set name(String value) native "HTMLAnchorElement_name_Setter";
-
-  @DomName('HTMLAnchorElement.origin')
-  @DocsEditable()
-  // WebKit only
-  @deprecated // nonstandard
-  String get origin native "HTMLAnchorElement_origin_Getter";
-
   @DomName('HTMLAnchorElement.pathname')
   @DocsEditable()
   String get pathname native "HTMLAnchorElement_pathname_Getter";
@@ -291,18 +273,6 @@
   @DocsEditable()
   void set pathname(String value) native "HTMLAnchorElement_pathname_Setter";
 
-  @DomName('HTMLAnchorElement.ping')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element
-  @deprecated // deprecated
-  String get ping native "HTMLAnchorElement_ping_Getter";
-
-  @DomName('HTMLAnchorElement.ping')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element
-  @deprecated // deprecated
-  void set ping(String value) native "HTMLAnchorElement_ping_Setter";
-
   @DomName('HTMLAnchorElement.port')
   @DocsEditable()
   String get port native "HTMLAnchorElement_port_Getter";
@@ -477,7 +447,7 @@
 
   @DomName('ApplicationCache.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "ApplicationCache_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "ApplicationCache_addEventListener_Callback";
 
   @DomName('ApplicationCache.dispatchEvent')
   @DocsEditable()
@@ -485,7 +455,7 @@
 
   @DomName('ApplicationCache.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "ApplicationCache_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "ApplicationCache_removeEventListener_Callback";
 
   @DomName('ApplicationCache.oncached')
   @DocsEditable()
@@ -593,18 +563,6 @@
   @DocsEditable()
   String get pathname native "HTMLAreaElement_pathname_Getter";
 
-  @DomName('HTMLAreaElement.ping')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLAreaElement-partial
-  @deprecated // deprecated
-  String get ping native "HTMLAreaElement_ping_Getter";
-
-  @DomName('HTMLAreaElement.ping')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLAreaElement-partial
-  @deprecated // deprecated
-  void set ping(String value) native "HTMLAreaElement_ping_Setter";
-
   @DomName('HTMLAreaElement.port')
   @DocsEditable()
   String get port native "HTMLAreaElement_port_Getter";
@@ -790,6 +748,21 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable()
+@DomName('BeforeUnloadEvent')
+@Experimental() // untriaged
+class BeforeUnloadEvent extends Event {
+  // To suppress missing implicit constructor warnings.
+  factory BeforeUnloadEvent._() { throw new UnsupportedError("Not supported"); }
+
+}
+// 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.
+
 
 @DomName('Blob')
 class Blob extends NativeFieldWrapperClass2 {
@@ -1199,9 +1172,6 @@
   /** An API for drawing on this canvas. */
   CanvasRenderingContext2D get context2D => getContext('2d');
 
-  @deprecated
-  CanvasRenderingContext2D get context2d => this.context2D;
-
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.FIREFOX)
   @Experimental()
@@ -1703,6 +1673,11 @@
   @Experimental() // untriaged
   void drawSystemFocusRing(Element element) native "CanvasRenderingContext2D_drawSystemFocusRing_Callback";
 
+  @DomName('CanvasRenderingContext2D.ellipse')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void ellipse(num x, num y, num radiusX, num radiusY, num rotation, num startAngle, num endAngle, bool anticlockwise) native "CanvasRenderingContext2D_ellipse_Callback";
+
   void fill([String winding]) {
     if (winding != null) {
       _fill_1(winding);
@@ -1745,7 +1720,7 @@
 
   @DomName('CanvasRenderingContext2D.getLineDash')
   @DocsEditable()
-  List<num> getLineDash() native "CanvasRenderingContext2D_getLineDash_Callback";
+  List<num> _getLineDash() native "CanvasRenderingContext2D_getLineDash_Callback";
 
   bool isPointInPath(num x, num y, [String winding]) {
     if (winding != null) {
@@ -1798,6 +1773,11 @@
   @DocsEditable()
   void rect(num x, num y, num width, num height) native "CanvasRenderingContext2D_rect_Callback";
 
+  @DomName('CanvasRenderingContext2D.resetTransform')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void resetTransform() native "CanvasRenderingContext2D_resetTransform_Callback";
+
   @DomName('CanvasRenderingContext2D.restore')
   @DocsEditable()
   void restore() native "CanvasRenderingContext2D_restore_Callback";
@@ -2084,6 +2064,23 @@
 
   // TODO(amouravski): Add Dartium native methods for drawImage once we figure
   // out how to not break native bindings.
+
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @SupportedBrowser(SupportedBrowser.IE, '11')
+  @Unstable()
+  @DomName('CanvasRenderingContext2D.getLineDash')
+  List<num> getLineDash() {
+    // TODO(14316): Firefox has this functionality with mozDash, but it's a bit
+    // different.
+    var result = _getLineDash();
+    if (result == null) {
+      result = [];
+    }
+    return result;
+  }
+
+
 }
 
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -2376,7 +2373,7 @@
   @DomName('ConsoleBase.markTimeline')
   @DocsEditable()
   @Experimental() // untriaged
-  void markTimeline(Object arg) native "ConsoleBase_markTimeline_Callback";
+  void markTimeline(String title) native "ConsoleBase_markTimeline_Callback";
 
   @DomName('ConsoleBase.profile')
   @DocsEditable()
@@ -2406,7 +2403,17 @@
   @DomName('ConsoleBase.timeStamp')
   @DocsEditable()
   @Experimental() // untriaged
-  void timeStamp(Object arg) native "ConsoleBase_timeStamp_Callback";
+  void timeStamp(String title) native "ConsoleBase_timeStamp_Callback";
+
+  @DomName('ConsoleBase.timeline')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void timeline(String title) native "ConsoleBase_timeline_Callback";
+
+  @DomName('ConsoleBase.timelineEnd')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void timelineEnd(String title) native "ConsoleBase_timelineEnd_Callback";
 
   @DomName('ConsoleBase.trace')
   @DocsEditable()
@@ -2736,13 +2743,10 @@
   // To suppress missing implicit constructor warnings.
   factory CssFontFaceLoadEvent._() { throw new UnsupportedError("Not supported"); }
 
-  @DomName('CSSFontFaceLoadEvent.error')
+  @DomName('CSSFontFaceLoadEvent.fontfaces')
   @DocsEditable()
-  DomError get error native "CSSFontFaceLoadEvent_error_Getter";
-
-  @DomName('CSSFontFaceLoadEvent.fontface')
-  @DocsEditable()
-  CssFontFaceRule get fontface native "CSSFontFaceLoadEvent_fontface_Getter";
+  @Experimental() // untriaged
+  List<FontFace> get fontfaces native "CSSFontFaceLoadEvent_fontfaces_Getter";
 
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -3299,12 +3303,6 @@
   @DocsEditable()
   static const int SUPPORTS_RULE = 12;
 
-  @DomName('CSSRule.UNKNOWN_RULE')
-  @DocsEditable()
-  // http://dev.w3.org/csswg/cssom/#changes-from-dom2
-  @deprecated // deprecated
-  static const int UNKNOWN_RULE = 0;
-
   @DomName('CSSRule.VIEWPORT_RULE')
   @DocsEditable()
   @Experimental() // untriaged
@@ -7701,16 +7699,6 @@
   @DocsEditable()
   void set _body(HtmlElement value) native "Document_body_Setter";
 
-  @DomName('Document.charset')
-  @DocsEditable()
-  @deprecated // nonstandard
-  String get charset native "Document_charset_Getter";
-
-  @DomName('Document.charset')
-  @DocsEditable()
-  @deprecated // nonstandard
-  void set charset(String value) native "Document_charset_Setter";
-
   @DomName('Document.cookie')
   @DocsEditable()
   String get cookie native "Document_cookie_Getter";
@@ -7736,11 +7724,10 @@
   @DocsEditable()
   String get domain native "Document_domain_Getter";
 
-  @DomName('Document.fontloader')
+  @DomName('Document.fonts')
   @DocsEditable()
-  // http://www.w3.org/TR/css3-fonts/#document-fontloader
-  @Experimental()
-  FontLoader get fontloader native "Document_fontloader_Getter";
+  @Experimental() // untriaged
+  FontFaceSet get fonts native "Document_fonts_Getter";
 
   @DomName('Document.head')
   @DocsEditable()
@@ -7816,15 +7803,6 @@
   // https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/PageVisibility/Overview.html#document
   bool get _webkitHidden native "Document_webkitHidden_Getter";
 
-  @DomName('Document.webkitIsFullScreen')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html
-  @deprecated // deprecated
-  bool get _webkitIsFullScreen native "Document_webkitIsFullScreen_Getter";
-
   @DomName('Document.webkitPointerLockElement')
   @DocsEditable()
   @SupportedBrowser(SupportedBrowser.CHROME)
@@ -7851,12 +7829,6 @@
   @Experimental()
   Range _caretRangeFromPoint(int x, int y) native "Document_caretRangeFromPoint_Callback";
 
-  @DomName('Document.createCDATASection')
-  @DocsEditable()
-  // http://dom.spec.whatwg.org/#dom-document-createcdatasection
-  @deprecated // deprecated
-  CDataSection createCDataSection(String data) native "Document_createCDATASection_Callback";
-
   @DomName('Document.createDocumentFragment')
   @DocsEditable()
   DocumentFragment createDocumentFragment() native "Document_createDocumentFragment_Callback";
@@ -7908,12 +7880,6 @@
   @Experimental()
   Touch _createTouch(Window window, EventTarget target, int identifier, int pageX, int pageY, int screenX, int screenY, int webkitRadiusX, int webkitRadiusY, num webkitRotationAngle, num webkitForce) native "Document_createTouch_Callback";
 
-  @DomName('Document.createTouchList')
-  @DocsEditable()
-  // http://www.w3.org/TR/touch-events/, http://www.chromestatus.com/features
-  @Experimental()
-  TouchList _createTouchList() native "Document_createTouchList_Callback";
-
   TreeWalker _createTreeWalker(Node root, [int whatToShow, NodeFilter filter, bool expandEntityReferences]) {
     if (expandEntityReferences != null) {
       return _createTreeWalker_1(root, whatToShow, filter, expandEntityReferences);
@@ -8020,15 +7986,6 @@
   @DocsEditable()
   List<Node> _querySelectorAll(String selectors) native "Document_querySelectorAll_Callback";
 
-  @DomName('Document.webkitCancelFullScreen')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html
-  @deprecated // deprecated
-  void _webkitCancelFullScreen() native "Document_webkitCancelFullScreen_Callback";
-
   @DomName('Document.webkitExitFullscreen')
   @DocsEditable()
   @SupportedBrowser(SupportedBrowser.CHROME)
@@ -10073,140 +10030,6 @@
     return false;
   }
 
-  Element _templateInstanceRef;
-
-  // Note: only used if `this is! TemplateElement`
-  DocumentFragment _templateContent;
-
-  bool _templateIsDecorated;
-
-
-
-  /**
-   * Gets the template this node refers to.
-   * This is only supported if [isTemplate] is true.
-   */
-  @Experimental()
-  Element get ref {
-    _ensureTemplate();
-
-    Element result = null;
-    var refId = attributes['ref'];
-    if (refId != null) {
-      var treeScope = this;
-      while (treeScope.parentNode != null) {
-        treeScope = treeScope.parentNode;
-      }
-
-      // Note: JS code tests that getElementById is present. We can't do that
-      // easily, so instead check for the types known to implement it.
-      if (treeScope is Document ||
-          treeScope is ShadowRoot ||
-          treeScope is svg.SvgSvgElement) {
-
-        result = treeScope.getElementById(refId);
-      }
-    }
-
-    if (result == null) {
-      result = _templateInstanceRef;
-      if (result == null) return this;
-    }
-
-    var nextRef = result.ref;
-    return nextRef != null ? nextRef : result;
-  }
-
-  /**
-   * Gets the content of this template.
-   * This is only supported if [isTemplate] is true.
-   */
-  @Experimental()
-  DocumentFragment get content {
-    _ensureTemplate();
-    return _templateContent;
-  }
-
-  /**
-   * Creates an instance of the template, using the provided model and optional
-   * binding delegate.
-   *
-   * This is only supported if [isTemplate] is true.
-   */
-  @Experimental()
-  DocumentFragment createInstance(model, [BindingDelegate delegate]) {
-    _ensureTemplate();
-    return TemplateElement.mdvPackage(this).createInstance(model, delegate);
-  }
-
-  /**
-   * The data model which is inherited through the tree.
-   * This is only supported if [isTemplate] is true.
-   */
-  @Experimental()
-  get model => TemplateElement.mdvPackage(this).model;
-
-  @Experimental()
-  void set model(value) {
-    _ensureTemplate();
-    TemplateElement.mdvPackage(this).model = value;
-  }
-
-  /**
-   * The binding delegate which is inherited through the tree. It can be used
-   * to configure custom syntax for `{{bindings}}` inside this template.
-   *
-   * This is only supported if [isTemplate] is true.
-   */
-  @Experimental()
-  BindingDelegate get bindingDelegate =>
-      TemplateElement.mdvPackage(this).bindingDelegate;
-
-  @Experimental()
-  void set bindingDelegate(BindingDelegate value) {
-    _ensureTemplate();
-    TemplateElement.mdvPackage(this).bindingDelegate = value;
-  }
-
-  // TODO(jmesserly): const set would be better
-  static const _TABLE_TAGS = const {
-    'caption': null,
-    'col': null,
-    'colgroup': null,
-    'tbody': null,
-    'td': null,
-    'tfoot': null,
-    'th': null,
-    'thead': null,
-    'tr': null,
-  };
-
-  bool get _isAttributeTemplate => attributes.containsKey('template') &&
-      (localName == 'option' || localName == 'optgroup' ||
-       _TABLE_TAGS.containsKey(localName));
-
-  /**
-   * Returns true if this node is a template.
-   *
-   * A node is a template if [tagName] is TEMPLATE, or the node has the
-   * 'template' attribute and this tag supports attribute form for backwards
-   * compatibility with existing HTML parsers. The nodes that can use attribute
-   * form are table elments (THEAD, TBODY, TFOOT, TH, TR, TD, CAPTION, COLGROUP
-   * and COL), OPTION, and OPTGROUP.
-   */
-  // TODO(jmesserly): this is not a public MDV API, but it seems like a useful
-  // place to document which tags our polyfill considers to be templates.
-  // Otherwise I'd be repeating it in several other places.
-  // See if we can replace this with a TemplateMixin.
-  @Experimental()
-  bool get isTemplate => tagName == 'TEMPLATE' || _isAttributeTemplate;
-
-  void _ensureTemplate() {
-    if (!isTemplate) {
-      throw new UnsupportedError('$this is not a template.');
-    }
-    TemplateElement.decorate(this);
-  }
 
   /**
    * Access this element's content position.
@@ -10289,6 +10112,7 @@
    * This method is the Dart equivalent to jQuery's
    * [offset](http://api.jquery.com/offset/) method.
    */
+  @Experimental()
   Point get documentOffset => offsetTo(document.documentElement);
 
   /**
@@ -10302,6 +10126,7 @@
    * element is _not_ an offset parent or transitive offset parent to this
    * element, an [ArgumentError] is thrown.
    */
+  @Experimental()
   Point offsetTo(Element parent) {
     return Element._offsetToHelper(this, parent);
   }
@@ -10446,15 +10271,6 @@
   String get innerHtml => _innerHtml;
 
   /**
-   * For use while transitioning to the safe [innerHtml] or [setInnerHtml].
-   * Unsafe because it opens the app to cross-site scripting vulnerabilities.
-   */
-  @deprecated
-  void set unsafeInnerHtml(String html) {
-    _innerHtml = html;
-  }
-
-  /**
    * This is an ease-of-use accessor for event streams which should only be
    * used when an explicit accessor is not available.
    */
@@ -10726,12 +10542,6 @@
 
   void insertAdjacentText(String where, String text);
 
-  @DomName('Element.ALLOW_KEYBOARD_INPUT')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#dom-element-requestfullscreen
-  @deprecated // deprecated
-  static const int ALLOW_KEYBOARD_INPUT = 1;
-
   @DomName('Element.attributes')
   @DocsEditable()
   _NamedNodeMap get _attributes native "Element_attributes_Getter";
@@ -10871,12 +10681,12 @@
 
   @DomName('Element.getAttribute')
   @DocsEditable()
-  @deprecated
+  @Experimental() // untriaged
   String getAttribute(String name) native "Element_getAttribute_Callback";
 
   @DomName('Element.getAttributeNS')
   @DocsEditable()
-  @deprecated
+  @Experimental() // untriaged
   String getAttributeNS(String namespaceURI, String localName) native "Element_getAttributeNS_Callback";
 
   @DomName('Element.getBoundingClientRect')
@@ -10977,12 +10787,10 @@
 
   @DomName('Element.setAttribute')
   @DocsEditable()
-  @deprecated
   void setAttribute(String name, String value) native "Element_setAttribute_Callback";
 
   @DomName('Element.setAttributeNS')
   @DocsEditable()
-  @deprecated
   void setAttributeNS(String namespaceURI, String qualifiedName, String value) native "Element_setAttributeNS_Callback";
 
   @DomName('Element.webkitGetRegionFlowRanges')
@@ -10999,15 +10807,6 @@
   // http://dev.w3.org/2006/webapi/selectors-api2/#matches
   bool matches(String selectors) native "Element_webkitMatchesSelector_Callback";
 
-  @DomName('Element.webkitRequestFullScreen')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#dom-element-requestfullscreen
-  @deprecated // deprecated
-  void requestFullScreen(int flags) native "Element_webkitRequestFullScreen_Callback";
-
   @DomName('Element.webkitRequestFullscreen')
   @DocsEditable()
   @SupportedBrowser(SupportedBrowser.CHROME)
@@ -11335,18 +11134,6 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => true;
 
-  @DomName('HTMLEmbedElement.align')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLEmbedElement-partial
-  @deprecated // deprecated
-  String get align native "HTMLEmbedElement_align_Getter";
-
-  @DomName('HTMLEmbedElement.align')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLEmbedElement-partial
-  @deprecated // deprecated
-  void set align(String value) native "HTMLEmbedElement_align_Setter";
-
   @DomName('HTMLEmbedElement.height')
   @DocsEditable()
   String get height native "HTMLEmbedElement_height_Getter";
@@ -11651,12 +11438,6 @@
   @DocsEditable()
   static const int AT_TARGET = 2;
 
-  @DomName('Event.BLUR')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int BLUR = 8192;
-
   @DomName('Event.BUBBLING_PHASE')
   @DocsEditable()
   static const int BUBBLING_PHASE = 3;
@@ -11665,118 +11446,10 @@
   @DocsEditable()
   static const int CAPTURING_PHASE = 1;
 
-  @DomName('Event.CHANGE')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int CHANGE = 32768;
-
-  @DomName('Event.CLICK')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int CLICK = 64;
-
-  @DomName('Event.DBLCLICK')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int DBLCLICK = 128;
-
-  @DomName('Event.DRAGDROP')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int DRAGDROP = 2048;
-
-  @DomName('Event.FOCUS')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int FOCUS = 4096;
-
-  @DomName('Event.KEYDOWN')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int KEYDOWN = 256;
-
-  @DomName('Event.KEYPRESS')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int KEYPRESS = 1024;
-
-  @DomName('Event.KEYUP')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int KEYUP = 512;
-
-  @DomName('Event.MOUSEDOWN')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int MOUSEDOWN = 1;
-
-  @DomName('Event.MOUSEDRAG')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int MOUSEDRAG = 32;
-
-  @DomName('Event.MOUSEMOVE')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int MOUSEMOVE = 16;
-
-  @DomName('Event.MOUSEOUT')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int MOUSEOUT = 8;
-
-  @DomName('Event.MOUSEOVER')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int MOUSEOVER = 4;
-
-  @DomName('Event.MOUSEUP')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int MOUSEUP = 2;
-
-  @DomName('Event.NONE')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int NONE = 0;
-
-  @DomName('Event.SELECT')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.captureEvents
-  @deprecated // deprecated
-  static const int SELECT = 16384;
-
   @DomName('Event.bubbles')
   @DocsEditable()
   bool get bubbles native "Event_bubbles_Getter";
 
-  @DomName('Event.cancelBubble')
-  @DocsEditable()
-  // http://www.w3.org/TR/DOM-Level-3-Events/#events-event-type-stopPropagation
-  @deprecated // deprecated
-  bool get cancelBubble native "Event_cancelBubble_Getter";
-
-  @DomName('Event.cancelBubble')
-  @DocsEditable()
-  // http://www.w3.org/TR/DOM-Level-3-Events/#events-event-type-stopPropagation
-  @deprecated // deprecated
-  void set cancelBubble(bool value) native "Event_cancelBubble_Setter";
-
   @DomName('Event.cancelable')
   @DocsEditable()
   bool get cancelable native "Event_cancelable_Getter";
@@ -11906,7 +11579,7 @@
 
   @DomName('EventSource.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "EventSource_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "EventSource_addEventListener_Callback";
 
   @DomName('EventSource.dispatchEvent')
   @DocsEditable()
@@ -11914,7 +11587,7 @@
 
   @DomName('EventSource.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "EventSource_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "EventSource_removeEventListener_Callback";
 
   @DomName('EventSource.onerror')
   @DocsEditable()
@@ -11984,10 +11657,32 @@
 class ElementEvents extends Events {
   /* Raw event target. */
   final Element _ptr;
+  static final webkitEvents = {
+    'animationend' : 'webkitAnimationEnd', 
+    'animationiteration' : 'webkitAnimationIteration', 
+    'animationstart' : 'webkitAnimationStart', 
+    'fullscreenchange' : 'webkitfullscreenchange', 
+    'fullscreenerror' : 'webkitfullscreenerror',
+    'keyadded' : 'webkitkeyadded', 
+    'keyerror' : 'webkitkeyerror', 
+    'keymessage' : 'webkitkeymessage', 
+    'needkey' : 'webkitneedkey', 
+    'pointerlockchange' : 'webkitpointerlockchange', 
+    'pointerlockerror' : 'webkitpointerlockerror', 
+    'resourcetimingbufferfull' : 'webkitresourcetimingbufferfull', 
+    'transitionend': 'webkitTransitionEnd',
+    'speechchange' : 'webkitSpeechChange'
+  };
 
   ElementEvents(Element ptr) : this._ptr = ptr, super(ptr);
 
   Stream operator [](String type) {
+    if (webkitEvents.keys.contains(type.toLowerCase())) {
+      if (Device.isWebKit) {
+        return new _ElementEventStreamImpl(
+            _ptr, webkitEvents[type.toLowerCase()], false);
+      }
+    }
     return new _ElementEventStreamImpl(_ptr, type, false);
   }
 }
@@ -11995,8 +11690,7 @@
 /**
  * Base class for all browser objects that support events.
  *
- * Use the [on] property to add, and remove events (rather than
- * [$dom_addEventListener] and [$dom_removeEventListener]
+ * Use the [on] property to add, and remove events
  * for compile-time type checks and a more concise API.
  */
 @DomName('EventTarget')
@@ -12015,8 +11709,7 @@
 
   @DomName('EventTarget.addEventListener')
   @DocsEditable()
-  @deprecated
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "EventTarget_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "EventTarget_addEventListener_Callback";
 
   @DomName('EventTarget.dispatchEvent')
   @DocsEditable()
@@ -12024,8 +11717,7 @@
 
   @DomName('EventTarget.removeEventListener')
   @DocsEditable()
-  @deprecated
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "EventTarget_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "EventTarget_removeEventListener_Callback";
 
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -12395,12 +12087,6 @@
   @DocsEditable()
   void readAsArrayBuffer(Blob blob) native "FileReader_readAsArrayBuffer_Callback";
 
-  @DomName('FileReader.readAsBinaryString')
-  @DocsEditable()
-  // http://blog.whatwg.org/weekly-stream-autocomplete
-  @deprecated // deprecated
-  void readAsBinaryString(Blob blob) native "FileReader_readAsBinaryString_Callback";
-
   @DomName('FileReader.readAsDataURL')
   @DocsEditable()
   void readAsDataUrl(Blob blob) native "FileReader_readAsDataURL_Callback";
@@ -12420,7 +12106,7 @@
 
   @DomName('FileReader.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "FileReader_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "FileReader_addEventListener_Callback";
 
   @DomName('FileReader.dispatchEvent')
   @DocsEditable()
@@ -12428,7 +12114,7 @@
 
   @DomName('FileReader.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "FileReader_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "FileReader_removeEventListener_Callback";
 
   @DomName('FileReader.onabort')
   @DocsEditable()
@@ -12599,7 +12285,7 @@
 
   @DomName('FileWriter.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "FileWriter_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "FileWriter_addEventListener_Callback";
 
   @DomName('FileWriter.dispatchEvent')
   @DocsEditable()
@@ -12607,7 +12293,7 @@
 
   @DomName('FileWriter.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "FileWriter_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "FileWriter_removeEventListener_Callback";
 
   @DomName('FileWriter.onabort')
   @DocsEditable()
@@ -12671,87 +12357,140 @@
 
 
 @DocsEditable()
-@DomName('FontLoader')
-// http://www.w3.org/TR/css3-fonts/#document-fontloader
-@Experimental()
-class FontLoader extends EventTarget {
+@DomName('FontFace')
+@Experimental() // untriaged
+class FontFace extends NativeFieldWrapperClass2 {
   // To suppress missing implicit constructor warnings.
-  factory FontLoader._() { throw new UnsupportedError("Not supported"); }
+  factory FontFace._() { throw new UnsupportedError("Not supported"); }
 
-  @DomName('FontLoader.errorEvent')
+  @DomName('FontFace.FontFace')
   @DocsEditable()
-  static const EventStreamProvider<Event> errorEvent = const EventStreamProvider<Event>('error');
-
-  @DomName('FontLoader.loadEvent')
-  @DocsEditable()
-  static const EventStreamProvider<CssFontFaceLoadEvent> loadEvent = const EventStreamProvider<CssFontFaceLoadEvent>('load');
-
-  @DomName('FontLoader.loadingEvent')
-  @DocsEditable()
-  static const EventStreamProvider<CssFontFaceLoadEvent> loadingEvent = const EventStreamProvider<CssFontFaceLoadEvent>('loading');
-
-  @DomName('FontLoader.loadingdoneEvent')
-  @DocsEditable()
-  static const EventStreamProvider<CssFontFaceLoadEvent> loadingDoneEvent = const EventStreamProvider<CssFontFaceLoadEvent>('loadingdone');
-
-  @DomName('FontLoader.loadstartEvent')
-  @DocsEditable()
-  static const EventStreamProvider<CssFontFaceLoadEvent> loadStartEvent = const EventStreamProvider<CssFontFaceLoadEvent>('loadstart');
-
-  @DomName('FontLoader.loading')
-  @DocsEditable()
-  bool get loading native "FontLoader_loading_Getter";
-
-  @DomName('FontLoader.checkFont')
-  @DocsEditable()
-  bool checkFont(String font, String text) native "FontLoader_checkFont_Callback";
-
-  @DomName('FontLoader.loadFont')
-  @DocsEditable()
-  void loadFont(Map params) native "FontLoader_loadFont_Callback";
-
-  @DomName('FontLoader.notifyWhenFontsReady')
-  @DocsEditable()
-  void _notifyWhenFontsReady(VoidCallback callback) native "FontLoader_notifyWhenFontsReady_Callback";
-
-  Future notifyWhenFontsReady() {
-    var completer = new Completer();
-    _notifyWhenFontsReady(
-        () { completer.complete(); });
-    return completer.future;
+  factory FontFace(String family, String source, Map descriptors) {
+    return FontFace._create_1(family, source, descriptors);
   }
 
-  @DomName('FontLoader.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "FontLoader_addEventListener_Callback";
+  static FontFace _create_1(family, source, descriptors) native "FontFace__create_1constructorCallback";
 
-  @DomName('FontLoader.dispatchEvent')
+  @DomName('FontFace.family')
   @DocsEditable()
-  bool dispatchEvent(Event event) native "FontLoader_dispatchEvent_Callback";
+  @Experimental() // untriaged
+  String get family native "FontFace_family_Getter";
 
-  @DomName('FontLoader.removeEventListener')
+  @DomName('FontFace.family')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "FontLoader_removeEventListener_Callback";
+  @Experimental() // untriaged
+  void set family(String value) native "FontFace_family_Setter";
 
-  @DomName('FontLoader.onerror')
+  @DomName('FontFace.featureSettings')
   @DocsEditable()
-  Stream<Event> get onError => errorEvent.forTarget(this);
+  @Experimental() // untriaged
+  String get featureSettings native "FontFace_featureSettings_Getter";
 
-  @DomName('FontLoader.onload')
+  @DomName('FontFace.featureSettings')
   @DocsEditable()
-  Stream<CssFontFaceLoadEvent> get onLoad => loadEvent.forTarget(this);
+  @Experimental() // untriaged
+  void set featureSettings(String value) native "FontFace_featureSettings_Setter";
 
-  @DomName('FontLoader.onloading')
+  @DomName('FontFace.status')
   @DocsEditable()
-  Stream<CssFontFaceLoadEvent> get onLoading => loadingEvent.forTarget(this);
+  @Experimental() // untriaged
+  String get status native "FontFace_status_Getter";
 
-  @DomName('FontLoader.onloadingdone')
+  @DomName('FontFace.stretch')
   @DocsEditable()
-  Stream<CssFontFaceLoadEvent> get onLoadingDone => loadingDoneEvent.forTarget(this);
+  @Experimental() // untriaged
+  String get stretch native "FontFace_stretch_Getter";
 
-  @DomName('FontLoader.onloadstart')
+  @DomName('FontFace.stretch')
   @DocsEditable()
-  Stream<CssFontFaceLoadEvent> get onLoadStart => loadStartEvent.forTarget(this);
+  @Experimental() // untriaged
+  void set stretch(String value) native "FontFace_stretch_Setter";
+
+  @DomName('FontFace.style')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String get style native "FontFace_style_Getter";
+
+  @DomName('FontFace.style')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void set style(String value) native "FontFace_style_Setter";
+
+  @DomName('FontFace.unicodeRange')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String get unicodeRange native "FontFace_unicodeRange_Getter";
+
+  @DomName('FontFace.unicodeRange')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void set unicodeRange(String value) native "FontFace_unicodeRange_Setter";
+
+  @DomName('FontFace.variant')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String get variant native "FontFace_variant_Getter";
+
+  @DomName('FontFace.variant')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void set variant(String value) native "FontFace_variant_Setter";
+
+  @DomName('FontFace.weight')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String get weight native "FontFace_weight_Getter";
+
+  @DomName('FontFace.weight')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void set weight(String value) native "FontFace_weight_Setter";
+
+}
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable()
+@DomName('FontFaceSet')
+@Experimental() // untriaged
+class FontFaceSet extends EventTarget {
+  // To suppress missing implicit constructor warnings.
+  factory FontFaceSet._() { throw new UnsupportedError("Not supported"); }
+
+  @DomName('FontFaceSet.status')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String get status native "FontFaceSet_status_Getter";
+
+  @DomName('FontFaceSet.check')
+  @DocsEditable()
+  @Experimental() // untriaged
+  bool check(String font, String text) native "FontFaceSet_check_Callback";
+
+  @DomName('FontFaceSet.match')
+  @DocsEditable()
+  @Experimental() // untriaged
+  List<FontFace> match(String font, String text) native "FontFaceSet_match_Callback";
+
+  @DomName('FontFaceSet.addEventListener')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "FontFaceSet_addEventListener_Callback";
+
+  @DomName('FontFaceSet.dispatchEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  bool dispatchEvent(Event event) native "FontFaceSet_dispatchEvent_Callback";
+
+  @DomName('FontFaceSet.removeEventListener')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "FontFaceSet_removeEventListener_Callback";
 
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -13504,18 +13243,6 @@
   @DocsEditable()
   Element get activeElement native "HTMLDocument_activeElement_Getter";
 
-  @DomName('HTMLDocument.captureEvents')
-  @DocsEditable()
-  // http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture
-  @deprecated // deprecated
-  void captureEvents() native "HTMLDocument_captureEvents_Callback";
-
-  @DomName('HTMLDocument.releaseEvents')
-  @DocsEditable()
-  // http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture
-  @deprecated // deprecated
-  void releaseEvents() native "HTMLDocument_releaseEvents_Callback";
-
 
   @DomName('Document.body')
   BodyElement get body => _body;
@@ -13603,14 +13330,6 @@
     _title = value;
   }
 
-  @DomName('Document.webkitCancelFullScreen')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  void cancelFullScreen() {
-    _webkitCancelFullScreen();
-  }
-
   @DomName('Document.webkitExitFullscreen')
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.SAFARI)
@@ -13645,12 +13364,6 @@
   @Experimental()
   bool get hidden => _webkitHidden;
 
-  @DomName('Document.webkitIsFullScreen')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  bool get isFullScreen => _webkitIsFullScreen;
-
   @DomName('Document.webkitPointerLockElement')
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.SAFARI)
@@ -13665,7 +13378,7 @@
   @Experimental()
   String get visibilityState => _webkitVisibilityState;
 
-  @Experimental
+  @Experimental()
   /**
    * Register a custom subclass of Element to be instantiatable by the DOM.
    *
@@ -13737,9 +13450,6 @@
     _Utils.register(this, tag, customElementClass, extendsTag);
   }
 
-  // Note: used to polyfill <template>
-  Document _templateContentsOwner;
-
   @DomName('Document.visibilityChange')
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.FIREFOX)
@@ -14721,16 +14431,6 @@
   @DocsEditable()
   void set alt(String value) native "HTMLImageElement_alt_Setter";
 
-  @DomName('HTMLImageElement.border')
-  @DocsEditable()
-  @deprecated // deprecated
-  String get border native "HTMLImageElement_border_Getter";
-
-  @DomName('HTMLImageElement.border')
-  @DocsEditable()
-  @deprecated // deprecated
-  void set border(String value) native "HTMLImageElement_border_Setter";
-
   @DomName('HTMLImageElement.complete')
   @DocsEditable()
   bool get complete native "HTMLImageElement_complete_Getter";
@@ -14759,16 +14459,6 @@
   @DocsEditable()
   void set isMap(bool value) native "HTMLImageElement_isMap_Setter";
 
-  @DomName('HTMLImageElement.lowsrc')
-  @DocsEditable()
-  @deprecated // deprecated
-  String get lowsrc native "HTMLImageElement_lowsrc_Getter";
-
-  @DomName('HTMLImageElement.lowsrc')
-  @DocsEditable()
-  @deprecated // deprecated
-  void set lowsrc(String value) native "HTMLImageElement_lowsrc_Setter";
-
   @DomName('HTMLImageElement.naturalHeight')
   @DocsEditable()
   int get naturalHeight native "HTMLImageElement_naturalHeight_Getter";
@@ -14785,6 +14475,16 @@
   @DocsEditable()
   void set src(String value) native "HTMLImageElement_src_Setter";
 
+  @DomName('HTMLImageElement.srcset')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String get srcset native "HTMLImageElement_srcset_Getter";
+
+  @DomName('HTMLImageElement.srcset')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void set srcset(String value) native "HTMLImageElement_srcset_Setter";
+
   @DomName('HTMLImageElement.useMap')
   @DocsEditable()
   String get useMap native "HTMLImageElement_useMap_Getter";
@@ -14801,16 +14501,6 @@
   @DocsEditable()
   void set width(int value) native "HTMLImageElement_width_Setter";
 
-  @DomName('HTMLImageElement.x')
-  @DocsEditable()
-  @deprecated // deprecated
-  int get x native "HTMLImageElement_x_Getter";
-
-  @DomName('HTMLImageElement.y')
-  @DocsEditable()
-  @deprecated // deprecated
-  int get y native "HTMLImageElement_y_Getter";
-
 }
 // 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
@@ -15168,18 +14858,6 @@
   @DocsEditable()
   void set type(String value) native "HTMLInputElement_type_Setter";
 
-  @DomName('HTMLInputElement.useMap')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLInputElement-partial
-  @deprecated // deprecated
-  String get useMap native "HTMLInputElement_useMap_Getter";
-
-  @DomName('HTMLInputElement.useMap')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLInputElement-partial
-  @deprecated // deprecated
-  void set useMap(String value) native "HTMLInputElement_useMap_Setter";
-
   @DomName('HTMLInputElement.validationMessage')
   @DocsEditable()
   String get validationMessage native "HTMLInputElement_validationMessage_Getter";
@@ -15955,6 +15633,31 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable()
+@DomName('KeyPair')
+@Experimental() // untriaged
+class KeyPair extends NativeFieldWrapperClass2 {
+  // To suppress missing implicit constructor warnings.
+  factory KeyPair._() { throw new UnsupportedError("Not supported"); }
+
+  @DomName('KeyPair.privateKey')
+  @DocsEditable()
+  @Experimental() // untriaged
+  CryptoKey get privateKey native "KeyPair_privateKey_Getter";
+
+  @DomName('KeyPair.publicKey')
+  @DocsEditable()
+  @Experimental() // untriaged
+  CryptoKey get publicKey native "KeyPair_publicKey_Getter";
+
+}
+// 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.
+
 
 @DomName('KeyboardEvent')
 class KeyboardEvent extends UIEvent {
@@ -16174,18 +15877,6 @@
    */
   LIElement.created() : super.created();
 
-  @DomName('HTMLLIElement.type')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLLIElement-partial
-  @deprecated // deprecated
-  String get type native "HTMLLIElement_type_Getter";
-
-  @DomName('HTMLLIElement.type')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLLIElement-partial
-  @deprecated // deprecated
-  void set type(String value) native "HTMLLIElement_type_Setter";
-
   @DomName('HTMLLIElement.value')
   @DocsEditable()
   int get value native "HTMLLIElement_value_Getter";
@@ -16616,7 +16307,7 @@
 
   @DomName('MediaController.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "MediaController_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "MediaController_addEventListener_Callback";
 
   @DomName('MediaController.dispatchEvent')
   @DocsEditable()
@@ -16624,7 +16315,7 @@
 
   @DomName('MediaController.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "MediaController_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "MediaController_removeEventListener_Callback";
 
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -17448,7 +17139,7 @@
 
   @DomName('MediaKeySession.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "MediaKeySession_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "MediaKeySession_addEventListener_Callback";
 
   @DomName('MediaKeySession.dispatchEvent')
   @DocsEditable()
@@ -17456,7 +17147,7 @@
 
   @DomName('MediaKeySession.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "MediaKeySession_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "MediaKeySession_removeEventListener_Callback";
 
   @DomName('MediaKeySession.onwebkitkeyadded')
   @DocsEditable()
@@ -17655,7 +17346,7 @@
 
   @DomName('MediaSource.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "MediaSource_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "MediaSource_addEventListener_Callback";
 
   @DomName('MediaSource.dispatchEvent')
   @DocsEditable()
@@ -17663,7 +17354,7 @@
 
   @DomName('MediaSource.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "MediaSource_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "MediaSource_removeEventListener_Callback";
 
 }
 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
@@ -17754,7 +17445,7 @@
 
   @DomName('MediaStream.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "MediaStream_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "MediaStream_addEventListener_Callback";
 
   @DomName('MediaStream.dispatchEvent')
   @DocsEditable()
@@ -17762,7 +17453,7 @@
 
   @DomName('MediaStream.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "MediaStream_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "MediaStream_removeEventListener_Callback";
 
   @DomName('MediaStream.onaddtrack')
   @DocsEditable()
@@ -17876,7 +17567,7 @@
 
   @DomName('MediaStreamTrack.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "MediaStreamTrack_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "MediaStreamTrack_addEventListener_Callback";
 
   @DomName('MediaStreamTrack.dispatchEvent')
   @DocsEditable()
@@ -17884,7 +17575,7 @@
 
   @DomName('MediaStreamTrack.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "MediaStreamTrack_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "MediaStreamTrack_removeEventListener_Callback";
 
   @DomName('MediaStreamTrack.onended')
   @DocsEditable()
@@ -18054,11 +17745,6 @@
   @DocsEditable()
   String get origin native "MessageEvent_origin_Getter";
 
-  @DomName('MessageEvent.ports')
-  @DocsEditable()
-  @Unstable()
-  List<MessagePort> get ports native "MessageEvent_ports_Getter";
-
   @DomName('MessageEvent.source')
   @DocsEditable()
   EventTarget get source native "MessageEvent_source_Getter";
@@ -18100,7 +17786,7 @@
 
   @DomName('MessagePort.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "MessagePort_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "MessagePort_addEventListener_Callback";
 
   @DomName('MessagePort.dispatchEvent')
   @DocsEditable()
@@ -18108,7 +17794,7 @@
 
   @DomName('MessagePort.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "MessagePort_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "MessagePort_removeEventListener_Callback";
 
   @DomName('MessagePort.onmessage')
   @DocsEditable()
@@ -18315,7 +18001,7 @@
 
   @DomName('MIDIAccess.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "MIDIAccess_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "MIDIAccess_addEventListener_Callback";
 
   @DomName('MIDIAccess.dispatchEvent')
   @DocsEditable()
@@ -18323,7 +18009,7 @@
 
   @DomName('MIDIAccess.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "MIDIAccess_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "MIDIAccess_removeEventListener_Callback";
 
   @DomName('MIDIAccess.onconnect')
   @DocsEditable()
@@ -18492,7 +18178,7 @@
 
   @DomName('MIDIPort.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "MIDIPort_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "MIDIPort_addEventListener_Callback";
 
   @DomName('MIDIPort.dispatchEvent')
   @DocsEditable()
@@ -18500,7 +18186,7 @@
 
   @DomName('MIDIPort.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "MIDIPort_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "MIDIPort_removeEventListener_Callback";
 
   @DomName('MIDIPort.ondisconnect')
   @DocsEditable()
@@ -19055,7 +18741,7 @@
 
   @DomName('WebKitNamedFlow.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "WebKitNamedFlow_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "WebKitNamedFlow_addEventListener_Callback";
 
   @DomName('WebKitNamedFlow.dispatchEvent')
   @DocsEditable()
@@ -19063,7 +18749,7 @@
 
   @DomName('WebKitNamedFlow.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "WebKitNamedFlow_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "WebKitNamedFlow_removeEventListener_Callback";
 
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -19167,11 +18853,6 @@
   // To suppress missing implicit constructor warnings.
   factory Navigator._() { throw new UnsupportedError("Not supported"); }
 
-  @DomName('Navigator.appCodeName')
-  @DocsEditable()
-  @Experimental() // non-standard
-  String get appCodeName native "Navigator_appCodeName_Getter";
-
   @DomName('Navigator.cookieEnabled')
   @DocsEditable()
   @Unstable()
@@ -19197,16 +18878,6 @@
   @Experimental() // nonstandard
   MimeTypeArray get mimeTypes native "Navigator_mimeTypes_Getter";
 
-  @DomName('Navigator.plugins')
-  @DocsEditable()
-  @deprecated // nonstandard
-  PluginArray get plugins native "Navigator_plugins_Getter";
-
-  @DomName('Navigator.product')
-  @DocsEditable()
-  @Unstable()
-  String get product native "Navigator_product_Getter";
-
   @DomName('Navigator.productSub')
   @DocsEditable()
   @Unstable()
@@ -19244,11 +18915,6 @@
   @Experimental()
   void getStorageUpdates() native "Navigator_getStorageUpdates_Callback";
 
-  @DomName('Navigator.javaEnabled')
-  @DocsEditable()
-  @deprecated // nonstandard
-  bool javaEnabled() native "Navigator_javaEnabled_Callback";
-
   @DomName('Navigator.registerProtocolHandler')
   @DocsEditable()
   @Unstable()
@@ -19273,6 +18939,11 @@
   @Experimental()
   void _getUserMedia(Map options, _NavigatorUserMediaSuccessCallback successCallback, [_NavigatorUserMediaErrorCallback errorCallback]) native "Navigator_webkitGetUserMedia_Callback";
 
+  @DomName('Navigator.appCodeName')
+  @DocsEditable()
+  @Experimental() // non-standard
+  String get appCodeName native "Navigator_appCodeName_Getter";
+
   @DomName('Navigator.appName')
   @DocsEditable()
   String get appName native "Navigator_appName_Getter";
@@ -19285,6 +18956,11 @@
   @DocsEditable()
   String get platform native "Navigator_platform_Getter";
 
+  @DomName('Navigator.product')
+  @DocsEditable()
+  @Unstable()
+  String get product native "Navigator_product_Getter";
+
   @DomName('Navigator.userAgent')
   @DocsEditable()
   String get userAgent native "Navigator_userAgent_Getter";
@@ -19309,6 +18985,11 @@
   // To suppress missing implicit constructor warnings.
   factory NavigatorID._() { throw new UnsupportedError("Not supported"); }
 
+  @DomName('NavigatorID.appCodeName')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String get appCodeName native "NavigatorID_appCodeName_Getter";
+
   @DomName('NavigatorID.appName')
   @DocsEditable()
   @Experimental() // untriaged
@@ -19324,6 +19005,11 @@
   @Experimental() // untriaged
   String get platform native "NavigatorID_platform_Getter";
 
+  @DomName('NavigatorID.product')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String get product native "NavigatorID_product_Getter";
+
   @DomName('NavigatorID.userAgent')
   @DocsEditable()
   @Experimental() // untriaged
@@ -19564,27 +19250,6 @@
   Node operator[](int index) => _this.childNodes[index];
 }
 
-/** Information about the instantiated template. */
-class TemplateInstance {
-  // TODO(rafaelw): firstNode & lastNode should be read-synchronous
-  // in cases where script has modified the template instance boundary.
-
-  /** The first node of this template instantiation. */
-  final Node firstNode;
-
-  /**
-   * The last node of this template instantiation.
-   * This could be identical to [firstNode] if the template only expanded to a
-   * single node.
-   */
-  final Node lastNode;
-
-  /** The model used to instantiate the template. */
-  final model;
-
-  TemplateInstance(this.firstNode, this.lastNode, this.model);
-}
-
 
 @DomName('Node')
 class Node extends EventTarget {
@@ -19663,52 +19328,6 @@
    */
   String toString() => nodeValue == null ? super.toString() : nodeValue;
 
-
-  /**
-   * Creates a binding to the attribute [name] to the [path] of the [model].
-   *
-   * This can be overridden by custom elements to provide the binding used in
-   * [Node.bind]. This will only create the binding; it will not add it to
-   * [bindings].
-   *
-   * You should not need to call this directly except from [Node.bind].
-   */
-  @Experimental()
-  createBinding(String name, model, String path) =>
-      TemplateElement.mdvPackage(this).createBinding(name, model, path);
-
-  /**
-   * Binds the attribute [name] to the [path] of the [model].
-   * Path is a String of accessors such as `foo.bar.baz`.
-   * Returns the `NodeBinding` instance.
-   */
-  @Experimental()
-  bind(String name, model, String path) =>
-      TemplateElement.mdvPackage(this).bind(name, model, path);
-
-  /** Unbinds the attribute [name]. */
-  @Experimental()
-  void unbind(String name) {
-    TemplateElement.mdvPackage(this).unbind(name);
-  }
-
-  /** Unbinds all bound attributes. */
-  @Experimental()
-  void unbindAll() {
-    TemplateElement.mdvPackage(this).unbindAll();
-  }
-
-  /** Gets the data bindings that are associated with this node. */
-  @Experimental()
-  Map<String, dynamic> get bindings =>
-      TemplateElement.mdvPackage(this).bindings;
-
-  /** Gets the template instance that instantiated this node, if any. */
-  @Experimental()
-  TemplateInstance get templateInstance =>
-      TemplateElement.mdvPackage(this).templateInstance;
-
-
   /**
    * Use ownerDocument instead.
    */
@@ -19772,7 +19391,6 @@
 
   @DomName('Node.childNodes')
   @DocsEditable()
-  @deprecated
   List<Node> get childNodes native "Node_childNodes_Getter";
 
   @DomName('Node.firstChild')
@@ -19785,14 +19403,10 @@
 
   @DomName('Node.localName')
   @DocsEditable()
-  // http://dom.spec.whatwg.org/#dom-node-localname
-  @deprecated // deprecated
   String get _localName native "Node_localName_Getter";
 
   @DomName('Node.namespaceURI')
   @DocsEditable()
-  // http://dom.spec.whatwg.org/#dom-node-namespaceuri
-  @deprecated // deprecated
   String get _namespaceUri native "Node_namespaceURI_Getter";
 
   @DomName('Node.nextSibling')
@@ -19874,7 +19488,7 @@
 
   @DomName('Node.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "Node_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "Node_addEventListener_Callback";
 
   @DomName('Node.dispatchEvent')
   @DocsEditable()
@@ -19882,7 +19496,7 @@
 
   @DomName('Node.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "Node_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "Node_removeEventListener_Callback";
 
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -19915,16 +19529,6 @@
   @DocsEditable()
   static const int SHOW_ALL = 0xFFFFFFFF;
 
-  @DomName('NodeFilter.SHOW_ATTRIBUTE')
-  @DocsEditable()
-  @deprecated // deprecated
-  static const int SHOW_ATTRIBUTE = 0x00000002;
-
-  @DomName('NodeFilter.SHOW_CDATA_SECTION')
-  @DocsEditable()
-  @deprecated // deprecated
-  static const int SHOW_CDATA_SECTION = 0x00000008;
-
   @DomName('NodeFilter.SHOW_COMMENT')
   @DocsEditable()
   static const int SHOW_COMMENT = 0x00000080;
@@ -19945,21 +19549,6 @@
   @DocsEditable()
   static const int SHOW_ELEMENT = 0x00000001;
 
-  @DomName('NodeFilter.SHOW_ENTITY')
-  @DocsEditable()
-  @deprecated // deprecated
-  static const int SHOW_ENTITY = 0x00000020;
-
-  @DomName('NodeFilter.SHOW_ENTITY_REFERENCE')
-  @DocsEditable()
-  @deprecated // deprecated
-  static const int SHOW_ENTITY_REFERENCE = 0x00000010;
-
-  @DomName('NodeFilter.SHOW_NOTATION')
-  @DocsEditable()
-  @deprecated // deprecated
-  static const int SHOW_NOTATION = 0x00000800;
-
   @DomName('NodeFilter.SHOW_PROCESSING_INSTRUCTION')
   @DocsEditable()
   static const int SHOW_PROCESSING_INSTRUCTION = 0x00000040;
@@ -20094,14 +19683,6 @@
   // To suppress missing implicit constructor warnings.
   factory Notation._() { throw new UnsupportedError("Not supported"); }
 
-  @DomName('Notation.publicId')
-  @DocsEditable()
-  String get publicId native "Notation_publicId_Getter";
-
-  @DomName('Notation.systemId')
-  @DocsEditable()
-  String get systemId native "Notation_systemId_Getter";
-
 }
 // 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
@@ -20219,7 +19800,7 @@
 
   @DomName('Notification.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "Notification_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "Notification_addEventListener_Callback";
 
   @DomName('Notification.dispatchEvent')
   @DocsEditable()
@@ -20227,7 +19808,7 @@
 
   @DomName('Notification.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "Notification_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "Notification_removeEventListener_Callback";
 
   @DomName('Notification.onclick')
   @DocsEditable()
@@ -20381,18 +19962,6 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => true;
 
-  @DomName('HTMLObjectElement.code')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLObjectElement-partial
-  @deprecated // deprecated
-  String get code native "HTMLObjectElement_code_Getter";
-
-  @DomName('HTMLObjectElement.code')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLObjectElement-partial
-  @deprecated // deprecated
-  void set code(String value) native "HTMLObjectElement_code_Setter";
-
   @DomName('HTMLObjectElement.data')
   @DocsEditable()
   String get data native "HTMLObjectElement_data_Getter";
@@ -21016,7 +20585,7 @@
   @DomName('Performance.addEventListener')
   @DocsEditable()
   @Experimental() // untriaged
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "Performance_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "Performance_addEventListener_Callback";
 
   @DomName('Performance.dispatchEvent')
   @DocsEditable()
@@ -21026,7 +20595,7 @@
   @DomName('Performance.removeEventListener')
   @DocsEditable()
   @Experimental() // untriaged
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "Performance_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "Performance_removeEventListener_Callback";
 
   @DomName('Performance.onwebkitresourcetimingbufferfull')
   @DocsEditable()
@@ -21527,16 +21096,6 @@
    */
   PreElement.created() : super.created();
 
-  @DomName('HTMLPreElement.wrap')
-  @DocsEditable()
-  @deprecated // deprecated
-  bool get wrap native "HTMLPreElement_wrap_Getter";
-
-  @DomName('HTMLPreElement.wrap')
-  @DocsEditable()
-  @deprecated // deprecated
-  void set wrap(bool value) native "HTMLPreElement_wrap_Setter";
-
 }
 // 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
@@ -21668,11 +21227,6 @@
   @Experimental() // untriaged
   static Promise every(Object values) native "Promise_every_Callback";
 
-  @DomName('Promise.fulfill')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static Promise fulfill(Object value) native "Promise_fulfill_Callback";
-
   @DomName('Promise.reject')
   @DocsEditable()
   @Experimental() // untriaged
@@ -21683,41 +21237,6 @@
   @Experimental() // untriaged
   static Promise resolve(Object value) native "Promise_resolve_Callback";
 
-  @DomName('Promise.some')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static Promise some(Object values) native "Promise_some_Callback";
-
-}
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// WARNING: Do not edit - generated code.
-
-
-@DocsEditable()
-@DomName('PromiseResolver')
-@Experimental() // untriaged
-class PromiseResolver extends NativeFieldWrapperClass2 {
-  // To suppress missing implicit constructor warnings.
-  factory PromiseResolver._() { throw new UnsupportedError("Not supported"); }
-
-  @DomName('PromiseResolver.fulfill')
-  @DocsEditable()
-  @Experimental() // untriaged
-  void fulfill([Object value]) native "PromiseResolver_fulfill_Callback";
-
-  @DomName('PromiseResolver.reject')
-  @DocsEditable()
-  @Experimental() // untriaged
-  void reject([Object value]) native "PromiseResolver_reject_Callback";
-
-  @DomName('PromiseResolver.resolve')
-  @DocsEditable()
-  @Experimental() // untriaged
-  void resolve([Object value]) native "PromiseResolver_resolve_Callback";
-
 }
 // 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
@@ -21873,11 +21392,6 @@
   @DocsEditable()
   void collapse(bool toStart) native "Range_collapse_Callback";
 
-  @DomName('Range.compareNode')
-  @DocsEditable()
-  @deprecated // deprecated
-  int compareNode(Node refNode) native "Range_compareNode_Callback";
-
   @DomName('Range.comparePoint')
   @DocsEditable()
   int comparePoint(Node refNode, int offset) native "Range_comparePoint_Callback";
@@ -21915,11 +21429,6 @@
   @DocsEditable()
   void insertNode(Node newNode) native "Range_insertNode_Callback";
 
-  @DomName('Range.intersectsNode')
-  @DocsEditable()
-  @deprecated // deprecated
-  bool intersectsNode(Node refNode) native "Range_intersectsNode_Callback";
-
   @DomName('Range.isPointInRange')
   @DocsEditable()
   bool isPointInRange(Node refNode, int offset) native "Range_isPointInRange_Callback";
@@ -22183,7 +21692,7 @@
 
   @DomName('RTCDataChannel.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "RTCDataChannel_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "RTCDataChannel_addEventListener_Callback";
 
   @DomName('RTCDataChannel.dispatchEvent')
   @DocsEditable()
@@ -22191,7 +21700,7 @@
 
   @DomName('RTCDataChannel.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "RTCDataChannel_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "RTCDataChannel_removeEventListener_Callback";
 
   @DomName('RTCDataChannel.onclose')
   @DocsEditable()
@@ -22290,7 +21799,7 @@
 
   @DomName('RTCDTMFSender.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "RTCDTMFSender_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "RTCDTMFSender_addEventListener_Callback";
 
   @DomName('RTCDTMFSender.dispatchEvent')
   @DocsEditable()
@@ -22298,7 +21807,7 @@
 
   @DomName('RTCDTMFSender.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "RTCDTMFSender_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "RTCDTMFSender_removeEventListener_Callback";
 
   @DomName('RTCDTMFSender.ontonechange')
   @DocsEditable()
@@ -22483,7 +21992,7 @@
 
   @DomName('RTCPeerConnection.addIceCandidate')
   @DocsEditable()
-  void addIceCandidate(RtcIceCandidate candidate) native "RTCPeerConnection_addIceCandidate_Callback";
+  void addIceCandidate(RtcIceCandidate candidate, VoidCallback successCallback, _RtcErrorCallback failureCallback) native "RTCPeerConnection_addIceCandidate_Callback";
 
   @DomName('RTCPeerConnection.addStream')
   @DocsEditable()
@@ -22559,7 +22068,7 @@
 
   @DomName('RTCPeerConnection.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "RTCPeerConnection_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "RTCPeerConnection_addEventListener_Callback";
 
   @DomName('RTCPeerConnection.dispatchEvent')
   @DocsEditable()
@@ -22567,7 +22076,7 @@
 
   @DomName('RTCPeerConnection.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "RTCPeerConnection_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "RTCPeerConnection_removeEventListener_Callback";
 
   @DomName('RTCPeerConnection.onaddstream')
   @DocsEditable()
@@ -22823,30 +22332,6 @@
   @DocsEditable()
   void set defer(bool value) native "HTMLScriptElement_defer_Setter";
 
-  @DomName('HTMLScriptElement.event')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLScriptElement-partial
-  @deprecated // deprecated
-  String get event native "HTMLScriptElement_event_Getter";
-
-  @DomName('HTMLScriptElement.event')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLScriptElement-partial
-  @deprecated // deprecated
-  void set event(String value) native "HTMLScriptElement_event_Setter";
-
-  @DomName('HTMLScriptElement.htmlFor')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLScriptElement-partial
-  @deprecated // deprecated
-  String get htmlFor native "HTMLScriptElement_htmlFor_Getter";
-
-  @DomName('HTMLScriptElement.htmlFor')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLScriptElement-partial
-  @deprecated // deprecated
-  void set htmlFor(String value) native "HTMLScriptElement_htmlFor_Setter";
-
   @DomName('HTMLScriptElement.nonce')
   @DocsEditable()
   // https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html#interaction-with-the-script-src-directive
@@ -23301,6 +22786,21 @@
 
 
 @DocsEditable()
+@DomName('ServiceWorker')
+@Experimental() // untriaged
+class ServiceWorker extends NativeFieldWrapperClass2 {
+  // To suppress missing implicit constructor warnings.
+  factory ServiceWorker._() { throw new UnsupportedError("Not supported"); }
+
+}
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable()
 @DomName('HTMLShadowElement')
 @SupportedBrowser(SupportedBrowser.CHROME, '26')
 @Experimental()
@@ -23500,10 +23000,23 @@
   @Experimental() // untriaged
   void appendBuffer(ByteBuffer data) native "SourceBuffer_appendBuffer_Callback";
 
-  @DomName('SourceBuffer.appendBufferView')
+  void appendStream(FileStream stream, [int maxSize]) {
+    if (maxSize != null) {
+      _appendStream_1(stream, maxSize);
+      return;
+    }
+    _appendStream_2(stream);
+    return;
+  }
+
+  void _appendStream_1(stream, maxSize) native "SourceBuffer__appendStream_1_Callback";
+
+  void _appendStream_2(stream) native "SourceBuffer__appendStream_2_Callback";
+
+  @DomName('SourceBuffer.appendTypedData')
   @DocsEditable()
   @Experimental() // untriaged
-  void appendBufferView(TypedData data) native "SourceBuffer_appendBufferView_Callback";
+  void appendTypedData(TypedData data) native "SourceBuffer_appendTypedData_Callback";
 
   @DomName('SourceBuffer.remove')
   @DocsEditable()
@@ -23513,7 +23026,7 @@
   @DomName('SourceBuffer.addEventListener')
   @DocsEditable()
   @Experimental() // untriaged
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "SourceBuffer_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "SourceBuffer_addEventListener_Callback";
 
   @DomName('SourceBuffer.dispatchEvent')
   @DocsEditable()
@@ -23523,7 +23036,7 @@
   @DomName('SourceBuffer.removeEventListener')
   @DocsEditable()
   @Experimental() // untriaged
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "SourceBuffer_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "SourceBuffer_removeEventListener_Callback";
 
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -23596,7 +23109,7 @@
 
   @DomName('SourceBufferList.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "SourceBufferList_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "SourceBufferList_addEventListener_Callback";
 
   @DomName('SourceBufferList.dispatchEvent')
   @DocsEditable()
@@ -23604,7 +23117,7 @@
 
   @DomName('SourceBufferList.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "SourceBufferList_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "SourceBufferList_removeEventListener_Callback";
 
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -24029,7 +23542,7 @@
 
   @DomName('SpeechRecognition.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "SpeechRecognition_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "SpeechRecognition_addEventListener_Callback";
 
   @DomName('SpeechRecognition.dispatchEvent')
   @DocsEditable()
@@ -24037,7 +23550,7 @@
 
   @DomName('SpeechRecognition.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "SpeechRecognition_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "SpeechRecognition_removeEventListener_Callback";
 
   @DomName('SpeechRecognition.onaudioend')
   @DocsEditable()
@@ -24375,7 +23888,7 @@
   @DomName('SpeechSynthesisUtterance.addEventListener')
   @DocsEditable()
   @Experimental() // untriaged
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "SpeechSynthesisUtterance_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "SpeechSynthesisUtterance_addEventListener_Callback";
 
   @DomName('SpeechSynthesisUtterance.dispatchEvent')
   @DocsEditable()
@@ -24385,7 +23898,7 @@
   @DomName('SpeechSynthesisUtterance.removeEventListener')
   @DocsEditable()
   @Experimental() // untriaged
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "SpeechSynthesisUtterance_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "SpeechSynthesisUtterance_removeEventListener_Callback";
 
   @DomName('SpeechSynthesisUtterance.onboundary')
   @DocsEditable()
@@ -25066,18 +24579,6 @@
    */
   TableElement.created() : super.created();
 
-  @DomName('HTMLTableElement.border')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLTableElement-partial
-  @deprecated // deprecated
-  String get border native "HTMLTableElement_border_Getter";
-
-  @DomName('HTMLTableElement.border')
-  @DocsEditable()
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLTableElement-partial
-  @deprecated // deprecated
-  void set border(String value) native "HTMLTableElement_border_Setter";
-
   @DomName('HTMLTableElement.caption')
   @DocsEditable()
   TableCaptionElement get caption native "HTMLTableElement_caption_Getter";
@@ -25247,88 +24748,6 @@
 // WARNING: Do not edit - generated code.
 
 
-/**
- * Model-Driven Views (MDV)'s native features enables a wide-range of use cases,
- * but (by design) don't attempt to implement a wide array of specialized
- * behaviors.
- *
- * Enabling these features in MDV is a matter of implementing and registering an
- * MDV Custom Syntax. A Custom Syntax is an object which contains one or more
- * delegation functions which implement specialized behavior. This object is
- * registered with MDV via [Element.bindingDelegate]:
- *
- *
- * HTML:
- *     <template bind>
- *       {{ What!Ever('crazy')->thing^^^I+Want(data) }}
- *     </template>
- *
- * Dart:
- *     class MySyntax extends BindingDelegate {
- *       getBinding(model, path, name, node) {
- *         // The magic happens here!
- *       }
- *     }
- *     ...
- *     query('template').bindingDelegate = new MySyntax();
- *     query('template').model = new MyModel();
- *
- * See <https://github.com/polymer-project/mdv/blob/master/docs/syntax.md> for
- * more information about Custom Syntax.
- */
-// TODO(jmesserly): move this type to the MDV package? Two issues: we'd lose
-// type annotation on [Element.bindingDelegate], and "mdv" is normally imported
-// with a prefix.
-@Experimental()
-abstract class BindingDelegate {
-  /**
-   * This syntax method allows for a custom interpretation of the contents of
-   * mustaches (`{{` ... `}}`).
-   *
-   * When a template is inserting an instance, it will invoke this method for
-   * each mustache which is encountered. The function is invoked with four
-   * arguments:
-   *
-   * - [model]: The data context for which this instance is being created.
-   * - [path]: The text contents (trimmed of outer whitespace) of the mustache.
-   * - [name]: The context in which the mustache occurs. Within element
-   *   attributes, this will be the name of the attribute. Within text,
-   *   this will be 'text'.
-   * - [node]: A reference to the node to which this binding will be created.
-   *
-   * If the method wishes to handle binding, it is required to return an object
-   * which has at least a `value` property that can be observed. If it does,
-   * then MDV will call [Node.bind on the node:
-   *
-   *     node.bind(name, retval, 'value');
-   *
-   * If the 'getBinding' does not wish to override the binding, it should return
-   * null.
-   */
-  // TODO(jmesserly): I had to remove type annotations from "name" and "node"
-  // Normally they are String and Node respectively. But sometimes it will pass
-  // (int name, CompoundBinding node). That seems very confusing; we may want
-  // to change this API.
-  getBinding(model, String path, name, node) => null;
-
-  /**
-   * This syntax method allows a syntax to provide an alterate model than the
-   * one the template would otherwise use when producing an instance.
-   *
-   * When a template is about to create an instance, it will invoke this method
-   * The function is invoked with two arguments:
-   *
-   * - [template]: The template element which is about to create and insert an
-   *   instance.
-   * - [model]: The data context for which this instance is being created.
-   *
-   * The template element will always use the return value of `getInstanceModel`
-   * as the model for the new instance. If the syntax does not wish to override
-   * the value, it should simply return the `model` value it was passed.
-   */
-  getInstanceModel(Element template, model) => model;
-}
-
 @Experimental()
 @DomName('HTMLTemplateElement')
 @SupportedBrowser(SupportedBrowser.CHROME)
@@ -25353,208 +24772,9 @@
 
   @DomName('HTMLTemplateElement.content')
   @DocsEditable()
-  DocumentFragment get _content native "HTMLTemplateElement_content_Getter";
+  DocumentFragment get content native "HTMLTemplateElement_content_Getter";
 
 
-  // For real TemplateElement use the actual DOM .content field instead of
-  // our polyfilled expando.
-  @Experimental()
-  DocumentFragment get content => _content;
-
-
-  /**
-   * The MDV package, if available.
-   *
-   * This can be used to initialize MDV support via:
-   *
-   *     import 'dart:html';
-   *     import 'package:mdv/mdv.dart' as mdv;
-   *     main() {
-   *       mdv.initialize();
-   *     }
-   */
-  static Function mdvPackage = (node) {
-    throw new UnsupportedError("The MDV package is not available. "
-        "You can enable it with `import 'package:mdv/mdv.dart' as mdv;` and "
-        "`mdv.initialize()`");
-  };
-
-  /**
-   * Ensures proper API and content model for template elements.
-   *
-   * [instanceRef] can be used to set the [Element.ref] property of [template],
-   * and use the ref's content will be used as source when createInstance() is
-   * invoked.
-   *
-   * Returns true if this template was just decorated, or false if it was
-   * already decorated.
-   */
-  @Experimental()
-  static bool decorate(Element template, [Element instanceRef]) {
-    // == true check because it starts as a null field.
-    if (template._templateIsDecorated == true) return false;
-
-    _injectStylesheet();
-
-    var templateElement = template;
-    templateElement._templateIsDecorated = true;
-    var isNative = templateElement is TemplateElement;
-    var bootstrapContents = isNative;
-    var liftContents = !isNative;
-    var liftRoot = false;
-
-    if (!isNative && templateElement._isAttributeTemplate) {
-      if (instanceRef != null) {
-        // TODO(jmesserly): this is just an assert in MDV.
-        throw new ArgumentError('instanceRef should not be supplied for '
-            'attribute templates.');
-      }
-      templateElement = _extractTemplateFromAttributeTemplate(template);
-      templateElement._templateIsDecorated = true;
-      isNative = templateElement is TemplateElement;
-      liftRoot = true;
-     }
-
-    if (!isNative) {
-      var doc = _getTemplateContentsOwner(templateElement.document);
-      templateElement._templateContent = doc.createDocumentFragment();
-    }
-
-    if (instanceRef != null) {
-      // template is contained within an instance, its direct content must be
-      // empty
-      templateElement._templateInstanceRef = instanceRef;
-    } else if (liftContents) {
-      _liftNonNativeChildrenIntoContent(templateElement, template, liftRoot);
-    } else if (bootstrapContents) {
-      bootstrap(templateElement.content);
-    }
-
-    return true;
-  }
-
-  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
-  static Document _getTemplateContentsOwner(HtmlDocument 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.lastChild != null) {
-        d.lastChild.remove();
-      }
-      doc._templateContentsOwner = d;
-    }
-    return d;
-  }
-
-  // For non-template browsers, the parser will disallow <template> in certain
-  // locations, so we allow "attribute templates" which combine the template
-  // element with the top-level container node of the content, e.g.
-  //
-  //   <tr template repeat="{{ foo }}"" class="bar"><td>Bar</td></tr>
-  //
-  // becomes
-  //
-  //   <template repeat="{{ foo }}">
-  //   + #document-fragment
-  //     + <tr class="bar">
-  //       + <td>Bar</td>
-  //
-  static Element _extractTemplateFromAttributeTemplate(Element el) {
-    var template = el.document.createElement('template');
-    el.parentNode.insertBefore(template, el);
-
-    for (var name in el.attributes.keys.toList()) {
-      switch (name) {
-        case 'template':
-          el.attributes.remove(name);
-          break;
-        case 'repeat':
-        case 'bind':
-        case 'ref':
-          template.attributes[name] = el.attributes.remove(name);
-          break;
-      }
-    }
-
-    return template;
-  }
-
-  static void _liftNonNativeChildrenIntoContent(Element template, Element el,
-      bool useRoot) {
-
-    var content = template.content;
-    if (useRoot) {
-      content.append(el);
-      return;
-    }
-
-    var child;
-    while ((child = el.firstChild) != null) {
-      content.append(child);
-    }
-  }
-
-  /**
-   * This used to decorate recursively all templates from a given node.
-   *
-   * By default [decorate] will be called on templates lazily when certain
-   * properties such as [model] are accessed, but it can be run eagerly to
-   * decorate an entire tree recursively.
-   */
-  // TODO(rafaelw): Review whether this is the right public API.
-  @Experimental()
-  static void bootstrap(Node content) {
-    void _bootstrap(template) {
-      if (!TemplateElement.decorate(template)) {
-        bootstrap(template.content);
-      }
-    }
-
-    // Need to do this first as the contents may get lifted if |node| is
-    // template.
-    // TODO(jmesserly): content is DocumentFragment or Element
-    var descendents =
-        (content as dynamic).querySelectorAll(_allTemplatesSelectors);
-    if (content is Element && (content as Element).isTemplate) {
-      _bootstrap(content);
-    }
-
-    descendents.forEach(_bootstrap);
-  }
-
-  static final String _allTemplatesSelectors =
-      'template, option[template], optgroup[template], ' +
-      Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", ");
-
-  static bool _initStyles;
-
-  static void _injectStylesheet() {
-    if (_initStyles == true) return;
-    _initStyles = true;
-
-    var style = new StyleElement();
-    style.text = r'''
-template,
-thead[template],
-tbody[template],
-tfoot[template],
-th[template],
-tr[template],
-td[template],
-caption[template],
-colgroup[template],
-col[template],
-option[template] {
-  display: none;
-}''';
-    document.head.append(style);
-  }
-
   /**
    * An override to place the contents into content rather than as child nodes.
    *
@@ -25593,12 +24813,6 @@
   @Experimental() // untriaged
   List<Node> getDestinationInsertionPoints() native "Text_getDestinationInsertionPoints_Callback";
 
-  @DomName('Text.replaceWholeText')
-  @DocsEditable()
-  // http://dom.spec.whatwg.org/#dom-text-replacewholetext
-  @deprecated // deprecated
-  Text replaceWholeText(String content) native "Text_replaceWholeText_Callback";
-
   @DomName('Text.splitText')
   @DocsEditable()
   Text splitText(int offset) native "Text_splitText_Callback";
@@ -25946,7 +25160,7 @@
 
   @DomName('TextTrack.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "TextTrack_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "TextTrack_addEventListener_Callback";
 
   @DomName('TextTrack.dispatchEvent')
   @DocsEditable()
@@ -25954,7 +25168,7 @@
 
   @DomName('TextTrack.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "TextTrack_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "TextTrack_removeEventListener_Callback";
 
   @DomName('TextTrack.oncuechange')
   @DocsEditable()
@@ -26106,7 +25320,7 @@
 
   @DomName('TextTrackCue.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "TextTrackCue_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "TextTrackCue_addEventListener_Callback";
 
   @DomName('TextTrackCue.dispatchEvent')
   @DocsEditable()
@@ -26114,7 +25328,7 @@
 
   @DomName('TextTrackCue.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "TextTrackCue_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "TextTrackCue_removeEventListener_Callback";
 
   @DomName('TextTrackCue.onenter')
   @DocsEditable()
@@ -26272,7 +25486,7 @@
 
   @DomName('TextTrackList.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "TextTrackList_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "TextTrackList_addEventListener_Callback";
 
   @DomName('TextTrackList.dispatchEvent')
   @DocsEditable()
@@ -26280,7 +25494,7 @@
 
   @DomName('TextTrackList.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "TextTrackList_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "TextTrackList_removeEventListener_Callback";
 
   @DomName('TextTrackList.onaddtrack')
   @DocsEditable()
@@ -26520,7 +25734,8 @@
   /// 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.
-  factory TouchList() => document._createTouchList();
+  // TODO(5760): createTouchList now uses varargs.
+  factory TouchList() => null;//document._createTouchList();
   // To suppress missing implicit constructor warnings.
   factory TouchList._() { throw new UnsupportedError("Not supported"); }
 
@@ -26744,12 +25959,6 @@
   @DocsEditable()
   void set currentNode(Node value) native "TreeWalker_currentNode_Setter";
 
-  @DomName('TreeWalker.expandEntityReferences')
-  @DocsEditable()
-  // http://dom.spec.whatwg.org/#dom-traversal
-  @deprecated // deprecated
-  bool get expandEntityReferences native "TreeWalker_expandEntityReferences_Getter";
-
   @DomName('TreeWalker.filter')
   @DocsEditable()
   NodeFilter get filter native "TreeWalker_filter_Getter";
@@ -26871,16 +26080,6 @@
   void _initUIEvent(String type, bool canBubble, bool cancelable, Window view, int detail) native "UIEvent_initUIEvent_Callback";
 
 
-  @deprecated
-  int get layerX => layer.x;
-  @deprecated
-  int get layerY => layer.y;
-
-  @deprecated
-  int get pageX => page.x;
-  @deprecated
-  int get pageY => page.y;
-
   @DomName('UIEvent.layerX')
   @DomName('UIEvent.layerY')
   Point get layer => new Point(_layerX, _layerY);
@@ -27097,15 +26296,6 @@
   @Experimental()
   int get decodedFrameCount native "HTMLVideoElement_webkitDecodedFrameCount_Getter";
 
-  @DomName('HTMLVideoElement.webkitDisplayingFullscreen')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html
-  @deprecated // deprecated
-  bool get displayingFullscreen native "HTMLVideoElement_webkitDisplayingFullscreen_Getter";
-
   @DomName('HTMLVideoElement.webkitDroppedFrameCount')
   @DocsEditable()
   @SupportedBrowser(SupportedBrowser.CHROME)
@@ -27113,15 +26303,6 @@
   @Experimental()
   int get droppedFrameCount native "HTMLVideoElement_webkitDroppedFrameCount_Getter";
 
-  @DomName('HTMLVideoElement.webkitSupportsFullscreen')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html
-  @deprecated // deprecated
-  bool get supportsFullscreen native "HTMLVideoElement_webkitSupportsFullscreen_Getter";
-
   @DomName('HTMLVideoElement.width')
   @DocsEditable()
   int get width native "HTMLVideoElement_width_Getter";
@@ -27130,15 +26311,6 @@
   @DocsEditable()
   void set width(int value) native "HTMLVideoElement_width_Setter";
 
-  @DomName('HTMLVideoElement.webkitEnterFullScreen')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html
-  @deprecated // deprecated
-  void enterFullScreen() native "HTMLVideoElement_webkitEnterFullScreen_Callback";
-
   @DomName('HTMLVideoElement.webkitEnterFullscreen')
   @DocsEditable()
   @SupportedBrowser(SupportedBrowser.CHROME)
@@ -27147,15 +26319,6 @@
   // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html
   void enterFullscreen() native "HTMLVideoElement_webkitEnterFullscreen_Callback";
 
-  @DomName('HTMLVideoElement.webkitExitFullScreen')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#dom-document-exitfullscreen
-  @deprecated // deprecated
-  void exitFullScreen() native "HTMLVideoElement_webkitExitFullScreen_Callback";
-
   @DomName('HTMLVideoElement.webkitExitFullscreen')
   @DocsEditable()
   @SupportedBrowser(SupportedBrowser.CHROME)
@@ -27287,11 +26450,6 @@
   @DocsEditable()
   static const int OPEN = 1;
 
-  @DomName('WebSocket.URL')
-  @DocsEditable()
-  @deprecated // deprecated
-  String get Url native "WebSocket_URL_Getter";
-
   @DomName('WebSocket.binaryType')
   @DocsEditable()
   String get binaryType native "WebSocket_binaryType_Getter";
@@ -27368,7 +26526,7 @@
 
   @DomName('WebSocket.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "WebSocket_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "WebSocket_addEventListener_Callback";
 
   @DomName('WebSocket.dispatchEvent')
   @DocsEditable()
@@ -27376,7 +26534,7 @@
 
   @DomName('WebSocket.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "WebSocket_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "WebSocket_removeEventListener_Callback";
 
   @DomName('WebSocket.onclose')
   @DocsEditable()
@@ -27778,11 +26936,6 @@
   @DocsEditable()
   Document get document native "Window_document_Getter";
 
-  @DomName('Window.event')
-  @DocsEditable()
-  @deprecated // deprecated
-  Event get event native "Window_event_Getter";
-
   @DomName('Window.history')
   @DocsEditable()
   History get history native "Window_history_Getter";
@@ -27867,12 +27020,6 @@
   @SupportedBrowser(SupportedBrowser.IE)
   Performance get performance native "Window_performance_Getter";
 
-  @DomName('Window.personalbar')
-  @DocsEditable()
-  // https://developer.mozilla.org/en-US/docs/DOM/window.personalbar
-  @deprecated // deprecated
-  BarProp get personalbar native "Window_personalbar_Getter";
-
   @DomName('Window.screen')
   @DocsEditable()
   Screen get screen native "Window_screen_Getter";
@@ -27945,24 +27092,6 @@
   @DocsEditable()
   WindowBase get top native "Window_top_Getter";
 
-  @DomName('Window.webkitNotifications')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  // https://plus.sandbox.google.com/u/0/+GoogleChromeDevelopers/posts/8vWo8hq4pDm?e=Showroom
-  @deprecated // deprecated
-  NotificationCenter get notifications native "Window_webkitNotifications_Getter";
-
-  @DomName('Window.webkitStorageInfo')
-  @DocsEditable()
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  // http://www.w3.org/TR/file-system-api/
-  @deprecated // deprecated
-  StorageInfo get storageInfo native "Window_webkitStorageInfo_Getter";
-
   @DomName('Window.window')
   @DocsEditable()
   WindowBase get window native "Window_window_Getter";
@@ -27989,12 +27118,6 @@
   @DocsEditable()
   void cancelAnimationFrame(int id) native "Window_cancelAnimationFrame_Callback";
 
-  @DomName('Window.captureEvents')
-  @DocsEditable()
-  // http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture
-  @deprecated // deprecated
-  void captureEvents() native "Window_captureEvents_Callback";
-
   @DomName('Window.close')
   @DocsEditable()
   void close() native "Window_close_Callback";
@@ -28003,50 +27126,6 @@
   @DocsEditable()
   bool confirm(String message) native "Window_confirm_Callback";
 
-  Object _createImageBitmap(canvas_OR_context_OR_image_OR_video, [int sx, int sy, int sw, int sh]) {
-    if ((canvas_OR_context_OR_image_OR_video is ImageElement || canvas_OR_context_OR_image_OR_video == null) && sx == null && sy == null && sw == null && sh == null) {
-      return _createImageBitmap_1(canvas_OR_context_OR_image_OR_video);
-    }
-    if ((sh is int || sh == null) && (sw is int || sw == null) && (sy is int || sy == null) && (sx is int || sx == null) && (canvas_OR_context_OR_image_OR_video is ImageElement || canvas_OR_context_OR_image_OR_video == null)) {
-      return _createImageBitmap_2(canvas_OR_context_OR_image_OR_video, sx, sy, sw, sh);
-    }
-    if ((canvas_OR_context_OR_image_OR_video is CanvasRenderingContext2D || canvas_OR_context_OR_image_OR_video == null) && sx == null && sy == null && sw == null && sh == null) {
-      return _createImageBitmap_3(canvas_OR_context_OR_image_OR_video);
-    }
-    if ((sh is int || sh == null) && (sw is int || sw == null) && (sy is int || sy == null) && (sx is int || sx == null) && (canvas_OR_context_OR_image_OR_video is CanvasElement || canvas_OR_context_OR_image_OR_video == null)) {
-      return _createImageBitmap_4(canvas_OR_context_OR_image_OR_video, sx, sy, sw, sh);
-    }
-    if ((canvas_OR_context_OR_image_OR_video is CanvasElement || canvas_OR_context_OR_image_OR_video == null) && sx == null && sy == null && sw == null && sh == null) {
-      return _createImageBitmap_5(canvas_OR_context_OR_image_OR_video);
-    }
-    if ((canvas_OR_context_OR_image_OR_video is VideoElement || canvas_OR_context_OR_image_OR_video == null) && sx == null && sy == null && sw == null && sh == null) {
-      return _createImageBitmap_6(canvas_OR_context_OR_image_OR_video);
-    }
-    if ((sh is int || sh == null) && (sw is int || sw == null) && (sy is int || sy == null) && (sx is int || sx == null) && (canvas_OR_context_OR_image_OR_video is VideoElement || canvas_OR_context_OR_image_OR_video == null)) {
-      return _createImageBitmap_7(canvas_OR_context_OR_image_OR_video, sx, sy, sw, sh);
-    }
-    if ((sh is int || sh == null) && (sw is int || sw == null) && (sy is int || sy == null) && (sx is int || sx == null) && (canvas_OR_context_OR_image_OR_video is CanvasRenderingContext2D || canvas_OR_context_OR_image_OR_video == null)) {
-      return _createImageBitmap_8(canvas_OR_context_OR_image_OR_video, sx, sy, sw, sh);
-    }
-    throw new ArgumentError("Incorrect number or type of arguments");
-  }
-
-  Object _createImageBitmap_1(canvas_OR_context_OR_image_OR_video) native "Window__createImageBitmap_1_Callback";
-
-  Object _createImageBitmap_2(canvas_OR_context_OR_image_OR_video, sx, sy, sw, sh) native "Window__createImageBitmap_2_Callback";
-
-  Object _createImageBitmap_3(canvas_OR_context_OR_image_OR_video) native "Window__createImageBitmap_3_Callback";
-
-  Object _createImageBitmap_4(canvas_OR_context_OR_image_OR_video, sx, sy, sw, sh) native "Window__createImageBitmap_4_Callback";
-
-  Object _createImageBitmap_5(canvas_OR_context_OR_image_OR_video) native "Window__createImageBitmap_5_Callback";
-
-  Object _createImageBitmap_6(canvas_OR_context_OR_image_OR_video) native "Window__createImageBitmap_6_Callback";
-
-  Object _createImageBitmap_7(canvas_OR_context_OR_image_OR_video, sx, sy, sw, sh) native "Window__createImageBitmap_7_Callback";
-
-  Object _createImageBitmap_8(canvas_OR_context_OR_image_OR_video, sx, sy, sw, sh) native "Window__createImageBitmap_8_Callback";
-
   @DomName('Window.find')
   @DocsEditable()
   @Experimental() // non-standard
@@ -28098,12 +27177,6 @@
   @DocsEditable()
   void print() native "Window_print_Callback";
 
-  @DomName('Window.releaseEvents')
-  @DocsEditable()
-  // http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture
-  @deprecated // deprecated
-  void releaseEvents() native "Window_releaseEvents_Callback";
-
   @DomName('Window.requestAnimationFrame')
   @DocsEditable()
   int _requestAnimationFrame(RequestAnimationFrameCallback callback) native "Window_requestAnimationFrame_Callback";
@@ -28188,7 +27261,7 @@
 
   @DomName('Window.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "Window_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "Window_addEventListener_Callback";
 
   @DomName('Window.dispatchEvent')
   @DocsEditable()
@@ -28196,7 +27269,7 @@
 
   @DomName('Window.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "Window_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "Window_removeEventListener_Callback";
 
   @DomName('Window.atob')
   @DocsEditable()
@@ -28477,21 +27550,6 @@
 
 }
 
-/**
- * Event object that is fired before the window is closed.
- *
- * The standard window close behavior can be prevented by setting the
- * [returnValue]. This will display a dialog to the user confirming that they
- * want to close the page.
- */
-abstract class BeforeUnloadEvent implements Event {
-  /**
-   * If set to a non-null value, a dialog will be presented to the user
-   * confirming that they want to close the page.
-   */
-  String returnValue;
-}
-
 class _BeforeUnloadEvent extends _WrappedEvent implements BeforeUnloadEvent {
   String _returnValue;
 
@@ -28602,7 +27660,7 @@
   @DomName('Worker.addEventListener')
   @DocsEditable()
   @Experimental() // untriaged
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "Worker_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "Worker_addEventListener_Callback";
 
   @DomName('Worker.dispatchEvent')
   @DocsEditable()
@@ -28612,7 +27670,7 @@
   @DomName('Worker.removeEventListener')
   @DocsEditable()
   @Experimental() // untriaged
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "Worker_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "Worker_removeEventListener_Callback";
 
   @DomName('Worker.onerror')
   @DocsEditable()
@@ -28791,7 +27849,7 @@
   @DomName('WorkerGlobalScope.addEventListener')
   @DocsEditable()
   @Experimental() // untriaged
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "WorkerGlobalScope_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "WorkerGlobalScope_addEventListener_Callback";
 
   @DomName('WorkerGlobalScope.dispatchEvent')
   @DocsEditable()
@@ -28801,7 +27859,7 @@
   @DomName('WorkerGlobalScope.removeEventListener')
   @DocsEditable()
   @Experimental() // untriaged
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "WorkerGlobalScope_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "WorkerGlobalScope_removeEventListener_Callback";
 
   @DomName('WorkerGlobalScope.atob')
   @DocsEditable()
@@ -29080,7 +28138,7 @@
   @DomName('XMLHttpRequestEventTarget.addEventListener')
   @DocsEditable()
   @Experimental() // untriaged
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "XMLHttpRequestEventTarget_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "XMLHttpRequestEventTarget_addEventListener_Callback";
 
   @DomName('XMLHttpRequestEventTarget.dispatchEvent')
   @DocsEditable()
@@ -29090,7 +28148,7 @@
   @DomName('XMLHttpRequestEventTarget.removeEventListener')
   @DocsEditable()
   @Experimental() // untriaged
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "XMLHttpRequestEventTarget_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "XMLHttpRequestEventTarget_removeEventListener_Callback";
 
   @DomName('XMLHttpRequestEventTarget.onabort')
   @DocsEditable()
@@ -29258,16 +28316,6 @@
   @Experimental() // untriaged
   String get _namespaceUri native "Attr_namespaceURI_Getter";
 
-  @DomName('Attr.ownerElement')
-  @DocsEditable()
-  @deprecated // deprecated
-  Element get ownerElement native "Attr_ownerElement_Getter";
-
-  @DomName('Attr.specified')
-  @DocsEditable()
-  @deprecated // deprecated
-  bool get specified native "Attr_specified_Getter";
-
   @DomName('Attr.value')
   @DocsEditable()
   String get value native "Attr_value_Getter";
@@ -29817,18 +28865,6 @@
   // To suppress missing implicit constructor warnings.
   factory _Entity._() { throw new UnsupportedError("Not supported"); }
 
-  @DomName('Entity.notationName')
-  @DocsEditable()
-  String get notationName native "Entity_notationName_Getter";
-
-  @DomName('Entity.publicId')
-  @DocsEditable()
-  String get publicId native "Entity_publicId_Getter";
-
-  @DomName('Entity.systemId')
-  @DocsEditable()
-  String get systemId native "Entity_systemId_Getter";
-
 }
 // 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
@@ -31889,13 +30925,13 @@
 
   void _tryResume() {
     if (_onData != null && !isPaused) {
-      _target.$dom_addEventListener(_eventType, _onData, _useCapture);
+      _target.addEventListener(_eventType, _onData, _useCapture);
     }
   }
 
   void _unlisten() {
     if (_onData != null) {
-      _target.$dom_removeEventListener(_eventType, _onData, _useCapture);
+      _target.removeEventListener(_eventType, _onData, _useCapture);
     }
   }
 
@@ -34857,11 +33893,6 @@
 
   bool get bubbles => wrapped.bubbles;
 
-  bool get cancelBubble => wrapped.bubbles;
-  void set cancelBubble(bool value) {
-    wrapped.cancelBubble = value;
-  }
-
   bool get cancelable => wrapped.cancelable;
 
   DataTransfer get clipboardData => wrapped.clipboardData;
@@ -35204,16 +34235,6 @@
    * error.
    */
   static final supportsSimd = true;
-
-  /**
-   * Upgrade all custom elements in the subtree which have not been upgraded.
-   *
-   * This is needed to cover timing scenarios which the custom element polyfill
-   * does not cover.
-   */
-  static void upgradeCustomElements(Node node) {
-    // no-op, provided for dart2js polyfill.
-  }
 }
 // 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
@@ -35328,6 +34349,15 @@
     return result;
   }
 
+  static List captureParsedStackTrace() {
+    try {
+      // Throwing an exception is the only way to generate a stack trace.
+      throw new Exception();
+    } catch (e, stackTrace) {
+      return parseStackTrace(stackTrace);
+    }
+  }
+
   static void populateMap(Map result, List list) {
     for (int i = 0; i < list.length; i += 2) {
       result[list[i]] = list[i + 1];
@@ -35336,6 +34366,8 @@
 
   static bool isMap(obj) => obj is Map;
 
+  static List toListIfIterable(obj) => obj is Iterable ? obj.toList() : null;
+
   static Map createMap() => {};
 
   static makeUnimplementedError(String fileName, int lineNo) {
@@ -35403,7 +34435,11 @@
    * that does not expect REPL support.
    */
   static const _CONSOLE_API_SUPPORT_HEADER =
-      'with ((this && this.console && this.console._commandLineAPI) || {}) {\n';
+      'with ((console && console._commandLineAPI) || {}) {\n';
+
+  static bool expectsConsoleApi(String expression) {
+    return expression.indexOf(_CONSOLE_API_SUPPORT_HEADER) == 0;;
+  }
 
   /**
    * Takes an [expression] and a list of [local] variable and returns an
@@ -35449,7 +34485,7 @@
       args[arg] = value;
     }
 
-    if (expression.indexOf(_CONSOLE_API_SUPPORT_HEADER) == 0) {
+    if (expectsConsoleApi(expression)) {
       expression = expression.substring(expression.indexOf('\n') + 1);
       expression = expression.substring(0, expression.lastIndexOf('\n'));
 
@@ -35642,10 +34678,6 @@
 
   static bool isNoSuchMethodError(obj) => obj is NoSuchMethodError;
 
-  // TODO(jacobr): we need a failsafe way to determine that a Node is really a
-  // DOM node rather than just a class that extends Node.
-  static bool isNode(obj) => obj is Node;
-
   static bool _isBuiltinType(ClassMirror cls) {
     // TODO(vsm): Find a less hackish way to do this.
     LibraryMirror lib = cls.owner;
@@ -35661,9 +34693,38 @@
       throw new UnsupportedError("Invalid custom element from $libName.");
     }
     var className = MirrorSystem.getName(cls.simpleName);
-    if (!cls.constructors.containsKey(new Symbol('$className.created'))) {
-      throw new UnsupportedError('Class is missing constructor $className.created');
+    var createdConstructor = cls.constructors[new Symbol('$className.created')];
+    if (createdConstructor == null) {
+      throw new UnsupportedError(
+          'Class is missing constructor $className.created');
     }
+
+    if (createdConstructor.parameters.length > 0) {
+      throw new UnsupportedError(
+          'Constructor $className.created must take zero arguments');
+    }
+
+    Symbol objectName = reflectClass(Object).qualifiedName;
+    bool isRoot(ClassMirror cls) =>
+        cls == null || cls.qualifiedName == objectName;
+    Symbol elementName = reflectClass(HtmlElement).qualifiedName;
+    bool isElement(ClassMirror cls) =>
+        cls != null && cls.qualifiedName == elementName;
+    ClassMirror superClass = cls.superclass;
+    ClassMirror nativeClass = _isBuiltinType(superClass) ? superClass : null;
+    while(!isRoot(superClass) && !isElement(superClass)) {
+      superClass = superClass.superclass;
+      if (nativeClass == null && _isBuiltinType(superClass)) {
+        nativeClass = superClass;
+      }
+    }
+    if (extendsTagName == null) {
+      if (nativeClass.reflectedType != HtmlElement) {
+        throw new UnsupportedError('Class must provide extendsTag if base '
+            'native class is not HTMLElement');
+      }
+    }
+
     _register(document, tag, type, extendsTagName);
   }
 
diff --git a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
index 3a467ba..33a79bd 100644
--- a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
+++ b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
@@ -226,7 +226,7 @@
 
   @DomName('IDBDatabase.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "IDBDatabase_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "IDBDatabase_addEventListener_Callback";
 
   @DomName('IDBDatabase.dispatchEvent')
   @DocsEditable()
@@ -234,7 +234,7 @@
 
   @DomName('IDBDatabase.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "IDBDatabase_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "IDBDatabase_removeEventListener_Callback";
 
   @DomName('IDBDatabase.onabort')
   @DocsEditable()
@@ -902,7 +902,7 @@
 
   @DomName('IDBRequest.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "IDBRequest_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "IDBRequest_addEventListener_Callback";
 
   @DomName('IDBRequest.dispatchEvent')
   @DocsEditable()
@@ -910,7 +910,7 @@
 
   @DomName('IDBRequest.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "IDBRequest_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "IDBRequest_removeEventListener_Callback";
 
   @DomName('IDBRequest.onerror')
   @DocsEditable()
@@ -995,7 +995,7 @@
 
   @DomName('IDBTransaction.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "IDBTransaction_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "IDBTransaction_addEventListener_Callback";
 
   @DomName('IDBTransaction.dispatchEvent')
   @DocsEditable()
@@ -1003,7 +1003,7 @@
 
   @DomName('IDBTransaction.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "IDBTransaction_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "IDBTransaction_removeEventListener_Callback";
 
   @DomName('IDBTransaction.onabort')
   @DocsEditable()
diff --git a/sdk/lib/io/directory.dart b/sdk/lib/io/directory.dart
index 80391d4..95e6aa8 100644
--- a/sdk/lib/io/directory.dart
+++ b/sdk/lib/io/directory.dart
@@ -85,11 +85,6 @@
    *
    * Returns a [:Future<Directory>:] that completes with the newly
    * created temporary directory.
-   *
-   * Deprecated behavior, to be removed Oct 18, 2013: If the path is the
-   * empty string, the directory is created in the default system temp
-   * directory. This capability has been moved to the static getter
-   * [systemTemp].
    */
   Future<Directory> createTemp([String template]);
 
@@ -100,11 +95,6 @@
    * string is used for [prefix].
    *
    * Returns the newly created temporary directory.
-   *
-   * Deprecated behavior, to be removed Oct 18, 2013: If the path is the
-   * empty string, the directory is created in the default system temp
-   * directory. This capability has been moved to the static function
-   * [createSystemTemp].
    */
   Directory createTempSync([String template]);
 
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart
index 2883648..662107f 100644
--- a/sdk/lib/io/directory_impl.dart
+++ b/sdk/lib/io/directory_impl.dart
@@ -91,12 +91,11 @@
   }
 
   Future<Directory> createRecursively() {
-    var path = new _Path(this.path);
     var dirsToCreate = [];
-    var terminator = path.isAbsolute ? '/' : '';
-    while (path.toString() != terminator) {
-      dirsToCreate.add(new Directory(path.toNativePath()));
-      path = path.directoryPath;
+    var dir = this;
+    while (dir.path != dir.parent.path) {
+      dirsToCreate.add(dir);
+      dir = dir.parent;
     }
     return _computeExistingIndex(dirsToCreate).then((index) {
       var future;
@@ -128,14 +127,12 @@
   }
 
   void createRecursivelySync() {
-    var path = new _Path(this.path);
+    var dir = this;
     var dirsToCreate = [];
-    var terminator = path.isAbsolute ? '/' : '';
-    while (path.toString() != terminator) {
-      var dir = new Directory(path.toNativePath());
+    while (dir.path != dir.parent.path) {
       if (dir.existsSync()) break;
       dirsToCreate.add(dir);
-      path = path.directoryPath;
+      dir = dir.parent;
     }
     for (var i = dirsToCreate.length - 1; i >= 0; i--) {
       dirsToCreate[i].createSync();
@@ -155,9 +152,9 @@
   Future<Directory> createTemp([String prefix]) {
     if (prefix == null) prefix = '';
     if (path == '') {
-      return systemTemp.createTemp(prefix);
-      // TODO(13720): On Oct 18, 2013, replace this with
-      // an error.  createTemp cannot be called on a Directory with empty path.
+      throw new ArgumentError(
+          "Directory.createTemp called with an empty path. "
+          "To use the system temp directory, use Directory.systemTemp");
     }
     String fullPrefix;
     if (path.endsWith('/') || (Platform.isWindows && path.endsWith('\\'))) {
@@ -178,9 +175,9 @@
   Directory createTempSync([String prefix]) {
     if (prefix == null) prefix = '';
     if (path == '') {
-      return systemTemp.createTempSync(prefix);
-      // TODO(13720): On Oct 18, 2013, replace this with
-      // an error.  createTemp cannot be called on a Directory with empty path.
+      throw new ArgumentError(
+          "Directory.createTemp called with an empty path. "
+          "To use the system temp directory, use Directory.systemTemp");
     }
     String fullPrefix;
     if (path.endsWith('/') || (Platform.isWindows && path.endsWith('\\'))) {
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index 2e9df8e..b7bfea2 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -81,8 +81,10 @@
 
   /**
    * Get a [Directory] object for the directory containing this
-   * file.
+   * file. Deprecated: Replaced by [FileSystemEntity.parent].
+   * Will be removed on Oct 25, 2013.
    */
+  @deprecated
   Directory get directory;
 
   /**
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index 941f1da..5249f9f 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -308,10 +308,7 @@
     return new File(newPath);
   }
 
-  Directory get directory {
-    _Path path = new _Path(this.path).directoryPath;
-    return new Directory(path.toNativePath());
-  }
+  Directory get directory => super.parent;
 
   Future<RandomAccessFile> open({FileMode mode: FileMode.READ}) {
     if (mode != FileMode.READ &&
diff --git a/sdk/lib/io/file_system_entity.dart b/sdk/lib/io/file_system_entity.dart
index fdeb923..2594ff5 100644
--- a/sdk/lib/io/file_system_entity.dart
+++ b/sdk/lib/io/file_system_entity.dart
@@ -530,6 +530,48 @@
   external static _identical(String path1, String path2);
   external static _resolveSymbolicLinks(String path);
 
+  // Finds the next-to-last component when dividing at path separators.
+  static final RegExp _parentRegExp = Platform.isWindows ?
+     new RegExp(r'[^/\\][/\\]+[^/\\]') :
+     new RegExp(r'[^/]/+[^/]');
+
+  /**
+   * Removes the final path component of a path, using the platform's
+   * path separator to split the path.  Will not remove the root component
+   * of a Windows path, like "C:\" or "\\server_name\".
+   * Ignores trailing path separators, and leaves no trailing path separators.
+   */
+  static String parentOf(String path) {
+    int rootEnd = -1;
+    if (Platform.isWindows) {
+      if (path.startsWith(_absoluteWindowsPathPattern)) {
+        // Root ends at first / or \ after the first two characters.
+        rootEnd = path.indexOf(new RegExp(r'[/\\]'), 2);
+        if (rootEnd == -1) return path;
+      } else if (path.startsWith('\\') || path.startsWith('/')) {
+        rootEnd = 0;
+      }
+    } else if (path.startsWith('/')) {
+      rootEnd = 0;
+    }
+    // Ignore trailing slashes.
+    // All non-trivial cases have separators between two non-separators.
+    int pos = path.lastIndexOf(_parentRegExp);
+    if (pos > rootEnd) {
+      return path.substring(0, pos + 1);
+    } else if (rootEnd > -1) {
+      return path.substring(0, rootEnd + 1);
+    } else {
+      return '.';
+    }
+  }
+
+  /**
+   * The directory containing [this].  If [this] is a root
+   * directory, returns [this].
+   */
+  Directory get parent => new Directory(parentOf(path));
+
   static int _getTypeSync(String path, bool followLinks) {
     var result = _getType(path, followLinks);
     _throwIfError(result, 'Error getting type of FileSystemEntity');
@@ -537,12 +579,13 @@
   }
 
   static Future<int> _getTypeAsync(String path, bool followLinks) {
-    return _IOService.dispatch(_FILE_TYPE, [path, followLinks]).then((response) {
-      if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "Error getting type", path);
-      }
-      return response;
-    });
+    return _IOService.dispatch(_FILE_TYPE, [path, followLinks])
+      .then((response) {
+        if (_isErrorResponse(response)) {
+          throw _exceptionFromResponse(response, "Error getting type", path);
+        }
+        return response;
+      });
   }
 
   static _throwIfError(Object result, String msg, [String path]) {
diff --git a/sdk/lib/io/http.dart b/sdk/lib/io/http.dart
index 76fe619..2d31161 100644
--- a/sdk/lib/io/http.dart
+++ b/sdk/lib/io/http.dart
@@ -171,12 +171,14 @@
 
   /**
    * Permanently stops this [HttpServer] from listening for new
-   * connections.  This closes this [Stream] of [HttpRequest]s with a
+   * connections.  This closes the [Stream] of [HttpRequest]s with a
    * done event. The returned future completes when the server is
    * stopped. For a server started using [bind] or [bindSecure] this
    * means that the port listened on no longer in use.
+   *
+   * If [force] is `true`, active connections will be closed immediately.
    */
-  Future close();
+  Future close({bool force: false});
 
   /**
    * Returns the port that the server is listening on. This can be
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index b586f09..42b8d6f 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -538,11 +538,11 @@
         headers.chunkedTransferEncoding = false;
         headers.contentLength = 0;
       } else if (!_ignoreBody && headers.contentLength > 0) {
-        _headersSink.close().catchError((_) {});
-        return new Future.error(new HttpException(
+        _headersSink.addError(new HttpException(
             "No content while contentLength was specified to be greater "
-            " than 0: ${headers.contentLength}.",
+            "than 0: ${headers.contentLength}.",
             uri: _uri));
+        return _headersSink.done;
       }
     }
     return _writeHeaders().then((_) => _headersSink.close());
@@ -620,11 +620,9 @@
     }
     _completer = new Completer();
     _subscription = stream.listen(
-        (data) {
-          _controller.add(data);
-        },
+        (data) => _controller.add(data),
         onDone: _done,
-        onError: _done,
+        onError: (e, s) => _controller.addError(e, s),
         cancelOnError: true);
     // Pause the first request.
     if (_controller == null) _subscription.pause();
@@ -1878,7 +1876,9 @@
                 if (_state == _DETACHED) return;
                 if (response.persistentConnection &&
                     request.persistentConnection &&
-                    incoming.fullBodyRead) {
+                    incoming.fullBodyRead &&
+                    !_httpParser.upgrade &&
+                    !_httpServer.closed) {
                   _state = _IDLE;
                   _startTimeout();
                   // Resume the subscription for incoming requests as the
@@ -2007,7 +2007,7 @@
                                      cancelOnError: cancelOnError);
   }
 
-  Future close() {
+  Future close({bool force: false}) {
     closed = true;
     Future result;
     if (_serverSocket != null && _closeServer) {
@@ -2015,15 +2015,27 @@
     } else {
       result = new Future.value();
     }
-    if (_sessionManagerInstance != null) {
+    if (force) {
+      for (var c in _connections.toList()) {
+        c.destroy();
+      }
+      assert(_connections.isEmpty);
+    } else {
+      for (var c in _connections.where((c) => c._isIdle).toList()) {
+        c.destroy();
+      }
+    }
+    _maybeCloseSessionManager();
+    return result;
+  }
+
+  void _maybeCloseSessionManager() {
+    if (closed &&
+        _connections.isEmpty &&
+        _sessionManagerInstance != null) {
       _sessionManagerInstance.close();
       _sessionManagerInstance = null;
     }
-    for (_HttpConnection connection in _connections.toList()) {
-      connection.destroy();
-    }
-    _connections.clear();
-    return result;
   }
 
   int get port {
@@ -2050,6 +2062,7 @@
 
   void _connectionClosed(_HttpConnection connection) {
     _connections.remove(connection);
+    _maybeCloseSessionManager();
   }
 
   _HttpSessionManager get _sessionManager {
@@ -2176,7 +2189,7 @@
   static _HttpConnectionInfo create(Socket socket) {
     if (socket == null) return null;
     try {
-      _HttpConnectionInfo info = new _HttpConnectionInfo._();
+      _HttpConnectionInfo info = new _HttpConnectionInfo();
       info.remoteHost = socket.remoteHost;
       info.remotePort = socket.remotePort;
       info.localPort = socket.port;
@@ -2185,8 +2198,6 @@
     return null;
   }
 
-  _HttpConnectionInfo._();
-
   String remoteHost;
   int remotePort;
   int localPort;
diff --git a/sdk/lib/io/io.dart b/sdk/lib/io/io.dart
index e2fb691..cab4f3a 100644
--- a/sdk/lib/io/io.dart
+++ b/sdk/lib/io/io.dart
@@ -44,8 +44,6 @@
 part 'io_service.dart';
 part 'link.dart';
 part 'options.dart';
-part 'path.dart';
-part 'path_impl.dart';
 part 'platform.dart';
 part 'platform_impl.dart';
 part 'process.dart';
diff --git a/sdk/lib/io/iolib_sources.gypi b/sdk/lib/io/iolib_sources.gypi
index 4c7bdbe1..f58f786 100644
--- a/sdk/lib/io/iolib_sources.gypi
+++ b/sdk/lib/io/iolib_sources.gypi
@@ -24,8 +24,6 @@
     'io_service.dart',
     'link.dart',
     'options.dart',
-    'path.dart',
-    'path_impl.dart',
     'platform.dart',
     'platform_impl.dart',
     'process.dart',
diff --git a/sdk/lib/io/options.dart b/sdk/lib/io/options.dart
index 08dd129..0aec7c8 100644
--- a/sdk/lib/io/options.dart
+++ b/sdk/lib/io/options.dart
@@ -4,9 +4,16 @@
 
 part of dart.io;
 
+@deprecated
 /**
- * The Options object allows accessing the arguments which have been passed to
- * the current isolate.
+ * Deprecated: the Options object allows accessing the arguments which
+ * have been passed to the current isolate.
+ *
+ * This class has been replaced by making the arguments an optional parameter
+ * to main.  The other members, executable, script, and versione, are already
+ * available on Platform (which will move to the dart:plaform library).
+ *
+ * This class will be removed on October 28, 2013.
  */
 abstract class Options {
   /**
diff --git a/sdk/lib/io/path.dart b/sdk/lib/io/path.dart
deleted file mode 100644
index 0262e4b..0000000
--- a/sdk/lib/io/path.dart
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart.io;
-
-/**
- * A Path is an immutable wrapper of a String, with additional member functions
- * for useful path manipulations and queries.
- * On the Windows platform, Path also converts from native paths to paths using
- * '/' as a path separator, and vice versa.
- *
- * Joining of paths and path normalization handle '.' and '..' in the usual way.
- *
- * *Path is deprecated. Use package path. Path will be removed the 11th of
- * August 2013.*
- */
-@deprecated
-abstract class _Path {
-  /**
-   * Creates a Path from a String that uses the native filesystem's conventions.
-   *
-   * On Windows, this converts '\' to '/' and has special handling for drive
-   * letters and shares.
-   *
-   * If the path starts with a drive letter, like 'C:',  a '/' is added
-   * before the drive letter.
-   *
-   *     new _Path(r'c:\a\b').toString() == '/c:/a/b'
-   *
-   * A path starting with a drive letter is
-   * treated specially.  Backwards links ('..') cannot cancel the drive letter.
-   *
-   * If the path is a share path this is recorded in the Path object and
-   * maintained in operations on the Path object.
-   *
-   *     var share = new _Path(r'\\share\a\b\c');
-   *     share.isWindowsShare == true
-   *     share.toString() == '/share/a/b/c'
-   *     share.toNativePath() == r'\\share\a\b\c'
-   *     share.append('final').isWindowsShare == true
-   */
-  @deprecated
-  factory _Path(String source) => new __Path(source);
-
-  /**
-   * Creates a Path from the String [source].  [source] is used as-is, so if
-   * the string does not consist of segments separated by forward slashes, the
-   * behavior may not be as expected.  Paths are immutable.
-   */
-  @deprecated
-  factory _Path.raw(String source) => new __Path.raw(source);
-
-  /**
-   * Is this path the empty string?
-   */
-  bool get isEmpty;
-
-  /**
-   * Is this path an absolute path, beginning with a '/'?  Note that
-   * Windows paths beginning with '\' or with a drive letter are absolute,
-   * and a leading '/' is added when they are converted to a Path.
-   */
-  bool get isAbsolute;
-
-  /**
-   * Is this path a Windows share path?
-   */
-  bool get isWindowsShare;
-
-  /**
-   * Does this path end with a '/'?
-   */
-  bool get hasTrailingSeparator;
-
-  /**
-   * Does this path contain no consecutive '/'s, no segments that
-   * are '.' unless the path is exactly '.', and segments that are '..' only
-   * as the leading segments on a relative path?
-   */
-  bool get isCanonical;
-
-  /**
-   * Make a path canonical by dropping segments that are '.', cancelling
-   * segments that are '..' with preceding segments, if possible,
-   * and combining consecutive '/'s.  Leading '..' segments
-   * are kept on relative paths, and dropped from absolute paths.
-   */
-  _Path canonicalize();
-
-  /**
-   * Joins the relative path [further] to this path.  Canonicalizes the
-   * resulting joined path using [canonicalize],
-   * interpreting '.' and '..' as directory traversal commands, and removing
-   * consecutive '/'s.
-   *
-   * If [further] is an absolute path, an IllegalArgument exception is thrown.
-   *
-   * Examples:
-   *   `new _Path('/a/b/c').join(new _Path('d/e'))` returns the Path object
-   *   containing `'a/b/c/d/e'`.
-   *
-   *   `new _Path('a/b/../c/').join(new _Path('d/./e//')` returns the Path
-   *   containing `'a/c/d/e/'`.
-   *
-   *   `new _Path('a/b/c').join(new _Path('d/../../e')` returns the Path
-   *   containing `'a/b/e'`.
-   *
-   * Note that the join operation does not drop the last segment of the
-   * base path, the way URL joining does.  To join basepath to further using
-   * URL semantics, use
-   *    [:basepath.directoryPath.join(further):].
-   *
-   * If you want to avoid joins that traverse
-   * parent directories in the base, you can check whether
-   * `further.canonicalize()` starts with '../' or equals '..'.
-   */
-  _Path join(_Path further);
-
-
-  /**
-   * Returns a path [:relative:] such that
-   *    [:base.join(relative) == this.canonicalize():].
-   * Throws an exception if such a path is impossible.
-   * For example, if [base] is '../../a/b' and [this] is '.'.
-   * The computation is independent of the file system and current directory.
-   *
-   * To compute a relative path using URL semantics, where the final
-   * path component of the base is dropped unless it ends with a slash,
-   * call [: a.relativeTo(b.directoryPath) :] instead of [: a.relativeTo(b) :].
-   */
-  _Path relativeTo(_Path base);
-
-  /**
-   * Converts a path to a string using the native filesystem's conventions.
-   *
-   * Always returns '.' if the path is empty.
-   * On Windows, converts '/'s to backwards slashes, and removes
-   * the leading '/' if the path starts with a drive specification.
-   * For most valid Windows paths, this should be the inverse of the
-   * conversion that the constructor new _Path() performs.  If the path is
-   * a Windows share, restores the '\\' at the start of the path.
-   */
-  String toNativePath();
-
-  /**
-   * Returns the path as a string.  If this path is constructed using
-   * new _Path.raw(), or new _Path() on a non-Windows system, the
-   * returned value is the original string argument to the constructor.
-   */
-  String toString();
-
-  /**
-   * Gets the segments of a Path. The segments are just the result of
-   * splitting the path on any '/' characters, except that a '/' at the
-   * beginning does not create an empty segment before it, and a '/' at
-   * the end does not create an empty segment after it.
-   *
-   *     new _Path('/a/b/c/d').segments() == ['a', 'b', 'c', d'];
-   *     new _Path(' foo bar //../') == [' foo bar ', '', '..'];
-   */
-  List<String> segments();
-
-  /**
-   * Appends [finalSegment] to a path as a new segment.  Adds a '/'
-   * between the path and [finalSegment] if the path does not already end in
-   * a '/'.  The path is not canonicalized, and [finalSegment] may
-   * contain '/'s.
-   */
-  _Path append(String finalSegment);
-
-  /**
-   * Drops the final '/' and whatever follows it from this Path,
-   * and returns the resulting Path object.  If the only '/' in
-   * this Path is the first character, returns '/' instead of the empty string.
-   * If there is no '/' in the Path, returns the empty string.
-   *
-   *     new _Path('../images/dot.gif').directoryPath == '../images'
-   *     new _Path('/usr/geoffrey/www/').directoryPath == '/usr/geoffrey/www'
-   *     new _Path('lost_file_old').directoryPath == ''
-   *     new _Path('/src').directoryPath == '/'
-   *     Note: new _Path('/D:/src').directoryPath == '/D:'
-   */
-  _Path get directoryPath;
-
-  /**
-   * The part of the path after the last '/', or the entire path if
-   * it contains no '/'.
-   *
-   *     new _Path('images/DSC_0027.jpg).filename == 'DSC_0027.jpg'
-   *     new _Path('users/fred/').filename == ''
-   */
-  String get filename;
-
-  /**
-   * The part of [filename] before the last '.', or the entire filename if it
-   * contains no '.'.  If [filename] is '.' or '..' it is unchanged.
-   *
-   *     new _Path('/c:/My Documents/Heidi.txt').filenameWithoutExtension
-   *     would return 'Heidi'.
-   *     new _Path('not what I would call a path').filenameWithoutExtension
-   *     would return 'not what I would call a path'.
-   */
-  String get filenameWithoutExtension;
-
-  /**
-   * The part of [filename] after the last '.', or '' if [filename]
-   * contains no '.'.  If [filename] is '.' or '..', returns ''.
-   *
-   *     new _Path('tiger.svg').extension == 'svg'
-   *     new _Path('/src/dart/dart_secrets').extension == ''
-   */
-  String get extension;
-}
diff --git a/sdk/lib/io/path_impl.dart b/sdk/lib/io/path_impl.dart
deleted file mode 100644
index 9915863..0000000
--- a/sdk/lib/io/path_impl.dart
+++ /dev/null
@@ -1,309 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart.io;
-
-class __Path implements _Path {
-  final String _path;
-  final bool isWindowsShare;
-
-  __Path(String source)
-      : _path = _clean(source), isWindowsShare = _isWindowsShare(source);
-
-  __Path.raw(String source) : _path = source, isWindowsShare = false;
-
-  __Path._internal(String this._path, bool this.isWindowsShare);
-
-  static String _clean(String source) {
-    if (Platform.operatingSystem == 'windows') return _cleanWindows(source);
-    return source;
-  }
-
-  static String _cleanWindows(String source) {
-    // Change \ to /.
-    var clean = source.replaceAll('\\', '/');
-    // Add / before intial [Drive letter]:
-    if (clean.length >= 2 && clean[1] == ':') {
-      clean = '/$clean';
-    }
-    if (_isWindowsShare(source)) {
-      return clean.substring(1, clean.length);
-    }
-    return clean;
-  }
-
-  static bool _isWindowsShare(String source) {
-    return Platform.operatingSystem == 'windows' && source.startsWith('\\\\');
-  }
-
-  int get hashCode => _path.hashCode;
-  bool get isEmpty => _path.isEmpty;
-  bool get isAbsolute => _path.startsWith('/');
-  bool get hasTrailingSeparator => _path.endsWith('/');
-
-  String toString() => _path;
-
-  _Path relativeTo(_Path base) {
-    // Returns a path "relative" such that
-    // base.join(relative) == this.canonicalize.
-    // Throws exception if an impossible case is reached.
-    if (base.isAbsolute != isAbsolute ||
-        base.isWindowsShare != isWindowsShare) {
-      throw new ArgumentError(
-          "Invalid case of _Path.relativeTo(base):\n"
-          "  Path and base must both be relative, or both absolute.\n"
-          "  Arguments: $_path.relativeTo($base)");
-    }
-
-    var basePath = base.toString();
-    // Handle drive letters specially on Windows.
-    if (base.isAbsolute && Platform.operatingSystem == 'windows') {
-      bool baseHasDrive =
-          basePath.length >= 4 && basePath[2] == ':' && basePath[3] == '/';
-      bool pathHasDrive =
-          _path.length >= 4 && _path[2] == ':' && _path[3] == '/';
-      if (baseHasDrive && pathHasDrive) {
-        int baseDrive = basePath.codeUnitAt(1) | 32;  // Convert to uppercase.
-        if (baseDrive >= 'a'.codeUnitAt(0) &&
-            baseDrive <= 'z'.codeUnitAt(0) &&
-            baseDrive == (_path.codeUnitAt(1) | 32)) {
-          if(basePath[1] != _path[1]) {
-            // Replace the drive letter in basePath with that from _path.
-            basePath = '/${_path[1]}:/${basePath.substring(4)}';
-            base = new _Path(basePath);
-          }
-        } else {
-          throw new ArgumentError(
-              "Invalid case of _Path.relativeTo(base):\n"
-              "  Base path and target path are on different Windows drives.\n"
-              "  Arguments: $_path.relativeTo($base)");
-        }
-      } else if (baseHasDrive != pathHasDrive) {
-        throw new ArgumentError(
-            "Invalid case of _Path.relativeTo(base):\n"
-            "  Base path must start with a drive letter if and "
-            "only if target path does.\n"
-            "  Arguments: $_path.relativeTo($base)");
-      }
-
-    }
-    if (_path.startsWith(basePath)) {
-      if (_path == basePath) return new _Path('.');
-      // There must be a '/' at the end of the match, or immediately after.
-      int matchEnd = basePath.length;
-      if (_path[matchEnd - 1] == '/' || _path[matchEnd] == '/') {
-        // Drop any extra '/' characters at matchEnd
-        while (matchEnd < _path.length && _path[matchEnd] == '/') {
-          matchEnd++;
-        }
-        return new _Path(_path.substring(matchEnd)).canonicalize();
-      }
-    }
-
-    List<String> baseSegments = base.canonicalize().segments();
-    List<String> pathSegments = canonicalize().segments();
-    if (baseSegments.length == 1 && baseSegments[0] == '.') {
-      baseSegments = [];
-    }
-    if (pathSegments.length == 1 && pathSegments[0] == '.') {
-      pathSegments = [];
-    }
-    int common = 0;
-    int length = min(pathSegments.length, baseSegments.length);
-    while (common < length && pathSegments[common] == baseSegments[common]) {
-      common++;
-    }
-    final segments = new List<String>();
-
-    if (common < baseSegments.length && baseSegments[common] == '..') {
-      throw new ArgumentError(
-          "Invalid case of _Path.relativeTo(base):\n"
-          "  Base path has more '..'s than path does.\n"
-          "  Arguments: $_path.relativeTo($base)");
-    }
-    for (int i = common; i < baseSegments.length; i++) {
-      segments.add('..');
-    }
-    for (int i = common; i < pathSegments.length; i++) {
-      segments.add('${pathSegments[i]}');
-    }
-    if (segments.isEmpty) {
-      segments.add('.');
-    }
-    if (hasTrailingSeparator) {
-        segments.add('');
-    }
-    return new _Path(segments.join('/'));
-  }
-
-
-  _Path join(_Path further) {
-    if (further.isAbsolute) {
-      throw new ArgumentError(
-          "Path.join called with absolute Path as argument.");
-    }
-    if (isEmpty) {
-      return further.canonicalize();
-    }
-    if (hasTrailingSeparator) {
-      var joined = new __Path._internal('$_path${further}', isWindowsShare);
-      return joined.canonicalize();
-    }
-    var joined = new __Path._internal('$_path/${further}', isWindowsShare);
-    return joined.canonicalize();
-  }
-
-  // Note: The URI RFC names for canonicalize, join, and relativeTo
-  // are normalize, resolve, and relativize.  But resolve and relativize
-  // drop the last segment of the base path (the filename), on URIs.
-  _Path canonicalize() {
-    if (isCanonical) return this;
-    return makeCanonical();
-  }
-
-  bool get isCanonical {
-    // Contains no consecutive path separators.
-    // Contains no segments that are '.'.
-    // Absolute paths have no segments that are '..'.
-    // All '..' segments of a relative path are at the beginning.
-    if (isEmpty) return false;  // The canonical form of '' is '.'.
-    if (_path == '.') return true;
-    List segs = _path.split('/');  // Don't mask the getter 'segments'.
-    if (segs[0] == '') {  // Absolute path
-      segs[0] = null;  // Faster than removeRange().
-    } else {  // A canonical relative path may start with .. segments.
-      for (int pos = 0;
-           pos < segs.length && segs[pos] == '..';
-           ++pos) {
-        segs[pos] = null;
-      }
-    }
-    if (segs.last == '') segs.removeLast();  // Path ends with /.
-    // No remaining segments can be ., .., or empty.
-    return !segs.any((s) => s == '' || s == '.' || s == '..');
-  }
-
-  _Path makeCanonical() {
-    bool isAbs = isAbsolute;
-    List segs = segments();
-    String drive;
-    if (isAbs &&
-        !segs.isEmpty &&
-        segs[0].length == 2 &&
-        segs[0][1] == ':') {
-      drive = segs[0];
-      segs.removeRange(0, 1);
-    }
-    List newSegs = [];
-    for (String segment in segs) {
-      switch (segment) {
-        case '..':
-          // Absolute paths drop leading .. markers, including after a drive.
-          if (newSegs.isEmpty) {
-            if (isAbs) {
-              // Do nothing: drop the segment.
-            } else {
-              newSegs.add('..');
-            }
-          } else if (newSegs.last == '..') {
-            newSegs.add('..');
-          } else {
-            newSegs.removeLast();
-          }
-          break;
-        case '.':
-        case '':
-          // Do nothing - drop the segment.
-          break;
-        default:
-          newSegs.add(segment);
-          break;
-      }
-    }
-
-    List segmentsToJoin = [];
-    if (isAbs) {
-      segmentsToJoin.add('');
-      if (drive != null) {
-        segmentsToJoin.add(drive);
-      }
-    }
-
-    if (newSegs.isEmpty) {
-      if (isAbs) {
-        segmentsToJoin.add('');
-      } else {
-        segmentsToJoin.add('.');
-      }
-    } else {
-      segmentsToJoin.addAll(newSegs);
-      if (hasTrailingSeparator) {
-        segmentsToJoin.add('');
-      }
-    }
-    return new __Path._internal(segmentsToJoin.join('/'), isWindowsShare);
-  }
-
-  String toNativePath() {
-    if (isEmpty) return '.';
-    if (Platform.operatingSystem == 'windows') {
-      String nativePath = _path;
-      // Drop '/' before a drive letter.
-      if (nativePath.length >= 3 &&
-          nativePath.startsWith('/') &&
-          nativePath[2] == ':') {
-        nativePath = nativePath.substring(1);
-      }
-      nativePath = nativePath.replaceAll('/', '\\');
-      if (isWindowsShare) {
-        return '\\$nativePath';
-      }
-      return nativePath;
-    }
-    return _path;
-  }
-
-  List<String> segments() {
-    List result = _path.split('/');
-    if (isAbsolute) result.removeRange(0, 1);
-    if (hasTrailingSeparator) result.removeLast();
-    return result;
-  }
-
-  _Path append(String finalSegment) {
-    if (isEmpty) {
-      return new __Path._internal(finalSegment, isWindowsShare);
-    } else if (hasTrailingSeparator) {
-      return new __Path._internal('$_path$finalSegment', isWindowsShare);
-    } else {
-      return new __Path._internal('$_path/$finalSegment', isWindowsShare);
-    }
-  }
-
-  String get filenameWithoutExtension {
-    var name = filename;
-    if (name == '.' || name == '..') return name;
-    int pos = name.lastIndexOf('.');
-    return (pos < 0) ? name : name.substring(0, pos);
-  }
-
-  String get extension {
-    var name = filename;
-    int pos = name.lastIndexOf('.');
-    return (pos < 0) ? '' : name.substring(pos + 1);
-  }
-
-  _Path get directoryPath {
-    int pos = _path.lastIndexOf('/');
-    if (pos < 0) return new _Path('');
-    while (pos > 0 && _path[pos - 1] == '/') --pos;
-    var dirPath = (pos > 0) ? _path.substring(0, pos) : '/';
-    return new __Path._internal(dirPath, isWindowsShare);
-  }
-
-  String get filename {
-    int pos = _path.lastIndexOf('/');
-    return _path.substring(pos + 1);
-  }
-}
diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart
index 213a444..852b0db 100644
--- a/sdk/lib/js/dart2js/js_dart2js.dart
+++ b/sdk/lib/js/dart2js/js_dart2js.dart
@@ -272,9 +272,12 @@
       JS('bool', 'typeof # == "number"', o) ||
       JS('bool', 'typeof # == "boolean"', o)) {
     return o;
-  } else if (o is Blob || o is DateTime || o is KeyRange 
-      || o is ImageData || o is Node || o is TypedData) {
-    return JS('Blob|DateTime|KeyRange|ImageData|Node|TypedData', '#', o);
+  } else if (o is Blob || o is KeyRange || o is ImageData || o is Node
+    || o is TypedData) {
+    return JS('Blob|KeyRange|ImageData|Node|TypedData', '#', o);
+  } else if (JS('bool', '# instanceof Date', o)) {
+    var ms = JS('num', '#.getMilliseconds()', o);
+    return new DateTime.fromMillisecondsSinceEpoch(ms);
   } else if (JS('bool', 'typeof # == "function"', o)) {
     return _getDartProxy(o, _DART_CLOSURE_PROPERTY_NAME,
         (o) => new JsFunction._fromJs(o));
diff --git a/sdk/lib/js/dartium/js_dartium.dart b/sdk/lib/js/dartium/js_dartium.dart
index 4a4b46d..5fcb5ce 100644
--- a/sdk/lib/js/dartium/js_dartium.dart
+++ b/sdk/lib/js/dartium/js_dartium.dart
@@ -111,5 +111,35 @@
 
   apply(List args, {thisArg}) native "JsFunction_apply";
 
+  /**
+   * Internal only version of apply which uses debugger proxies of Dart objects
+   * rather than opaque handles. This method is private because it cannot be
+   * efficiently implemented in Dart2Js so should only be used by internal
+   * tools.
+   */
+  _applyDebuggerOnly(List args, {thisArg}) native "JsFunction_applyDebuggerOnly";
+
   static JsFunction _withThis(Function f) native "JsFunction_withThis";
 }
+
+/**
+ * Placeholder object for cases where we need to determine exactly how many
+ * args were passed to a function.
+ */
+const _UNDEFINED = const Object();
+
+// FIXME(jacobr): this method is a hack to work around the lack of proper dart
+// support for varargs methods.
+List _stripUndefinedArgs(List args) =>
+    args.takeWhile((i) => i != _UNDEFINED).toList();
+
+/**
+ * Returns a method that can be called with an arbitrary number (for n less
+ * than 11) of arguments without violating Dart type checks.
+ */
+Function _wrapAsDebuggerVarArgsFunction(JsFunction jsFunction) =>
+  ([a1=_UNDEFINED, a2=_UNDEFINED, a3=_UNDEFINED, a4=_UNDEFINED,
+    a5=_UNDEFINED, a6=_UNDEFINED, a7=_UNDEFINED, a8=_UNDEFINED,
+    a9=_UNDEFINED, a10=_UNDEFINED]) =>
+    jsFunction._applyDebuggerOnly(_stripUndefinedArgs(
+        [a1,a2,a3,a4,a5,a6,a7,a8,a9,a10]));
diff --git a/sdk/lib/svg/dart2js/svg_dart2js.dart b/sdk/lib/svg/dart2js/svg_dart2js.dart
index 4414538..c837f1f 100644
--- a/sdk/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk/lib/svg/dart2js/svg_dart2js.dart
@@ -6761,30 +6761,6 @@
 
 
 @DocsEditable()
-@DomName('SVGTRefElement')
-@Unstable()
-abstract class _SVGTRefElement extends TextPositioningElement implements UriReference native "SVGTRefElement" {
-  // To suppress missing implicit constructor warnings.
-  factory _SVGTRefElement._() { throw new UnsupportedError("Not supported"); }
-
-  @DomName('SVGTRefElement.SVGTRefElement')
-  @DocsEditable()
-  factory _SVGTRefElement() => _SvgElementFactoryProvider.createSvgElement_tag("tref");
-  /**
-   * Constructor instantiated by the DOM when a custom element has been created.
-   *
-   * This can only be called by subclasses from their created constructor.
-   */
-  _SVGTRefElement.created() : super.created();
-
-  // From SVGURIReference
-}
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-
-@DocsEditable()
 @DomName('SVGVKernElement')
 @Unstable()
 abstract class _SVGVKernElement extends SvgElement native "SVGVKernElement" {
diff --git a/sdk/lib/svg/dartium/svg_dartium.dart b/sdk/lib/svg/dartium/svg_dartium.dart
index 0b8bea3..f25ee0a 100644
--- a/sdk/lib/svg/dartium/svg_dartium.dart
+++ b/sdk/lib/svg/dartium/svg_dartium.dart
@@ -999,7 +999,7 @@
   @DomName('SVGElementInstance.addEventListener')
   @DocsEditable()
   @Experimental() // untriaged
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "SVGElementInstance_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "SVGElementInstance_addEventListener_Callback";
 
   @DomName('SVGElementInstance.dispatchEvent')
   @DocsEditable()
@@ -1009,7 +1009,7 @@
   @DomName('SVGElementInstance.removeEventListener')
   @DocsEditable()
   @Experimental() // untriaged
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "SVGElementInstance_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "SVGElementInstance_removeEventListener_Callback";
 
   @DomName('SVGElementInstance.onabort')
   @DocsEditable()
@@ -7453,31 +7453,6 @@
 
 
 @DocsEditable()
-@DomName('SVGTRefElement')
-@Unstable()
-abstract class _SVGTRefElement extends TextPositioningElement implements UriReference {
-  // To suppress missing implicit constructor warnings.
-  factory _SVGTRefElement._() { throw new UnsupportedError("Not supported"); }
-
-  @DomName('SVGTRefElement.SVGTRefElement')
-  @DocsEditable()
-  factory _SVGTRefElement() => _SvgElementFactoryProvider.createSvgElement_tag("tref");
-  /**
-   * Constructor instantiated by the DOM when a custom element has been created.
-   *
-   * This can only be called by subclasses from their created constructor.
-   */
-  _SVGTRefElement.created() : super.created();
-
-}
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// WARNING: Do not edit - generated code.
-
-
-@DocsEditable()
 @DomName('SVGVKernElement')
 @Unstable()
 abstract class _SVGVKernElement extends SvgElement {
diff --git a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
index 18dfce2..2caaa64 100644
--- a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
+++ b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
@@ -889,12 +889,6 @@
   @Experimental() // untriaged
   static const EventStreamProvider<Event> endedEvent = const EventStreamProvider<Event>('ended');
 
-  @DomName('OscillatorNode.CUSTOM')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int CUSTOM = 4;
-
   @DomName('OscillatorNode.FINISHED_STATE')
   @DocsEditable()
   static const int FINISHED_STATE = 3;
@@ -903,34 +897,10 @@
   @DocsEditable()
   static const int PLAYING_STATE = 2;
 
-  @DomName('OscillatorNode.SAWTOOTH')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int SAWTOOTH = 2;
-
   @DomName('OscillatorNode.SCHEDULED_STATE')
   @DocsEditable()
   static const int SCHEDULED_STATE = 1;
 
-  @DomName('OscillatorNode.SINE')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int SINE = 0;
-
-  @DomName('OscillatorNode.SQUARE')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int SQUARE = 1;
-
-  @DomName('OscillatorNode.TRIANGLE')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int TRIANGLE = 3;
-
   @DomName('OscillatorNode.UNSCHEDULED_STATE')
   @DocsEditable()
   static const int UNSCHEDULED_STATE = 0;
@@ -990,42 +960,6 @@
   // To suppress missing implicit constructor warnings.
   factory PannerNode._() { throw new UnsupportedError("Not supported"); }
 
-  @DomName('PannerNode.EQUALPOWER')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int EQUALPOWER = 0;
-
-  @DomName('PannerNode.EXPONENTIAL_DISTANCE')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int EXPONENTIAL_DISTANCE = 2;
-
-  @DomName('PannerNode.HRTF')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int HRTF = 1;
-
-  @DomName('PannerNode.INVERSE_DISTANCE')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int INVERSE_DISTANCE = 1;
-
-  @DomName('PannerNode.LINEAR_DISTANCE')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int LINEAR_DISTANCE = 0;
-
-  @DomName('PannerNode.SOUNDFIELD')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int SOUNDFIELD = 2;
-
   @DomName('PannerNode.coneInnerAngle')
   @DocsEditable()
   num coneInnerAngle;
diff --git a/sdk/lib/web_audio/dartium/web_audio_dartium.dart b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
index c33212c..e5cc155 100644
--- a/sdk/lib/web_audio/dartium/web_audio_dartium.dart
+++ b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
@@ -462,7 +462,7 @@
   @DomName('AudioContext.addEventListener')
   @DocsEditable()
   @Experimental() // untriaged
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "AudioContext_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "AudioContext_addEventListener_Callback";
 
   @DomName('AudioContext.dispatchEvent')
   @DocsEditable()
@@ -472,7 +472,7 @@
   @DomName('AudioContext.removeEventListener')
   @DocsEditable()
   @Experimental() // untriaged
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "AudioContext_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "AudioContext_removeEventListener_Callback";
 
   @DomName('AudioContext.oncomplete')
   @DocsEditable()
@@ -613,7 +613,7 @@
 
   @DomName('AudioNode.addEventListener')
   @DocsEditable()
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "AudioNode_addEventListener_Callback";
+  void addEventListener(String type, EventListener listener, [bool useCapture]) native "AudioNode_addEventListener_Callback";
 
   @DomName('AudioNode.dispatchEvent')
   @DocsEditable()
@@ -621,7 +621,7 @@
 
   @DomName('AudioNode.removeEventListener')
   @DocsEditable()
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "AudioNode_removeEventListener_Callback";
+  void removeEventListener(String type, EventListener listener, [bool useCapture]) native "AudioNode_removeEventListener_Callback";
 
   @DomName('AudioNode.connect')
   void connectNode(AudioNode destination, [int output = 0, int input = 0]) =>
@@ -1089,12 +1089,6 @@
   @Experimental() // untriaged
   static const EventStreamProvider<Event> endedEvent = const EventStreamProvider<Event>('ended');
 
-  @DomName('OscillatorNode.CUSTOM')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int CUSTOM = 4;
-
   @DomName('OscillatorNode.FINISHED_STATE')
   @DocsEditable()
   static const int FINISHED_STATE = 3;
@@ -1103,34 +1097,10 @@
   @DocsEditable()
   static const int PLAYING_STATE = 2;
 
-  @DomName('OscillatorNode.SAWTOOTH')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int SAWTOOTH = 2;
-
   @DomName('OscillatorNode.SCHEDULED_STATE')
   @DocsEditable()
   static const int SCHEDULED_STATE = 1;
 
-  @DomName('OscillatorNode.SINE')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int SINE = 0;
-
-  @DomName('OscillatorNode.SQUARE')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int SQUARE = 1;
-
-  @DomName('OscillatorNode.TRIANGLE')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int TRIANGLE = 3;
-
   @DomName('OscillatorNode.UNSCHEDULED_STATE')
   @DocsEditable()
   static const int UNSCHEDULED_STATE = 0;
@@ -1197,42 +1167,6 @@
   // To suppress missing implicit constructor warnings.
   factory PannerNode._() { throw new UnsupportedError("Not supported"); }
 
-  @DomName('PannerNode.EQUALPOWER')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int EQUALPOWER = 0;
-
-  @DomName('PannerNode.EXPONENTIAL_DISTANCE')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int EXPONENTIAL_DISTANCE = 2;
-
-  @DomName('PannerNode.HRTF')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int HRTF = 1;
-
-  @DomName('PannerNode.INVERSE_DISTANCE')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int INVERSE_DISTANCE = 1;
-
-  @DomName('PannerNode.LINEAR_DISTANCE')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int LINEAR_DISTANCE = 0;
-
-  @DomName('PannerNode.SOUNDFIELD')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
-  @deprecated // deprecated
-  static const int SOUNDFIELD = 2;
-
   @DomName('PannerNode.coneInnerAngle')
   @DocsEditable()
   num get coneInnerAngle native "PannerNode_coneInnerAngle_Getter";
diff --git a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
index 747c686..14e3fee 100644
--- a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
+++ b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
@@ -2203,25 +2203,71 @@
   void blendFuncSeparate(int srcRGB, int dstRGB, int srcAlpha, int dstAlpha) native;
 
   @JSName('bufferData')
+  /**
+   * Buffers the specified data.
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but
+   * it is highly recommended that you use [bufferDataTyped] or [bufferByteData]
+   * depending on your purposes.
+   */
   @DomName('WebGLRenderingContext.bufferData')
   @DocsEditable()
   void bufferByteData(int target, ByteBuffer data, int usage) native;
 
+  /**
+   * Buffers the specified data.
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but
+   * it is highly recommended that you use [bufferDataTyped] or [bufferByteData]
+   * depending on your purposes.
+   */
   @DomName('WebGLRenderingContext.bufferData')
   @DocsEditable()
-  void bufferData(int target, int size, int usage) native;
+  void bufferData(int target, data_OR_size, int usage) native;
 
   @JSName('bufferData')
+  /**
+   * Buffers the specified data.
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but
+   * it is highly recommended that you use [bufferDataTyped] or [bufferByteData]
+   * depending on your purposes.
+   */
   @DomName('WebGLRenderingContext.bufferData')
   @DocsEditable()
   void bufferDataTyped(int target, TypedData data, int usage) native;
 
   @JSName('bufferSubData')
+  /**
+   * Buffers the specified subset of data.
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but
+   * it is highly recommended that you use [bufferSubDataTyped] or [bufferSubByteData]
+   * depending on your purposes.
+   */
   @DomName('WebGLRenderingContext.bufferSubData')
   @DocsEditable()
   void bufferSubByteData(int target, int offset, ByteBuffer data) native;
 
+  /**
+   * Buffers the specified subset of data.
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but
+   * it is highly recommended that you use [bufferSubDataTyped] or [bufferSubByteData]
+   * depending on your purposes.
+   */
+  @DomName('WebGLRenderingContext.bufferSubData')
+  @DocsEditable()
+  void bufferSubData(int target, int offset, data) native;
+
   @JSName('bufferSubData')
+  /**
+   * Buffers the specified subset of data.
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but
+   * it is highly recommended that you use [bufferSubDataTyped] or [bufferSubByteData]
+   * depending on your purposes.
+   */
   @DomName('WebGLRenderingContext.bufferSubData')
   @DocsEditable()
   void bufferSubDataTyped(int target, int offset, TypedData data) native;
@@ -2592,16 +2638,135 @@
   @DocsEditable()
   void stencilOpSeparate(int face, int fail, int zfail, int zpass) native;
 
+  /**
+   * Updates the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
+   * (or for more specificity, the more specialized [texImage2DImageData],
+   * [texImage2DCanvas], [texImage2DVideo]).
+   */
+  @DomName('WebGLRenderingContext.texImage2D')
+  @DocsEditable()
+  void texImage2D(int target, int level, int internalformat, int format_OR_width, int height_OR_type, border_OR_canvas_OR_image_OR_pixels_OR_video, [int format, int type, TypedData pixels]) {
+    if (pixels != null && type != null && format != null && (border_OR_canvas_OR_image_OR_pixels_OR_video is int || border_OR_canvas_OR_image_OR_pixels_OR_video == null)) {
+      _texImage2D_1(target, level, internalformat, format_OR_width, height_OR_type, border_OR_canvas_OR_image_OR_pixels_OR_video, format, type, pixels);
+      return;
+    }
+    if ((border_OR_canvas_OR_image_OR_pixels_OR_video is ImageData || border_OR_canvas_OR_image_OR_pixels_OR_video == null) && format == null && type == null && pixels == null) {
+      var pixels_1 = convertDartToNative_ImageData(border_OR_canvas_OR_image_OR_pixels_OR_video);
+      _texImage2D_2(target, level, internalformat, format_OR_width, height_OR_type, pixels_1);
+      return;
+    }
+    if ((border_OR_canvas_OR_image_OR_pixels_OR_video is ImageElement || border_OR_canvas_OR_image_OR_pixels_OR_video == null) && format == null && type == null && pixels == null) {
+      _texImage2D_3(target, level, internalformat, format_OR_width, height_OR_type, border_OR_canvas_OR_image_OR_pixels_OR_video);
+      return;
+    }
+    if ((border_OR_canvas_OR_image_OR_pixels_OR_video is CanvasElement || border_OR_canvas_OR_image_OR_pixels_OR_video == null) && format == null && type == null && pixels == null) {
+      _texImage2D_4(target, level, internalformat, format_OR_width, height_OR_type, border_OR_canvas_OR_image_OR_pixels_OR_video);
+      return;
+    }
+    if ((border_OR_canvas_OR_image_OR_pixels_OR_video is VideoElement || border_OR_canvas_OR_image_OR_pixels_OR_video == null) && format == null && type == null && pixels == null) {
+      _texImage2D_5(target, level, internalformat, format_OR_width, height_OR_type, border_OR_canvas_OR_image_OR_pixels_OR_video);
+      return;
+    }
+    throw new ArgumentError("Incorrect number or type of arguments");
+  }
   @JSName('texImage2D')
+  /**
+   * Updates the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
+   * (or for more specificity, the more specialized [texImage2DImageData],
+   * [texImage2DCanvas], [texImage2DVideo]).
+   */
+  @DomName('WebGLRenderingContext.texImage2D')
+  @DocsEditable()
+  void _texImage2D_1(target, level, internalformat, width, height, int border, format, type, TypedData pixels) native;
+  @JSName('texImage2D')
+  /**
+   * Updates the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
+   * (or for more specificity, the more specialized [texImage2DImageData],
+   * [texImage2DCanvas], [texImage2DVideo]).
+   */
+  @DomName('WebGLRenderingContext.texImage2D')
+  @DocsEditable()
+  void _texImage2D_2(target, level, internalformat, format, type, pixels) native;
+  @JSName('texImage2D')
+  /**
+   * Updates the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
+   * (or for more specificity, the more specialized [texImage2DImageData],
+   * [texImage2DCanvas], [texImage2DVideo]).
+   */
+  @DomName('WebGLRenderingContext.texImage2D')
+  @DocsEditable()
+  void _texImage2D_3(target, level, internalformat, format, type, ImageElement image) native;
+  @JSName('texImage2D')
+  /**
+   * Updates the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
+   * (or for more specificity, the more specialized [texImage2DImageData],
+   * [texImage2DCanvas], [texImage2DVideo]).
+   */
+  @DomName('WebGLRenderingContext.texImage2D')
+  @DocsEditable()
+  void _texImage2D_4(target, level, internalformat, format, type, CanvasElement canvas) native;
+  @JSName('texImage2D')
+  /**
+   * Updates the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
+   * (or for more specificity, the more specialized [texImage2DImageData],
+   * [texImage2DCanvas], [texImage2DVideo]).
+   */
+  @DomName('WebGLRenderingContext.texImage2D')
+  @DocsEditable()
+  void _texImage2D_5(target, level, internalformat, format, type, VideoElement video) native;
+
+  @JSName('texImage2D')
+  /**
+   * Updates the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
+   * (or for more specificity, the more specialized [texImage2DImageData],
+   * [texImage2DCanvas], [texImage2DVideo]).
+   */
   @DomName('WebGLRenderingContext.texImage2D')
   @DocsEditable()
   void texImage2DCanvas(int target, int level, int internalformat, int format, int type, CanvasElement canvas) native;
 
   @JSName('texImage2D')
+  /**
+   * Updates the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
+   * (or for more specificity, the more specialized [texImage2DImageData],
+   * [texImage2DCanvas], [texImage2DVideo]).
+   */
   @DomName('WebGLRenderingContext.texImage2D')
   @DocsEditable()
   void texImage2DImage(int target, int level, int internalformat, int format, int type, ImageElement image) native;
 
+  /**
+   * Updates the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
+   * (or for more specificity, the more specialized [texImage2DImageData],
+   * [texImage2DCanvas], [texImage2DVideo]).
+   */
   @DomName('WebGLRenderingContext.texImage2D')
   @DocsEditable()
   void texImage2DImageData(int target, int level, int internalformat, int format, int type, ImageData pixels) {
@@ -2610,11 +2775,27 @@
     return;
   }
   @JSName('texImage2D')
+  /**
+   * Updates the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
+   * (or for more specificity, the more specialized [texImage2DImageData],
+   * [texImage2DCanvas], [texImage2DVideo]).
+   */
   @DomName('WebGLRenderingContext.texImage2D')
   @DocsEditable()
   void _texImage2DImageData_1(target, level, internalformat, format, type, pixels) native;
 
   @JSName('texImage2D')
+  /**
+   * Updates the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
+   * (or for more specificity, the more specialized [texImage2DImageData],
+   * [texImage2DCanvas], [texImage2DVideo]).
+   */
   @DomName('WebGLRenderingContext.texImage2D')
   @DocsEditable()
   void texImage2DVideo(int target, int level, int internalformat, int format, int type, VideoElement video) native;
@@ -2627,16 +2808,135 @@
   @DocsEditable()
   void texParameteri(int target, int pname, int param) native;
 
+  /**
+   * Updates a sub-rectangle of the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
+   * (or for more specificity, the more specialized [texSubImage2DImageData],
+   * [texSubImage2DCanvas], [texSubImage2DVideo]).
+   */
+  @DomName('WebGLRenderingContext.texSubImage2D')
+  @DocsEditable()
+  void texSubImage2D(int target, int level, int xoffset, int yoffset, int format_OR_width, int height_OR_type, canvas_OR_format_OR_image_OR_pixels_OR_video, [int type, TypedData pixels]) {
+    if (pixels != null && type != null && (canvas_OR_format_OR_image_OR_pixels_OR_video is int || canvas_OR_format_OR_image_OR_pixels_OR_video == null)) {
+      _texSubImage2D_1(target, level, xoffset, yoffset, format_OR_width, height_OR_type, canvas_OR_format_OR_image_OR_pixels_OR_video, type, pixels);
+      return;
+    }
+    if ((canvas_OR_format_OR_image_OR_pixels_OR_video is ImageData || canvas_OR_format_OR_image_OR_pixels_OR_video == null) && type == null && pixels == null) {
+      var pixels_1 = convertDartToNative_ImageData(canvas_OR_format_OR_image_OR_pixels_OR_video);
+      _texSubImage2D_2(target, level, xoffset, yoffset, format_OR_width, height_OR_type, pixels_1);
+      return;
+    }
+    if ((canvas_OR_format_OR_image_OR_pixels_OR_video is ImageElement || canvas_OR_format_OR_image_OR_pixels_OR_video == null) && type == null && pixels == null) {
+      _texSubImage2D_3(target, level, xoffset, yoffset, format_OR_width, height_OR_type, canvas_OR_format_OR_image_OR_pixels_OR_video);
+      return;
+    }
+    if ((canvas_OR_format_OR_image_OR_pixels_OR_video is CanvasElement || canvas_OR_format_OR_image_OR_pixels_OR_video == null) && type == null && pixels == null) {
+      _texSubImage2D_4(target, level, xoffset, yoffset, format_OR_width, height_OR_type, canvas_OR_format_OR_image_OR_pixels_OR_video);
+      return;
+    }
+    if ((canvas_OR_format_OR_image_OR_pixels_OR_video is VideoElement || canvas_OR_format_OR_image_OR_pixels_OR_video == null) && type == null && pixels == null) {
+      _texSubImage2D_5(target, level, xoffset, yoffset, format_OR_width, height_OR_type, canvas_OR_format_OR_image_OR_pixels_OR_video);
+      return;
+    }
+    throw new ArgumentError("Incorrect number or type of arguments");
+  }
   @JSName('texSubImage2D')
+  /**
+   * Updates a sub-rectangle of the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
+   * (or for more specificity, the more specialized [texSubImage2DImageData],
+   * [texSubImage2DCanvas], [texSubImage2DVideo]).
+   */
+  @DomName('WebGLRenderingContext.texSubImage2D')
+  @DocsEditable()
+  void _texSubImage2D_1(target, level, xoffset, yoffset, width, height, int format, type, TypedData pixels) native;
+  @JSName('texSubImage2D')
+  /**
+   * Updates a sub-rectangle of the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
+   * (or for more specificity, the more specialized [texSubImage2DImageData],
+   * [texSubImage2DCanvas], [texSubImage2DVideo]).
+   */
+  @DomName('WebGLRenderingContext.texSubImage2D')
+  @DocsEditable()
+  void _texSubImage2D_2(target, level, xoffset, yoffset, format, type, pixels) native;
+  @JSName('texSubImage2D')
+  /**
+   * Updates a sub-rectangle of the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
+   * (or for more specificity, the more specialized [texSubImage2DImageData],
+   * [texSubImage2DCanvas], [texSubImage2DVideo]).
+   */
+  @DomName('WebGLRenderingContext.texSubImage2D')
+  @DocsEditable()
+  void _texSubImage2D_3(target, level, xoffset, yoffset, format, type, ImageElement image) native;
+  @JSName('texSubImage2D')
+  /**
+   * Updates a sub-rectangle of the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
+   * (or for more specificity, the more specialized [texSubImage2DImageData],
+   * [texSubImage2DCanvas], [texSubImage2DVideo]).
+   */
+  @DomName('WebGLRenderingContext.texSubImage2D')
+  @DocsEditable()
+  void _texSubImage2D_4(target, level, xoffset, yoffset, format, type, CanvasElement canvas) native;
+  @JSName('texSubImage2D')
+  /**
+   * Updates a sub-rectangle of the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
+   * (or for more specificity, the more specialized [texSubImage2DImageData],
+   * [texSubImage2DCanvas], [texSubImage2DVideo]).
+   */
+  @DomName('WebGLRenderingContext.texSubImage2D')
+  @DocsEditable()
+  void _texSubImage2D_5(target, level, xoffset, yoffset, format, type, VideoElement video) native;
+
+  @JSName('texSubImage2D')
+  /**
+   * Updates a sub-rectangle of the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
+   * (or for more specificity, the more specialized [texSubImage2DImageData],
+   * [texSubImage2DCanvas], [texSubImage2DVideo]).
+   */
   @DomName('WebGLRenderingContext.texSubImage2D')
   @DocsEditable()
   void texSubImage2DCanvas(int target, int level, int xoffset, int yoffset, int format, int type, CanvasElement canvas) native;
 
   @JSName('texSubImage2D')
+  /**
+   * Updates a sub-rectangle of the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
+   * (or for more specificity, the more specialized [texSubImage2DImageData],
+   * [texSubImage2DCanvas], [texSubImage2DVideo]).
+   */
   @DomName('WebGLRenderingContext.texSubImage2D')
   @DocsEditable()
   void texSubImage2DImage(int target, int level, int xoffset, int yoffset, int format, int type, ImageElement image) native;
 
+  /**
+   * Updates a sub-rectangle of the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
+   * (or for more specificity, the more specialized [texSubImage2DImageData],
+   * [texSubImage2DCanvas], [texSubImage2DVideo]).
+   */
   @DomName('WebGLRenderingContext.texSubImage2D')
   @DocsEditable()
   void texSubImage2DImageData(int target, int level, int xoffset, int yoffset, int format, int type, ImageData pixels) {
@@ -2645,11 +2945,27 @@
     return;
   }
   @JSName('texSubImage2D')
+  /**
+   * Updates a sub-rectangle of the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
+   * (or for more specificity, the more specialized [texSubImage2DImageData],
+   * [texSubImage2DCanvas], [texSubImage2DVideo]).
+   */
   @DomName('WebGLRenderingContext.texSubImage2D')
   @DocsEditable()
   void _texSubImage2DImageData_1(target, level, xoffset, yoffset, format, type, pixels) native;
 
   @JSName('texSubImage2D')
+  /**
+   * Updates a sub-rectangle of the currently bound texture to [data].
+   *
+   * This specific method is provided for WebGL API compatibility reasons, but it
+   * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
+   * (or for more specificity, the more specialized [texSubImage2DImageData],
+   * [texSubImage2DCanvas], [texSubImage2DVideo]).
+   */
   @DomName('WebGLRenderingContext.texSubImage2D')
   @DocsEditable()
   void texSubImage2DVideo(int target, int level, int xoffset, int yoffset, int format, int type, VideoElement video) native;
@@ -2788,10 +3104,9 @@
    * To use [texImage2d] with a TypedData object, use [texImage2dTyped].
    *
    */
-  @DomName('WebGLRenderingContext.texImage2D')
   @JSName('texImage2D')
-  void texImage2D(int targetTexture, int levelOfDetail, int internalFormat,
-      int format, int type, data) native;
+  void texImage2DUntyped(int targetTexture, int levelOfDetail, 
+      int internalFormat, int format, int type, data) native;
 
   /**
    * Sets the currently bound texture to [data].
@@ -2810,10 +3125,9 @@
    * To use [texSubImage2d] with a TypedData object, use [texSubImage2dTyped].
    *
    */
-  @DomName('WebGLRenderingContext.texSubImage2D')
   @JSName('texSubImage2D')
-  void texSubImage2D(int targetTexture, int levelOfDetail, int internalFormat,
-      int format, int type, data) native;
+  void texSubImage2DUntyped(int targetTexture, int levelOfDetail,
+      int internalFormat, int format, int type, data) native;
 
   /**
    * Updates a sub-rectangle of the currently bound texture to [data].
diff --git a/sdk/lib/web_gl/dartium/web_gl_dartium.dart b/sdk/lib/web_gl/dartium/web_gl_dartium.dart
index aa4703c..e09051c 100644
--- a/sdk/lib/web_gl/dartium/web_gl_dartium.dart
+++ b/sdk/lib/web_gl/dartium/web_gl_dartium.dart
@@ -2292,9 +2292,27 @@
   @DocsEditable()
   void bufferByteData(int target, ByteBuffer data, int usage) native "WebGLRenderingContext_bufferByteData_Callback";
 
-  @DomName('WebGLRenderingContext.bufferData')
-  @DocsEditable()
-  void bufferData(int target, int size, int usage) native "WebGLRenderingContext_bufferData_Callback";
+  void bufferData(int target, data_OR_size, int usage) {
+    if ((usage is int || usage == null) && (data_OR_size is TypedData || data_OR_size == null) && (target is int || target == null)) {
+      _bufferData_1(target, data_OR_size, usage);
+      return;
+    }
+    if ((usage is int || usage == null) && (data_OR_size is ByteBuffer || data_OR_size == null) && (target is int || target == null)) {
+      _bufferData_2(target, data_OR_size, usage);
+      return;
+    }
+    if ((usage is int || usage == null) && (data_OR_size is int || data_OR_size == null) && (target is int || target == null)) {
+      _bufferData_3(target, data_OR_size, usage);
+      return;
+    }
+    throw new ArgumentError("Incorrect number or type of arguments");
+  }
+
+  void _bufferData_1(target, data_OR_size, usage) native "WebGLRenderingContext__bufferData_1_Callback";
+
+  void _bufferData_2(target, data_OR_size, usage) native "WebGLRenderingContext__bufferData_2_Callback";
+
+  void _bufferData_3(target, data_OR_size, usage) native "WebGLRenderingContext__bufferData_3_Callback";
 
   @DomName('WebGLRenderingContext.bufferDataTyped')
   @DocsEditable()
@@ -2304,6 +2322,22 @@
   @DocsEditable()
   void bufferSubByteData(int target, int offset, ByteBuffer data) native "WebGLRenderingContext_bufferSubByteData_Callback";
 
+  void bufferSubData(int target, int offset, data) {
+    if ((data is TypedData || data == null) && (offset is int || offset == null) && (target is int || target == null)) {
+      _bufferSubData_1(target, offset, data);
+      return;
+    }
+    if ((data is ByteBuffer || data == null) && (offset is int || offset == null) && (target is int || target == null)) {
+      _bufferSubData_2(target, offset, data);
+      return;
+    }
+    throw new ArgumentError("Incorrect number or type of arguments");
+  }
+
+  void _bufferSubData_1(target, offset, data) native "WebGLRenderingContext__bufferSubData_1_Callback";
+
+  void _bufferSubData_2(target, offset, data) native "WebGLRenderingContext__bufferSubData_2_Callback";
+
   @DomName('WebGLRenderingContext.bufferSubDataTyped')
   @DocsEditable()
   void bufferSubDataTyped(int target, int offset, TypedData data) native "WebGLRenderingContext_bufferSubDataTyped_Callback";
@@ -2656,9 +2690,39 @@
   @DocsEditable()
   void stencilOpSeparate(int face, int fail, int zfail, int zpass) native "WebGLRenderingContext_stencilOpSeparate_Callback";
 
-  @DomName('WebGLRenderingContext.texImage2D')
-  @DocsEditable()
-  void _texImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, TypedData pixels) native "WebGLRenderingContext_texImage2D_Callback";
+  void texImage2D(int target, int level, int internalformat, int format_OR_width, int height_OR_type, border_OR_canvas_OR_image_OR_pixels_OR_video, [int format, int type, TypedData pixels]) {
+    if ((pixels is TypedData || pixels == null) && (type is int || type == null) && (format is int || format == null) && (border_OR_canvas_OR_image_OR_pixels_OR_video is int || border_OR_canvas_OR_image_OR_pixels_OR_video == null) && (height_OR_type is int || height_OR_type == null) && (format_OR_width is int || format_OR_width == null) && (internalformat is int || internalformat == null) && (level is int || level == null) && (target is int || target == null)) {
+      _texImage2D_1(target, level, internalformat, format_OR_width, height_OR_type, border_OR_canvas_OR_image_OR_pixels_OR_video, format, type, pixels);
+      return;
+    }
+    if ((border_OR_canvas_OR_image_OR_pixels_OR_video is ImageData || border_OR_canvas_OR_image_OR_pixels_OR_video == null) && (height_OR_type is int || height_OR_type == null) && (format_OR_width is int || format_OR_width == null) && (internalformat is int || internalformat == null) && (level is int || level == null) && (target is int || target == null) && format == null && type == null && pixels == null) {
+      _texImage2D_2(target, level, internalformat, format_OR_width, height_OR_type, border_OR_canvas_OR_image_OR_pixels_OR_video);
+      return;
+    }
+    if ((border_OR_canvas_OR_image_OR_pixels_OR_video is ImageElement || border_OR_canvas_OR_image_OR_pixels_OR_video == null) && (height_OR_type is int || height_OR_type == null) && (format_OR_width is int || format_OR_width == null) && (internalformat is int || internalformat == null) && (level is int || level == null) && (target is int || target == null) && format == null && type == null && pixels == null) {
+      _texImage2D_3(target, level, internalformat, format_OR_width, height_OR_type, border_OR_canvas_OR_image_OR_pixels_OR_video);
+      return;
+    }
+    if ((border_OR_canvas_OR_image_OR_pixels_OR_video is CanvasElement || border_OR_canvas_OR_image_OR_pixels_OR_video == null) && (height_OR_type is int || height_OR_type == null) && (format_OR_width is int || format_OR_width == null) && (internalformat is int || internalformat == null) && (level is int || level == null) && (target is int || target == null) && format == null && type == null && pixels == null) {
+      _texImage2D_4(target, level, internalformat, format_OR_width, height_OR_type, border_OR_canvas_OR_image_OR_pixels_OR_video);
+      return;
+    }
+    if ((border_OR_canvas_OR_image_OR_pixels_OR_video is VideoElement || border_OR_canvas_OR_image_OR_pixels_OR_video == null) && (height_OR_type is int || height_OR_type == null) && (format_OR_width is int || format_OR_width == null) && (internalformat is int || internalformat == null) && (level is int || level == null) && (target is int || target == null) && format == null && type == null && pixels == null) {
+      _texImage2D_5(target, level, internalformat, format_OR_width, height_OR_type, border_OR_canvas_OR_image_OR_pixels_OR_video);
+      return;
+    }
+    throw new ArgumentError("Incorrect number or type of arguments");
+  }
+
+  void _texImage2D_1(target, level, internalformat, format_OR_width, height_OR_type, border_OR_canvas_OR_image_OR_pixels_OR_video, format, type, pixels) native "WebGLRenderingContext__texImage2D_1_Callback";
+
+  void _texImage2D_2(target, level, internalformat, format_OR_width, height_OR_type, border_OR_canvas_OR_image_OR_pixels_OR_video) native "WebGLRenderingContext__texImage2D_2_Callback";
+
+  void _texImage2D_3(target, level, internalformat, format_OR_width, height_OR_type, border_OR_canvas_OR_image_OR_pixels_OR_video) native "WebGLRenderingContext__texImage2D_3_Callback";
+
+  void _texImage2D_4(target, level, internalformat, format_OR_width, height_OR_type, border_OR_canvas_OR_image_OR_pixels_OR_video) native "WebGLRenderingContext__texImage2D_4_Callback";
+
+  void _texImage2D_5(target, level, internalformat, format_OR_width, height_OR_type, border_OR_canvas_OR_image_OR_pixels_OR_video) native "WebGLRenderingContext__texImage2D_5_Callback";
 
   @DomName('WebGLRenderingContext.texImage2DCanvas')
   @DocsEditable()
@@ -2684,9 +2748,39 @@
   @DocsEditable()
   void texParameteri(int target, int pname, int param) native "WebGLRenderingContext_texParameteri_Callback";
 
-  @DomName('WebGLRenderingContext.texSubImage2D')
-  @DocsEditable()
-  void _texSubImageImage2D(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, TypedData pixels) native "WebGLRenderingContext_texSubImage2D_Callback";
+  void texSubImage2D(int target, int level, int xoffset, int yoffset, int format_OR_width, int height_OR_type, canvas_OR_format_OR_image_OR_pixels_OR_video, [int type, TypedData pixels]) {
+    if ((pixels is TypedData || pixels == null) && (type is int || type == null) && (canvas_OR_format_OR_image_OR_pixels_OR_video is int || canvas_OR_format_OR_image_OR_pixels_OR_video == null) && (height_OR_type is int || height_OR_type == null) && (format_OR_width is int || format_OR_width == null) && (yoffset is int || yoffset == null) && (xoffset is int || xoffset == null) && (level is int || level == null) && (target is int || target == null)) {
+      _texSubImage2D_1(target, level, xoffset, yoffset, format_OR_width, height_OR_type, canvas_OR_format_OR_image_OR_pixels_OR_video, type, pixels);
+      return;
+    }
+    if ((canvas_OR_format_OR_image_OR_pixels_OR_video is ImageData || canvas_OR_format_OR_image_OR_pixels_OR_video == null) && (height_OR_type is int || height_OR_type == null) && (format_OR_width is int || format_OR_width == null) && (yoffset is int || yoffset == null) && (xoffset is int || xoffset == null) && (level is int || level == null) && (target is int || target == null) && type == null && pixels == null) {
+      _texSubImage2D_2(target, level, xoffset, yoffset, format_OR_width, height_OR_type, canvas_OR_format_OR_image_OR_pixels_OR_video);
+      return;
+    }
+    if ((canvas_OR_format_OR_image_OR_pixels_OR_video is ImageElement || canvas_OR_format_OR_image_OR_pixels_OR_video == null) && (height_OR_type is int || height_OR_type == null) && (format_OR_width is int || format_OR_width == null) && (yoffset is int || yoffset == null) && (xoffset is int || xoffset == null) && (level is int || level == null) && (target is int || target == null) && type == null && pixels == null) {
+      _texSubImage2D_3(target, level, xoffset, yoffset, format_OR_width, height_OR_type, canvas_OR_format_OR_image_OR_pixels_OR_video);
+      return;
+    }
+    if ((canvas_OR_format_OR_image_OR_pixels_OR_video is CanvasElement || canvas_OR_format_OR_image_OR_pixels_OR_video == null) && (height_OR_type is int || height_OR_type == null) && (format_OR_width is int || format_OR_width == null) && (yoffset is int || yoffset == null) && (xoffset is int || xoffset == null) && (level is int || level == null) && (target is int || target == null) && type == null && pixels == null) {
+      _texSubImage2D_4(target, level, xoffset, yoffset, format_OR_width, height_OR_type, canvas_OR_format_OR_image_OR_pixels_OR_video);
+      return;
+    }
+    if ((canvas_OR_format_OR_image_OR_pixels_OR_video is VideoElement || canvas_OR_format_OR_image_OR_pixels_OR_video == null) && (height_OR_type is int || height_OR_type == null) && (format_OR_width is int || format_OR_width == null) && (yoffset is int || yoffset == null) && (xoffset is int || xoffset == null) && (level is int || level == null) && (target is int || target == null) && type == null && pixels == null) {
+      _texSubImage2D_5(target, level, xoffset, yoffset, format_OR_width, height_OR_type, canvas_OR_format_OR_image_OR_pixels_OR_video);
+      return;
+    }
+    throw new ArgumentError("Incorrect number or type of arguments");
+  }
+
+  void _texSubImage2D_1(target, level, xoffset, yoffset, format_OR_width, height_OR_type, canvas_OR_format_OR_image_OR_pixels_OR_video, type, pixels) native "WebGLRenderingContext__texSubImage2D_1_Callback";
+
+  void _texSubImage2D_2(target, level, xoffset, yoffset, format_OR_width, height_OR_type, canvas_OR_format_OR_image_OR_pixels_OR_video) native "WebGLRenderingContext__texSubImage2D_2_Callback";
+
+  void _texSubImage2D_3(target, level, xoffset, yoffset, format_OR_width, height_OR_type, canvas_OR_format_OR_image_OR_pixels_OR_video) native "WebGLRenderingContext__texSubImage2D_3_Callback";
+
+  void _texSubImage2D_4(target, level, xoffset, yoffset, format_OR_width, height_OR_type, canvas_OR_format_OR_image_OR_pixels_OR_video) native "WebGLRenderingContext__texSubImage2D_4_Callback";
+
+  void _texSubImage2D_5(target, level, xoffset, yoffset, format_OR_width, height_OR_type, canvas_OR_format_OR_image_OR_pixels_OR_video) native "WebGLRenderingContext__texSubImage2D_5_Callback";
 
   @DomName('WebGLRenderingContext.texSubImage2DCanvas')
   @DocsEditable()
@@ -2838,9 +2932,8 @@
    * To use [texImage2d] with a TypedData object, use [texImage2dTyped].
    *
    */
-  @DomName('WebGLRenderingContext.texImage2D')
-  void texImage2D(int targetTexture, int levelOfDetail, int internalFormat,
-      int format, int type, data) {
+  void texImage2DUntyped(int targetTexture, int levelOfDetail, 
+      int internalFormat, int format, int type, data) {
     if (data is ImageElement) {
       texImage2DImage(targetTexture, levelOfDetail, internalFormat, format,
           type, data);
@@ -2861,7 +2954,7 @@
    */
   void texImage2DTyped(int targetTexture, int levelOfDetail, int internalFormat,
       int width, int height, int border, int format, int type, TypedData data) {
-    _texImage2D(targetTexture, levelOfDetail, internalFormat,
+    texImage2D(targetTexture, levelOfDetail, internalFormat,
         width, height, border, format, type, data);
   }
 
@@ -2874,10 +2967,9 @@
    * To use [texSubImage2d] with a TypedData object, use [texSubImage2dTyped].
    *
    */
-  @DomName('WebGLRenderingContext.texSubImage2D')
-  void texSubImage2D(int targetTexture, int levelOfDetail, int internalFormat,
-      int format, int type, data) {
-    _texSubImage2D(targetTexture, levelOfDetail, internalFormat,
+  void texSubImage2DUntyped(int targetTexture, int levelOfDetail, 
+      int internalFormat, int format, int type, data) {
+    texSubImage2D(targetTexture, levelOfDetail, internalFormat,
         format, type, data);
   }
 
@@ -2887,7 +2979,7 @@
   void texSubImage2DTyped(int targetTexture, int levelOfDetail,
       int internalFormat, int width, int height, int border, int format,
       int type, TypedData data) {
-    _texSubImage2D(targetTexture, levelOfDetail, internalFormat,
+    texSubImage2D(targetTexture, levelOfDetail, internalFormat,
         width, height, border, format, type, data);
   }
 }
diff --git a/tests/co19/co19-analyzer.status b/tests/co19/co19-analyzer.status
index 9de5e51..4b8925e 100644
--- a/tests/co19/co19-analyzer.status
+++ b/tests/co19/co19-analyzer.status
@@ -12,17 +12,9 @@
 # TBF: infinite look: class A {const A();final m = const A();}
 Language/12_Expressions/01_Constants_A17_t03: fail
 
-# analyzer issue https://code.google.com/p/dart/issues/detail?id=11534
-Language/15_Types/4_Interface_Types_A11_t01: Skip
-Language/15_Types/4_Interface_Types_A11_t02: Skip
-
 # TBF: malformed or malbounded type in "conts" is static warning
 Language/12_Expressions/12_Instance_Creation_A01_t08: Fail
 
-# TBF: typedef self reference
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t08: Fail
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t09: Fail
-
 
 
 # co19 issue #442, undefined name "Expect"
@@ -157,10 +149,14 @@
 LibTest/async/StreamEventTransformer/handleDone_A01_t01: Fail
 LibTest/async/StreamEventTransformer/handleError_A01_t01: Fail
 
+#co19 issue 631
+Language/05_Variables/05_Variables_A11_t01: Fail
+Language/12_Expressions/30_Identifier_Reference_A02_t01: Fail
+Language/13_Statements/03_Variable_Declaration_A01_t09: Fail
+Language/13_Statements/03_Variable_Declaration_A01_t16: Fail
+
 Language/13_Statements/09_Switch_A02_t04: Fail  # Issue 629
 
-Language/07_Classes/6_Constructors/2_Factories_A14_t01: Fail # co19-roll r623: Please triage this failure
-Language/07_Classes/6_Constructors/2_Factories_A14_t02: Fail # co19-roll r623: Please triage this failure
 Language/12_Expressions/05_Strings_A20_t01: Fail # co19-roll r623: Please triage this failure
 LibTest/collection/DoubleLinkedQueue/DoubleLinkedQueue_class_A01_t01: Fail # co19-roll r623: Please triage this failure
 LibTest/collection/ListQueue/ListQueue_class_A01_t01: Fail # co19-roll r623: Please triage this failure
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index 11c10df..be9a01b 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -162,8 +162,8 @@
 ### CHECKED MODE FAILURES ###
 
 [ ($runtime == vm || $compiler == dart2js) && $checked]
+Language/13_Statements/09_Switch_A09_t01: PASS, FAIL, OK # co19 issue 633
 Language/07_Classes/6_Constructors/2_Factories_A12_t02: fail # co19-roll r587: Please triage this failure
-Language/13_Statements/09_Switch_A05_t01: FAIL, OK # co19 issue 498
 Language/14_Libraries_and_Scripts/1_Imports_A03_t46: PASS, FAIL, OK # co19 issue 560
 Language/14_Libraries_and_Scripts/1_Imports_A03_t66: PASS, FAIL, OK # co19 issue 560
 LibTest/async/EventTransformStream/contains_A01_t01: FAIL, OK  # co19 issue 498
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index 2c64a3f..171db73 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -121,8 +121,6 @@
 Language/12_Expressions/12_Instance_Creation/1_New_A06_t04: fail # co19-roll r546: Please triage this failure
 Language/12_Expressions/12_Instance_Creation/1_New_A06_t05: fail # co19-roll r546: Please triage this failure
 Language/12_Expressions/12_Instance_Creation/1_New_A06_t06: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/12_Instance_Creation/1_New_A06_t12: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/12_Instance_Creation/1_New_A09_t09: fail # co19-roll r546: Please triage this failure
 Language/12_Expressions/22_Equality_A01_t01: fail # co19-roll r546: Please triage this failure
 Language/12_Expressions/22_Equality_A01_t19: fail # co19-roll r546: Please triage this failure
 Language/12_Expressions/22_Equality_A01_t20: fail # co19-roll r546: Please triage this failure
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index ed14cd3..cabdf4d 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -109,6 +109,7 @@
 LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Fail # TODO(ngeoaffray): Please triage these failure.
 
 [ $compiler == dart2js && $checked ]
+Language/13_Statements/09_Switch_A05_t01: Fail # Missing type check in switch expression
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A17_t03: Fail # TODO(ahe): Please triage this failure.
 Language/15_Types/2_Dynamic_Type_System_A01_t02: RuntimeError # co19-roll r607: Please triage this failure
 Language/15_Types/8_Parameterized_Types_A03_t07: RuntimeError # co19-roll r607: Please triage this failure
diff --git a/tests/co19/co19-dartium.status b/tests/co19/co19-dartium.status
index 87bc8a6..2be217a 100644
--- a/tests/co19/co19-dartium.status
+++ b/tests/co19/co19-dartium.status
@@ -27,8 +27,6 @@
 Language/07_Classes/6_Constructors/2_Factories_A14_t02: Fail # co19-roll r623: Please triage this failure
 Language/12_Expressions/01_Constants_A16_t04: Fail # Issue 13719: Please triage this failure.
 Language/12_Expressions/01_Constants_A16_t05: Fail # Issue 13719: Please triage this failure.
-Language/12_Expressions/12_Instance_Creation/1_New_A06_t12: Fail # Issue 13719: Please triage this failure.
-Language/12_Expressions/12_Instance_Creation/1_New_A09_t09: Fail # Issue 13719: Please triage this failure.
 Language/12_Expressions/12_Instance_Creation/2_Const_A10_t01: Fail # Issue 13719: Please triage this failure.
 Language/12_Expressions/18_Assignment_A04_t09: Fail # co19-roll r607: Please triage this failure
 Language/12_Expressions/30_Identifier_Reference_A08_t02: Fail # Issue 13719: Please triage this failure.
@@ -46,12 +44,6 @@
 Language/14_Libraries_and_Scripts/2_Exports_A04_t03: Fail # Issue 13719: Please triage this failure.
 Language/14_Libraries_and_Scripts/3_Parts_A02_t02: Pass, Timeout # Issue 13719: Please triage this failure.
 Language/14_Libraries_and_Scripts/4_Scripts_A03_t02: Fail # Issue 13719: Please triage this failure.
-Language/14_Libraries_and_Scripts/5_URIs_A01_t04: Fail # Issue 13719: Please triage this failure.
-Language/14_Libraries_and_Scripts/5_URIs_A01_t05: Fail # Issue 13719: Please triage this failure.
-Language/14_Libraries_and_Scripts/5_URIs_A01_t14: Fail # Issue 13719: Please triage this failure.
-Language/14_Libraries_and_Scripts/5_URIs_A01_t15: Fail # Issue 13719: Please triage this failure.
-Language/14_Libraries_and_Scripts/5_URIs_A01_t24: Fail # Issue 13719: Please triage this failure.
-Language/14_Libraries_and_Scripts/5_URIs_A01_t25: Fail # Issue 13719: Please triage this failure.
 Language/15_Types/3_Type_Declarations/1_Typedef_A07_t08: Fail # co19-roll r607: Please triage this failure
 Language/15_Types/3_Type_Declarations/1_Typedef_A07_t09: Fail # co19-roll r607: Please triage this failure
 LibTest/async/Completer/completeError_A02_t01: Pass, Fail # Issue 13719: Please triage this failure.
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 06df489..1017509 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -32,8 +32,6 @@
 
 Language/05_Variables/05_Variables_A05_t01: fail # Dart issue 12539
 Language/05_Variables/05_Variables_A05_t02: fail # Dart issue 12539
-Language/12_Expressions/12_Instance_Creation/1_New_A06_t12: fail # Dart issue 12549
-Language/12_Expressions/12_Instance_Creation/1_New_A09_t09: fail # Dart issue 1372
 Language/12_Expressions/12_Instance_Creation/2_Const_A10_t01: fail # co19 issue 525
 Language/12_Expressions/30_Identifier_Reference_A08_t02: fail # Dart issue 12593
 Language/13_Statements/03_Variable_Declaration_A04_t07: fail # co19 issue 535
@@ -44,10 +42,6 @@
 Language/14_Libraries_and_Scripts/2_Exports_A04_t02: fail # Dart issue 12916
 Language/14_Libraries_and_Scripts/2_Exports_A04_t03: fail # Dart issue 12916
 Language/14_Libraries_and_Scripts/4_Scripts_A03_t03: MissingRuntimeError, OK # co19 issue
-Language/14_Libraries_and_Scripts/5_URIs_A01_t04: fail # Issue 12521
-Language/14_Libraries_and_Scripts/5_URIs_A01_t05: fail # Issue 12521
-Language/14_Libraries_and_Scripts/5_URIs_A01_t14: fail # Issue 12521
-Language/14_Libraries_and_Scripts/5_URIs_A01_t15: fail # Issue 12521
 
 LibTest/core/DateTime/parse_A03_t01: fail # Issue 12514
 
@@ -61,13 +55,9 @@
 LibTest/isolate/isolate_api/spawnUri_A02_t02: Fail # VM triage, check spec.
 LibTest/isolate/isolate_api/spawnUri_A02_t03: Fail # VM triage, check spec.
 
-Language/14_Libraries_and_Scripts/5_URIs_A01_t24: fail # co19-roll r587: Please triage this failure
-Language/14_Libraries_and_Scripts/5_URIs_A01_t25: fail # co19-roll r587: Please triage this failure
-
-LibTest/typed_data/Float32x4/clamp_A01_t01: Pass, Fail # Issue 13543
-LibTest/typed_data/Float32x4/clamp_A02_t01: Pass, Fail # Issue 13543
-LibTest/typed_data/Float32x4/reciprocalSqrt_A01_t01: Pass, Fail # Issue 13543
-LibTest/typed_data/Float32x4/reciprocal_A01_t01: Pass, Fail # Issue 13543
+LibTest/typed_data/Float32x4/clamp_A01_t01: Pass, Fail # Issue 13106 
+LibTest/typed_data/Float32x4/reciprocalSqrt_A01_t01: Pass, Fail # Issue 13398
+LibTest/typed_data/Float32x4/reciprocal_A01_t01: Pass, Fail # Issue 13398
 Language/15_Types/3_Type_Declarations/1_Typedef_A07_t08: MissingCompileTimeError # co19-roll r607: Please triage this failure
 Language/15_Types/3_Type_Declarations/1_Typedef_A07_t09: MissingCompileTimeError # co19-roll r607: Please triage this failure
 LibTest/core/Invocation/positionalArguments_A01_t01: RuntimeError # co19-roll r607: Please triage this failure
diff --git a/tests/compiler/dart2js/bailout_indexable_test.dart b/tests/compiler/dart2js/bailout_indexable_test.dart
deleted file mode 100644
index 8a44ac8..0000000
--- a/tests/compiler/dart2js/bailout_indexable_test.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "package:expect/expect.dart";
-import 'compiler_helper.dart';
-
-const String TEST = '''
-foo(a) {
-  foo([]);
-  print(a[0]);
-}
-''';
-
-main() {
-  String generated = compile(
-      TEST,
-      entry: 'foo',
-      interceptorsSource: DEFAULT_INTERCEPTORSLIB
-      // ADD a bogus indexable class that does not have [].
-          + 'class BogusIndexable implements JSIndexable {}');
-
-  // Ensure that we still generate an optimized version, even if there
-  // is an indexable class that does not implement [].
-  Expect.isTrue(!generated.contains('index'));
-}
diff --git a/tests/compiler/dart2js/builtin_interceptor_test.dart b/tests/compiler/dart2js/builtin_interceptor_test.dart
index d26f97f..00aead3 100644
--- a/tests/compiler/dart2js/builtin_interceptor_test.dart
+++ b/tests/compiler/dart2js/builtin_interceptor_test.dart
@@ -6,31 +6,18 @@
 import 'compiler_helper.dart';
 
 const String TEST_ONE = r"""
-foo(String a) {
-  // Make sure the string class is registered.
-  var c = 'foo';
-  // index into the parameter and move into a loop to make sure we'll get a
-  // type guard.
-  for (int i = 0; i < 1; i++) {
-    print(a[0] + c);
-  }
-  return a.length;
-}
-""";
-
-const String TEST_TWO = r"""
 foo() {
   return "foo".length;
 }
 """;
 
-const String TEST_THREE = r"""
+const String TEST_TWO = r"""
 foo() {
   return r"foo".length;
 }
 """;
 
-const String TEST_FOUR = r"""
+const String TEST_THREE = r"""
 foo() {
   return new List().add(2);
 }
@@ -38,14 +25,11 @@
 
 main() {
   String generated = compile(TEST_ONE, entry: 'foo');
-  Expect.isTrue(generated.contains("a.length"));
+  Expect.isTrue(generated.contains("return 3;"));
 
   generated = compile(TEST_TWO, entry: 'foo');
   Expect.isTrue(generated.contains("return 3;"));
 
   generated = compile(TEST_THREE, entry: 'foo');
-  Expect.isTrue(generated.contains("return 3;"));
-
-  generated = compile(TEST_FOUR, entry: 'foo');
   Expect.isTrue(generated.contains("push(2);"));
 }
diff --git a/tests/compiler/dart2js/dead_bailout_target_test.dart b/tests/compiler/dart2js/dead_bailout_target_test.dart
deleted file mode 100644
index 5c369b2..0000000
--- a/tests/compiler/dart2js/dead_bailout_target_test.dart
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// This unit test of dart2js checks that a SSA bailout target
-// instruction gets removed from the graph when it's not used.
-
-import "package:expect/expect.dart";
-import "package:async_helper/async_helper.dart";
-import 'compiler_helper.dart';
-
-String TEST = r'''
-main() {
-  foo(1);
-  foo([]);
-}
-
-class A {
-  operator -() => this;
-}
-
-foo(a) {
-  new A(); // Force having another operator-
-  // Make the method recursive to always enable bailouts
-  // and force a list instantiation.
-  foo([]);
-  // Force bailout on [a].
-  for (int i = 0; i < 100; i++) a[0] = 42;
-  // Force bailout on [:a.length:].
-  for (int i = 0; i < 200; i++) a[0] = -a.length;
-}
-''';
-
-main() {
-  String generated = compile(TEST, entry: 'foo');
-  // Check that we only have one bailout call. The second bailout call
-  // is dead code because we know [:a.length:] is an int.
-  checkNumberOfMatches(new RegExp('bailout').allMatches(generated).iterator, 1);
-
-  // Check that the foo method does not have any call to
-  // 'getInterceptor'. The environment for the second bailout contains
-  // the interceptor of [:a.length:], but since the bailout is
-  // removed, the interceptor is removed too.
-  if (generated.contains(r'getInterceptor(a).$is')) {
-    // If we have an interceptor for a type check, it should be the only one.
-    checkNumberOfMatches(
-        new RegExp('getInterceptor').allMatches(generated).iterator, 1);
-  } else {
-    Expect.isTrue(!generated.contains('getInterceptor'));
-  }
-
-  asyncTest(() => compileAll(TEST).then((generated) {
-    // Check that the foo bailout method is generated.
-    checkNumberOfMatches(
-        new RegExp('foo\\\$bailout').allMatches(generated).iterator, 2);
-
-    // Check that it's the only bailout method.
-    checkNumberOfMatches(new RegExp('bailout').allMatches(generated).iterator, 2);
-
-    // Check that the bailout method has a case 2 for the state, which
-    // is the second bailout in foo.
-    Expect.isTrue(generated.contains('case 2:'));
-
-    // Finally, make sure that the reason foo does not contain
-    // 'getInterceptor' is not because the compiler renamed it.
-    Expect.isTrue(generated.contains('getInterceptor'));
-  }));
-}
diff --git a/tests/compiler/dart2js/interceptor_test.dart b/tests/compiler/dart2js/interceptor_test.dart
index a87ffe0..59fa151 100644
--- a/tests/compiler/dart2js/interceptor_test.dart
+++ b/tests/compiler/dart2js/interceptor_test.dart
@@ -7,23 +7,13 @@
 
 const String TEST_ONE = r"""
   foo(a) {
-    // Make sure there is a bailout version.
-    foo(a);
-    // This will make a one shot interceptor that will be optimized in
-    // the non-bailout version because we know a is a number.
-    return (a + 42).toString;
-  }
-""";
-
-const String TEST_TWO = r"""
-  foo(a) {
     var myVariableName = a.toString();
     print(myVariableName);
     print(myVariableName);
   }
 """;
 
-const String TEST_THREE = r"""
+const String TEST_TWO = r"""
   class A {
     var length;
   }
@@ -34,21 +24,16 @@
 """;
 
 main() {
-  var generated = compile(TEST_ONE, entry: 'foo');
-  // Check that the one shot interceptor got converted to a direct
-  // call to the interceptor object.
-  Expect.isTrue(generated.contains('JSNumber_methods.get\$toString(a + 42);'));
-
   // Check that one-shot interceptors preserve variable names, see
   // https://code.google.com/p/dart/issues/detail?id=8106.
-  generated = compile(TEST_TWO, entry: 'foo');
+  String generated = compile(TEST_ONE, entry: 'foo');
   Expect.isTrue(generated.contains(new RegExp(r'[$A-Z]+\.toString\$0\(a\)')));
   Expect.isTrue(generated.contains('myVariableName'));
 
   // Check that an intercepted getter that does not need to be
   // intercepted, is turned into a regular getter call or field
   // access.
-  generated = compile(TEST_THREE, entry: 'foo');
+  generated = compile(TEST_TWO, entry: 'foo');
   Expect.isFalse(generated.contains(r'a.get$length()'));
   Expect.isTrue(generated.contains(new RegExp(r'[$A-Z]+\.A\$\(\)\.length')));
   Expect.isTrue(
diff --git a/tests/compiler/dart2js/list_tracer_test.dart b/tests/compiler/dart2js/list_tracer_test.dart
index 5668c63..aaa56b5 100644
--- a/tests/compiler/dart2js/list_tracer_test.dart
+++ b/tests/compiler/dart2js/list_tracer_test.dart
@@ -209,7 +209,7 @@
     checkType('listPassedToSelector', typesTask.numType);
     checkType('listReturnedFromSelector', typesTask.numType);
     checkType('listUsedWithAddAndInsert', typesTask.numType);
-    checkType('listUsedWithConstraint', typesTask.numType);
+    checkType('listUsedWithConstraint', typesTask.intType);
     checkType('listEscapingFromSetter', typesTask.numType);
     checkType('listUsedInLocal', typesTask.numType);
     checkType('listEscapingInSetterValue', typesTask.numType);
diff --git a/tests/compiler/dart2js/rewrite_better_user_test.dart b/tests/compiler/dart2js/rewrite_better_user_test.dart
deleted file mode 100644
index ec1fcbc..0000000
--- a/tests/compiler/dart2js/rewrite_better_user_test.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-// Test that we get rid of duplicate type guards on a field when that
-// field is being gvn'ed.
-
-import 'compiler_helper.dart';
-import "package:async_helper/async_helper.dart";
-
-const String TEST = r"""
-class A {
-  var field = 52;
-  foo() {
-    var a = this.field;
-    while (a + 42 == 42);
-    // This field get should be GVN'ed
-    a = this.field;
-    while (a + 87 == 87);
-    field = 'bar';
-  }
-}
-
-main() {
-  while (true) new A().foo();
-}
-""";
-
-main() {
-  asyncTest(() => compileAll(TEST).then((generated) {
-    RegExp regexp = new RegExp('foo\\\$0\\\$bailout');
-    Iterator matches = regexp.allMatches(generated).iterator;
-
-    // We check that there is only one call to the bailout method.
-    // One match for the call, one for the definition.
-    checkNumberOfMatches(matches, 2);
-  }));
-}
diff --git a/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart b/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
index af06626..bc17e71 100644
--- a/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
@@ -120,8 +120,7 @@
 
   var compiler2 = compilerFor(TEST2, uri);
   asyncTest(() => compiler2.runCompiler(uri).then((_) {
-    checkReturn(compiler2, 'test1',
-        compiler2.typesTask.dynamicType.nonNullable());
+    checkReturn(compiler2, 'test1', compiler2.typesTask.mapType.nonNullable());
     checkReturn(compiler2, 'test2', compiler2.typesTask.mapType);
     checkReturn(compiler2, 'test3', compiler2.typesTask.mapType);
     checkReturn(compiler2, 'test4', compiler2.typesTask.mapType);
diff --git a/tests/compiler/dart2js/type_inference3_test.dart b/tests/compiler/dart2js/type_inference3_test.dart
index e3fcf5a..17aa7be 100644
--- a/tests/compiler/dart2js/type_inference3_test.dart
+++ b/tests/compiler/dart2js/type_inference3_test.dart
@@ -15,8 +15,6 @@
 
 main() {
   String generated = compile(TEST_ONE, entry: 'sum');
-  RegExp regexp = new RegExp(getNumberTypeCheck('(param0|a)'));
-  Expect.isTrue(regexp.hasMatch(generated));
-  regexp = new RegExp(getNumberTypeCheck('(param1|b)'));
+  RegExp regexp = new RegExp(getNumberTypeCheck('(param1|b)'));
   Expect.isTrue(regexp.hasMatch(generated));
 }
diff --git a/tests/compiler/dart2js/type_inference_test.dart b/tests/compiler/dart2js/type_inference_test.dart
deleted file mode 100644
index 8c3d91b..0000000
--- a/tests/compiler/dart2js/type_inference_test.dart
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "package:expect/expect.dart";
-import 'compiler_helper.dart';
-
-const String TEST_ONE = r"""
-sum(a, b) {
-  var c = 0;
-  for (var d = a; d < b; d += 1) c = c + d;
-  return c;
-}
-""";
-
-const String TEST_TWO = r"""
-foo(int a) {
-  return -a;
-}
-""";
-
-const String TEST_TWO_WITH_BAILOUT = r"""
-foo(int a) {
-  for (int b = 0; b < 1; b++) {
-    a = -a;
-  }
-  return a;
-}
-""";
-
-const String TEST_THREE = r"""
-foo(a) {
-  print([]); // Force a list to be instantiated.
-  for (int b = 0; b < 10; b++) print(a[b]);
-}
-""";
-
-const String TEST_FOUR = r"""
-foo(a) {
-  print([]); // Force a list to be instantiated.
-  print(a[0]); // Force a type guard.
-  while (true) print(a.length);
-}
-""";
-
-const String TEST_FIVE = r"""
-foo(a) {
-  a[0] = 1;
-  print(a[1]);
-}
-""";
-
-const String TEST_FIVE_WITH_BAILOUT = r"""
-foo(a) {
-  print([]); // Force a list to be instantiated.
-  for (int i = 0; i < 1; i++) {
-    a[0] = 1;
-    print(a[1]);
-  }
-}
-""";
-
-const String TEST_SIX = r"""
-foo(a) {
-  print([]); // Force a list to be instantiated.
-  print(a[0]);
-  while (true) {
-    a[0] = a[1];
-  }
-}
-""";
-
-main() {
-  compileAndMatchFuzzy(TEST_ONE, 'sum', "x \\+= x");
-  compileAndMatchFuzzy(TEST_ONE, 'sum', 'typeof x !== "number"');
-
-  var generated = compile(TEST_TWO, entry: 'foo');
-  RegExp regexp = new RegExp(getNumberTypeCheck('a'));
-  Expect.isTrue(!regexp.hasMatch(generated));
-
-  regexp = new RegExp('-a');
-  Expect.isTrue(!regexp.hasMatch(generated));
-
-  generated = compile(TEST_TWO_WITH_BAILOUT, entry: 'foo');
-  regexp = new RegExp(getNumberTypeCheck('a'));
-  Expect.isTrue(regexp.hasMatch(generated));
-
-  regexp = new RegExp('-a');
-  Expect.isTrue(regexp.hasMatch(generated));
-
-  generated = compile(TEST_THREE, entry: 'foo');
-  regexp = new RegExp("a[$anyIdentifier]");
-  Expect.isTrue(regexp.hasMatch(generated));
-
-  generated = compile(TEST_FOUR, entry: 'foo');
-  regexp = new RegExp("a.length");
-  Expect.isTrue(regexp.hasMatch(generated));
-
-  generated = compile(TEST_FIVE, entry: 'foo');
-  regexp = new RegExp('a.constructor !== Array');
-  Expect.isTrue(!regexp.hasMatch(generated));
-  Expect.isTrue(generated.contains('index'));
-  Expect.isTrue(generated.contains('indexSet'));
-
-  generated = compile(TEST_FIVE_WITH_BAILOUT, entry: 'foo');
-  regexp = new RegExp('a.constructor !== Array');
-  Expect.isTrue(regexp.hasMatch(generated));
-  Expect.isTrue(!generated.contains('index'));
-  Expect.isTrue(!generated.contains('indexSet'));
-
-  generated = compile(TEST_SIX, entry: 'foo');
-  regexp = new RegExp('a.constructor !== Array');
-  Expect.isTrue(regexp.hasMatch(generated));
-  Expect.isTrue(!generated.contains('index(0)'));
-  Expect.isTrue(!generated.contains('index(1)'));
-  Expect.isTrue(!generated.contains('indexSet'));
-}
diff --git a/tests/compiler/dart2js/value_range_test.dart b/tests/compiler/dart2js/value_range_test.dart
index f14c1de..3825bee 100644
--- a/tests/compiler/dart2js/value_range_test.dart
+++ b/tests/compiler/dart2js/value_range_test.dart
@@ -158,8 +158,7 @@
 
 """
 main(value) {
-  // Force [value] to be an int by having the speculative optimizer
-  // want an int.
+  value = value is int ? value as int : 42;
   int sum = ~value;
   for (int i = 0; i < 42; i++) sum += (value & 4);
   var a = new List();
@@ -172,8 +171,7 @@
 
 """
 main(value) {
-  // Force [value] to be an int by having the speculative optimizer
-  // want an int.
+  value = value is int ? value as int : 42;
   int sum = ~value;
   for (int i = 0; i < 42; i++) sum += (value & 4);
   var a = new List();
@@ -187,8 +185,7 @@
 REMOVED,
 """
 main(value) {
-  // Force [value] to be an int by having the speculative optimizer
-  // want an int.
+  value = value is int ? value as int : 42;
   int sum = ~value;
   for (int i = 0; i < 42; i++) sum += (value & 4);
   var a = new List();
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index 1603aa3..ff4d572 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -42,3 +42,6 @@
 [ $csp ]
 deferred/deferred_class_test: Fail # http://dartbug.com/3940
 deferred/deferred_constant_test: Fail # http://dartbug.com/3940
+
+[ $compiler == dart2js && $browser ]
+mirror_printer_test: Fail # Issue 14304
\ No newline at end of file
diff --git a/tests/compiler/dart2js_native/dart2js_native.status b/tests/compiler/dart2js_native/dart2js_native.status
index 1daea78..c8e3e7f 100644
--- a/tests/compiler/dart2js_native/dart2js_native.status
+++ b/tests/compiler/dart2js_native/dart2js_native.status
@@ -8,6 +8,8 @@
 [ $compiler == dart2js ]
 native_no_such_method_exception4_frog_test: Fail  # Issue 9631
 native_no_such_method_exception5_frog_test: Fail  # Issue 9631
+subclassing_super_field_1_test: Fail  # Issue 14096
+subclassing_super_field_2_test: Fail  # Issue 14096
 
 [ $compiler == dart2js && $unminified ]
 fake_thing_test: Fail # Issue 13010
diff --git a/tests/compiler/dart2js_native/subclassing_constructor_1_test.dart b/tests/compiler/dart2js_native/subclassing_constructor_1_test.dart
index 333a9f2..36fed2e 100644
--- a/tests/compiler/dart2js_native/subclassing_constructor_1_test.dart
+++ b/tests/compiler/dart2js_native/subclassing_constructor_1_test.dart
@@ -6,7 +6,7 @@
 import 'dart:_foreign_helper' show JS;
 import 'dart:_js_helper' show Creates, setNativeSubclassDispatchRecord;
 import 'dart:_interceptors' show
-    findInterceptorForType, findConstructorForWebComponentType;
+    findInterceptorForType, findConstructorForNativeSubclassType;
 
 // Test that subclasses of native classes can be initialized by calling the
 // 'upgrade' constructor.
@@ -69,9 +69,9 @@
 
 test_one() {
   trace = [];
-  var constructor = findConstructorForWebComponentType(B, 'one');
+  var constructor = findConstructorForNativeSubclassType(B, 'one');
   Expect.isNotNull(constructor);
-  Expect.isNull(findConstructorForWebComponentType(B, 'Missing'));
+  Expect.isNull(findConstructorForNativeSubclassType(B, 'Missing'));
 
   var b = makeB();
   Expect.isTrue(b is B);
@@ -93,7 +93,7 @@
 
 test_two() {
   trace = [];
-  var constructor = findConstructorForWebComponentType(B, 'two');
+  var constructor = findConstructorForNativeSubclassType(B, 'two');
   Expect.isNotNull(constructor);
 
   var b = makeB();
@@ -117,7 +117,7 @@
 
 test_three() {
   trace = [];
-  var constructor = findConstructorForWebComponentType(B, 'three');
+  var constructor = findConstructorForNativeSubclassType(B, 'three');
   Expect.isNotNull(constructor);
 
   var b = makeB();
@@ -128,7 +128,7 @@
   // is as though the web components runtime explicitly passed `null` for all
   // parameters.
   //
-  // TODO(sra): The constructor returned by findConstructorForWebComponentType
+  // TODO(sra): The constructor returned by findConstructorForNativeSubclassType
   // should be a function that fills in the default values.
   JS('', '#(#)', constructor, b);
   Expect.isTrue(b is B);
diff --git a/tests/compiler/dart2js_native/subclassing_super_field_1_test.dart b/tests/compiler/dart2js_native/subclassing_super_field_1_test.dart
new file mode 100644
index 0000000..250c884
--- /dev/null
+++ b/tests/compiler/dart2js_native/subclassing_super_field_1_test.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import 'dart:_foreign_helper' show JS;
+import 'dart:_js_helper' show Creates, setNativeSubclassDispatchRecord;
+import 'dart:_interceptors' show
+    findInterceptorForType, findConstructorForNativeSubclassType;
+
+// Test for shadowed fields in classes that extend native classes.
+
+class N native "N" {
+  N.init();
+}
+
+class A extends N {
+  var foo = 111;
+  A.init() : super.init();
+}
+
+class B extends A  {
+  var foo = 222;
+  B.init() : super.init();
+
+  Afoo() => super.foo;
+  Bfoo() => foo;
+}
+
+B makeB() native;
+
+@Creates('=Object')
+getBPrototype() native;
+
+void setup() native r"""
+function B() { }
+makeB = function(){return new B;};
+
+getBPrototype = function(){return B.prototype;};
+""";
+
+var inscrutable;
+
+main() {
+  setup();
+  inscrutable = (x) => x;
+
+  setNativeSubclassDispatchRecord(getBPrototype(), findInterceptorForType(B));
+
+  B b = makeB();
+
+  var constructor = findConstructorForNativeSubclassType(B, 'init');
+  Expect.isNotNull(constructor);
+  JS('', '#(#)', constructor, b);
+
+  print(b);
+
+  Expect.equals(222, inscrutable(b).Bfoo());
+  Expect.equals(111, inscrutable(b).Afoo());
+
+  Expect.equals(222, b.Bfoo());
+  Expect.equals(111, b.Afoo());
+}
diff --git a/tests/compiler/dart2js_native/subclassing_super_field_2_test.dart b/tests/compiler/dart2js_native/subclassing_super_field_2_test.dart
new file mode 100644
index 0000000..dca071b
--- /dev/null
+++ b/tests/compiler/dart2js_native/subclassing_super_field_2_test.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import 'dart:_foreign_helper' show JS;
+import 'dart:_js_helper' show Creates, setNativeSubclassDispatchRecord;
+import 'dart:_interceptors' show
+    findInterceptorForType, findConstructorForNativeSubclassType;
+
+// Test for fields with same name as native fields.  We expect N.foo to have the
+// property name 'foo' and A.foo and B.foo to have non-conflicting names.
+
+class N native "N" {
+  var foo;
+  N.init();
+}
+
+class A extends N {
+  var foo = 222;
+  A.init() : super.init();
+  Nfoo() => super.foo;     // TODO(sra): Fix compiler assert.
+}
+
+class B extends A  {
+  var foo = 333;
+  B.init() : super.init();
+  Afoo() => super.foo;
+  Bfoo() => foo;
+
+  toString() => '[N.foo = ${Nfoo()}, A.foo = ${Afoo()}, B.foo = ${Bfoo()}]';
+}
+
+B makeB() native;
+
+@Creates('=Object')
+getBPrototype() native;
+
+void setup() native r"""
+function B() { this.foo = 111; }  // N.foo
+makeB = function(){return new B;};
+
+getBPrototype = function(){return B.prototype;};
+""";
+
+var inscrutable;
+
+main() {
+  setup();
+  inscrutable = (x) => x;
+
+  setNativeSubclassDispatchRecord(getBPrototype(), findInterceptorForType(B));
+
+  B b = makeB();
+
+  var constructor = findConstructorForNativeSubclassType(B, 'init');
+  Expect.isNotNull(constructor);
+  JS('', '#(#)', constructor, b);
+
+  print(b);
+
+  Expect.equals(333, inscrutable(b).Bfoo());
+  Expect.equals(222, inscrutable(b).Afoo());
+  Expect.equals(111, inscrutable(b).Nfoo());
+
+  Expect.equals(333, b.Bfoo());
+  Expect.equals(222, b.Afoo());
+  Expect.equals(111, b.Nfoo());
+}
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index c475d9b..3ea6490 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -47,6 +47,7 @@
 bit_twiddling_bigint_test: RuntimeError # Requires bigint support.
 compare_to2_test: RuntimeError, OK    # Requires bigint support.
 string_base_vm_test: RuntimeError, OK # VM specific test.
+nan_infinity_test/01: Fail # Issue 11551
 
 [ $compiler == dart2js && $runtime == none ]
 *: Fail, Pass # TODO(ahe): Triage these tests.
diff --git a/tests/corelib/nan_infinity_test.dart b/tests/corelib/nan_infinity_test.dart
index 83e9455..9496584 100644
--- a/tests/corelib/nan_infinity_test.dart
+++ b/tests/corelib/nan_infinity_test.dart
@@ -7,33 +7,84 @@
 // Dart test program for testing NaN and Infinity.
 
 void main() {
+  // Sanity tests.
+  Expect.isFalse(1.5.isNaN);
+  Expect.isFalse(1.5.isInfinite);
+  Expect.isTrue(1.5.isFinite);
+  Expect.isFalse(1.5.isNegative);
+  Expect.isTrue((-1.5).isNegative);
+  Expect.isFalse(0.0.isNegative);
+  Expect.isTrue((-0.0).isNegative);
+  Expect.isTrue((-0.0).isFinite);
+
+  Expect.isFalse(1.isNaN);
+  Expect.isFalse(1.isInfinite);
+  Expect.isTrue(1.isFinite);
+  Expect.isFalse(1.isNegative);
+  Expect.isTrue((-1).isNegative);
+
+  // Test that predicates give the correct result.
   Expect.isTrue(double.NAN.isNaN);
   Expect.isFalse(double.NAN.isInfinite);
+  Expect.isFalse(double.NAN.isFinite);
+  Expect.isFalse(double.NAN.isNegative);
+  Expect.isFalse((-double.NAN).isNegative);
+
   Expect.isFalse(double.INFINITY.isNaN);
   Expect.isTrue(double.INFINITY.isInfinite);
+  Expect.isFalse(double.INFINITY.isFinite);
+  Expect.isFalse(double.INFINITY.isNegative);
+  Expect.isTrue((-double.INFINITY).isNegative);
+
   Expect.isFalse(double.NEGATIVE_INFINITY.isNaN);
   Expect.isTrue(double.NEGATIVE_INFINITY.isInfinite);
+  Expect.isFalse(double.NEGATIVE_INFINITY.isFinite);
+  Expect.isTrue(double.NEGATIVE_INFINITY.isNegative);
+  Expect.isFalse((-double.NEGATIVE_INFINITY).isNegative);
+
+  // Test toString.
   Expect.equals("NaN", double.NAN.toString());
   Expect.equals("Infinity", double.INFINITY.toString());
   Expect.equals("-Infinity", double.NEGATIVE_INFINITY.toString());
-  Expect.isFalse(double.NAN == double.NAN);
+
+  // Test identities.
+  Expect.isTrue(identical(double.NAN, double.NAN));  /// 01: ok
+  Expect.isTrue(identical(double.INFINITY, double.INFINITY));
+  Expect.isTrue(identical(double.NEGATIVE_INFINITY, double.NEGATIVE_INFINITY));
+  Expect.isFalse(identical(double.NAN, double.INFINITY));
+  Expect.isFalse(identical(double.NAN, double.NEGATIVE_INFINITY));
+  Expect.isFalse(identical(double.INFINITY, double.NEGATIVE_INFINITY));
+  Expect.isTrue(identical(double.NAN, -double.NAN));  /// 01: continued
+  Expect.isTrue(identical(double.INFINITY, -double.NEGATIVE_INFINITY));
+  Expect.isTrue(identical(double.NEGATIVE_INFINITY, -double.INFINITY));
+
+  // Test equalities
   Expect.isTrue(double.INFINITY == double.INFINITY);
   Expect.isTrue(double.NEGATIVE_INFINITY == double.NEGATIVE_INFINITY);
+  Expect.isFalse(double.INFINITY == double.NEGATIVE_INFINITY);
+  Expect.isFalse(double.NEGATIVE_INFINITY == double.INFINITY);
+  Expect.isFalse(double.NAN == double.NAN);
+  Expect.isFalse(double.NAN == double.INFINITY);
+  Expect.isFalse(double.NAN == double.NEGATIVE_INFINITY);
+  Expect.isFalse(double.INFINITY == double.NAN);
+  Expect.isFalse(double.NEGATIVE_INFINITY == double.NAN);
+
+  // Test relational order.
   Expect.isFalse(double.NAN < double.NAN);
   Expect.isFalse(double.NAN < double.INFINITY);
   Expect.isFalse(double.NAN < double.NEGATIVE_INFINITY);
   Expect.isFalse(double.NAN > double.NAN);
   Expect.isFalse(double.NAN > double.INFINITY);
   Expect.isFalse(double.NAN > double.NEGATIVE_INFINITY);
-  Expect.isFalse(double.NAN == double.NAN);
-  Expect.isFalse(double.NAN == double.INFINITY);
-  Expect.isFalse(double.NAN == double.NEGATIVE_INFINITY);
   Expect.isFalse(double.INFINITY < double.NAN);
   Expect.isFalse(double.NEGATIVE_INFINITY < double.NAN);
   Expect.isFalse(double.INFINITY > double.NAN);
   Expect.isFalse(double.NEGATIVE_INFINITY > double.NAN);
-  Expect.isFalse(double.INFINITY == double.NAN);
-  Expect.isFalse(double.NEGATIVE_INFINITY == double.NAN);
-  Expect.isTrue((3.0 * double.NAN).isNaN);
   Expect.isTrue(double.INFINITY > double.NEGATIVE_INFINITY);
+  Expect.isFalse(double.INFINITY < double.NEGATIVE_INFINITY);
+
+  // NaN is contagious.
+  Expect.isTrue((3.0 * double.NAN).isNaN);
+  Expect.isTrue((3.0 + double.NAN).isNaN);
+  Expect.isTrue((-double.NAN).isNaN);
 }
diff --git a/tests/html/audiocontext_test.dart b/tests/html/audiocontext_test.dart
index e5b1558..dda3d25 100644
--- a/tests/html/audiocontext_test.dart
+++ b/tests/html/audiocontext_test.dart
@@ -60,6 +60,8 @@
       }
     });
 
+    // TODO(9322): This test times out.
+    /*
     test('onAudioProcess', () {
       if(AudioContext.supported) {
         var completer = new Completer<bool>();
@@ -76,5 +78,35 @@
         return completer.future;
       }
     });
+    */
+
+    test('oscillatorTypes', () {
+      if(AudioContext.supported) {
+        AudioContext context = new AudioContext();
+        OscillatorNode oscillator = context.createOscillator();
+        oscillator.connectNode(context.destination);
+
+        oscillator.type = 'sawtooth';
+        expect(oscillator.type, equals('sawtooth'));
+
+        oscillator.type = 'sine';
+        expect(oscillator.type, equals('sine'));
+   
+        oscillator.type = 'square';
+        expect(oscillator.type, equals('square'));
+   
+        oscillator.type = 'triangle';
+        expect(oscillator.type, equals('triangle'));
+
+        expect(() => oscillator.type = 'somethingUnsupported', throws);
+        expect(oscillator.type, equals('triangle'));
+
+        expect(() => oscillator.type = 7, throws);
+        expect(oscillator.type, equals('triangle'));
+
+        expect(() => oscillator.type = ['heap object not a string'], throws);
+        expect(oscillator.type, equals('triangle'));
+      }
+    });
   });
 }
diff --git a/tests/html/canvasrenderingcontext2d_test.dart b/tests/html/canvasrenderingcontext2d_test.dart
index da9338b..3f17dc9 100644
--- a/tests/html/canvasrenderingcontext2d_test.dart
+++ b/tests/html/canvasrenderingcontext2d_test.dart
@@ -674,4 +674,74 @@
       //var pattern2 = context.createPatternFromImage(new ImageElement(), '');
     });
   });
+
+  group('fillText', () {
+    setUp(setupFunc);
+    tearDown(tearDownFunc);
+
+    final x = 20;
+    final y = 20;
+
+    test('without maxWidth', () {
+      context.font = '40pt Garamond';
+      context.fillStyle = 'blue';
+
+      // Draw a blue box.
+      context.fillText('â–ˆ', x, y);
+
+      var width = context.measureText('â–ˆ').width.toInt();
+
+      checkPixel(readPixel(x, y), [0, 0, 255, 255]);
+      checkPixel(readPixel(x + 10, y), [0, 0, 255, 255]);
+
+      expectPixelUnfilled(x - 10, y);
+      expectPixelFilled(x, y);
+      expectPixelFilled(x + 10, y);
+
+      // The box does not draw after `width` pixels.
+      expectPixelFilled(x + width - 1, y);
+      expectPixelUnfilled(x + width + 1, y);
+    });
+
+    test('with maxWidth null', () {
+      context.font = '40pt Garamond';
+      context.fillStyle = 'blue';
+
+      // Draw a blue box with null maxWidth.
+      context.fillText('â–ˆ', x, y, null);
+
+      var width = context.measureText('â–ˆ').width.toInt();
+
+      checkPixel(readPixel(x, y), [0, 0, 255, 255]);
+      checkPixel(readPixel(x + 10, y), [0, 0, 255, 255]);
+
+      expectPixelUnfilled(x - 10, y);
+      expectPixelFilled(x, y);
+      expectPixelFilled(x + 10, y);
+
+      // The box does not draw after `width` pixels.
+      expectPixelFilled(x + width - 1, y);
+      expectPixelUnfilled(x + width + 1, y);
+    });
+
+    test('with maxWidth defined', () {
+      context.font = '40pt Garamond';
+      context.fillStyle = 'blue';
+
+      final maxWidth = 20;
+
+      // Draw a blue box that's at most 20 pixels wide.
+      context.fillText('â–ˆ', x, y, maxWidth);
+
+      checkPixel(readPixel(x, y), [0, 0, 255, 255]);
+      checkPixel(readPixel(x + 10, y), [0, 0, 255, 255]);
+
+      // The box does not draw after 20 pixels.
+      expectPixelUnfilled(x - 10, y);
+      expectPixelUnfilled(x + maxWidth + 1, y);
+      expectPixelUnfilled(x + maxWidth + 20, y);
+      expectPixelFilled(x, y);
+      expectPixelFilled(x + 10, y);
+    });
+  });
 }
diff --git a/tests/html/custom/created_callback_test.dart b/tests/html/custom/created_callback_test.dart
index 1ca50fd..3faa981 100644
--- a/tests/html/custom/created_callback_test.dart
+++ b/tests/html/custom/created_callback_test.dart
@@ -88,7 +88,7 @@
 <x-b id="w"></x-b>
 """, treeSanitizer: new NullTreeSanitizer());
 
-    Platform.upgradeCustomElements(div);
+    upgradeCustomElements(div);
 
     expect(C.createdInvocations, 2);
     expect(div.query('#w') is B, isTrue);
@@ -147,6 +147,12 @@
     expect(e is ErrorConstructorElement, isFalse);
   });
 
+  test('cannot register created with params', () {
+    expect(() {
+      document.register('x-created-with-params', CreatedWithParametersElement);
+    }, throws);
+  });
+
   test('created cannot be called from nested constructor',
       NestedCreatedConstructorElement.test);
 
@@ -273,6 +279,10 @@
   }
 }
 
+class CreatedWithParametersElement extends HtmlElement {
+  CreatedWithParametersElement.created(ignoredParam) : super.created();
+}
+
 void expectGlobalError(Function test) {
   js.context['testExpectsGlobalError'] = true;
   try {
diff --git a/tests/html/custom/document_register_basic_test.dart b/tests/html/custom/document_register_basic_test.dart
index 7e094e8b..22b45b2 100644
--- a/tests/html/custom/document_register_basic_test.dart
+++ b/tests/html/custom/document_register_basic_test.dart
@@ -91,7 +91,7 @@
     document.body.append(container);
     container.setInnerHtml("<x-foo></x-foo>",
         treeSanitizer: new NullTreeSanitizer());
-    Platform.upgradeCustomElements(container);
+    upgradeCustomElements(container);
     var parsedFoo = container.firstChild;
 
     expect(parsedFoo is Foo, isTrue);
@@ -127,7 +127,7 @@
 
     container.setInnerHtml("<X-BAR></X-BAR><X-Bar></X-Bar>",
         treeSanitizer: new NullTreeSanitizer());
-    Platform.upgradeCustomElements(container);
+    upgradeCustomElements(container);
     expect(container.firstChild is Bar, isTrue);
     expect(container.firstChild.tagName, "X-BAR");
     expect(container.lastChild is Bar, isTrue);
diff --git a/tests/html/custom/document_register_type_extensions_test.dart b/tests/html/custom/document_register_type_extensions_test.dart
index 10b06ef..9ce14e6 100644
--- a/tests/html/custom/document_register_type_extensions_test.dart
+++ b/tests/html/custom/document_register_type_extensions_test.dart
@@ -65,6 +65,15 @@
   }
 }
 
+class CustomDiv extends DivElement {
+  CustomDiv.created() : super.created();
+}
+
+class CustomCustomDiv extends CustomDiv {
+  static const tag = 'custom-custom';
+  CustomCustomDiv.created() : super.created();
+}
+
 main() {
   useHtmlIndividualConfiguration();
 
@@ -89,6 +98,7 @@
     document.register(Baz.tag, Baz);
     document.register(Qux.tag, Qux, extendsTag: 'input');
     document.register(MyCanvas.tag, MyCanvas, extendsTag: 'canvas');
+    document.register(CustomCustomDiv.tag, CustomCustomDiv, extendsTag: 'div');
   }
 
   setUp(loadPolyfills);
@@ -97,7 +107,8 @@
     setUp(registerTypes);
 
     test('cannot register twice', () {
-      expect(() => document.register(FooBad.tag, Foo), throws);
+      expect(() => document.register(FooBad.tag, Foo, extendsTag: 'div'),
+          throws);
     });
 
     test('cannot register for non-matching tag', () {
@@ -105,6 +116,12 @@
         document.register('x-input-div', Bar, extendsTag: 'div');
       }, throws);
     });
+
+    test('cannot register type extension for custom tag', () {
+      expect(() {
+        document.register('x-custom-tag', CustomCustomDiv);
+      }, throws);
+    });
   });
 
   group('construction', () {
@@ -261,7 +278,7 @@
       createElementFromHtml(html) {
         var container = new DivElement()..setInnerHtml(html,
           treeSanitizer: new NullTreeSanitizer());
-        Platform.upgradeCustomElements(container);
+        upgradeCustomElements(container);
         return container.firstChild;
       }
 
diff --git a/tests/html/custom/entered_left_view_test.dart b/tests/html/custom/entered_left_view_test.dart
index f30b794..06795cf 100644
--- a/tests/html/custom/entered_left_view_test.dart
+++ b/tests/html/custom/entered_left_view_test.dart
@@ -150,7 +150,7 @@
 
     test('Created in a document without a view', () {
       docB.body.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
-      Platform.upgradeCustomElements(docB.body);
+      upgradeCustomElements(docB.body);
 
       expect(invocations, ['created'],
           reason: 'only created callback should be invoked when parsing a '
@@ -173,7 +173,7 @@
 
     test('Created in Shadow DOM that is not in a document', () {
       s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
-      Platform.upgradeCustomElements(s);
+      upgradeCustomElements(s);
 
       expect(invocations, ['created'],
           reason: 'the entered callback should not be invoked when entering a '
@@ -189,7 +189,7 @@
 
     test('Enters a document with a view as a constituent of Shadow DOM', () {
       s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
-      Platform.upgradeCustomElements(s);
+      upgradeCustomElements(s);
 
       document.body.append(div);
       customElementsTakeRecords();
@@ -216,7 +216,7 @@
 
     test('Enters a disconnected subtree of DOM', () {
       div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
-      Platform.upgradeCustomElements(div);
+      upgradeCustomElements(div);
 
       expect(invocations, ['created'],
           reason: 'the entered callback should not be invoked when inserted '
@@ -232,7 +232,7 @@
 
     test('Enters a document with a view as a constituent of a subtree', () {
       div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
-      Platform.upgradeCustomElements(div);
+      upgradeCustomElements(div);
       invocations = [];
       document.body.append(div);
       customElementsTakeRecords();
diff --git a/tests/html/custom_elements_test.dart b/tests/html/custom_elements_test.dart
index 9d6b560..07111b5 100644
--- a/tests/html/custom_elements_test.dart
+++ b/tests/html/custom_elements_test.dart
@@ -118,7 +118,7 @@
       });
 
       document.register(tag, CustomType);
-      Platform.upgradeCustomElements(dom);
+      upgradeCustomElements(dom);
 
       var postElement = dom.children[0];
       expect(postElement, isNotNull);
@@ -148,7 +148,7 @@
       var element = new DivElement();
       element.setInnerHtml('<$tag></$tag>',
           treeSanitizer: new NullTreeSanitizer());
-	  Platform.upgradeCustomElements(element);
+	  upgradeCustomElements(element);
       document.body.nodes.add(element);
       var queried = query(tag);
 
@@ -163,7 +163,7 @@
       var element = new DivElement();
       element.setInnerHtml('<$tag id="someid"></$tag>',
           treeSanitizer: new NullTreeSanitizer());
-	  Platform.upgradeCustomElements(element);
+	  upgradeCustomElements(element);
       document.body.nodes.add(element);
       var queried = query('#someid');
 
@@ -181,7 +181,7 @@
       var element = new DivElement();
       element.setInnerHtml('<$tag></$tag>',
           treeSanitizer: new NullTreeSanitizer());
-      Platform.upgradeCustomElements(element);
+      upgradeCustomElements(element);
       document.body.nodes.add(element);
       expect(customCreatedCount, oldCount + 1);
     });
diff --git a/tests/html/html.status b/tests/html/html.status
index d3d7586..e211881 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -55,7 +55,6 @@
 fileapi_test/directoryReader: Fail # TODO(kasperl): Please triage.
 input_element_test/supported_week: Fail # TODO(kasperl): Please triage.
 media_stream_test/supported_media: Fail # TODO(kasperl): Please triage.
-notifications_test/supported: Fail # TODO(kasperl): Please triage.
 rtc_test/supported: Fail # TODO(kasperl): Please triage.
 speechrecognition_test/supported: Fail # TODO(kasperl): Please triage.
 speechrecognition_test/types: Fail # TODO(kasperl): Please triage.
@@ -65,10 +64,10 @@
 [ $compiler == dart2js && $runtime == ie10 ]
 async_test: Pass, Fail # timers test fails on ie10.
 indexeddb_5_test: Fail # Issue 12893
+js_test: Fail # Issue 14246
 
 [ $compiler == dart2js && ( $runtime == ie9 || $runtime == ie10 ) ]
 worker_api_test: Fail # IE does not support URL.createObjectURL in web workers.
-js_test: Fail # Issue 14246
 
 [ $compiler == dart2js && $runtime == safari ]
 url_test: Fail # Issue 10096
@@ -87,9 +86,6 @@
 xhr_test: Pass, Fail # Issue 11884
 xhr_cross_origin_test: Pass, Fail # Issue 11884
 
-[ $runtime == chrome || $runtime == chromeOnAndroid || $runtime == drt || $runtime == safari ]
-audiocontext_test: Skip # Issue 9322
-
 [$runtime == drt || $runtime == dartium || $runtime == chrome || $runtime == chromeOnAndroid]
 webgl_1_test: Pass, Fail # Issue 8219
 
@@ -146,7 +142,6 @@
 media_stream_test/supported_MediaStreamTrackEvent: Fail
 media_stream_test/supported_media: Fail
 mutationobserver_test/supported: Fail
-notifications_test/supported: Fail
 rtc_test/supported: Fail
 shadow_dom_test/supported: Fail
 speechrecognition_test/supported: Fail
@@ -227,7 +222,6 @@
 media_stream_test/supported_MediaStreamTrackEvent: Fail
 media_stream_test/supported_media: Fail
 mutationobserver_test/supported: Fail
-notifications_test/supported: Fail
 range_test/supported: Fail
 rtc_test/supported: Fail
 shadow_dom_test/supported: Fail
@@ -274,7 +268,6 @@
 [ $runtime == safari ]
 worker_test: Skip # Issue 13221
 worker_api_test: Skip # Issue 13221
-notifications_test/supported: Pass, Fail # Issue 13210
 element_types_test/supported_track: Pass, Fail
 input_element_test/supported_month: Fail, Crash
 input_element_test/supported_time: Fail, Crash
@@ -284,6 +277,8 @@
 xhr_test/xhr_requestBlob: Fail # Issue: 9178 Safari doesn't support Blob responses.
 canvasrenderingcontext2d_test/drawImage_video_element: Fail # Safari does not support drawImage w/ video element
 canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Fail # Safari does not support drawImage w/ video element
+audiocontext_test/functional: Fail # Issue 14354
+
 
 # Safari Feature support statuses-
 # All changes should be accompanied by platform support annotation changes.
@@ -299,7 +294,6 @@
 media_stream_test/supported_MediaStreamEvent: Fail
 media_stream_test/supported_MediaStreamTrackEvent: Fail
 media_stream_test/supported_media: Fail
-notifications_test/supported: Fail
 performance_api_test/supported: Fail
 rtc_test/supported: Fail
 shadow_dom_test/supported: Fail
@@ -343,7 +337,6 @@
 indexeddb_1_test/supported: Fail
 indexeddb_1_test/supportsDatabaseNames: Fail
 mutationobserver_test/supported: Fail
-notifications_test/supported: Fail
 performance_api_test/supported: Fail
 speechrecognition_test/supported: Fail
 websql_test/supported: Fail
@@ -379,7 +372,6 @@
 input_element_test/supported_week: Fail
 media_stream_test/supported_MediaStreamEvent: Fail
 media_stream_test/supported_MediaStreamTrackEvent: Fail
-notifications_test/supported: Fail
 shadow_dom_test/supported: Fail
 speechrecognition_test/supported: Fail
 touchevent_test/supported: Fail
@@ -401,7 +393,6 @@
 js_interop_3_test: Skip            # Test cannot run under CSP restrictions (times out).
 js_test: Skip                      # Test cannot run under CSP restrictions (times out).
 postmessage_structured_test: Skip  # Test cannot run under CSP restrictions (times out).
-safe_dom_test: Skip                # Test cannot run under CSP restrictions (times out).
 
 [ $compiler == dart2js && $runtime == drt ]
 wheelevent_test: Fail # http://dartbug.com/12958
@@ -411,6 +402,3 @@
 dromaeo_smoke_test: Fail # Issue 13719: Please triage this failure.
 element_offset_test/offset: Pass, Fail # Issue 13719, 13296
 touchevent_test/supported: Fail # Issue 13719: Please triage this failure.
-
-[ $compiler == dart2js ]
-custom/document_register_type_extensions_test/registration: Fail # Issue 14093
diff --git a/tests/html/js_test.dart b/tests/html/js_test.dart
index e120895..c7d53f3 100644
--- a/tests/html/js_test.dart
+++ b/tests/html/js_test.dart
@@ -180,6 +180,15 @@
   document.body.append(script);
 }
 
+// Some test are either causing other test to fail in IE9, or they are failing
+// for unknown reasons
+// useHtmlConfiguration+ImageData bug: dartbug.com/14355
+skipIE9_test(String description, t()) {
+  if (Platform.supportsTypedData) {
+    test(description, t);
+  }
+}
+
 class Foo {
   final JsObject _proxy;
 
@@ -445,9 +454,10 @@
 
     test('Nodes are proxied', () {
       var node = new JsObject.fromBrowserObject(new DivElement());
-      context['addTestProperty'].apply([node]);
+      context.callMethod('addTestProperty', [node]);
       expect(node is JsObject, isTrue);
-      expect(node.instanceof(context['HTMLDivElement']), isTrue);
+      // TODO(justinfagnani): make this work in IE9
+      // expect(node.instanceof(context['HTMLDivElement']), isTrue);
       expect(node['testProperty'], 'test');
     });
 
@@ -647,9 +657,9 @@
 
     group('JS->Dart', () {
 
-      test('Date', () {
+      test('DateTime', () {
         var date = context.callMethod('getNewDate');
-        expect(date is Date, isTrue);
+        expect(date is DateTime, isTrue);
       });
 
       test('window', () {
@@ -660,7 +670,7 @@
         expect(context['document'] is Document, isTrue);
       });
 
-      test('Blob', () {
+      skipIE9_test('Blob', () {
         var blob = context.callMethod('getNewBlob');
         expect(blob is Blob, isTrue);
         expect(blob.type, equals('text/html'));
@@ -668,7 +678,7 @@
 
       test('unattached DivElement', () {
         var node = context.callMethod('getNewDivElement');
-        expect(node is Div, isTrue);
+        expect(node is DivElement, isTrue);
       });
 
       test('KeyRange', () {
@@ -684,10 +694,12 @@
       });
 
       test('typed data: Int32Array', () {
-        var list = context.callMethod('getNewInt32Array');
-        print(list);
-        expect(list is Int32List, isTrue);
-        expect(list, orderedEquals([1, 2, 3, 4, 5, 6, 7, 8]));
+        if (Platform.supportsTypedData) {
+          var list = context.callMethod('getNewInt32Array');
+          print(list);
+          expect(list is Int32List, isTrue);
+          expect(list, orderedEquals([1, 2, 3, 4, 5, 6, 7, 8]));
+        }
       });
 
     });
@@ -702,7 +714,7 @@
         context.deleteProperty('o');
       });
 
-      test('window', () {
+      skipIE9_test('window', () {
         context['o'] = window;
         var windowType = context['Window'];
         expect(context.callMethod('isPropertyInstanceOf', ['o', windowType]),
@@ -710,7 +722,7 @@
         context.deleteProperty('o');
       });
 
-      test('document', () {
+      skipIE9_test('document', () {
         context['o'] = document;
         var documentType = context['Document'];
         expect(context.callMethod('isPropertyInstanceOf', ['o', documentType]),
@@ -718,7 +730,7 @@
         context.deleteProperty('o');
       });
 
-      test('Blob', () {
+      skipIE9_test('Blob', () {
         var fileParts = ['<a id="a"><b id="b">hey!</b></a>'];
         context['o'] = new Blob(fileParts, 'text/html');
         var blobType = context['Blob'];
@@ -745,7 +757,10 @@
         }
       });
 
-      test('ImageData', () {
+      // this test fails in IE9 for very weird, but unknown, reasons
+      // the expression context['ImageData'] fails if useHtmlConfiguration()
+      // is called, or if the other tests in this file are enabled
+      skipIE9_test('ImageData', () {
         var canvas = new CanvasElement();
         var ctx = canvas.getContext('2d');
         context['o'] = ctx.createImageData(1, 1);
@@ -756,13 +771,15 @@
       });
 
       test('typed data: Int32List', () {
-        context['o'] = new Int32List.fromList([1, 2, 3, 4]);
-        var listType = context['Int32Array'];
-        // TODO(jacobr): make this test pass. Currently some type information
-        // is lost when typed arrays are passed between JS and Dart.
-        // expect(context.callMethod('isPropertyInstanceOf', ['o', listType]),
-        //    isTrue);
-        context.deleteProperty('o');
+        if (Platform.supportsTypedData) {
+          context['o'] = new Int32List.fromList([1, 2, 3, 4]);
+          var listType = context['Int32Array'];
+          // TODO(jacobr): make this test pass. Currently some type information
+          // is lost when typed arrays are passed between JS and Dart.
+          // expect(context.callMethod('isPropertyInstanceOf', ['o', listType]),
+          //    isTrue);
+          context.deleteProperty('o');
+        }
       });
 
     });
diff --git a/tests/html/node_validator_test.dart b/tests/html/node_validator_test.dart
index ae25743..3189ec3 100644
--- a/tests/html/node_validator_test.dart
+++ b/tests/html/node_validator_test.dart
@@ -112,6 +112,8 @@
         '<span>![CDATA[ some text ]]></span>');
 
     test('sanitizes template contents', () {
+      if (!TemplateElement.supported) return;
+
       var html = '<template>'
           '<div></div>'
           '<script></script>'
diff --git a/tests/html/notifications_test.dart b/tests/html/notifications_test.dart
deleted file mode 100644
index 8e3ae43..0000000
--- a/tests/html/notifications_test.dart
+++ /dev/null
@@ -1,42 +0,0 @@
-library NotificationsTest;
-import '../../pkg/unittest/lib/unittest.dart';
-import '../../pkg/unittest/lib/html_individual_config.dart';
-import 'dart:html';
-
-main() {
-  useHtmlIndividualConfiguration();
-
-  group('supported', () {
-    test('supported', () {
-      expect(NotificationCenter.supported, true);
-    });
-  });
-
-  group('unsupported_throws', () {
-    test('createNotification', () {
-      var expectation = NotificationCenter.supported ? returnsNormally : throws;
-      expect(() { window.notifications.createNotification; }, expectation);
-    });
-  });
-
-  group('webkitNotifications', () {
-    if (NotificationCenter.supported) {
-      test('DomException', () {
-        try {
-          window.notifications.createNotification('', '', '');
-        } on DomException catch (e) {
-          expect(e.name, DomException.SECURITY);
-        }
-      });
-
-      /*
-      // Sporadically flaky on Mac Chrome. Uncomment when Issue 8482 is fixed.
-      test('construct notification', () {
-        var note = new Notification('this is a notification');
-        var note2 = new Notification('another notificiation', titleDir: 'foo');
-      });
-      */
-    }
-  });
-}
-
diff --git a/tests/html/safe_dom_test.dart b/tests/html/safe_dom_test.dart
deleted file mode 100644
index ee2ddaa..0000000
--- a/tests/html/safe_dom_test.dart
+++ /dev/null
@@ -1,98 +0,0 @@
-library safe_dom_test;
-
-import 'dart:async';
-import 'dart:html';
-import '../../pkg/unittest/lib/unittest.dart';
-import '../../pkg/unittest/lib/html_config.dart';
-
-main() {
-  useHtmlConfiguration();
-
-  // Checks to see if any illegal properties were set via script.
-  var checkerScript = '''
-  window.addEventListener('message', function(e) {
-    if (e.data == 'check_unsafe') {
-      if (window.unsafe_value) {
-        window.postMessage('unsafe_check_failed', '*');
-      } else {
-        window.postMessage('unsafe_check_passed', '*');
-      }
-      //window.alert('checking!');
-    }
-  }, false);
-  ''';
-
-  var script = new ScriptElement();
-  script.text = checkerScript;
-  document.body.append(script);
-
-  var unsafeString =
-      '<img src="_.png" onerror="javascript:window.unsafe_value=1;" crap="1"/>';
-
-  test('Safe DOM', () {
-    var fragment = createContextualFragment(unsafeString);
-
-    expect(isSafe(), completion(true),
-        reason: 'Expected no unsafe code executed.');
-  });
-
-  // Make sure that scripts did get executed, so we know our detection works.
-  test('Unsafe Execution', () {
-    var div = new DivElement();
-    div.unsafeInnerHtml = unsafeString;
-    // Crashing DRT ??
-    // var fragment = createContextualFragment(unsafeString);
-    // div.append(fragment);
-    // document.body.append(div)
-
-    expect(isSafe(), completion(false),
-        reason: 'Expected unsafe code was executed.');
-  });
-
-  test('Validity', () {
-    var fragment = createContextualFragment('<span>content</span>');
-    var div = new DivElement();
-    div.append(fragment);
-
-    expect(div.nodes.length, 1);
-    expect(div.nodes[0] is SpanElement, isTrue);
-  });
-}
-
-DocumentFragment createContextualFragment(String html, [String contextTag]) {
-  var doc = document.implementation.createHtmlDocument('');
-
-  var contextElement;
-  if (contextTag != null) {
-    contextElement = doc.createElement(contextTag);
-  } else {
-    contextElement = doc.body;
-  }
-
-  if (Range.supportsCreateContextualFragment) {
-    var range = doc.createRange();
-    range.selectNode(contextElement);
-    return range.createContextualFragment(html);
-  } else {
-    contextElement.unsafeInnerHtml = html;
-    var fragment = new DocumentFragment();;
-    while (contextElement.firstChild != null) {
-      fragment.append(contextElement.firstChild);
-    }
-    return fragment;
-  }
-}
-
-// Delay to wait for the image load to fail.
-const Duration imageLoadDelay = const Duration(milliseconds: 500);
-
-Future<bool> isSafe() {
-  return new Future.delayed(imageLoadDelay).then((_) {
-    window.postMessage('check_unsafe', '*');
-  }).then((_) {
-    return window.onMessage.where(
-        (e) => e.data.startsWith('unsafe_check')).first;
-  }).then((e) {
-    return e.data == 'unsafe_check_passed';
-  });
-}
diff --git a/tests/html/utils.dart b/tests/html/utils.dart
index 04c8235..b1d7f68 100644
--- a/tests/html/utils.dart
+++ b/tests/html/utils.dart
@@ -2,6 +2,7 @@
 
 import 'dart:async';
 import 'dart:html';
+import 'dart:js' as js;
 import 'dart:typed_data';
 import 'package:unittest/unittest.dart';
 
@@ -173,3 +174,16 @@
 Future loadPolyfills() {
   return loadCustomElementPolyfill();
 }
+
+/**
+ * Upgrade all custom elements in the subtree which have not been upgraded.
+ *
+ * This is needed to cover timing scenarios which the custom element polyfill
+ * does not cover.
+ */
+void upgradeCustomElements(Node node) {
+  if (js.context.hasProperty('CustomElements') &&
+      js.context['CustomElements'].hasProperty('upgradeAll')) {
+    js.context['CustomElements'].callMethod('upgradeAll', [node]);
+  }
+}
diff --git a/tests/html/webgl_1_test.dart b/tests/html/webgl_1_test.dart
index 80b70ea..f09db72 100644
--- a/tests/html/webgl_1_test.dart
+++ b/tests/html/webgl_1_test.dart
@@ -59,7 +59,7 @@
         var canvas = new CanvasElement();
         var context = canvas.getContext3d();
         var pixels = new Uint8List.fromList([0,0,3,255,0,0,0,0,0,0]);
-        context.texImage2D(1, 1, 1, 1, 10, 10, 1, 1, pixels);
+        context.texImage2DUntyped(1, 1, 1, 1, 10, 10, 1, 1, pixels);
 
         canvas = new CanvasElement();
         document.body.children.add(canvas);
@@ -76,7 +76,7 @@
         var canvas = new CanvasElement();
         var context = canvas.getContext3d();
         var pixels = new Uint8List.fromList([0,0,3,255,0,0,0,0,0,0]);
-        context.texSubImage2D(1, 1, 1, 1, 10, 10, 1, 1, pixels);
+        context.texSubImage2DUntyped(1, 1, 1, 1, 10, 10, 1, 1, pixels);
 
         canvas = new CanvasElement();
         document.body.children.add(canvas);
diff --git a/tests/language/const_types_test.dart b/tests/language/const_types_test.dart
new file mode 100644
index 0000000..9a4a46a
--- /dev/null
+++ b/tests/language/const_types_test.dart
@@ -0,0 +1,84 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test handling of malformed types in constant expressions.
+
+use(x) {}
+
+class Class<T> implements Superclass {
+  const Class();
+  const Class.named();
+
+  void test() {
+    use(const []);
+    use(const <Class>[]);
+    use(const <Class<int>>[]);
+    use(const <Class<Unresolved>>[]); /// 01: static type warning
+    use(const <Unresolved>[]); /// 02: static type warning
+
+    use(const {});
+    use(const <Class>{}); /// 03: static type warning
+    use(const <String, Class>{});
+    use(const <String, Class<int>>{});
+    use(const <String, Class<Unresolved>>{}); /// 04: static type warning
+    use(const <String, Unresolved>{}); /// 05: static type warning
+
+    use(const Class());
+    use(const Class<int>());
+    use(const Class<Unresolved>()); /// 06: static type warning
+    use(const Class<T>()); /// 07: compile-time error
+    use(const Class<Class<T>>()); /// 08: compile-time error
+
+    use(const Unresolved()); /// 09: compile-time error
+    use(const Unresolved<int>()); /// 10: compile-time error
+    use(const prefix.Unresolved()); /// 11: compile-time error
+    use(const prefix.Unresolved<int>()); /// 12: compile-time error
+
+    use(const Class.named());
+    use(const Class<int>.named());
+    use(const Class<Unresolved>.named()); /// 13: static type warning
+    use(const Class<T>.named()); /// 14: compile-time error
+    use(const Class<Class<T>>.named()); /// 15: compile-time error
+
+    use(const Class.nonamed()); /// 16: compile-time error
+    use(const Class<int>.nonamed()); /// 17: compile-time error
+    use(const Class<Unresolved>.nonamed()); /// 18: compile-time error
+    use(const Class<T>.nonamed()); /// 19: compile-time error
+    use(const Class<Class<T>>.nonamed()); /// 20: compile-time error
+
+    use(const Unresolved.named()); /// 21: compile-time error
+    use(const Unresolved<int>.named()); /// 22: compile-time error
+  }
+}
+
+class Superclass<T> {
+  const factory Superclass() = Unresolved; /// 23: compile-time error
+  const factory Superclass() = Unresolved<int>; /// 24: compile-time error
+  const factory Superclass() = Unresolved.named; /// 25: compile-time error
+  const factory Superclass() = Unresolved<int>.named; /// 26: compile-time error
+
+  const factory Superclass() = prefix.Unresolved; /// 27: compile-time error
+  const factory Superclass() = prefix.Unresolved<int>; /// 28: compile-time error
+  const factory Superclass() = prefix.Unresolved.named; /// 29: compile-time error
+  const factory Superclass() = prefix.Unresolved<int>.named; /// 30: compile-time error
+
+  const factory Superclass() = Class; /// 31: ok
+  const factory Superclass() = Class<int>; /// 32: ok
+  const factory Superclass() = Class<T>; /// 33: ok
+  const factory Superclass() = Class<Class<T>>; /// 34: ok
+  const factory Superclass() = Class<Unresolved>; /// 35: static type warning
+
+  const factory Superclass() = Class.named; /// 36: ok
+  const factory Superclass() = Class<int>.named; /// 37: ok
+  const factory Superclass() = Class<T>.named; /// 38: ok
+  const factory Superclass() = Class<Class<T>>.named; /// 39: ok
+  const factory Superclass() = Class<Unresolved>.named; /// 40: static type warning
+
+  const factory Superclass() = T; /// 41: compile-time error
+}
+
+void main() {
+  new Class().test();
+  new Superclass();
+}
diff --git a/tests/language/constant_string_interpolation_test.dart b/tests/language/constant_string_interpolation_test.dart
new file mode 100644
index 0000000..0a8a81c
--- /dev/null
+++ b/tests/language/constant_string_interpolation_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--optimization-counter-threshold=10 --no-use-osr
+
+import "package:expect/expect.dart";
+
+main() {
+  final a = new A();
+  for (int i = 0; i < 20; i++) {
+    final r = interpolIt(a);
+    Expect.stringEquals("hello home", r);
+  }
+  final b = new B();
+  // Deoptimize "interpolIt".
+  final r = interpolIt(b);
+  Expect.stringEquals("hello world", r);
+}
+
+
+String interpolIt(v) {
+  // String interpolation will be constant folded.
+  return "hello ${v.foo()}";
+}
+
+class A {
+  foo() => "home";
+}
+
+class B {
+  foo() => "world";
+}
diff --git a/tests/language/factory_redirection_test.dart b/tests/language/factory_redirection_test.dart
index 2fcc27c8..86291d0 100644
--- a/tests/language/factory_redirection_test.dart
+++ b/tests/language/factory_redirection_test.dart
@@ -36,6 +36,8 @@
   factory B.test04() = A.test04;  /// 04: continued
 
   factory B.test05(int incompatible) = A<T>.factory;  /// 05: runtime error
+
+  factory B.test05(int incompatible) = A<T>.factory;  /// 06: runtime error
 }
 
 class C<K, V> extends B<V> {
@@ -49,7 +51,7 @@
 
   factory C.test04() = B.test04;  /// 04: continued
 
-  factory C.test06(int incompatible) = B<K>.test05;  /// 06: runtime error
+  factory C.test06(int incompatible) = B<K>.test05;  /// 06: continued
 
   const factory C.test07(V x) = B<V>.A;  /// 07: compile-time error
 }
@@ -60,8 +62,8 @@
   new A<List>.test03();  /// 03: continued
   new C.test04();  /// 04: continued
   new B.test05(0);  /// 05: continued
-  new C.test06<int, int>(0);  /// 06: continued
-  new C.test07<int, int>(0);  /// 07: continued
+  new C<int, int>.test06(0);  /// 06: continued
+  new C<int, int>.test07(0);  /// 07: continued
   Expect.isTrue(new A<List>() is A<List>);
   Expect.isTrue(new A<bool>.constant(true).x);
   Expect.isTrue(new A<Set>.factory() is B<Set>);
diff --git a/tests/language/function_type2_test.dart b/tests/language/function_type2_test.dart
new file mode 100644
index 0000000..7bd41a8
--- /dev/null
+++ b/tests/language/function_type2_test.dart
@@ -0,0 +1,36 @@
+// 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";
+
+bool get inCheckedMode {
+  try {
+    String a = 42;
+  } catch (e) {
+    return true;
+  }
+  return false;
+}
+
+class A<T> {
+  A(f) {
+    f(42);
+  }
+}
+
+class B<T> extends A<T> {
+  B() : super((T param) => 42);
+}
+
+main() {
+  var t = new B<int>();
+  bool caughtException = false;
+
+  try {
+    new B<String>();
+  } on TypeError catch (e) {
+    caughtException = true;
+  }
+  Expect.isTrue(!inCheckedMode || caughtException);
+}
diff --git a/tests/language/issue14014_2_test.dart b/tests/language/issue14014_2_test.dart
new file mode 100644
index 0000000..ee312c7
--- /dev/null
+++ b/tests/language/issue14014_2_test.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.
+
+// Test that a type variable used in a parameter of a constructor that
+// has a closure in its initializer list does not lead to a crash in
+// dart2js.
+
+class A<T> {
+  A(f);
+}
+
+class B<T> extends A<T> {
+  B({void f(T foo)}) : super((T a) { f = (a) => 42;});
+}
+
+main() {
+  var t = new B<int>();
+}
diff --git a/tests/language/issue14014_3_test.dart b/tests/language/issue14014_3_test.dart
new file mode 100644
index 0000000..58957fb
--- /dev/null
+++ b/tests/language/issue14014_3_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that an is check on a function type involving type parameters
+// does not crash dart2js, when the is test is in the initializer list
+// of a constructor.
+
+class A<T> {
+  var f;
+  A(this.f);
+}
+
+typedef foo<T>(T a);
+
+class B<T> extends A<T> {
+  B({void f(T foo)}) : super(() => f is foo<T>);
+}
+
+main() {
+  var t = new B<int>(f: (int a) => 42);
+  if (!t.f()) {
+    throw 'Test failed';
+  }
+}
diff --git a/tests/language/issue14014_test.dart b/tests/language/issue14014_test.dart
new file mode 100644
index 0000000..c887a33
--- /dev/null
+++ b/tests/language/issue14014_test.dart
@@ -0,0 +1,15 @@
+// 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.
+
+class A<T> {
+  A(f);
+}
+
+class B<T> extends A<T> {
+  B() : super((T param) => 42);
+}
+
+main() {
+  var t = new B<int>();
+}
diff --git a/tests/language/issue14242_test.dart b/tests/language/issue14242_test.dart
new file mode 100644
index 0000000..1bd3fe6
--- /dev/null
+++ b/tests/language/issue14242_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+// Regression test for dart2js that used to crash on type literals
+// used in a cascade send.
+
+class A {
+  var bar;
+  var foo = {};
+}
+
+main() {
+  var a = new A();
+  a..foo[Object] = 54
+   ..bar = 42;
+  if (a.foo.keys.first is! Type) {
+    throw 'Test failed';
+  }
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index e720d3e..24845db 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -12,7 +12,6 @@
 mixin_super_constructor_named_test: Fail # Issue 12631
 mixin_super_constructor_positionals_test: Fail # Issue 12631
 built_in_identifier_prefix_test: Fail # Issue 6970
-library_juxtaposition_test: Fail # Issue 6877
 throwing_lazy_variable_test: Fail # Issue 5802
 f_bounded_equality_test: RuntimeError # Issue 14000
 
@@ -23,10 +22,8 @@
 closure_in_initializer_test: Fail # Issue 6422
 
 # Regular bugs which should be fixed.
-super_first_constructor_test: Fail # Issue 1372.
 lazy_static3_test: Fail # Issue 12593
 duplicate_export_negative_test: Fail # Issue 6134
-on_catch_malformed_type_test: Fail # Issue 8601
 mixin_forwarding_constructor2_test: Fail # Issue 13641
 implicit_setter_test: Fail # Issue 13917
 
@@ -44,11 +41,6 @@
 compile_time_constant_checked3_test/05: MissingCompileTimeError # Issue 13685
 compile_time_constant_checked3_test/06: MissingCompileTimeError # Issue 13685
 
-[ $compiler == none && $checked ]
-malbounded_type_cast_test: Fail # Issue 14123
-malbounded_type_test_test/01: Fail # Issue 14131
-malbounded_instantiation_test/01: Fail # Issue 14132
-
 [ $compiler == none && $unchecked ]
 # Only checked mode reports an error on type assignment
 # problems in compile time constants.
@@ -102,3 +94,4 @@
 
 [ $compiler == none && ( $runtime == dartium || $runtime == drt ) ]
 typed_message_test: Fail # Issue 13921
+
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index f26cea0..53c27cc 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -29,18 +29,16 @@
 
 built_in_identifier_test/none: Fail # Issue 13023
 
-# test issue 13807, missing support for type promotion
-type_promotion_closure_test/none: Fail # Issue 13807
-type_promotion_functions_test/none: Fail # Issue 13807
-type_promotion_local_test/none: Fail # Issue 13807
-type_promotion_logical_and_test/none: Fail # Issue 13807
-type_promotion_multiple_test/none: Fail # Issue 13807
-type_promotion_parameter_test/none: Fail # Issue 13807
-
-# Missing checks for cyclic typedefs (through bounds)
-cyclic_typedef_test/10: Fail # Issue 13906
-cyclic_typedef_test/11: Fail # Issue 13906
-
+# Invalid constant redirecting factories should cause compile-time error.
+const_types_test/23: Fail # Issue 14306
+const_types_test/24: Fail # Issue 14306
+const_types_test/25: Fail # Issue 14306
+const_types_test/26: Fail # Issue 14306
+const_types_test/27: Fail # Issue 14306
+const_types_test/28: Fail # Issue 14306
+const_types_test/29: Fail # Issue 14306
+const_types_test/30: Fail # Issue 14306
+const_types_test/41: Fail # Issue 14306
 
 # Please add new failing tests before this line.
 # Section below is for invalid tests.
@@ -137,8 +135,6 @@
 # test issue 12156, fails only at runtime
 static_call_wrong_argument_count_negative_test: fail
 
-throw7_test/01: Fail # Issue 12159
-
 # test issue 12160, not annotated warnings for type variables from static member
 type_parameter_test/none: fail
 # test issue 12161, type variable in static, malformed type, static warning
@@ -158,8 +154,6 @@
 issue11724_test: fail # Issue 12381
 call_nonexistent_static_test/08: fail # Issue 12381
 
-scope_variable_test/01: fail # Issue 12397
-
 # test issue 12539, rules for finals were loosened, contradiction in spec was fixed
 const_syntax_test/09: fail # Issue 12539
 
@@ -191,6 +185,23 @@
 # test issue 14228
 black_listed_test/none: fail # test issue 14228, warnings are required but not expected
 
+# test issue 14289
+bailout3_test: fail # test issue 14289
+prefix9_test: fail # test issue 14289
+
+# test issue 14358, E does not implement inherited A.+
+type_promotion_closure_test/none: Fail
+
+# test issue 14362, wrong assumption that dynamic << A
+type_promotion_functions_test/none: Fail
+
+# test issue 14363, "if ((a is B))" has the same effect as "if (a is B)", so no static warning expected
+type_promotion_parameter_test/53: Fail
+
+# test issue 14364, "E<A> << D"
+type_promotion_more_specific_test/08: fail
+
+
 #
 # Please don't add new items here.
 # This is section for invalid tests.
diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status
index 1076d46..df55670 100644
--- a/tests/language/language_analyzer2.status
+++ b/tests/language/language_analyzer2.status
@@ -41,6 +41,16 @@
 cyclic_typedef_test/10: Fail # Issue 13906
 cyclic_typedef_test/11: Fail # Issue 13906
 
+# Invalid constant redirecting factories should cause compile-time error.
+const_types_test/23: Fail # Issue 14306
+const_types_test/24: Fail # Issue 14306
+const_types_test/25: Fail # Issue 14306
+const_types_test/26: Fail # Issue 14306
+const_types_test/27: Fail # Issue 14306
+const_types_test/28: Fail # Issue 14306
+const_types_test/29: Fail # Issue 14306
+const_types_test/30: Fail # Issue 14306
+const_types_test/41: Fail # Issue 14306
 
 # Please add new failing tests before this line.
 # Section below is for invalid tests.
@@ -137,8 +147,6 @@
 # test issue 12156, fails only at runtime
 static_call_wrong_argument_count_negative_test: fail
 
-throw7_test/01: Fail # Issue 12159
-
 # test issue 12160, not annotated warnings for type variables from static member
 type_parameter_test/none: fail
 # test issue 12161, type variable in static, malformed type, static warning
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 8e5d476..2b551b0 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -46,13 +46,12 @@
 closure_type_test: Fail # Issue 12745
 function_subtype_setter0_test: Fail # Issue 11273
 redirecting_factory_malbounded_test/01: Fail # Issue 12825
-malbounded_instantiation_test/01: Fail # Issue 14121
 malbounded_instantiation_test/02: Fail # Issue 14121
 malbounded_instantiation_test/03: Fail # Issue 14121
 malbounded_type_cast_test: Fail # Issue 14121
 malbounded_type_test_test/01: Fail # Issue 14121
-malbounded_type_test_test/02: Fail # Issue 14121
 malbounded_type_test_test/03: Fail # Issue 14121
+malbounded_type_test_test/04: Fail # Issue 14121
 
 [ $compiler == dart2js && $unchecked ]
 type_checks_in_factory_method_test: RuntimeError # Issue 12746
@@ -104,7 +103,6 @@
 mint_arithmetic_test: RuntimeError # Issue 1533
 left_shift_test: RuntimeError # Issue 1533
 factory_redirection_test/01: CompileTimeError # Issue 12752
-factory_redirection_test/07: MissingCompileTimeError # Issue 12752
 bad_override_test/01: CompileTimeError # Issue 11496
 bad_override_test/02: CompileTimeError # Issue 11496
 bad_override_test/06: CompileTimeError # Issue 11496
@@ -149,7 +147,6 @@
 map_literal1_test/01: MissingCompileTimeError # Issue 12993
 scope_variable_test/01: MissingCompileTimeError # Issue 13016
 static_final_field2_test/02: MissingCompileTimeError # Issue 13017
-throw7_test/01: MissingCompileTimeError # Issue 13019
 
 numbers_test: RuntimeError, OK # Issue 1533
 canonical_const2_test: RuntimeError, OK # Issue 1533
@@ -202,8 +199,6 @@
 factory3_test: Fail # Issue 13077
 type_checks_in_factory_method_test: Fail # Issue 12747
 
-on_catch_malformed_type_test: Fail # Issue 8601
-
 # Mixins fail on the VM.
 mixin_forwarding_constructor2_test: Fail # Issue 13641
 
@@ -252,12 +247,10 @@
 method_override4_test: Fail # Issue 12810
 method_override5_test: Fail # Issue 12810
 static_final_field2_test/02: Fail # Issue 13017
-throw7_test/01: Fail # Issue 13019
 scope_variable_test/01: Fail # Issue 13016
 factory_redirection_test/01: Fail # Issue 12753
 factory_redirection_test/02: Crash # Issue 12753
 factory_redirection_test/03: Crash # Issue 12753
-factory_redirection_test/07: Fail # Issue 12753
 factory_redirection_test/09: Fail # Issue 12753
 
 malbounded_type_literal_test: Fail # Issue 13960
@@ -266,7 +259,6 @@
 constructor5_test: Fail
 constructor6_test: Fail
 closure_in_initializer_test: Fail
-super_first_constructor_test: Fail
 throwing_lazy_variable_test: Fail # Issue 5802
 f_bounded_equality_test: RuntimeError # Issue 14000
 
diff --git a/tests/language/malbounded_instantiation_test.dart b/tests/language/malbounded_instantiation_test.dart
index d7f5829..5791198 100644
--- a/tests/language/malbounded_instantiation_test.dart
+++ b/tests/language/malbounded_instantiation_test.dart
@@ -9,7 +9,7 @@
 class Malbounded2 extends Super<String> {}  /// 02: static type warning
 
 main() {
-  new Malbounded1();  /// 01: static type warning, dynamic type error
+  new Malbounded1();  /// 01: static type warning
   new Malbounded2();  /// 02: static type warning, dynamic type error
   new Super<String>();  /// 03: static type warning, dynamic type error
 }
diff --git a/tests/language/malbounded_type_cast_test.dart b/tests/language/malbounded_type_cast_test.dart
index 26a8b11..e072110 100644
--- a/tests/language/malbounded_type_cast_test.dart
+++ b/tests/language/malbounded_type_cast_test.dart
@@ -23,8 +23,10 @@
   	expectedError = (e) => e is CastError;
   }
 
+  var m = new Malbounded1();
+  Expect.throws(() => m as Super<int>, expectedError);
   var s = new Super<int>();
-  Expect.throws(() => s as Malbounded1, expectedError);
+  Expect.throws(() => s as Malbounded1, (e) => e is CastError);
   Expect.throws(() => s as Malbounded2, expectedError);
   Expect.throws(() => s as Super<String>, expectedError); /// static type warning
 }
diff --git a/tests/language/malbounded_type_test_test.dart b/tests/language/malbounded_type_test_test.dart
index acae938..1c39630 100644
--- a/tests/language/malbounded_type_test_test.dart
+++ b/tests/language/malbounded_type_test_test.dart
@@ -5,12 +5,15 @@
 import 'package:expect/expect.dart';
 
 class Super<T extends num> {}
-class Malbounded1 implements Super<String> {}  /// 01: static type warning
-class Malbounded2 extends Super<String> {}  /// 02: static type warning
+class Malbounded1 implements Super<String> {}  /// 01: static type warning, dynamic type error
+class Malbounded1 implements Super<String> {}  /// 02: static type warning
+class Malbounded2 extends Super<String> {}  /// 03: static type warning, dynamic type error
 
 main() {
+  var m = new Malbounded1();  /// 01: continued
+  Expect.isFalse(m is Super<int>);  /// 01: continued
   var s = new Super<int>();
-  Expect.isFalse(s is Malbounded1);  /// 01: static type warning, dynamic type error
-  Expect.isFalse(s is Malbounded2);  /// 02: static type warning, dynamic type error
-  Expect.isFalse(s is Super<String>);  /// 03: static type warning, dynamic type error
+  Expect.isFalse(s is Malbounded1);  /// 02: continued
+  Expect.isFalse(s is Malbounded2);  /// 03: continued
+  Expect.isFalse(s is Super<String>);  /// 04: static type warning, dynamic type error
 }
diff --git a/tests/language/named_constructor_lib.dart b/tests/language/named_constructor_lib.dart
new file mode 100644
index 0000000..210d54c
--- /dev/null
+++ b/tests/language/named_constructor_lib.dart
@@ -0,0 +1,11 @@
+// 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 named_constructor_lib;
+
+class Class<T> {
+  final int value;
+  Class() : value = 2;
+  Class.named() : value = 3;
+}
diff --git a/tests/language/named_constructor_test.dart b/tests/language/named_constructor_test.dart
new file mode 100644
index 0000000..6db3929
--- /dev/null
+++ b/tests/language/named_constructor_test.dart
@@ -0,0 +1,49 @@
+// 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 named_constructor_test;
+
+import 'package:expect/expect.dart';
+import 'named_constructor_lib.dart' as prefix;
+
+class Class<T> {
+  final int value;
+  Class() : value = 0;
+  Class.named() : value = 1;
+}
+
+void main() {
+  Expect.equals(0, new Class().value);
+  Expect.equals(0, new Class<int>().value);
+
+  Expect.equals(1, new Class.named().value);
+  Expect.equals(1, new Class<int>.named().value);
+  // 'Class.named' is not a type:
+  Expect.equals(1, new Class.named<int>().value); /// 01: runtime error
+  // 'Class<int>.named<int>' doesn't fit the grammar syntax T.id:
+  Expect.equals(1, new Class<int>.named<int>().value); /// 02: compile-time error
+
+  Expect.equals(2, new prefix.Class().value);
+  // 'prefix' is not a type:
+  Expect.equals(2, new prefix<int>.Class().value); /// 03: runtime error
+  Expect.equals(2, new prefix.Class<int>().value);
+  // 'prefix<int>.Class<int>' doesn't fit the grammar syntax T.id:
+  Expect.equals(2, new prefix<int>.Class<int>().value); /// 04: compile-time error
+
+  Expect.equals(3, new prefix.Class.named().value);
+  // 'prefix<int>.Class.named' doesn't fit the grammar syntax T.id:
+  Expect.equals(3, new prefix<int>.Class.named().value); /// 05: compile-time error
+  // 'prefix.Class<int>.named' doesn't fit the grammar syntax T.id:
+  Expect.equals(3, new prefix.Class<int>.named().value);
+  // 'prefix.Class.named<int>' doesn't fit the grammar syntax T.id:
+  Expect.equals(3, new prefix.Class.named<int>().value); /// 06: compile-time error
+  // 'prefix<int>.Class<int>' doesn't fit the grammar syntax T.id:
+  Expect.equals(3, new prefix<int>.Class<int>.named().value); /// 07: compile-time error
+  // 'prefix<int>.Class.named<int>' doesn't fit the grammar syntax T.id:
+  Expect.equals(3, new prefix<int>.Class.named<int>().value); /// 08: compile-time error
+  // 'prefix.Class<int>.named<int>' doesn't fit the grammar syntax T.id:
+  Expect.equals(3, new prefix.Class<int>.named<int>().value); /// 09: compile-time error
+  // 'prefix<int>.Class<int>.named<int>' doesn't fit the grammar syntax T.id:
+  Expect.equals(3, new prefix<int>.Class<int>.named<int>().value); /// 10: compile-time error
+}
\ No newline at end of file
diff --git a/tests/language/throw7_test.dart b/tests/language/throw7_test.dart
deleted file mode 100644
index daa5655..0000000
--- a/tests/language/throw7_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-// Dart test program for testing throw statement
-
-main() {
-  int i = 0;
-  try {
-    i = 1;
-  } catch (exception) {
-    i = 2;
-  }
-  // Since there is a generic 'catch all' statement preceding this
-  // we expect to get a dead code error/warning over here.
-  on Exception catch (exception) { i = 3; }  /// 01: compile-time error
-}
diff --git a/tests/language/vm/load_to_load_forwarding_vm_test.dart b/tests/language/vm/load_to_load_forwarding_vm_test.dart
index fa1d2e4..7db38cf 100644
--- a/tests/language/vm/load_to_load_forwarding_vm_test.dart
+++ b/tests/language/vm/load_to_load_forwarding_vm_test.dart
@@ -195,6 +195,24 @@
   Expect.equals(2, u.y);
 }
 
+
+testPhiMultipleRepresentations(f, arr) {
+  var w;
+  if (f) {
+    w = arr[0] + arr[1];
+  } else {
+    w = arr[0] - arr[1];
+  }
+  var v;
+  if (f) {
+    v = arr[0];
+  } else {
+    v = arr[0];
+  }
+  return v + w;
+}
+
+
 main() {
   final fixed = new List(10);
   final growable = [];
@@ -236,6 +254,11 @@
     testPhiConvertions(false, u32List);
   }
 
+  for (var i = 0; i < 20; i++) {
+    Expect.equals(0.0, testPhiMultipleRepresentations(true, f64List));
+    Expect.equals(0, testPhiMultipleRepresentations(false, const [1,2]));
+  }
+
   final escape = new List(1);
   for (var i = 0; i < 20; i++) {
     fakeAliasing(escape);
diff --git a/tests/lib/async/event_helper.dart b/tests/lib/async/event_helper.dart
index 451ad39..08a6b8f 100644
--- a/tests/lib/async/event_helper.dart
+++ b/tests/lib/async/event_helper.dart
@@ -73,7 +73,7 @@
 
   /** Capture events from a stream into a new [Events] object. */
   factory Events.capture(Stream stream,
-                         { bool cancelOnError: false }) = CaptureEvents;
+                         { bool cancelOnError }) = CaptureEvents;
 
   // EventSink interface.
   void add(var value) {
diff --git a/tests/lib/async/stream_controller_async_test.dart b/tests/lib/async/stream_controller_async_test.dart
index 22226dd..d66a6f1 100644
--- a/tests/lib/async/stream_controller_async_test.dart
+++ b/tests/lib/async/stream_controller_async_test.dart
@@ -279,8 +279,8 @@
           })
         ..expectData(43)
         ..expectData(44)
-        ..expectDone()
-        ..expectCancel(test.terminate);
+        ..expectCancel()
+        ..expectDone(test.terminate);
     test.listen();
     test.add(42);
     test.add(43);
@@ -303,8 +303,8 @@
           })
         ..expectData(43)
         ..expectData(44)
-        ..expectDone()
-        ..expectCancel(test.terminate);
+        ..expectCancel()
+        ..expectDone(test.terminate);
     test..listen()
         ..add(42)
         ..add(43)
@@ -325,8 +325,8 @@
           })
         ..expectData(43)
         ..expectData(44)
-        ..expectDone()
-        ..expectCancel(test.terminate);
+        ..expectCancel()
+        ..expectDone(test.terminate);
     test..listen()
         ..add(42)
         ..add(43)
@@ -351,8 +351,8 @@
           })
         ..expectData(43)
         ..expectData(44)
-        ..expectDone()
-        ..expectCancel(test.terminate);
+        ..expectCancel()
+        ..expectDone(test.terminate);
     test..listen()
         ..add(42);
   });
@@ -417,8 +417,8 @@
     StreamProtocolTest test = new StreamProtocolTest.broadcast();
     test..expectListen()
         ..expectData(42)
-        ..expectDone()
-        ..expectCancel(test.terminate);
+        ..expectCancel()
+        ..expectDone(test.terminate);
     test..listen()
         ..add(42)
         ..close();
@@ -436,8 +436,8 @@
         ..expectData(37)
         ..expectData(37)
         ..expectDone()
-        ..expectDone()
-        ..expectCancel(test.terminate);
+        ..expectCancel()
+        ..expectDone(test.terminate);
     test.listen();
     test.add(42);
   });
@@ -459,8 +459,8 @@
     ..expectData(37, () {
       test.close();
     })
-    ..expectDone()
-    ..expectCancel(test.terminate);
+    ..expectCancel()
+    ..expectDone(test.terminate);
     test.listen();
   });
 
@@ -560,9 +560,9 @@
         ..expectResume(() {
             test.close();
           })
+        ..expectCancel()
         ..expectDone()
-        ..expectBroadcastCancel()
-        ..expectCancel(test.terminate);
+        ..expectBroadcastCancel((_) => test.terminate());
     sub = test.listen();
   });
 }
diff --git a/tests/lib/async/stream_state_nonzero_timer_test.dart b/tests/lib/async/stream_state_nonzero_timer_test.dart
index af459b0..34175de 100644
--- a/tests/lib/async/stream_state_nonzero_timer_test.dart
+++ b/tests/lib/async/stream_state_nonzero_timer_test.dart
@@ -30,8 +30,8 @@
      ..expectResume(() { t.pause(); })
      ..expectPause(() { t.resume(); })
      ..expectResume(() { t.close(); })
-     ..expectDone()
-     ..expectCancel(t.terminate);
+     ..expectCancel()
+     ..expectDone(t.terminate);
     t..listen()..add(42);
   });
 
@@ -42,8 +42,8 @@
          t.pause(new Future.delayed(ms5, () => null));
        })
      ..expectPause()
-     ..expectDone()
-     ..expectCancel(t.terminate);
+     ..expectCancel()
+     ..expectDone(t.terminate);
      // We are calling "close" while the controller is actually paused,
      // and it will stay paused until the pending events are sent.
     t..listen()..add(42)..close();
@@ -57,8 +57,8 @@
        })
      ..expectPause()
      ..expectResume(t.close)
-     ..expectDone()
-     ..expectCancel(t.terminate);
+     ..expectCancel()
+     ..expectDone(t.terminate);
     t..listen()..add(42);
   });
 
@@ -75,8 +75,8 @@
      ..expectPause()
      ..expectData(43)
      ..expectResume(t.close)
-     ..expectDone()
-     ..expectCancel(t.terminate);
+     ..expectCancel()
+     ..expectDone(t.terminate);
     t..listen()..add(42);
   });
 
@@ -94,8 +94,8 @@
        t.resume();
        t.close();
      })
-     ..expectDone()
-     ..expectCancel(t.terminate);
+     ..expectCancel()
+     ..expectDone(t.terminate);
     t..listen()
      ..add(42);
   });
diff --git a/tests/lib/async/stream_state_test.dart b/tests/lib/async/stream_state_test.dart
index f64d720..acf6904 100644
--- a/tests/lib/async/stream_state_test.dart
+++ b/tests/lib/async/stream_state_test.dart
@@ -17,6 +17,17 @@
   mainTest(sync: false, asBroadcast: true);
 }
 
+void terminateWithDone(t, asBroadcast) {
+  if (asBroadcast) {
+    t..expectCancel()
+     ..expectDone()
+     ..expectBroadcastCancel((_) => t.terminate());
+  } else {
+    t..expectCancel()
+     ..expectDone(t.terminate);
+  }
+}
+
 mainTest({bool sync, bool asBroadcast}) {
   var p = (sync ? "S" : "AS") + (asBroadcast ? "BC" : "SC");
   test("$p-sub-data-done", () {
@@ -24,10 +35,8 @@
                         : new StreamProtocolTest(sync: sync);
     t..expectListen()
      ..expectBroadcastListenOpt()
-     ..expectData(42)
-     ..expectDone()
-     ..expectBroadcastCancelOpt()
-     ..expectCancel(t.terminate);
+     ..expectData(42);
+    terminateWithDone(t, asBroadcast);
     t..listen()..add(42)..close();
   });
 
@@ -36,10 +45,8 @@
                         : new StreamProtocolTest(sync: sync);
     t..expectListen()
      ..expectBroadcastListenOpt()
-     ..expectData(42)
-     ..expectDone()
-     ..expectBroadcastCancelOpt()
-     ..expectCancel(t.terminate);
+     ..expectData(42);
+    terminateWithDone(t, asBroadcast);
     t..add(42)..close()..listen();
   });
 
@@ -48,10 +55,8 @@
                         : new StreamProtocolTest(sync: sync);
     t..expectListen()
      ..expectBroadcastListenOpt()
-     ..expectData(42)
-     ..expectDone()
-     ..expectBroadcastCancelOpt()
-     ..expectCancel(t.terminate);
+     ..expectData(42);
+    terminateWithDone(t, asBroadcast);
     t..add(42)..close()..listen();
   });
 
@@ -64,22 +69,27 @@
          t.pause();
          t.resume();
          t.close();
-       })
-     ..expectDone()
-     ..expectBroadcastCancelOpt()
-     ..expectCancel(t.terminate);
+       });
+    terminateWithDone(t, asBroadcast);
     t..listen()..add(42);
   });
 
   test("$p-sub-data-unsubonerror", () {
     var t = asBroadcast ? new StreamProtocolTest.asBroadcast(sync: sync)
                         : new StreamProtocolTest(sync: sync);
-    t..expectListen()
-     ..expectBroadcastListenOpt()
-     ..expectData(42)
-     ..expectError("bad")
-     ..expectBroadcastCancelOpt()
-     ..expectCancel(t.terminate);
+    if (asBroadcast) {
+      t..expectListen()
+       ..expectBroadcastListen()
+       ..expectData(42)
+       ..expectError("bad")
+       ..expectBroadcastCancel()
+       ..expectCancel(t.terminate);
+    } else {
+      t..expectListen()
+       ..expectData(42)
+       ..expectCancel()
+       ..expectError("bad", t.terminate);
+    }
     t..listen(cancelOnError: true)
      ..add(42)
      ..error("bad")
@@ -94,10 +104,8 @@
      ..expectBroadcastListenOpt()
      ..expectData(42)
      ..expectError("bad")
-     ..expectData(43)
-     ..expectDone()
-     ..expectBroadcastCancelOpt()
-     ..expectCancel(t.terminate);
+     ..expectData(43);
+    terminateWithDone(t, asBroadcast);
     t..listen(cancelOnError: false)
      ..add(42)
      ..error("bad")
@@ -117,11 +125,41 @@
     if (!asBroadcast && !sync) {
       t..expectPause();
     }
-    t..expectDone()
-     ..expectBroadcastCancelOpt()
-     ..expectCancel(t.terminate);
+    if (asBroadcast && sync) {
+      t..expectDone()
+       ..expectCancel(t.terminate);
+    } else {
+      t..expectCancel()
+       ..expectDone(t.terminate);
+    }
     t..listen()
      ..add(42)
      ..close();
   });
+
+  test("$p-cancel-on-data", () {
+    var t = asBroadcast ? new StreamProtocolTest.asBroadcast(sync: sync)
+                        : new StreamProtocolTest(sync: sync);
+    t..expectListen()
+     ..expectBroadcastListenOpt()
+     ..expectData(42, t.cancel)
+     ..expectBroadcastCancelOpt()
+     ..expectCancel(t.terminate);
+    t..listen(cancelOnError: false)
+     ..add(42)
+     ..close();
+  });
+
+  test("$p-cancel-on-error", () {
+    var t = asBroadcast ? new StreamProtocolTest.asBroadcast(sync: sync)
+                        : new StreamProtocolTest(sync: sync);
+    t..expectListen()
+     ..expectBroadcastListenOpt()
+     ..expectError(42, t.cancel)
+     ..expectBroadcastCancelOpt()
+     ..expectCancel(t.terminate);
+    t..listen(cancelOnError: false)
+     ..error(42)
+     ..close();
+  });
 }
diff --git a/tests/lib/async/stream_subscription_cancel_test.dart b/tests/lib/async/stream_subscription_cancel_test.dart
new file mode 100644
index 0000000..d6c6987
--- /dev/null
+++ b/tests/lib/async/stream_subscription_cancel_test.dart
@@ -0,0 +1,138 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test the StreamSubscription.cancel return Future.
+library stream_subscription_cancel;
+
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+void main() {
+  test('subscription.cancel', () {
+    var completer = new Completer();
+    StreamController controller = new StreamController(
+        onCancel: () => completer.future);
+
+    bool done = false;
+    expect(controller.stream.listen(null).cancel().then((_) => done),
+           completion(equals(true)));
+
+    Timer.run(() {
+      done = true;
+      completer.complete();
+    });
+  });
+
+  test('subscription.cancel after close', () {
+    var completer = new Completer();
+    StreamController controller = new StreamController(
+        onCancel: completer.complete);
+
+    controller.close();
+
+    var sub;
+    void onDone() {
+      expect(sub.cancel(), isNull);
+    }
+
+    sub = controller.stream.listen(null, onDone: onDone);
+    expect(completer.future, completes);
+  });
+
+  test('subscription.cancel after error', () {
+    var completer = new Completer();
+    StreamController controller = new StreamController(
+        onCancel: () => completer.future);
+
+    controller.addError("error");
+
+    bool done = false;
+
+    var subscription;
+    var doneCompleter = new Completer();
+    void onError(e) {
+      subscription.cancel().then((_) => doneCompleter.complete(done));
+      done = true;
+      completer.complete();
+    }
+    subscription = controller.stream.listen(null, onError: onError);
+    expect(doneCompleter.future, completion(equals(true)));
+  });
+
+  test('subscription.cancel after error (cancelOnError)', () {
+    bool called = false;
+    StreamController controller = new StreamController(
+        onCancel: () {
+          called = true;
+        });
+
+    controller.addError("error");
+
+    var doneCompleter = new Completer();
+    void onError(e) {
+      expect(called, equals(true));
+      doneCompleter.complete(true);
+    }
+    controller.stream.listen(null, onError: onError, cancelOnError: true);
+    expect(doneCompleter.future, completion(equals(true)));
+  });
+
+  test('subscription.cancel before error (cancelOnError)', () {
+    var doneCompleter = new Completer();
+    StreamController controller = new StreamController(
+        onCancel: () {
+          doneCompleter.complete(true);
+        });
+
+    controller.addError("error");
+
+    void onError(e) {
+      fail("onError is unexpected");
+    }
+    controller.stream
+      .listen(null, onError: onError, cancelOnError: true)
+      .cancel();
+    expect(doneCompleter.future, completion(equals(true)));
+  });
+
+  test('subscription.cancel on error (cancelOnError)', () {
+    bool called = false;
+    StreamController controller = new StreamController(
+        onCancel: () {
+          expect(called, isFalse);
+          called = true;
+        });
+
+    controller.addError("error");
+
+    var doneCompleter = new Completer();
+    var sub;
+    void onError(e) {
+      expect(called, equals(true));
+      sub.cancel();
+      doneCompleter.complete(true);
+    }
+    sub = controller.stream
+      .listen(null, onError: onError, cancelOnError: true);
+    expect(doneCompleter.future, completion(equals(true)));
+  });
+
+  test('subscription.cancel before done', () {
+    var doneCompleter = new Completer();
+    StreamController controller = new StreamController(
+        onCancel: () {
+          doneCompleter.complete(true);
+        });
+
+    controller.close();
+
+    void onDone() {
+      fail("onDone is unexpected");
+    }
+    controller.stream
+      .listen(null, onDone: onDone)
+      .cancel();
+    expect(doneCompleter.future, completion(equals(true)));
+  });
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 6b801d3..6961894 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -20,13 +20,14 @@
 mirrors/constructor_kinds_test: RuntimeError # Issue 13799
 mirrors/equality_test/02: RuntimeError # Issue 12333
 mirrors/fake_function_test: RuntimeError # Issue 11612
+mirrors/find_in_context_fake_function_test: Fail # Issue 6490
 mirrors/function_type_mirror_test: RuntimeError # Issue 12166
 mirrors/generics_test/01: RuntimeError # Issue 12087
 mirrors/generic_bounded_test/none: RuntimeError # Issue 12087
 mirrors/generic_bounded_test/01: RuntimeError # Issue 12087
 mirrors/generic_bounded_by_type_parameter_test/none: RuntimeError # Issue 12087
 mirrors/generic_bounded_by_type_parameter_test/01: RuntimeError # Issue 12087
-mirrors/generic_f_bounded_test: RuntimeError # Issue 12087
+mirrors/generic_f_bounded_test/01: RuntimeError # Issue 12087
 mirrors/generic_f_bounded_mixin_application_test: RuntimeError # Issue 12087
 mirrors/generic_function_typedef_test: RuntimeError # Issue 12333
 mirrors/generic_interface_test: RuntimeError # Issue 12087
@@ -67,15 +68,13 @@
 mirrors/typedef_test/none: RuntimeError # http://dartbug.com/6490
 mirrors/typedef_metadata_test: RuntimeError # Issue 12785
 mirrors/typevariable_mirror_metadata_test: CompileTimeError # Issue 10905
+mirrors/type_variable_owner_test/01: RuntimeError # Issue 12785
 mirrors/unnamed_library_test: RuntimeError # Issue 10580
 
 [ $compiler == dart2js && $unchecked ]
 mirrors/generic_bounded_test/02: RuntimeError # Issue 12087
 mirrors/generic_bounded_by_type_parameter_test/02: RuntimeError # Issue 12087
 
-[ $compiler == dart2js && $checked ]
-mirrors/redirection_type_shuffling_test: RuntimeError # Issue 13706
-
 [ $runtime == safari ]
 mirrors/return_type_test: Pass, Timeout # Issue 12858
 
@@ -175,16 +174,14 @@
 mirrors/intercepted_object_test: Fail, OK # TODO(ahe): Slight broken test to ensure test coverage on dart2js.
 mirrors/typedef_test/01: Fail, OK # Incorrect dart2js behavior.
 
-mirrors/generic_function_typedef_test: RuntimeError # Issue 12282
-mirrors/generic_f_bounded_test: RuntimeError # Issue 14000
-mirrors/immutable_collections_test: RuntimeError # Issue 14027
+mirrors/generic_f_bounded_test/01: RuntimeError # Issue 14000
 mirrors/symbol_validation_test: RuntimeError # Issue 13596
-mirrors/typevariable_mirror_metadata_test/none: RuntimeError # Issue 12282
 
 async/timer_isolate_test: Skip # See Issue 4997
 async/timer_not_available_test: SkipByDesign # only meant to test when there is no way to implement timer (currently only in d8)
 
 [ $compiler == none && ( $runtime == drt || $runtime == dartium ) ]
+mirrors/immutable_collections_test: Fail # Issue 11857, Issue 14321
 mirrors/library_uri_io_test: Skip # Not intended for drt as it uses dart:io.
 mirrors/local_isolate_test: Skip # http://dartbug.com/12188
 async/schedule_microtask6_test: Fail # Issue 10910
@@ -206,12 +203,15 @@
 mirrors/typedef_test/none: Fail # Issue 13093
 mirrors/generics_test/none: Fail # Issue 13432
 mirrors/generic_bounded_test/none: Fail # Issue 13432
+mirrors/generic_f_bounded_test/none: Fail # Issue 13432
 mirrors/generic_bounded_by_type_parameter_test/none: Fail # Issue 13432
 mirrors/generic_mixin_test/none: Fail # Issue 13432
 mirrors/invoke_named_test/none: Fail # http://dartbug.com/13612
 mirrors/generic_f_bounded_mixin_application_test: Fail # Issue 14116
 mirrors/generic_interface_test/none: Fail # Inexpressible in multitest
 mirrors/typevariable_mirror_metadata_test/none: Fail # Issue 13093
+mirrors/redirecting_factory_test/none: Fail # Issue 14285
+mirrors/type_variable_owner_test/none: Fail # Issue 14356
 
 [ $compiler == dart2analyzer ]
 mirrors/typedef_test/none: Fail # Issue 13093
@@ -222,7 +222,7 @@
 mirrors/invoke_named_test/none: Fail # http://dartbug.com/13612
 mirrors/generic_f_bounded_mixin_application_test: Fail # Issue 14116
 mirrors/generic_interface_test/none: Fail # Inexpressible in multitest
-mirrors/typevariable_mirror_metadata_test/none: Fail # Issue 13093
+mirrors/type_variable_owner_test/none: Fail # Issue 14356
 
 [ $compiler == none && $runtime == dartium ]
 async/schedule_microtask5_test: Pass, Timeout # Issue 13719: Please triage this failure.
@@ -230,3 +230,4 @@
 
 [ ($compiler != none && $runtime != none) || ($compiler == none && ($runtime != dartium && $runtime != drt)) ]
 async/schedule_microtask_test: Fail # Issue 9001, Issue 9002
+
diff --git a/tests/lib/mirrors/class_mirror_type_variables_test.dart b/tests/lib/mirrors/class_mirror_type_variables_test.dart
index 2a3ea7e..9694ee4 100644
--- a/tests/lib/mirrors/class_mirror_type_variables_test.dart
+++ b/tests/lib/mirrors/class_mirror_type_variables_test.dart
@@ -9,11 +9,15 @@
 class NoTypeParams {}
 class A<T, S extends String> {}
 class B<Z extends B<Z>> {}
-class C<R,S,T> {
+class C<Z extends B<Z>> {}
+class D<R,S,T> {
   R foo(R r) => r;
   S bar(S s) => s;
   T baz(T t) => t;
 }
+class Helper<S> {}
+class E<R extends Map<R, Helper<String>>> {}
+class F<Z extends Helper<F<Z>>> {}
 
 testNoTypeParams() {
   ClassMirror cm = reflectClass(NoTypeParams);
@@ -26,26 +30,57 @@
 
   TypeVariableMirror aT = a.typeVariables[0];
   TypeVariableMirror aS = a.typeVariables[1];
-  TypeMirror aTBound = aT.upperBound.originalDeclaration;
-  TypeMirror aSBound = aS.upperBound.originalDeclaration;
+  ClassMirror aTBound = aT.upperBound;
+  ClassMirror aSBound = aS.upperBound;
+
+  Expect.isTrue(aTBound.isOriginalDeclaration);
+  Expect.isTrue(aSBound.isOriginalDeclaration);
 
   Expect.equals(reflectClass(Object), aTBound);
   Expect.equals(reflectClass(String), aSBound);
 }
 
-void testB() {
+void testBAndC() {
   ClassMirror b = reflectClass(B);
+  ClassMirror c = reflectClass(C);
+
   Expect.equals(1, b.typeVariables.length);
+  Expect.equals(1, c.typeVariables.length);
 
   TypeVariableMirror bZ = b.typeVariables[0];
-  ClassMirror bZBound = bZ.upperBound.originalDeclaration;
-  Expect.equals(b, bZBound);
-  Expect.equals(bZ, bZBound.typeVariables[0]);
+  TypeVariableMirror cZ = c.typeVariables[0];
+  ClassMirror bZBound = bZ.upperBound;
+  ClassMirror cZBound = cZ.upperBound;
+
+  Expect.isFalse(bZBound.isOriginalDeclaration);
+  Expect.isFalse(cZBound.isOriginalDeclaration);
+
+  Expect.notEquals(bZBound, cZBound);
+  Expect.equals(b, bZBound.originalDeclaration);
+  Expect.equals(b, cZBound.originalDeclaration);
+
+  TypeMirror bZBoundTypeArgument = bZBound.typeArguments.single;
+  TypeMirror cZBoundTypeArgument = cZBound.typeArguments.single;
+  TypeVariableMirror bZBoundTypeVariable = bZBound.typeVariables.single;
+  TypeVariableMirror cZBoundTypeVariable = cZBound.typeVariables.single;
+
+  Expect.equals(b, bZ.owner);
+  Expect.equals(c, cZ.owner);
+  Expect.equals(b, bZBoundTypeVariable.owner); /// 01: ok
+  Expect.equals(b, cZBoundTypeVariable.owner); /// 01: ok
+  Expect.equals(b, bZBoundTypeArgument.owner);
+  Expect.equals(c, cZBoundTypeArgument.owner);
+
+  Expect.notEquals(bZ, cZ);
+  Expect.equals(bZ, bZBoundTypeArgument);
+  Expect.equals(cZ, cZBoundTypeArgument);
+  Expect.equals(bZ, bZBoundTypeVariable); /// 01: ok
+  Expect.equals(bZ, cZBoundTypeVariable); /// 01: ok
 }
 
-testC() {
+testD() {
   ClassMirror cm;
-  cm = reflectClass(C);
+  cm = reflectClass(D);
   Expect.equals(3, cm.typeVariables.length);
   var values = cm.typeVariables;
   values.forEach((e) {
@@ -56,9 +91,35 @@
   Expect.equals(#T, values.elementAt(2).simpleName);
 }
 
+void testE() {
+  ClassMirror e = reflectClass(E);
+  TypeVariableMirror eR = e.typeVariables.single;
+  ClassMirror mapRAndHelperOfString = eR.upperBound;
+
+  Expect.isFalse(mapRAndHelperOfString.isOriginalDeclaration);
+  Expect.equals(eR, mapRAndHelperOfString.typeArguments.first);
+  Expect.equals(reflect(new Helper<String>()).type,
+      mapRAndHelperOfString.typeArguments.last);
+}
+
+void testF() {
+  ClassMirror f = reflectClass(F);
+  TypeVariableMirror fZ = f.typeVariables[0];
+  ClassMirror fZBound = fZ.upperBound;
+  ClassMirror fZBoundTypeArgument = fZBound.typeArguments.single;
+
+  Expect.equals(1, f.typeVariables.length);
+  Expect.isFalse(fZBound.isOriginalDeclaration);
+  Expect.isFalse(fZBoundTypeArgument.isOriginalDeclaration);
+  Expect.equals(f, fZBoundTypeArgument.originalDeclaration);
+  Expect.equals(fZ, fZBoundTypeArgument.typeArguments.single);
+}
+
 main() {
   testNoTypeParams();
   testA();
-  testB();
-  testC();
-}
\ No newline at end of file
+  testBAndC();
+  testD();
+  testE();
+  testF();
+}
diff --git a/tests/lib/mirrors/equality_test.dart b/tests/lib/mirrors/equality_test.dart
index 77e724f..94c9856 100644
--- a/tests/lib/mirrors/equality_test.dart
+++ b/tests/lib/mirrors/equality_test.dart
@@ -24,6 +24,9 @@
   int get hashCode => count++;
 }
 
+typedef bool Predicate(Object o);
+Predicate somePredicate;
+
 checkEquality(List<Map> equivalenceClasses) {
   for (var equivalenceClass in equivalenceClasses) {
     equivalenceClass.forEach((name, member) {
@@ -117,6 +120,38 @@
      'thisLibrary.classes[#B]' : thisLibrary.classes[#B],
      'reflect(new B()).type' : reflect(new B()).type},
 
+    {'reflectClass(BadEqualityHash).methods[#==]'  /// 02: ok
+        : reflectClass(BadEqualityHash).methods[#==],  /// 02: ok
+     'reflect(new BadEqualityHash()).type.methods[#==]'  /// 02: ok
+        : reflect(new BadEqualityHash()).type.methods[#==]},  /// 02: ok
+
+    {'reflectClass(BadEqualityHash).methods[#==].parameters[0]'  /// 02: ok
+        : reflectClass(BadEqualityHash).methods[#==].parameters[0],  /// 02: ok
+     'reflect(new BadEqualityHash()).type.methods[#==].parameters[0]'  /// 02: ok
+        : reflect(new BadEqualityHash()).type.methods[#==].parameters[0]},  /// 02: ok
+
+    {'reflectClass(BadEqualityHash).variables[#count]'  /// 02: ok
+        : reflectClass(BadEqualityHash).variables[#count],  /// 02: ok
+     'reflect(new BadEqualityHash()).type.variables[#count]'  /// 02: ok
+        : reflect(new BadEqualityHash()).type.variables[#count]},  /// 02: ok
+
+    {'reflectType(Predicate)' : reflectType(Predicate),  /// 02: ok
+     'thisLibrary.variables[#somePredicate].type'  /// 02: ok
+        : thisLibrary.variables[#somePredicate].type},  /// 02: ok
+
+    {'reflectType(Predicate).referent' : reflectType(Predicate).referent,  /// 02: ok
+     'thisLibrary.variables[#somePredicate].type.referent'  /// 02: ok
+        : thisLibrary.variables[#somePredicate].type.referent},  /// 02: ok
+
+    {'reflectClass(A).typeVariables.single'  /// 02: ok
+        : reflectClass(A).typeVariables.single,  /// 02: ok
+     'reflect(new A<int>()).type.originalDeclaration.typeVariables.single'  /// 02: ok
+        : reflect(new A<int>()).type.originalDeclaration.typeVariables.single},  /// 02: ok
+
+    {'currentMirrorSystem()' : currentMirrorSystem()},
+
+    {'currentMirrorSystem().isolate' : currentMirrorSystem().isolate},
+
     {'thisLibrary' : thisLibrary,
      'reflectClass(A).owner' : reflectClass(A).owner,
      'reflectClass(B).owner' : reflectClass(B).owner,
diff --git a/tests/lib/mirrors/find_in_context_fake_function_test.dart b/tests/lib/mirrors/find_in_context_fake_function_test.dart
new file mode 100644
index 0000000..5ccfaee
--- /dev/null
+++ b/tests/lib/mirrors/find_in_context_fake_function_test.dart
@@ -0,0 +1,77 @@
+// 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.
+
+// Regression test: this used to crash the VM.
+
+library test.find_in_context_fake_function;
+
+import "dart:mirrors";
+import "package:expect/expect.dart";
+
+var topLevelField = 1;
+get topLevelGetter => 2;
+topLevelFunction() => 3;
+
+class FakeFunction1 {
+  var field = 4;
+  get getter => 5;
+  method() => 6;
+  static var staticField = 7;
+  static get staticGetter => 8;
+  staticFunction() => 9;
+  call(x) {
+    var local = x * 2;
+    return local;
+  }
+}
+
+class FakeFunction2 implements Function {
+  var field = 10;
+  get getter => 11;
+  method() => 12;
+  static var staticField = 13;
+  static get staticGetter => 14;
+  staticFunction() => 15;
+  noSuchMethod(msg) {
+    var local = msg.positionalArguments;
+    if (msg.memberName != #call) return super.noSuchMethod(msg);
+    return local.join('+');
+  }
+}
+
+doFindInContext(cm, name, value) {
+  Expect.equals(value,
+                cm.findInContext(name).reflectee);
+}
+dontFindInContext(cm, name) {
+  Expect.isNull(cm.findInContext(name));
+}
+
+main() {
+  ClosureMirror cm = reflect(new FakeFunction1());
+  dontFindInContext(cm, #local);
+  dontFindInContext(cm, const Symbol('this'));
+  dontFindInContext(cm, #field);
+  dontFindInContext(cm, #getter);
+  dontFindInContext(cm, #method);
+  dontFindInContext(cm, #staticField);
+  dontFindInContext(cm, #staticGetter);
+  dontFindInContext(cm, #staticFunction);
+  dontFindInContext(cm, #topLevelField);
+  dontFindInContext(cm, #topLevelGetter);
+  dontFindInContext(cm, #topLevelFunction);
+
+  cm = reflect(new FakeFunction2());
+  dontFindInContext(cm, #local);
+  dontFindInContext(cm, const Symbol('this'));
+  dontFindInContext(cm, #field);
+  dontFindInContext(cm, #getter);
+  dontFindInContext(cm, #method);
+  dontFindInContext(cm, #staticField);
+  dontFindInContext(cm, #staticGetter);
+  dontFindInContext(cm, #staticFunction);
+  dontFindInContext(cm, #topLevelField);
+  dontFindInContext(cm, #topLevelGetter);
+  dontFindInContext(cm, #topLevelFunction);
+}
diff --git a/tests/lib/mirrors/generic_f_bounded_test.dart b/tests/lib/mirrors/generic_f_bounded_test.dart
index 3d9244c..96148cc 100644
--- a/tests/lib/mirrors/generic_f_bounded_test.dart
+++ b/tests/lib/mirrors/generic_f_bounded_test.dart
@@ -27,8 +27,8 @@
   Expect.isTrue(realDecl.isOriginalDeclaration);
   Expect.isTrue(sorterDecl.isOriginalDeclaration);
   Expect.isTrue(realSorterDecl.isOriginalDeclaration);
-  Expect.isFalse(magnitudeOfReal.isOriginalDeclaration);
-  Expect.isFalse(sorterOfReal.isOriginalDeclaration);
+  Expect.isFalse(magnitudeOfReal.isOriginalDeclaration); ///  01: ok
+  Expect.isFalse(sorterOfReal.isOriginalDeclaration); ///  01: ok
 
   TypeVariableMirror tFromMagnitude = magnitudeDecl.typeVariables.single;
   TypeVariableMirror rFromSorter = sorterDecl.typeVariables.single;
@@ -52,7 +52,7 @@
   typeArguments(realDecl, []);
   typeArguments(sorterDecl, []);
   typeArguments(realSorterDecl, []);
-  typeArguments(magnitudeOfReal, [realDecl]);
-  typeArguments(sorterOfReal, [realDecl]);
+  typeArguments(magnitudeOfReal, [realDecl]); ///  01: ok
+  typeArguments(sorterOfReal, [realDecl]); /// 01: ok
   typeArguments(magnitudeOfR, [rFromSorter]);
 }
diff --git a/tests/lib/mirrors/generic_function_typedef_test.dart b/tests/lib/mirrors/generic_function_typedef_test.dart
index a2ce1f6..e0968f7 100644
--- a/tests/lib/mirrors/generic_function_typedef_test.dart
+++ b/tests/lib/mirrors/generic_function_typedef_test.dart
@@ -10,9 +10,9 @@
 
 import 'generics_test.dart';
 
-typedef bool NonGenericPredicate(num);
-typedef bool GenericPredicate<T>(T);
-typedef S GenericTransform<S>(S);
+typedef bool NonGenericPredicate(num n);
+typedef bool GenericPredicate<T>(T t);
+typedef S GenericTransform<S>(S s);
 
 class C<R> {
   GenericPredicate<num> predicateOfNum;
@@ -20,7 +20,7 @@
   GenericTransform<R> transformOfR;
 }
 
-reflectClass(t) => reflectType(t).originalDeclaration;
+reflectTypeDeclaration(t) => reflectType(t).originalDeclaration;
 
 main() {
   TypeMirror dynamicMirror = currentMirrorSystem().dynamicType;
@@ -30,65 +30,68 @@
   TypedefMirror transformOfR = reflectClass(C).variables[#transformOfR].type;
   TypedefMirror transformOfDouble = reflect(new C<double>()).type.variables[#transformOfR].type;
 
+  TypeVariableMirror tFromGenericPredicate = reflectTypeDeclaration(GenericPredicate).typeVariables[0];
+  TypeVariableMirror sFromGenericTransform = reflectTypeDeclaration(GenericTransform).typeVariables[0];
   TypeVariableMirror rFromC = reflectClass(C).typeVariables[0];
 
   // Typedefs.
-  typeParameters(reflectClass(NonGenericPredicate), []);
-  typeParameters(reflectClass(GenericPredicate), [#T]);
-  typeParameters(reflectClass(GenericTransform), [#S]);
+  typeParameters(reflectTypeDeclaration(NonGenericPredicate), []);
+  typeParameters(reflectTypeDeclaration(GenericPredicate), [#T]);
+  typeParameters(reflectTypeDeclaration(GenericTransform), [#S]);
   typeParameters(predicateOfNum, [#T]);
   typeParameters(transformOfString, [#S]);
-  typeParameters(transformOfR, [#R]);
-  typeParameters(transformOfDouble, [#R]);
+  typeParameters(transformOfR, [#S]);
+  typeParameters(transformOfDouble, [#S]);
 
-  typeArguments(reflectClass(NonGenericPredicate), []);
-  typeArguments(reflectClass(GenericPredicate), []);
-  typeArguments(reflectClass(GenericTransform), []);
+  typeArguments(reflectTypeDeclaration(NonGenericPredicate), []);
+  typeArguments(reflectTypeDeclaration(GenericPredicate), []);
+  typeArguments(reflectTypeDeclaration(GenericTransform), []);
   typeArguments(predicateOfNum, [reflectClass(num)]);
   typeArguments(transformOfString, [reflectClass(String)]);
   typeArguments(transformOfR, [rFromC]);
-  typeArguments(transformOfDouble, [reflect(double)]);
+  typeArguments(transformOfDouble, [reflectClass(double)]);
 
-  Expect.isTrue(reflectClass(NonGenericPredicate).isOriginalDeclaration);
-  Expect.isTrue(reflectClass(GenericPredicate).isOriginalDeclaration);
-  Expect.isTrue(reflectClass(GenericTransform).isOriginalDeclaration);  
+  Expect.isTrue(reflectTypeDeclaration(NonGenericPredicate).isOriginalDeclaration);
+  Expect.isTrue(reflectTypeDeclaration(GenericPredicate).isOriginalDeclaration);
+  Expect.isTrue(reflectTypeDeclaration(GenericTransform).isOriginalDeclaration);  
   Expect.isFalse(predicateOfNum.isOriginalDeclaration);  
   Expect.isFalse(transformOfString.isOriginalDeclaration);  
   Expect.isFalse(transformOfR.isOriginalDeclaration);  
   Expect.isFalse(transformOfDouble.isOriginalDeclaration);  
 
   // Function types.
-  typeParameters(reflectClass(NonGenericPredicate).referent, []);
-  typeParameters(reflectClass(GenericPredicate).referent, []);
-  typeParameters(reflectClass(GenericTransform).referent, []);
+  typeParameters(reflectTypeDeclaration(NonGenericPredicate).referent, []);
+  typeParameters(reflectTypeDeclaration(GenericPredicate).referent, []);
+  typeParameters(reflectTypeDeclaration(GenericTransform).referent, []);
   typeParameters(predicateOfNum.referent, []);
   typeParameters(transformOfString.referent, []);
   typeParameters(transformOfR.referent, []);
   typeParameters(transformOfDouble.referent, []);
 
-  typeArguments(reflectClass(NonGenericPredicate).referent, []);
-  typeArguments(reflectClass(GenericPredicate).referent, []);
-  typeArguments(reflectClass(GenericTransform).referent, []);
+  typeArguments(reflectTypeDeclaration(NonGenericPredicate).referent, []);
+  typeArguments(reflectTypeDeclaration(GenericPredicate).referent, []);
+  typeArguments(reflectTypeDeclaration(GenericTransform).referent, []);
   typeArguments(predicateOfNum.referent, []);
   typeArguments(transformOfString.referent, []);
   typeArguments(transformOfR.referent, []);
   typeArguments(transformOfDouble.referent, []);
 
   // Function types are always non-generic. Only the typedef is generic.
-  Expect.isTrue(reflectClass(NonGenericPredicate).referent.isOriginalDeclaration);
-  Expect.isTrue(reflectClass(GenericPredicate).referent.isOriginalDeclaration);
-  Expect.isTrue(reflectClass(GenericTransform).referent.isOriginalDeclaration);  
+  Expect.isTrue(reflectTypeDeclaration(NonGenericPredicate).referent.isOriginalDeclaration);
+  Expect.isTrue(reflectTypeDeclaration(GenericPredicate).referent.isOriginalDeclaration);
+  Expect.isTrue(reflectTypeDeclaration(GenericTransform).referent.isOriginalDeclaration);  
   Expect.isTrue(predicateOfNum.referent.isOriginalDeclaration);  
   Expect.isTrue(transformOfString.referent.isOriginalDeclaration); 
-  Expect.isTrue(transformOfR.referent.isOriginalDeclaration); // Er, but here we don't have concrete types...
+  Expect.isTrue(transformOfR.referent.isOriginalDeclaration);
   Expect.isTrue(transformOfDouble.referent.isOriginalDeclaration); 
 
   Expect.equals(reflectClass(num),
-                reflectClass(NonGenericPredicate).referent.parameters[0].type);
-  Expect.equals(dynamicMirror,
-                reflectClass(GenericPredicate).referent.parameters[0].type);
-  Expect.equals(dynamicMirror,
-                reflectClass(GenericTransform).referent.parameters[0].type);
+                reflectTypeDeclaration(NonGenericPredicate).referent.parameters[0].type);
+  Expect.equals(tFromGenericPredicate,
+                reflectTypeDeclaration(GenericPredicate).referent.parameters[0].type);
+  Expect.equals(sFromGenericTransform,
+                reflectTypeDeclaration(GenericTransform).referent.parameters[0].type);
+
   Expect.equals(reflectClass(num),
                 predicateOfNum.referent.parameters[0].type);
   Expect.equals(reflectClass(String),
@@ -99,11 +102,11 @@
                 transformOfDouble.referent.parameters[0].type);
 
   Expect.equals(reflectClass(bool),
-                reflectClass(NonGenericPredicate).referent.returnType);
+                reflectTypeDeclaration(NonGenericPredicate).referent.returnType);
   Expect.equals(reflectClass(bool),
-                reflectClass(GenericPredicate).referent.returnType);
-  Expect.equals(dynamicMirror,
-                reflectClass(GenericTransform).referent.returnType);
+                reflectTypeDeclaration(GenericPredicate).referent.returnType);
+  Expect.equals(sFromGenericTransform,
+                reflectTypeDeclaration(GenericTransform).referent.returnType);
   Expect.equals(reflectClass(bool),
                 predicateOfNum.referent.returnType);
   Expect.equals(reflectClass(String),
diff --git a/tests/lib/mirrors/immutable_collections_test.dart b/tests/lib/mirrors/immutable_collections_test.dart
index 268ebde..391fce4 100644
--- a/tests/lib/mirrors/immutable_collections_test.dart
+++ b/tests/lib/mirrors/immutable_collections_test.dart
@@ -60,18 +60,21 @@
   cm.typeVariables.forEach(checkTypeVariable);
 }
 
+checkType(TypeMirror tm) {
+  checkList(tm.metadata, 'TypeMirror.metadata');
+}
+
 checkLibrary(LibraryMirror lm) {
   checkMap(lm.members, 'LibraryMirror.members');
   checkMap(lm.variables, 'LibraryMirror.variables');
   checkMap(lm.classes, 'LibraryMirror.classes');
-  // TODO(rmacnak): Revisit after members hoisted to TypeMirror.
-  // checkMap(lm.types, 'LibraryMirror.types');
+  checkMap(lm.types, 'LibraryMirror.types');
   checkMap(lm.functions, 'LibraryMirror.functions');
   checkMap(lm.getters, 'LibraryMirror.getters');
   checkMap(lm.setters, 'LibraryMirror.setters');
   checkList(lm.metadata, 'LibraryMirror.metadata');
 
-  // lm.types.forEach(checkType);
+  lm.types.values.forEach(checkType);
   lm.classes.values.forEach(checkClass);
   lm.functions.values.forEach(checkMethod);
   lm.getters.values.forEach(checkMethod);
@@ -81,6 +84,6 @@
 
 main() {
   currentMirrorSystem().libraries.values.forEach(checkLibrary);
-  // checkType(currentMirrorSystem().voidType);
-  // checkType(currentMirrorSystem().dynamicType);
+  checkType(currentMirrorSystem().voidType);
+  checkType(currentMirrorSystem().dynamicType);
 }
diff --git a/tests/lib/mirrors/redirection_type_shuffling_test.dart b/tests/lib/mirrors/redirection_type_shuffling_test.dart
deleted file mode 100644
index 582b414..0000000
--- a/tests/lib/mirrors/redirection_type_shuffling_test.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "dart:mirrors";
-import "package:expect/expect.dart";
-
-class G<A extends int, B extends String> {
-  G();
-  factory G.swap() = G<B,A>;  /// static type warning
-  factory G.retain() = G<A,B>;
-}
-
-bool get inCheckedMode {
-  try {
-    var i = 1;
-    String s = i;
-    return false;
-  } catch(e) {
-    return true;
-  }
-}
-
-main() {
-  ClassMirror cm = reflect(new G<int, String>()).type;
-
-  if (inCheckedMode) {
-    Expect.throws(() => cm.newInstance(#swap, []),
-                  (e) => e is MirroredCompilationError,
-                  'Checked mode should not allow violation of type bounds');
-  } else {
-    Expect.isTrue(cm.newInstance(#swap, []).reflectee is G<String,int>);
-  }
-
-  Expect.isTrue(cm.newInstance(#retain, []).reflectee is G<int,String>);
-}
diff --git a/tests/lib/mirrors/type_variable_owner_test.dart b/tests/lib/mirrors/type_variable_owner_test.dart
new file mode 100644
index 0000000..282977d
--- /dev/null
+++ b/tests/lib/mirrors/type_variable_owner_test.dart
@@ -0,0 +1,54 @@
+// 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.
+
+// Owner of a type variable should be the declaration of the generic class or
+// typedef, not an instantiation.
+
+library test.type_variable_owner;
+
+import "dart:mirrors";
+
+import "package:expect/expect.dart";
+
+class A<T> {}
+class B<R> extends A<R> {}
+
+testTypeVariableOfClass() {
+  ClassMirror aDecl = reflectClass(A);
+  ClassMirror bDecl = reflectClass(B);
+  ClassMirror aOfInt = reflect(new A<int>()).type;
+  ClassMirror aOfR = bDecl.superclass;
+  ClassMirror bOfString = reflect(new B<String>()).type;
+  ClassMirror aOfString = bOfString.superclass;
+
+  Expect.equals(aDecl, aDecl.typeVariables[0].owner);
+  Expect.equals(aDecl, aOfInt.typeVariables[0].owner);
+  Expect.equals(aDecl, aOfR.typeVariables[0].owner);
+  Expect.equals(aDecl, aOfString.typeVariables[0].owner);
+  
+  Expect.equals(bDecl, bDecl.typeVariables[0].owner);
+  Expect.equals(bDecl, bOfString.typeVariables[0].owner);
+}
+
+typedef bool Predicate<T>(T t);
+Predicate<List> somePredicateOfList;
+
+testTypeVariableOfTypedef() {
+  LibraryMirror thisLibrary =
+      currentMirrorSystem().findLibrary(#test.type_variable_owner).single;
+
+  TypedefMirror predicateOfDynamic = reflectType(Predicate);
+  TypedefMirror predicateOfList =
+      thisLibrary.variables[#somePredicateOfList].type;
+  TypedefMirror predicateDecl = predicateOfList.originalDeclaration;
+  
+  Expect.equals(predicateDecl, predicateOfDynamic.typeVariables[0].owner);
+  Expect.equals(predicateDecl, predicateOfList.typeVariables[0].owner);
+  Expect.equals(predicateDecl, predicateDecl.typeVariables[0].owner);
+}
+
+main() {
+  testTypeVariableOfClass();
+  testTypeVariableOfTypedef();  /// 01: ok
+}
diff --git a/tests/lib/mirrors/typevariable_mirror_metadata_test.dart b/tests/lib/mirrors/typevariable_mirror_metadata_test.dart
index fa05d64..d31159b 100644
--- a/tests/lib/mirrors/typevariable_mirror_metadata_test.dart
+++ b/tests/lib/mirrors/typevariable_mirror_metadata_test.dart
@@ -27,9 +27,9 @@
   cm = reflectClass(B);
   checkMetadata(cm.typeVariables[0], [m3]);
 
-  // Partial coverage.
-  return; /// 01: ok
 
   TypedefMirror tm = reflectType(Predicate);
   checkMetadata(tm.typeVariables[0], [m1, m2]);
+  FunctionTypeMirror ftm = tm.referent;
+  checkMetadata(ftm, []);
 }
diff --git a/tests/standalone/http_launch_data/http_spawn_main.dart b/tests/standalone/http_launch_data/http_spawn_main.dart
index dadc385..3960ea6 100644
--- a/tests/standalone/http_launch_data/http_spawn_main.dart
+++ b/tests/standalone/http_launch_data/http_spawn_main.dart
@@ -7,8 +7,8 @@
 import 'dart:isolate';
 import 'dart:io';
 
-main() {
-  int port = int.parse(new Options().arguments[0]);
+main(List<String> arguments) {
+  int port = int.parse(arguments[0]);
   SendPort spawnedPort =
       spawnUri('http://127.0.0.1:$port/http_isolate_main.dart');
   spawnedPort.call('hello').then((response) {
diff --git a/tests/standalone/io/arguments_test.dart b/tests/standalone/io/arguments_test.dart
new file mode 100644
index 0000000..5a4ca68
--- /dev/null
+++ b/tests/standalone/io/arguments_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// DartOptions=tests/standalone/io/arguments_test.dart 10 arguments_test 20
+
+import "package:expect/expect.dart";
+
+main(List<String> args) {
+  // Basic test for functionality.
+  Expect.equals(3, args.length);
+  Expect.equals(10, int.parse(args[0]));
+  Expect.equals("arguments_test", args[1]);
+  Expect.equals(20, int.parse(args[2]));
+  // Cannot add an additional argument.
+  Expect.throws(() => args.add("Fourth"), (e) => e is UnsupportedError);
+}
diff --git a/tests/standalone/io/dart_std_io_pipe_script.dart b/tests/standalone/io/dart_std_io_pipe_script.dart
index 76402d6..9ae4c77 100644
--- a/tests/standalone/io/dart_std_io_pipe_script.dart
+++ b/tests/standalone/io/dart_std_io_pipe_script.dart
@@ -6,26 +6,25 @@
 
 import "dart:io";
 
-main() {
-  var options = new Options();
+main(List<String> arguments) {
   if (stdioType(stdin) is !StdioType) exit(1);
   if (stdioType(stdout) is !StdioType) exit(1);
   if (stdioType(stderr) is !StdioType) exit(1);
-  if (stdioType(stdin).name != options.arguments[1]) {
+  if (stdioType(stdin).name != arguments[1]) {
     throw stdioType(stdin).name;
   }
-  if (stdioType(stdout).name != options.arguments[2]) {
+  if (stdioType(stdout).name != arguments[2]) {
     throw stdioType(stdout).name;
   }
-  if (stdioType(stderr).name != options.arguments[3]) {
+  if (stdioType(stderr).name != arguments[3]) {
     throw stdioType(stderr).name;
   }
-  if (options.arguments.length > 0) {
-    if (options.arguments[0] == "0") {
+  if (arguments.length > 0) {
+    if (arguments[0] == "0") {
       stdin.pipe(stdout);
-    } else if (options.arguments[0] == "1") {
+    } else if (arguments[0] == "1") {
       stdin.pipe(stderr);
-    } else if (options.arguments[0] == "2") {
+    } else if (arguments[0] == "2") {
       stdin.listen((data) {
         stdout.add(data);
         stderr.add(data);
diff --git a/tests/standalone/io/file_test.dart b/tests/standalone/io/file_test.dart
index 5305f55..2827e1d 100644
--- a/tests/standalone/io/file_test.dart
+++ b/tests/standalone/io/file_test.dart
@@ -1210,56 +1210,57 @@
     Expect.isFalse(file.existsSync());
   }
 
-  // Test that opens the same file for writing then for appending to test
-  // that the file is not truncated when opened for appending.
-  static void testRename() {
+  static void testRename({bool targetExists}) {
+    lift(Function f) =>
+      (futureValue) => futureValue.then((value) => f(value));
     asyncTestStarted();
-    var file = new File('${tempDirectory.path}/rename_name');
-    file.create().then((file) {
-      file.rename("${tempDirectory.path}/rename_newname").then((newfile) {
-        file.exists().then((e) {
-          Expect.isFalse(e);
-          newfile.exists().then((e) {
-            Expect.isTrue(e);
-            newfile.delete().then((_) {
-              file.exists().then((e) {
-                Expect.isFalse(e);
-                if (Platform.operatingSystem != "windows") {
-                  var brokenLink =
-                      new Link('${tempDirectory.path}/rename_name');
-                  brokenLink.create(
-                      '${tempDirectory.path}/rename_newname').then((_) {
-                      file.rename("xxx").then((_) {
-                        throw "Rename of broken link succeeded";
-                      }).catchError((e) {
-                        Expect.isTrue(e is FileException);
-                        asyncTestDone("testRename");
-                      });
-                  });
 
-                } else {
-                  asyncTestDone("testRename");
-                }
-              });
+    String source = join(tempDirectory.path, 'rename_${targetExists}_source');
+    String dest = join(tempDirectory.path, 'rename_${targetExists}_dest');
+    var file = new File(source);
+    var newfile = new File(dest);
+    file.create()
+      .then((_) => targetExists ? newfile.create() : null)
+      .then((_) => file.rename(dest))
+      .then((_) => lift(Expect.isFalse)(file.exists()))
+      .then((_) => lift(Expect.isTrue)(newfile.exists()))
+      .then((_) => newfile.delete())
+      .then((_) => lift(Expect.isFalse)(newfile.exists()))
+      .then((_) {
+        if (Platform.operatingSystem != "windows") {
+          new Link(source).create(dest)
+            .then((_) => file.rename("xxx"))
+            .then((_) { throw "Rename of broken link succeeded"; })
+            .catchError((e) {
+              Expect.isTrue(e is FileException);
+              asyncTestDone("testRename$targetExists");
             });
-          });
-        });
+        } else {
+          asyncTestDone("testRename$targetExists");
+        }
       });
-    });
   }
 
-  static void testRenameSync() {
-    var file = new File('${tempDirectory.path}/rename_name_sync');
+  static void testRenameSync({bool targetExists}) {
+    String source = join(tempDirectory.path, 'rename_source');
+    String dest = join(tempDirectory.path, 'rename_dest');
+    var file = new File(source);
+    var newfile = new File(dest);
     file.createSync();
-    var newfile = file.renameSync('${tempDirectory.path}/rename_newname_sync');
+    if (targetExists) {
+      newfile.createSync();
+    }
+    var result = file.renameSync(dest);
     Expect.isFalse(file.existsSync());
     Expect.isTrue(newfile.existsSync());
+    Expect.equals(result.path, newfile.path);
     newfile.deleteSync();
     Expect.isFalse(newfile.existsSync());
     if (Platform.operatingSystem != "windows") {
-      var brokenLink = new Link('${tempDirectory.path}/rename_name_sync');
-      brokenLink.createSync('${tempDirectory.path}/rename_newname_sync');
+      var brokenLink = new Link(source);
+      brokenLink.createSync(dest);
       Expect.throws(() => file.renameSync('xxx'));
+      brokenLink.deleteSync();
     }
   }
 
@@ -1320,8 +1321,10 @@
       testDirectorySync();
       testWriteStringUtf8();
       testWriteStringUtf8Sync();
-      testRename();
-      testRenameSync();
+      testRename(targetExists: false);
+      testRenameSync(targetExists: false);
+      testRename(targetExists: true);
+      testRenameSync(targetExists: true);
       testLastModified();
       testDoubleAsyncOperation();
       asyncEnd();
diff --git a/tests/standalone/io/http_client_connect_test.dart b/tests/standalone/io/http_client_connect_test.dart
index 3c5b88b..b85896a 100644
--- a/tests/standalone/io/http_client_connect_test.dart
+++ b/tests/standalone/io/http_client_connect_test.dart
@@ -68,6 +68,41 @@
   HttpServer.bind("127.0.0.1", 0).then((server) {
     server.listen((request) {
       server.close();
+      new Timer(const Duration(milliseconds: 100), () {
+        request.response.close();
+      });
+    });
+
+    var client = new HttpClient();
+    client.get("127.0.0.1", server.port, "/")
+      .then((request) => request.close())
+      .then((response) => response.drain())
+      .then((_) => asyncEnd());
+  });
+}
+
+void testGetServerCloseNoKeepAlive() {
+  asyncStart();
+  var client = new HttpClient();
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    int port = server.port;
+    server.first.then((request) => request.response.close());
+
+    client.get("127.0.0.1", port, "/")
+      .then((request) => request.close())
+      .then((response) => response.drain())
+      .then((_) => client.get("127.0.0.1", port, "/"))
+      .then((request) => request.close())
+      .then((_) => Expect.fail('should not succeed'), onError: (_) {})
+      .then((_) => asyncEnd());
+  });
+}
+
+void testGetServerForceClose() {
+  asyncStart();
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      server.close(force: true);
     });
 
     var client = new HttpClient();
@@ -76,12 +111,12 @@
       .then((response) {
         Expect.fail("Request not expected");
       })
-        .catchError((error) => asyncEnd(),
-                    test: (error) => error is HttpException);
+      .catchError((error) => asyncEnd(),
+                  test: (error) => error is HttpException);
   });
 }
 
-void testGetDataServerClose() {
+void testGetDataServerForceClose() {
   asyncStart();
   var completer = new Completer();
   HttpServer.bind("127.0.0.1", 0).then((server) {
@@ -89,7 +124,7 @@
       request.response.contentLength = 100;
       request.response.write("data");
       request.response.write("more data");
-      completer.future.then((_) => server.close());
+      completer.future.then((_) => server.close(force: true));
     });
 
     var client = new HttpClient();
@@ -132,6 +167,8 @@
   testGetDataRequest();
   testGetInvalidHost();
   testGetServerClose();
-  testGetDataServerClose();
+  testGetServerCloseNoKeepAlive();
+  testGetServerForceClose();
+  testGetDataServerForceClose();
   testPostEmptyRequest();
 }
diff --git a/tests/standalone/io/http_client_request_test.dart b/tests/standalone/io/http_client_request_test.dart
index 5b6dc30..fb6dcd6 100644
--- a/tests/standalone/io/http_client_request_test.dart
+++ b/tests/standalone/io/http_client_request_test.dart
@@ -12,9 +12,9 @@
 void testClientRequest(Future handler(request)) {
   HttpServer.bind("127.0.0.1", 0).then((server) {
     server.listen((request) {
-      request.listen((_) {}, onDone: () {
-        request.response.close();
-      }, onError: (e) {});
+      request.drain()
+          .then((_) => request.response.close())
+          .catchError((_) {});
     });
 
     var client = new HttpClient();
@@ -22,15 +22,11 @@
       .then((request) {
         return handler(request);
       })
-      .then((response) {
-        response.listen((_) {}, onDone: () {
-          client.close();
-          server.close();
-        });
-      })
-      .catchError((error) {
-        server.close();
+      .then((response) => response.drain())
+      .catchError((_) {})
+      .whenComplete(() {
         client.close();
+        server.close();
       });
   });
 }
diff --git a/tests/standalone/io/http_cross_process_test.dart b/tests/standalone/io/http_cross_process_test.dart
index 08329a9..8fe7f60 100644
--- a/tests/standalone/io/http_cross_process_test.dart
+++ b/tests/standalone/io/http_cross_process_test.dart
@@ -9,8 +9,7 @@
 
 const int NUM_SERVERS = 10;
 
-void main() {
-  var args = new Options().arguments;
+void main(List<String> args) {
   if (args.isEmpty) {
     for (int i = 0; i < NUM_SERVERS; ++i) {
       makeServer().then((server) {
diff --git a/tests/standalone/io/http_detach_socket_test.dart b/tests/standalone/io/http_detach_socket_test.dart
index 6b38de2..3946017 100644
--- a/tests/standalone/io/http_detach_socket_test.dart
+++ b/tests/standalone/io/http_detach_socket_test.dart
@@ -62,8 +62,8 @@
       socket.write("GET / HTTP/1.1\r\n"
                    "content-length: 0\r\n\r\n");
       socket.listen((_) {}, onDone: () {
-          socket.close();
-        });
+        socket.close();
+      });
     });
   });
 }
diff --git a/tests/standalone/io/http_server_close_response_after_error_client.dart b/tests/standalone/io/http_server_close_response_after_error_client.dart
index 990d34a..cd73999 100644
--- a/tests/standalone/io/http_server_close_response_after_error_client.dart
+++ b/tests/standalone/io/http_server_close_response_after_error_client.dart
@@ -1,26 +1,25 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file

-// for details. All rights reserved. Use of this source code is governed by a

-// BSD-style license that can be found in the LICENSE file.

-

-import 'dart:async';

-import 'dart:io';

-

-void main() {

-  int port = int.parse(new Options().arguments.first);

-  var client = new HttpClient();

-  const MAX = 64;

-  int count = 0;

-  void run() {

-    if (count++ == MAX) exit(0);

-    Socket.connect('127.0.0.1', port).then((socket) {

-      socket.write("POST / HTTP/1.1\r\n");

-      socket.write("Content-Length: 10\r\n");

-      socket.write("\r\n");

-      socket.write("LALALA");

-      socket.destroy();

-      socket.listen(null, onDone: run);

-    });

-  }

-  for (int i = 0; i < 4; i++) run();

-}

-

+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+
+void main(List<String> arguments) {
+  int port = int.parse(arguments.first);
+  var client = new HttpClient();
+  const MAX = 64;
+  int count = 0;
+  void run() {
+    if (count++ == MAX) exit(0);
+    Socket.connect('127.0.0.1', port).then((socket) {
+      socket.write("POST / HTTP/1.1\r\n");
+      socket.write("Content-Length: 10\r\n");
+      socket.write("\r\n");
+      socket.write("LALALA");
+      socket.destroy();
+      socket.listen(null, onDone: run);
+    });
+  }
+  for (int i = 0; i < 4; i++) run();
+}
diff --git a/tests/standalone/io/http_server_early_server_close_test.dart b/tests/standalone/io/http_server_early_server_close_test.dart
deleted file mode 100644
index 2a1c3db..0000000
--- a/tests/standalone/io/http_server_early_server_close_test.dart
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "package:expect/expect.dart";
-import "dart:async";
-import "dart:io";
-import "dart:isolate";
-
-class Server {
-  static Future<int> start() {
-    return HttpServer.bind("127.0.0.1", 0).then((server) {
-      server.listen((HttpRequest request) {
-            Timer.run(server.close);
-          }, onError: (e) {
-            String msg = "No server errors expected: $e";
-            var trace = getAttachedStackTrace(e);
-            if (trace != null) msg += "\nStackTrace: $trace";
-            Expect.fail(msg);
-          });
-      return server.port;
-    });
-  }
-}
-
-class Client {
-  Client(int port) {
-    ReceivePort r = new ReceivePort();
-    HttpClient client = new HttpClient();
-    client.get("127.0.0.1", port, "/")
-        .then((HttpClientRequest request) {
-          return request.close();
-        })
-        .then((HttpClientResponse response) {
-          Expect.fail(
-              "Response should not be given, as not data was returned.");
-        })
-        .catchError((e) {
-          r.close();
-        });
-  }
-}
-
-main() {
-  Server.start().then((port) {
-    new Client(port);
-  });
-}
diff --git a/tests/standalone/io/https_bad_certificate_client.dart b/tests/standalone/io/https_bad_certificate_client.dart
index 62e9039..064131f 100644
--- a/tests/standalone/io/https_bad_certificate_client.dart
+++ b/tests/standalone/io/https_bad_certificate_client.dart
@@ -72,8 +72,7 @@
   return Future.wait(testFutures);
 }
 
-void main() {
-  final args = new Options().arguments;
+void main(List<String> args) {
   SecureSocket.initialize();
   int port = int.parse(args[0]);
   runHttpClient(port, args[1])
diff --git a/tests/standalone/io/https_bad_certificate_test.dart b/tests/standalone/io/https_bad_certificate_test.dart
index 9023680..b98aa46 100644
--- a/tests/standalone/io/https_bad_certificate_test.dart
+++ b/tests/standalone/io/https_bad_certificate_test.dart
@@ -14,7 +14,7 @@
 
 Future<SecureServerSocket> runServer() {
   SecureSocket.initialize(
-      database: join(dirname(new Options().script), 'pkcert'),
+      database: join(dirname(Platform.script), 'pkcert'),
       password: 'dartdart');
 
   return HttpServer.bindSecure(
@@ -28,12 +28,11 @@
 }
 
 void main() {
-  final options = new Options();
   var clientScript =
-      join(dirname(options.script), 'https_bad_certificate_client.dart');
+      join(dirname(Platform.script), 'https_bad_certificate_client.dart');
 
   Future clientProcess(int port, String acceptCertificate) {
-    return Process.run(options.executable,
+    return Process.run(Platform.executable,
         [clientScript, port.toString(), acceptCertificate])
     .then((ProcessResult result) {
       if (result.exitCode != 0 || !result.stdout.contains('SUCCESS')) {
diff --git a/tests/standalone/io/https_unauthorized_client.dart b/tests/standalone/io/https_unauthorized_client.dart
index e2057a1..925ccba 100644
--- a/tests/standalone/io/https_unauthorized_client.dart
+++ b/tests/standalone/io/https_unauthorized_client.dart
@@ -39,8 +39,7 @@
   return Future.wait(testFutures);
 }
 
-void main() {
-  final args = new Options().arguments;
+void main(List<String> args) {
   SecureSocket.initialize();
   runClients(int.parse(args[0]))
     .then((_) => print('SUCCESS'));
diff --git a/tests/standalone/io/https_unauthorized_test.dart b/tests/standalone/io/https_unauthorized_test.dart
index f8fe731..dc3a246 100644
--- a/tests/standalone/io/https_unauthorized_test.dart
+++ b/tests/standalone/io/https_unauthorized_test.dart
@@ -15,7 +15,7 @@
 
 Future<SecureServerSocket> runServer() {
   SecureSocket.initialize(
-      database: join(dirname(new Options().script), 'pkcert'),
+      database: join(dirname(Platform.script), 'pkcert'),
       password: 'dartdart');
 
   return HttpServer.bindSecure(
@@ -29,12 +29,11 @@
 }
 
 void main() {
-  final options = new Options();
-  var clientScript = join(dirname(options.script),
+  var clientScript = join(dirname(Platform.script),
                           'https_unauthorized_client.dart');
 
   Future clientProcess(int port) {
-    return Process.run(options.executable,
+    return Process.run(Platform.executable,
         [clientScript, port.toString()])
     .then((ProcessResult result) {
       if (result.exitCode != 0 || !result.stdout.contains('SUCCESS')) {
diff --git a/tests/standalone/io/options_test.dart b/tests/standalone/io/options_test.dart
deleted file mode 100644
index 9f61e35..0000000
--- a/tests/standalone/io/options_test.dart
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-// Stress test isolate generation.
-// DartOptions=tests/standalone/io/options_test.dart 10 options_test 20
-
-import "package:expect/expect.dart";
-import "dart:math";
-import "dart:io";
-
-main() {
-  var opts = new Options();
-
-  // Basic test for functionality.
-  Expect.equals(3, opts.arguments.length);
-  Expect.equals(10, int.parse(opts.arguments[0]));
-  Expect.equals("options_test", opts.arguments[1]);
-  Expect.equals(20, int.parse(opts.arguments[2]));
-
-  // Now add an additional argument.
-  opts.arguments.add("Fourth");
-  Expect.equals(4, opts.arguments.length);
-  Expect.equals(10, int.parse(opts.arguments[0]));
-  Expect.equals("options_test", opts.arguments[1]);
-  Expect.equals(20, int.parse(opts.arguments[2]));
-  Expect.equals("Fourth", opts.arguments[3]);
-
-  // Check that a new options object still gets the original arguments.
-  var opts2 = new Options();
-  Expect.equals(3, opts2.arguments.length);
-  Expect.equals(10, int.parse(opts2.arguments[0]));
-  Expect.equals("options_test", opts2.arguments[1]);
-  Expect.equals(20, int.parse(opts2.arguments[2]));
-}
diff --git a/tests/standalone/io/parent_test.dart b/tests/standalone/io/parent_test.dart
new file mode 100644
index 0000000..fc687e3
--- /dev/null
+++ b/tests/standalone/io/parent_test.dart
@@ -0,0 +1,127 @@
+// 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 file I/O.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:collection';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+String tempDirectory;
+
+void main() {
+  if (Platform.isWindows) {
+    testWindowsCases();
+  } else {
+    testPosixCases();
+  }
+  asyncStart();
+  createTempDirectories()
+    .then(testObjects)
+    .whenComplete(() {
+      asyncEnd();
+      new Directory(tempDirectory).delete(recursive: true);
+    });
+}
+
+testPosixCases() {
+  Expect.equals('/dir', FileSystemEntity.parentOf('/dir/file'));
+  Expect.equals('/dir', FileSystemEntity.parentOf('/dir/file/'));
+  Expect.equals('/dir', FileSystemEntity.parentOf('/dir//file//'));
+  Expect.equals('/', FileSystemEntity.parentOf('/dir'));
+  Expect.equals('/', FileSystemEntity.parentOf('/dir///'));
+  Expect.equals('/', FileSystemEntity.parentOf('/'));
+
+  Expect.equals('.', FileSystemEntity.parentOf('file'));
+  Expect.equals('.', FileSystemEntity.parentOf('file//'));
+  Expect.equals('.', FileSystemEntity.parentOf(''));
+  Expect.equals('.', FileSystemEntity.parentOf('..'));
+  Expect.equals('.', FileSystemEntity.parentOf('.'));
+  Expect.equals('.', FileSystemEntity.parentOf(''));
+  Expect.equals('/', FileSystemEntity.parentOf('/'));
+  Expect.equals('/', FileSystemEntity.parentOf('//'));
+  Expect.equals('/', FileSystemEntity.parentOf('//file///'));
+  Expect.equals('dir', FileSystemEntity.parentOf('dir/file'));
+  Expect.equals('dir', FileSystemEntity.parentOf('dir/file/'));
+  Expect.equals('dir', FileSystemEntity.parentOf('dir/file//'));
+  Expect.equals('dir/subdir', FileSystemEntity.parentOf('dir/subdir/file'));
+  Expect.equals('dir//subdir', FileSystemEntity.parentOf('dir//subdir//file/'));
+  Expect.equals('dir/sub.dir',
+                FileSystemEntity.parentOf('dir/sub.dir/fi le///'));
+  Expect.equals('dir/..', FileSystemEntity.parentOf('dir/../file/'));
+  Expect.equals('dir/..', FileSystemEntity.parentOf('dir/../..'));
+  Expect.equals('.', FileSystemEntity.parentOf('./..'));
+  Expect.equals('..', FileSystemEntity.parentOf('../.'));
+}
+
+testWindowsCases() {
+  Expect.equals(r'C:/dir', FileSystemEntity.parentOf(r'C:/dir/file'));
+  Expect.equals(r'C:/dir', FileSystemEntity.parentOf(r'C:/dir/file/'));
+  Expect.equals(r'C:\dir', FileSystemEntity.parentOf(r'C:\dir\file'));
+  Expect.equals(r'C:\dir', FileSystemEntity.parentOf(r'C:\dir\file\'));
+  Expect.equals(r'C:\dir', FileSystemEntity.parentOf(r'C:\dir\\file\\'));
+  Expect.equals(r'C:\', FileSystemEntity.parentOf(r'C:\dir'));
+  Expect.equals(r'C:\', FileSystemEntity.parentOf(r'C:\dir\/\'));
+  Expect.equals(r'C:\', FileSystemEntity.parentOf(r'C:\'));
+  // FileSystemEntity.isAbsolute returns false for 'C:'.
+  Expect.equals(r'.', FileSystemEntity.parentOf(r'C:'));
+
+  Expect.equals(r'\\server\share\dir',
+                FileSystemEntity.parentOf(r'\\server\share\dir\file'));
+  Expect.equals(r'\\server\share\dir',
+                FileSystemEntity.parentOf(r'\\server\share\dir\file\'));
+  Expect.equals(r'\\server\share',
+                FileSystemEntity.parentOf(r'\\server\share\file'));
+  Expect.equals(r'\\server\',
+                FileSystemEntity.parentOf(r'\\server\share'));
+  Expect.equals(r'\\server\',
+                FileSystemEntity.parentOf(r'\\server\share\'));
+  Expect.equals(r'\\server\',
+                FileSystemEntity.parentOf(r'\\server\'));
+  Expect.equals(r'\\server/',
+                FileSystemEntity.parentOf(r'\\server/'));
+  Expect.equals(r'\\serve',
+                FileSystemEntity.parentOf(r'\\serve'));
+
+  Expect.equals(r'.', FileSystemEntity.parentOf(r'file'));
+  Expect.equals(r'.', FileSystemEntity.parentOf(r''));
+  Expect.equals(r'.', FileSystemEntity.parentOf(r'..'));
+  Expect.equals(r'.', FileSystemEntity.parentOf(r'.'));
+  Expect.equals(r'.', FileSystemEntity.parentOf(r''));
+  Expect.equals(r'/', FileSystemEntity.parentOf(r'/'));
+  Expect.equals(r'\', FileSystemEntity.parentOf(r'\'));
+  Expect.equals(r'\', FileSystemEntity.parentOf(r'\file\\/'));
+  Expect.equals(r'dir', FileSystemEntity.parentOf(r'dir\file'));
+  Expect.equals(r'dir', FileSystemEntity.parentOf(r'dir\file\'));
+  Expect.equals(r'dir', FileSystemEntity.parentOf(r'dir/file/'));
+  Expect.equals(r'dir\subdir', FileSystemEntity.parentOf(r'dir\subdir\file'));
+  Expect.equals(r'dir\sub.dir',
+                FileSystemEntity.parentOf(r'dir\sub.dir\fi le'));
+}
+
+Future createTempDirectories() {
+  return Directory.systemTemp.createTemp('dart_parent_').then((dir) {
+    tempDirectory = dir.path;
+  }).then((_) => new File(join(tempDirectory, 'file1')).create())
+  .then((_) => new Link(join(tempDirectory, 'link1')).create('.'))
+  .then((_) => new Directory(join(tempDirectory, 'dir1')).create());
+}
+
+testObjects(var ignored) {
+  ['file1', 'link1', 'dir1', 'file2', 'link2', 'dir2'].map(testPath);
+}
+
+testPath(String path) {
+  Expect.equals(tempDirectory,
+                new File(join(tempDirectory, path)).parent.path);
+  Expect.equals(tempDirectory,
+                new Link(join(tempDirectory, path)).parent.path);
+  Expect.equals(tempDirectory,
+                new Directory(join(tempDirectory, path)).parent.path);
+}
diff --git a/tests/standalone/io/platform_test.dart b/tests/standalone/io/platform_test.dart
index 6c009e8..1bcfbd7 100644
--- a/tests/standalone/io/platform_test.dart
+++ b/tests/standalone/io/platform_test.dart
@@ -48,12 +48,6 @@
     if (msg == "Platform.executableArguments") {
       reply.send(Platform.executableArguments);
     }
-    if (msg == "new Options().executable") {
-      reply.send(new Options().executable);
-    }
-    if (msg == "new Options().script") {
-      reply.send(new Options().script);
-    }
     if (msg == "close") {
       reply.send("closed");
       port.close();
@@ -67,14 +61,10 @@
   Future.wait([sendPort.call("Platform.executable"),
                sendPort.call("Platform.script"),
                sendPort.call("Platform.packageRoot"),
-               sendPort.call("Platform.executableArguments"),
-               sendPort.call("new Options().executable"),
-               sendPort.call("new Options().script")])
+               sendPort.call("Platform.executableArguments")])
   .then((results) {
     Expect.equals(Platform.executable, results[0]);
-    Expect.equals(Platform.executable, results[4]);
     Uri uri = Uri.parse(results[1]);
-    Expect.equals(uri, Uri.parse(results[5]));
     Expect.equals("file", uri.scheme);
     Expect.isTrue(uri.path.endsWith('tests/standalone/io/platform_test.dart'));
     Expect.equals(Platform.packageRoot, results[2]);
diff --git a/tests/standalone/io/print_env.dart b/tests/standalone/io/print_env.dart
index 997c3a8..28f926c 100644
--- a/tests/standalone/io/print_env.dart
+++ b/tests/standalone/io/print_env.dart
@@ -4,6 +4,6 @@
 
 import "dart:io";
 
-main() {
-  print(Platform.environment[new Options().arguments[0]]);
+main(List<String> arguments) {
+  print(Platform.environment[arguments[0]]);
 }
diff --git a/tests/standalone/io/process_check_arguments_script.dart b/tests/standalone/io/process_check_arguments_script.dart
index 183beaf..094fba9 100644
--- a/tests/standalone/io/process_check_arguments_script.dart
+++ b/tests/standalone/io/process_check_arguments_script.dart
@@ -21,14 +21,13 @@
   }
 }
 
-main() {
-  var options = new Options();
+main(List<String> arguments) {
   Expect.isTrue(Platform.script.endsWith(
       'process_check_arguments_script.dart'));
-  var expected_num_args = int.parse(options.arguments[0]);
-  var contains_quote = int.parse(options.arguments[1]);
-  Expect.equals(expected_num_args, options.arguments.length);
-  for (var i = 2; i < options.arguments.length; i++) {
-    Expect.isTrue((contains_quote == 0) || options.arguments[i].contains('"'));
+  var expected_num_args = int.parse(arguments[0]);
+  var contains_quote = int.parse(arguments[1]);
+  Expect.equals(expected_num_args, arguments.length);
+  for (var i = 2; i < arguments.length; i++) {
+    Expect.isTrue((contains_quote == 0) || arguments[i].contains('"'));
   }
 }
diff --git a/tests/standalone/io/process_echo_util.dart b/tests/standalone/io/process_echo_util.dart
index 1cc501d..1c6d17e 100644
--- a/tests/standalone/io/process_echo_util.dart
+++ b/tests/standalone/io/process_echo_util.dart
@@ -4,6 +4,6 @@
 
 import "dart:io";
 
-void main() {
-  new Options().arguments.forEach(print);
+void main(List<String> arguments) {
+  arguments.forEach(print);
 }
diff --git a/tests/standalone/io/process_std_io_script.dart b/tests/standalone/io/process_std_io_script.dart
index 7e55c8d..8aee620 100644
--- a/tests/standalone/io/process_std_io_script.dart
+++ b/tests/standalone/io/process_std_io_script.dart
@@ -6,14 +6,13 @@
 
 import "dart:io";
 
-main() {
-  var options = new Options();
-  if (options.arguments.length > 0) {
-    if (options.arguments[0] == "0") {
+main(List<String> arguments) {
+  if (arguments.length > 0) {
+    if (arguments[0] == "0") {
       stdin.pipe(stdout);
-    } else if (options.arguments[0] == "1") {
+    } else if (arguments[0] == "1") {
       stdin.pipe(stderr);
-    } else if (options.arguments[0] == "2") {
+    } else if (arguments[0] == "2") {
       stdin.listen((data) {
         stdout.add(data);
         stderr.add(data);
diff --git a/tests/standalone/io/process_std_io_script2.dart b/tests/standalone/io/process_std_io_script2.dart
index 0bd1a3e..5fe578c 100644
--- a/tests/standalone/io/process_std_io_script2.dart
+++ b/tests/standalone/io/process_std_io_script2.dart
@@ -26,21 +26,20 @@
   }
 }
 
-main() {
+main(List<String> arguments) {
   var asciiString = 'abc';
   var latin1String = 'æøå';
   var utf8String = new String.fromCharCodes([955]);
   var binary = [0, 1, 2];
-  var options = new Options();
-  if (options.arguments.length > 1) {
-    var stream = options.arguments[1];
-    if (options.arguments[0] == "ascii") {
+  if (arguments.length > 1) {
+    var stream = arguments[1];
+    if (arguments[0] == "ascii") {
       writeData(asciiString, ASCII, stream);
-    } else if (options.arguments[0] == "latin1") {
+    } else if (arguments[0] == "latin1") {
       writeData(latin1String, LATIN1, stream);
-    } else if (options.arguments[0] == "utf8") {
+    } else if (arguments[0] == "utf8") {
       writeData(utf8String, UTF8, stream);
-    } else if (options.arguments[0] == "binary") {
+    } else if (arguments[0] == "binary") {
       writeData(binary, null, stream);
     }
   }
diff --git a/tests/standalone/io/process_sync_script.dart b/tests/standalone/io/process_sync_script.dart
index 5369124..6ef1241 100644
--- a/tests/standalone/io/process_sync_script.dart
+++ b/tests/standalone/io/process_sync_script.dart
@@ -8,11 +8,10 @@
 import "dart:math";
 import "dart:io";
 
-main() {
-  var options = new Options();
-  var blockCount = int.parse(options.arguments[0]);
-  var stdoutBlockSize = int.parse(options.arguments[1]);
-  var stderrBlockSize = int.parse(options.arguments[2]);
+main(List<String> arguments) {
+  var blockCount = int.parse(arguments[0]);
+  var stdoutBlockSize = int.parse(arguments[1]);
+  var stderrBlockSize = int.parse(arguments[2]);
   var stdoutBlock =
       new String.fromCharCodes(new List.filled(stdoutBlockSize, 65));
   var stderrBlock =
@@ -22,6 +21,6 @@
     stderr.write(stderrBlock);
   }
   Future.wait([stdout.close(), stderr.close()]).then((_) {
-    exit(int.parse(options.arguments[3]));
+    exit(int.parse(arguments[3]));
   });
 }
diff --git a/tests/standalone/io/raw_socket_cross_process_test.dart b/tests/standalone/io/raw_socket_cross_process_test.dart
index 188d9d3..df69fea 100644
--- a/tests/standalone/io/raw_socket_cross_process_test.dart
+++ b/tests/standalone/io/raw_socket_cross_process_test.dart
@@ -9,8 +9,7 @@
 
 const int NUM_SERVERS = 10;
 
-void main() {
-  var args = new Options().arguments;
+void main(List<String> args) {
   if (args.isEmpty) {
     for (int i = 0; i < NUM_SERVERS; ++i) {
       makeServer().then((server) {
diff --git a/tests/standalone/io/secure_bad_certificate_client.dart b/tests/standalone/io/secure_bad_certificate_client.dart
index 440bca2..c3922ae 100644
--- a/tests/standalone/io/secure_bad_certificate_client.dart
+++ b/tests/standalone/io/secure_bad_certificate_client.dart
@@ -52,8 +52,7 @@
 }
 
 
-void main() {
-  final args = new Options().arguments;
+void main(List<String> args) {
   SecureSocket.initialize();
   runClient(int.parse(args[0]), args[1]);
 }
diff --git a/tests/standalone/io/secure_bad_certificate_test.dart b/tests/standalone/io/secure_bad_certificate_test.dart
index ccdbf32..db31ad1 100644
--- a/tests/standalone/io/secure_bad_certificate_test.dart
+++ b/tests/standalone/io/secure_bad_certificate_test.dart
@@ -14,7 +14,7 @@
 
 
 String certificateDatabase() =>
-    join(dirname(new Options().script), 'pkcert');
+    join(dirname(Platform.script), 'pkcert');
 
 Future<SecureServerSocket> runServer() {
   SecureSocket.initialize(database: certificateDatabase(),
@@ -34,12 +34,11 @@
 
 
 void main() {
-  final options = new Options();
-  var clientScript = join(dirname(options.script),
+  var clientScript = join(dirname(Platform.script),
                           'secure_bad_certificate_client.dart');
 
   Future clientProcess(int port, String acceptCertificate) {
-    return Process.run(options.executable,
+    return Process.run(Platform.executable,
         [clientScript, port.toString(), acceptCertificate])
         .then((ProcessResult result) {
       if (result.exitCode != 0) {
diff --git a/tests/standalone/io/secure_builtin_roots_test.dart b/tests/standalone/io/secure_builtin_roots_test.dart
index f7b5cbb..b6bdfa3 100644
--- a/tests/standalone/io/secure_builtin_roots_test.dart
+++ b/tests/standalone/io/secure_builtin_roots_test.dart
@@ -9,8 +9,7 @@
 import "package:expect/expect.dart";
 import "package:path/path.dart";
 
-void main() {
-  var args = new Options().arguments;
+void main(List<String> args) {
   if (!args.contains('--child')) {
     runAllTestsInChildProcesses();
   } else {
diff --git a/tests/standalone/io/secure_socket_renegotiate_client.dart b/tests/standalone/io/secure_socket_renegotiate_client.dart
index 0c72412..cc3905a 100644
--- a/tests/standalone/io/secure_socket_renegotiate_client.dart
+++ b/tests/standalone/io/secure_socket_renegotiate_client.dart
@@ -73,8 +73,7 @@
 }
 
 
-void main() {
-  final args = new Options().arguments;
+void main(List<String> args) {
   SecureSocket.initialize(database: args[1], password: 'dartdart');
   runClient(int.parse(args[0]));
 }
diff --git a/tests/standalone/io/secure_socket_renegotiate_test.dart b/tests/standalone/io/secure_socket_renegotiate_test.dart
index ee115a9..922e9d0 100644
--- a/tests/standalone/io/secure_socket_renegotiate_test.dart
+++ b/tests/standalone/io/secure_socket_renegotiate_test.dart
@@ -17,7 +17,7 @@
 const CERTIFICATE = "localhost_cert";
 
 
-String certificateDatabase() => join(dirname(new Options().script), 'pkcert');
+String certificateDatabase() => join(dirname(Platform.script), 'pkcert');
 
 
 Future<SecureServerSocket> runServer() {
@@ -65,11 +65,10 @@
 void main() {
   runServer()
     .then((SecureServerSocket server) {
-      final options = new Options();
       var clientScript =
-          options.script.replaceFirst("_test.dart", "_client.dart");
+          Platform.script.replaceFirst("_test.dart", "_client.dart");
       Expect.isTrue(clientScript.endsWith("_client.dart"));
-      Process.run(options.executable,
+      Process.run(Platform.executable,
                   [clientScript,
                    server.port.toString(),
                    certificateDatabase()])
diff --git a/tests/standalone/io/secure_unauthorized_client.dart b/tests/standalone/io/secure_unauthorized_client.dart
index 964c63c..043577f 100644
--- a/tests/standalone/io/secure_unauthorized_client.dart
+++ b/tests/standalone/io/secure_unauthorized_client.dart
@@ -37,8 +37,7 @@
 }
 
 
-void main() {
-  final args = new Options().arguments;
+void main(List<String> args) {
   SecureSocket.initialize();
   runClients(int.parse(args[0]))
     .then((_) => print('SUCCESS'));
diff --git a/tests/standalone/io/secure_unauthorized_test.dart b/tests/standalone/io/secure_unauthorized_test.dart
index a86b95c..400ae7e 100644
--- a/tests/standalone/io/secure_unauthorized_test.dart
+++ b/tests/standalone/io/secure_unauthorized_test.dart
@@ -15,7 +15,7 @@
 
 Future<SecureServerSocket> runServer() {
   SecureSocket.initialize(
-      database: join(dirname(new Options().script), 'pkcert'),
+      database: join(dirname(Platform.script), 'pkcert'),
       password: 'dartdart');
 
   return SecureServerSocket.bind(HOST_NAME, 0, CERTIFICATE)
@@ -31,12 +31,11 @@
 }
 
 void main() {
-  final options = new Options();
-  var clientScript = join(dirname(options.script),
+  var clientScript = join(dirname(Platform.script),
                           'secure_unauthorized_client.dart');
 
   Future clientProcess(int port) {
-    return Process.run(options.executable,
+    return Process.run(Platform.executable,
         [clientScript, port.toString()])
     .then((ProcessResult result) {
       if (result.exitCode != 0 || !result.stdout.contains('SUCCESS')) {
diff --git a/tests/standalone/io/skipping_dart2js_compilations_helper.dart b/tests/standalone/io/skipping_dart2js_compilations_helper.dart
index 1728e3a..cda26da 100644
--- a/tests/standalone/io/skipping_dart2js_compilations_helper.dart
+++ b/tests/standalone/io/skipping_dart2js_compilations_helper.dart
@@ -4,8 +4,8 @@
 
 import 'dart:io';
 
-main() {
-  var outputFile = new Options().arguments[0];
+main(List<String> arguments) {
+  var outputFile = arguments[0];
   var file = new File(outputFile);
   file.createSync();
 }
diff --git a/tests/standalone/io/skipping_dart2js_compilations_test.dart b/tests/standalone/io/skipping_dart2js_compilations_test.dart
index dc39ca4..17ba2cfd 100644
--- a/tests/standalone/io/skipping_dart2js_compilations_test.dart
+++ b/tests/standalone/io/skipping_dart2js_compilations_test.dart
@@ -22,6 +22,7 @@
 import '../../../tools/testing/dart/test_runner.dart' as runner;
 import '../../../tools/testing/dart/test_options.dart' as options;
 import '../../../tools/testing/dart/status_file_parser.dart' as status;
+import '../../../tools/testing/dart/utils.dart';
 
 /**
  * This class is reponsible for setting up the files necessary for this test
diff --git a/tests/standalone/io/socket_cross_process_test.dart b/tests/standalone/io/socket_cross_process_test.dart
index f44b369..013c9f4 100644
--- a/tests/standalone/io/socket_cross_process_test.dart
+++ b/tests/standalone/io/socket_cross_process_test.dart
@@ -9,8 +9,7 @@
 
 const int NUM_SERVERS = 10;
 
-void main() {
-  var args = new Options().arguments;
+void main(List<String> args) {
   if (args.isEmpty) {
     for (int i = 0; i < NUM_SERVERS; ++i) {
       makeServer().then((server) {
diff --git a/tests/standalone/io/stdin_sync_script.dart b/tests/standalone/io/stdin_sync_script.dart
index ed60a9c..42b648e 100644
--- a/tests/standalone/io/stdin_sync_script.dart
+++ b/tests/standalone/io/stdin_sync_script.dart
@@ -6,8 +6,7 @@
 import "dart:io";
 import "dart:json";
 
-void main() {
-  var arguments = new Options().arguments;
+void main(List<String> arguments) {
   int i = 0;
   String line;
   while ((line = stdin.readLineSync(encoding: UTF8)) != null) {
diff --git a/tests/standalone/io/test_runner_exit_code_script.dart b/tests/standalone/io/test_runner_exit_code_script.dart
index 1cfe603..f503d1b 100644
--- a/tests/standalone/io/test_runner_exit_code_script.dart
+++ b/tests/standalone/io/test_runner_exit_code_script.dart
@@ -9,8 +9,8 @@
 import "../../../tools/testing/dart/test_runner.dart";
 import "../../../tools/testing/dart/test_options.dart";
 
-main() {
-  var progressType = new Options().arguments[0];
+main(List<String> arguments) {
+  var progressType = arguments[0];
   // Build a progress indicator.
   var startTime = new DateTime.now();
   var progress =
diff --git a/tests/standalone/io/test_runner_test.dart b/tests/standalone/io/test_runner_test.dart
index 9859e23..86e4842 100644
--- a/tests/standalone/io/test_runner_test.dart
+++ b/tests/standalone/io/test_runner_test.dart
@@ -125,11 +125,10 @@
   }
 }
 
-void main() {
+void main(List<String> arguments) {
   // Run the test_runner_test if there are no command-line options.
   // Otherwise, run one of the component tests that always pass,
   // fail, or timeout.
-  var arguments = new Options().arguments;
   if (arguments.isEmpty) {
     testProcessQueue();
   } else {
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 4b14041..5478aab 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -7,12 +7,6 @@
 # listed in tests/lib/analyzer/analyze_tests.status without the "standalone"
 # prefix.
 
-# The testing infrastructure is using the dart:io Path and LineTransformer
-# classes.
-io/skipping_dart2js_compilations_test: Skip # http/dartbug.com/12449
-io/dependency_graph_test: Skip # http/dartbug.com/12449
-io/status_file_parser_test: Skip # http/dartbug.com/12449
-
 package/invalid_uri_test: Fail, OK # CompileTimeErrors intentionally
 
 [ $runtime == vm && $system == windows ]
@@ -130,15 +124,21 @@
 oom_error_stacktrace_test: RuntimeError, OK # (OOM on JS may produce a stacktrace).
 vmservice/*: Skip # Do not run standalone vm service tests with dart2js.
 
+# Suppress tests that use main(List<String> args) until issue 14200 is fixed.
+io/secure_builtin_roots_test: Fail # Issue 14200
+io/test_runner_test: Fail # Issue 14200
+io/http_cross_process_test: Fail # Issue 14200
+io/socket_cross_process_test: Fail # Issue 14200
+io/raw_socket_cross_process_test: Fail # Issue 14200
 
 [ $compiler == dart2js && $jscl ]
 assert_test: RuntimeError, OK # Assumes unspecified fields on the AssertionError.
 deoptimization_test: RuntimeError, OK # Requires bigint.
 out_of_memory_test: RuntimeError, OK # d8 handles much larger arrays than Dart VM.
-io/options_test: CompileTimeError, OK # Cannot pass options to d8.
+io/arguments_test: CompileTimeError, OK # Cannot pass arguments to d8.
 
 [ $compiler == dart2js && $runtime == none ]
-io/options_test: Fail
+io/arguments_test: Fail # DartOptions not supported by dart2js, and issue 14200.
 medium_integer_test: Pass # The test only fails at runtime, not at compilation.
 oom_error_stacktrace_test: Pass # The test only fails at runtime.
 
diff --git a/tools/VERSION b/tools/VERSION
index d19bd6f..64d19d0 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 8
-BUILD 5
-PATCH 1 
+BUILD 6
+PATCH 0
diff --git a/tools/bots/cross-vm.py b/tools/bots/cross-vm.py
index 2c407d8..08ae335 100644
--- a/tools/bots/cross-vm.py
+++ b/tools/bots/cross-vm.py
@@ -42,11 +42,7 @@
     if num_run == 1:
       with bot.BuildStep('Build %s %s' % (arch, mode)):
         run([sys.executable, build_py,
-             '-m%s' % mode, '--arch=%s' % arch, 'runtime'])
-        # We need to build 'run_vm_tests.host' as well to enable
-        # test.py to list the VM tests.
-        run([sys.executable, build_py,
-             '-m%s' % mode, '--arch=%s' % arch, 'run_vm_tests.host'])
+             '-m%s' % mode, '--arch=%s' % arch])
 
       with bot.BuildStep('Create build tarball'):
         run(['tar', '-cjf', tarball, '--exclude=**/obj',
diff --git a/tools/dom/docs/docs.json b/tools/dom/docs/docs.json
index 5341563..7494d1f 100644
--- a/tools/dom/docs/docs.json
+++ b/tools/dom/docs/docs.json
@@ -529,6 +529,50 @@
       }
     }
   },
+  "dart.dom.web_gl": {
+    "WebGLRenderingContext": {
+      "members": {
+        "bufferData": [
+          "/**",
+          "   * Buffers the specified data.",
+          "   *",
+          "   * This specific method is provided for WebGL API compatibility reasons, but",
+          "   * it is highly recommended that you use [bufferDataTyped] or [bufferByteData]",
+          "   * depending on your purposes.",
+          "   */"
+        ],
+        "bufferSubData": [
+          "/**",
+          "   * Buffers the specified subset of data.",
+          "   *",
+          "   * This specific method is provided for WebGL API compatibility reasons, but",
+          "   * it is highly recommended that you use [bufferSubDataTyped] or [bufferSubByteData]",
+          "   * depending on your purposes.",
+          "   */"
+        ],
+        "texImage2D": [
+          "/**",
+          "   * Updates the currently bound texture to [data].",
+          "   *",
+          "   * This specific method is provided for WebGL API compatibility reasons, but it",
+          "   * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]",
+          "   * (or for more specificity, the more specialized [texImage2DImageData],",
+          "   * [texImage2DCanvas], [texImage2DVideo]).",
+          "   */"
+        ],
+        "texSubImage2D": [
+          "/**",
+          "   * Updates a sub-rectangle of the currently bound texture to [data].",
+          "   *",
+          "   * This specific method is provided for WebGL API compatibility reasons, but it",
+          "   * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]",
+          "   * (or for more specificity, the more specialized [texSubImage2DImageData],",
+          "   * [texSubImage2DCanvas], [texSubImage2DVideo]).",
+          "   */"
+        ]
+      }
+    }
+  },
   "dart.dom.web_sql": {
     "Database": {
       "members": {
diff --git a/tools/dom/docs/lib/docs.dart b/tools/dom/docs/lib/docs.dart
index 190a679..0f59276 100644
--- a/tools/dom/docs/lib/docs.dart
+++ b/tools/dom/docs/lib/docs.dart
@@ -24,6 +24,7 @@
                                                'dart:indexed_db',
                                                'dart:svg',
                                                'dart:web_audio',
+                                               'dart:web_gl',
                                                'dart:web_sql'];
 /**
  * Converts the libraries in [HTML_LIBRARY_NAMES] to a json file at [jsonPath]
diff --git a/tools/dom/dom.json b/tools/dom/dom.json
index 970a7b7..e429275 100644
--- a/tools/dom/dom.json
+++ b/tools/dom/dom.json
@@ -332,6 +332,10 @@
     },
     "support_level": "experimental"
   },
+  "BeforeUnloadEvent": {
+    "members": {},
+    "support_level": "untriaged"
+  },
   "BiquadFilterNode": {
     "comment": "https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#BiquadFilterNode-section",
     "members": {
@@ -388,7 +392,10 @@
     "comment": "http://www.w3.org/TR/css3-fonts/",
     "members": {
       "error": {},
-      "fontface": {}
+      "fontface": {},
+      "fontfaces": {
+        "support_level": "untriaged"
+      }
     },
     "support_level": "experimental"
   },
@@ -757,6 +764,9 @@
       "drawSystemFocusRing": {
         "support_level": "untriaged"
       },
+      "ellipse": {
+        "support_level": "untriaged"
+      },
       "fill": {},
       "fillRect": {},
       "fillStyle": {},
@@ -786,6 +796,9 @@
       "putImageData": {},
       "quadraticCurveTo": {},
       "rect": {},
+      "resetTransform": {
+        "support_level": "untriaged"
+      },
       "restore": {},
       "rotate": {},
       "save": {},
@@ -1092,6 +1105,12 @@
       "timeStamp": {
         "support_level": "untriaged"
       },
+      "timeline": {
+        "support_level": "untriaged"
+      },
+      "timelineEnd": {
+        "support_level": "untriaged"
+      },
       "trace": {
         "support_level": "untriaged"
       },
@@ -1718,6 +1737,9 @@
         "comment": "http://www.w3.org/TR/css3-fonts/#document-fontloader",
         "support_level": "experimental"
       },
+      "fonts": {
+        "support_level": "untriaged"
+      },
       "forms": {},
       "getCSSCanvasContext": {
         "comment": "https://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariCSSRef/Articles/Functions.html",
@@ -1767,6 +1789,9 @@
       "oncopy": {},
       "oncut": {},
       "ondblclick": {},
+      "ondoubleclick": {
+        "support_level": "untriaged"
+      },
       "ondrag": {},
       "ondragend": {},
       "ondragenter": {},
@@ -1776,6 +1801,12 @@
       "ondrop": {},
       "onerror": {},
       "onfocus": {},
+      "onfullscreenchange": {
+        "support_level": "untriaged"
+      },
+      "onfullscreenerror": {
+        "support_level": "untriaged"
+      },
       "oninput": {},
       "oninvalid": {
         "comment": "http://www.whatwg.org/specs/web-apps/current-work/multipage/section-index.html#attributes-1"
@@ -1797,6 +1828,12 @@
       "onmouseup": {},
       "onmousewheel": {},
       "onpaste": {},
+      "onpointerlockchange": {
+        "support_level": "untriaged"
+      },
+      "onpointerlockerror": {
+        "support_level": "untriaged"
+      },
       "onreadystatechange": {},
       "onreset": {},
       "onscroll": {},
@@ -2069,10 +2106,10 @@
       "firstElementChild": {},
       "focus": {},
       "getAttribute": {
-        "support_level": "deprecated"
+        "support_level": "untriaged"
       },
       "getAttributeNS": {
-        "support_level": "deprecated"
+        "support_level": "untriaged"
       },
       "getAttributeNode": {
         "comment": "http://dom.spec.whatwg.org/#dom-element-getattributenode",
@@ -2119,6 +2156,15 @@
       "inputMethodContext": {
         "support_level": "untriaged"
       },
+      "insertAdjacentElement": {
+        "support_level": "untriaged"
+      },
+      "insertAdjacentHTML": {
+        "support_level": "untriaged"
+      },
+      "insertAdjacentText": {
+        "support_level": "untriaged"
+      },
       "isContentEditable": {
         "comment": "http://www.whatwg.org/specs/web-apps/2007-10-26/multipage/section-elements.html#htmlelement",
         "dart_action": "stable",
@@ -2153,6 +2199,9 @@
       "oncopy": {},
       "oncut": {},
       "ondblclick": {},
+      "ondoubleclick": {
+        "support_level": "untriaged"
+      },
       "ondrag": {},
       "ondragend": {},
       "ondragenter": {},
@@ -2162,6 +2211,12 @@
       "ondrop": {},
       "onerror": {},
       "onfocus": {},
+      "onfullscreenchange": {
+        "support_level": "untriaged"
+      },
+      "onfullscreenerror": {
+        "support_level": "untriaged"
+      },
       "oninput": {},
       "oninvalid": {
         "comment": "http://www.whatwg.org/specs/web-apps/current-work/multipage/section-index.html#attributes-1"
@@ -2272,12 +2327,8 @@
       "scrollLeft": {},
       "scrollTop": {},
       "scrollWidth": {},
-      "setAttribute": {
-        "support_level": "deprecated"
-      },
-      "setAttributeNS": {
-        "support_level": "deprecated"
-      },
+      "setAttribute": {},
+      "setAttributeNS": {},
       "setAttributeNode": {
         "comment": "http://dom.spec.whatwg.org/#dom-element-setattributenode",
         "dart_action": "suppress",
@@ -2645,13 +2696,9 @@
   },
   "EventTarget": {
     "members": {
-      "addEventListener": {
-        "support_level": "deprecated"
-      },
+      "addEventListener": {},
       "dispatchEvent": {},
-      "removeEventListener": {
-        "support_level": "deprecated"
-      }
+      "removeEventListener": {}
     },
     "support_level": "stable"
   },
@@ -2858,6 +2905,59 @@
     },
     "support_level": "stable"
   },
+  "FontFace": {
+    "members": {
+      "FontFace": {},
+      "family": {
+        "support_level": "untriaged"
+      },
+      "featureSettings": {
+        "support_level": "untriaged"
+      },
+      "status": {
+        "support_level": "untriaged"
+      },
+      "stretch": {
+        "support_level": "untriaged"
+      },
+      "style": {
+        "support_level": "untriaged"
+      },
+      "unicodeRange": {
+        "support_level": "untriaged"
+      },
+      "variant": {
+        "support_level": "untriaged"
+      },
+      "weight": {
+        "support_level": "untriaged"
+      }
+    },
+    "support_level": "untriaged"
+  },
+  "FontFaceSet": {
+    "members": {
+      "addEventListener": {
+        "support_level": "untriaged"
+      },
+      "check": {
+        "support_level": "untriaged"
+      },
+      "dispatchEvent": {
+        "support_level": "untriaged"
+      },
+      "match": {
+        "support_level": "untriaged"
+      },
+      "removeEventListener": {
+        "support_level": "untriaged"
+      },
+      "status": {
+        "support_level": "untriaged"
+      }
+    },
+    "support_level": "untriaged"
+  },
   "FontLoader": {
     "comment": "http://www.w3.org/TR/css3-fonts/#document-fontloader",
     "members": {
@@ -3689,6 +3789,9 @@
       "naturalHeight": {},
       "naturalWidth": {},
       "src": {},
+      "srcset": {
+        "support_level": "untriaged"
+      },
       "useMap": {},
       "vspace": {
         "comment": "http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLImageElement-partial",
@@ -3750,6 +3853,9 @@
       "min": {},
       "multiple": {},
       "name": {},
+      "onspeechchange": {
+        "support_level": "untriaged"
+      },
       "onwebkitSpeechChange": {
         "comment": "http://lists.w3.org/Archives/Public/public-xg-htmlspeech/2011Feb/att-0020/api-draft.html#extending_html_elements",
         "support_level": "experimental"
@@ -3982,11 +4088,23 @@
       "ondurationchange": {},
       "onemptied": {},
       "onended": {},
+      "onkeyadded": {
+        "support_level": "untriaged"
+      },
+      "onkeyerror": {
+        "support_level": "untriaged"
+      },
+      "onkeymessage": {
+        "support_level": "untriaged"
+      },
       "onloadeddata": {},
       "onloadedmetadata": {},
       "onloadstart": {
         "comment": "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#event-media-loadstart"
       },
+      "onneedkey": {
+        "support_level": "untriaged"
+      },
       "onpause": {
         "comment": "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#event-media-loadstart"
       },
@@ -4786,6 +4904,9 @@
       "LOADING": {},
       "NONE": {},
       "default": {},
+      "defaultValue": {
+        "support_level": "untriaged"
+      },
       "kind": {},
       "label": {},
       "readyState": {},
@@ -5190,6 +5311,17 @@
     },
     "support_level": "untriaged"
   },
+  "KeyPair": {
+    "members": {
+      "privateKey": {
+        "support_level": "untriaged"
+      },
+      "publicKey": {
+        "support_level": "untriaged"
+      }
+    },
+    "support_level": "untriaged"
+  },
   "KeyboardEvent": {
     "comment": "http://www.w3.org/TR/DOM-Level-3-Events/#events-KeyboardEvent",
     "members": {
@@ -5460,6 +5592,15 @@
       "dispatchEvent": {},
       "error": {},
       "keySystem": {},
+      "onkeyadded": {
+        "support_level": "untriaged"
+      },
+      "onkeyerror": {
+        "support_level": "untriaged"
+      },
+      "onkeymessage": {
+        "support_level": "untriaged"
+      },
       "onwebkitkeyadded": {},
       "onwebkitkeyerror": {},
       "onwebkitkeymessage": {},
@@ -5909,6 +6050,9 @@
   },
   "NavigatorID": {
     "members": {
+      "appCodeName": {
+        "support_level": "untriaged"
+      },
       "appName": {
         "support_level": "untriaged"
       },
@@ -5918,6 +6062,9 @@
       "platform": {
         "support_level": "untriaged"
       },
+      "product": {
+        "support_level": "untriaged"
+      },
       "userAgent": {
         "support_level": "untriaged"
       }
@@ -5987,9 +6134,7 @@
       "addEventListener": {},
       "appendChild": {},
       "baseURI": {},
-      "childNodes": {
-        "support_level": "deprecated"
-      },
+      "childNodes": {},
       "cloneNode": {},
       "compareDocumentPosition": {},
       "contains": {},
@@ -6011,16 +6156,12 @@
       },
       "lastChild": {},
       "localName": {
-        "comment": "http://dom.spec.whatwg.org/#dom-node-localname",
-        "dart_action": "suppress",
-        "support_level": "deprecated"
+        "comment": "http://dom.spec.whatwg.org/#dom-node-localname"
       },
       "lookupNamespaceURI": {},
       "lookupPrefix": {},
       "namespaceURI": {
-        "comment": "http://dom.spec.whatwg.org/#dom-node-namespaceuri",
-        "dart_action": "suppress",
-        "support_level": "deprecated"
+        "comment": "http://dom.spec.whatwg.org/#dom-node-namespaceuri"
       },
       "nextSibling": {},
       "nodeName": {},
@@ -6452,6 +6593,9 @@
       "now": {
         "comment": "https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/HighResolutionTime/Overview.html#sec-extenstions-performance-interface"
       },
+      "onresourcetimingbufferfull": {
+        "support_level": "untriaged"
+      },
       "onwebkitresourcetimingbufferfull": {
         "comment": "http://www.w3c-test.org/webperf/specs/ResourceTiming/#performanceresourcetiming-methods",
         "support_level": "experimental"
@@ -7673,6 +7817,9 @@
       "oncopy": {},
       "oncut": {},
       "ondblclick": {},
+      "ondoubleclick": {
+        "support_level": "untriaged"
+      },
       "ondrag": {},
       "ondragend": {},
       "ondragenter": {},
@@ -10332,6 +10479,10 @@
     },
     "support_level": "stable"
   },
+  "ServiceWorker": {
+    "members": {},
+    "support_level": "untriaged"
+  },
   "ShadowRoot": {
     "comment": "https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#api-shadow-root",
     "members": {
@@ -10396,6 +10547,15 @@
       "appendBufferView": {
         "support_level": "untriaged"
       },
+      "appendByteBuffer": {
+        "support_level": "untriaged"
+      },
+      "appendStream": {
+        "support_level": "untriaged"
+      },
+      "appendTypedData": {
+        "support_level": "untriaged"
+      },
       "appendWindowEnd": {
         "support_level": "untriaged"
       },
@@ -10618,6 +10778,9 @@
     "comment": "https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#tts-section",
     "members": {
       "default": {},
+      "defaultValue": {
+        "support_level": "untriaged"
+      },
       "lang": {},
       "localService": {},
       "name": {},
@@ -12143,12 +12306,24 @@
       },
       "onDOMContentLoaded": {},
       "onabort": {},
+      "onanimationend": {
+        "support_level": "untriaged"
+      },
+      "onanimationiteration": {
+        "support_level": "untriaged"
+      },
+      "onanimationstart": {
+        "support_level": "untriaged"
+      },
       "onbeforeunload": {},
       "onblur": {},
       "oncanplay": {},
       "oncanplaythrough": {},
       "onchange": {},
       "onclick": {},
+      "oncontentloaded": {
+        "support_level": "untriaged"
+      },
       "oncontextmenu": {},
       "ondblclick": {},
       "ondevicemotion": {
@@ -12159,6 +12334,9 @@
         "comment": "http://dev.w3.org/geo/api/spec-source-orientation.html#devicemotion",
         "support_level": "experimental"
       },
+      "ondoubleclick": {
+        "support_level": "untriaged"
+      },
       "ondrag": {},
       "ondragend": {},
       "ondragenter": {},
diff --git a/tools/dom/idl/dart/dart.idl b/tools/dom/idl/dart/dart.idl
index 88ee11e..726ae66 100644
--- a/tools/dom/idl/dart/dart.idl
+++ b/tools/dom/idl/dart/dart.idl
@@ -92,12 +92,15 @@
 [Supplemental]
 interface HTMLOptionsCollection {
   [Suppressed] void add(optional HTMLOptionElement element, optional long before);
+  [Suppressed] void remove(HTMLOptionElement option); // Non standard.
 };
 
 [Supplemental]
 interface HTMLSelectElement {
   [Suppressed] void add([Default=Undefined] HTMLElement element, [Default=Undefined] HTMLElement before);
   [Suppressed, Custom] void remove();
+  [Suppressed] void remove(long index);
+  [Suppressed] void remove(HTMLOptionElement option); // Non standard.
 };
 
 [Supplemental]
@@ -132,6 +135,11 @@
 };
 
 [Supplemental]
+interface RTCPeerConnection {
+  [Suppressed, RaisesException] void addIceCandidate(RTCIceCandidate candidate);
+};
+
+[Supplemental]
 interface WebGLContextEvent {
   [Suppressed] void initEvent(optional DOMString eventTypeArg,
                               optional boolean canBubbleArg,
diff --git a/tools/dom/scripts/dartdomgenerator.py b/tools/dom/scripts/dartdomgenerator.py
index 10bd6fc..04923b2 100755
--- a/tools/dom/scripts/dartdomgenerator.py
+++ b/tools/dom/scripts/dartdomgenerator.py
@@ -69,11 +69,11 @@
   generator.AddMissingArguments(webkit_database)
 
   emitters = multiemitter.MultiEmitter()
-  renamer = HtmlRenamer(webkit_database)
-  type_registry = TypeRegistry(webkit_database, renamer)
   metadata = DartMetadata(
       os.path.join(current_dir, '..', 'dom.json'),
       os.path.join(current_dir, '..', 'docs', 'docs.json'))
+  renamer = HtmlRenamer(webkit_database, metadata)
+  type_registry = TypeRegistry(webkit_database, renamer)
 
   def RunGenerator(dart_libraries, dart_output_dir,
                    template_loader, backend_factory):
diff --git a/tools/dom/scripts/dartmetadata.py b/tools/dom/scripts/dartmetadata.py
index c0104c2..0dc0752 100644
--- a/tools/dom/scripts/dartmetadata.py
+++ b/tools/dom/scripts/dartmetadata.py
@@ -599,6 +599,11 @@
         annotations = ann2
     return annotations
 
+  def IsDeprecated(self, interface, member_name):
+    annotations = self._GetSupportLevelAnnotations(interface.id, member_name)
+    return any(
+        annotation.startswith('@deprecated') for annotation in annotations)
+
   def _GetCommonAnnotations(self, interface, member_name=None,
       source_member_name=None):
     if member_name:
diff --git a/tools/dom/scripts/htmldartgenerator.py b/tools/dom/scripts/htmldartgenerator.py
index 43114ee..8205dad 100644
--- a/tools/dom/scripts/htmldartgenerator.py
+++ b/tools/dom/scripts/htmldartgenerator.py
@@ -12,8 +12,8 @@
     TypeOrNothing, ConvertToFuture, GetCallbackInfo
 from copy import deepcopy
 from htmlrenamer import convert_to_future_members, custom_html_constructors, \
-    keep_overloaded_members, private_html_members, dom_private_html_members, renamed_html_members, \
-    renamed_overloads, removed_html_members
+    keep_overloaded_members, overloaded_and_renamed, private_html_members, \
+    renamed_html_members, renamed_overloads, removed_html_members
 import logging
 import monitored
 import sys
@@ -155,25 +155,33 @@
     """The IDL has a number of functions with the same name but that accept
     different types. This is fine for JavaScript, but results in vague type
     signatures for Dart. We rename some of these (by adding a new identical
-    operation with a different DartName), and leave the original version in a
-    few specific instances."""
+    operation with a different DartName), but leave the original version as
+    well in some cases."""
     potential_added_operations = set()
     operations_by_name = self._OperationsByName(interface)
     already_renamed = [operation.ext_attrs['DartName'] if 'DartName' in
         operation.ext_attrs else '' for operation in interface.operations]
 
+    added_operations = []
     for operation in interface.operations:
       full_operation_str = self._GetStringRepresentation(interface, operation)
       if (full_operation_str in renamed_overloads and
           renamed_overloads[full_operation_str] not in already_renamed):
-        dart_name = renamed_overloads[full_operation_str]
-        if not dart_name:
-          continue
+        if '%s.%s' % (interface.id, operation.id) in overloaded_and_renamed:
+          cloned_operation = deepcopy(operation)
+          cloned_operation.ext_attrs['DartName'] = renamed_overloads[
+              full_operation_str]
+          added_operations.append(cloned_operation)
+        else:
+          dart_name = renamed_overloads[full_operation_str]
+          if not dart_name:
+            continue
 
-        operation.ext_attrs['DartName'] = dart_name
-        potential_added_operations.add(operation.id)
+          operation.ext_attrs['DartName'] = dart_name
+          potential_added_operations.add(operation.id)
       self._EnsureNoMultipleTypeSignatures(interface, operation,
           operations_by_name)
+    interface.operations += added_operations
     self._AddDesiredOverloadedOperations(potential_added_operations, interface,
         operations_by_name)
 
@@ -201,18 +209,17 @@
         len(filter(lambda overload: overload.startswith(operation_str),
             renamed_overloads.keys())) == 0 and
         operation_str not in keep_overloaded_members and
+        operation_str not in overloaded_and_renamed and
         operation_str not in renamed_html_members and
         operation_str not in private_html_members and
-        operation_str not in dom_private_html_members and
         operation_str not in removed_html_members and
         operation.id != '__getter__' and
         operation.id != '__setter__' and
         operation.id != '__delete__'):
-      _logger.error('Multiple type signatures for %s.%s' % (
+      _logger.error('Multiple type signatures for %s.%s. Please file a bug with'
+          ' the dart:html team to determine if one of these functions should be'
+          ' renamed.' % (
           interface.id, operation.id))
-      raise Exception('Rename one of the methods in renamed_overloads or add it'
-          ' to  keep_overloaded_members.\n'
-          'Generation UNsuccessful.')
 
   def _GetStringRepresentation(self, interface, operation):
     """Given an IDLOperation, return a object-independent representation of the
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index 3d9f5a0..c819d95 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -156,15 +156,6 @@
   'WorkerGlobalScope.webkitResolveLocalFileSystemURL',
 ])
 
-# "Private" members in the form $dom_foo.
-# TODO(efortuna): Remove this set. This allows us to make the change of removing
-# $dom in installments instead of all at once, but the intent is to move all of
-# these either into private_html_members or remove them from this list entirely.
-dom_private_html_members = monitored.Set('htmlrenamer.private_html_members', [
-  'EventTarget.addEventListener',
-  'EventTarget.removeEventListener',
-])
-
 # Classes where we have customized constructors, but we need to keep the old
 # constructor for dispatch purposes.
 custom_html_constructors = monitored.Set(
@@ -181,6 +172,7 @@
   'AudioNode.connect',
   'CanvasRenderingContext2D.arc',
   'CanvasRenderingContext2D.drawImage',
+  'CanvasRenderingContext2D.getLineDash',
   'CSSStyleDeclaration.getPropertyValue',
   'CSSStyleDeclaration.setProperty',
   'CSSStyleDeclaration.var',
@@ -249,7 +241,6 @@
   'HTMLTableRowElement.insertCell',
   'HTMLTableSectionElement.insertRow',
   'HTMLTableSectionElement.rows',
-  'HTMLTemplateElement.content',
   'IDBCursor.delete',
   'IDBCursor.update',
   'IDBDatabase.createObjectStore',
@@ -323,11 +314,9 @@
   'UIEvent.layerY',
   'UIEvent.pageX',
   'UIEvent.pageY',
-  'WebGLRenderingContext.texImage2D',
   'WheelEvent.initWebKitWheelEvent',
   'WheelEvent.deltaX',
   'WheelEvent.deltaY',
-  'Window.createImageBitmap',
   'Window.getComputedStyle',
   'Window.clearInterval',
   'Window.clearTimeout',
@@ -363,7 +352,6 @@
     'SVGStopElement.offset': 'gradientOffset',
     'URL.createObjectURL': 'createObjectUrl',
     'URL.revokeObjectURL': 'revokeObjectUrl',
-    'WebGLRenderingContext.texSubImage2D': '_texSubImageImage2D',
     #'WorkerContext.webkitRequestFileSystem': '_requestFileSystem',
     #'WorkerContext.webkitRequestFileSystemSync': '_requestFileSystemSync',
 })
@@ -378,8 +366,6 @@
       'DOMString repetitionType)': 'createPatternFromImage',
   'DataTransferItemList.add(File file)': 'addFile',
   'DataTransferItemList.add(DOMString data, DOMString type)': 'addData',
-  'Document.createElement(DOMString tagName)': None,
-  'Document.createElementNS(DOMString namespaceURI, DOMString qualifiedName)': None,
   'FormData.append(DOMString name, Blob value, DOMString filename)':
       'appendBlob',
   'IDBDatabase.transaction(DOMStringList storeNames, DOMString mode)':
@@ -388,25 +374,11 @@
       'transactionList',
   'IDBDatabase.transaction(DOMString storeName, DOMString mode)':
       'transactionStore',
-  'ImageBitmapFactories.createImageBitmap(HTMLImageElement image)' : 'createImageBitmap0',
-  'ImageBitmapFactories.createImageBitmap(HTMLImageElement image, long sx, long sy, long sw, long sh)' : 'createImageBitmap1',
-  'ImageBitmapFactories.createImageBitmap(HTMLVideoElement video)' : 'createImageBitmap2',
-  'ImageBitmapFactories.createImageBitmap(HTMLVideoElement video, long sx, long sy, long sw, long sh)' : 'createImageBitmap3',
-  'ImageBitmapFactories.createImageBitmap(CanvasRenderingContext2D context)' : 'createImageBitmap4',
-  'ImageBitmapFactories.createImageBitmap(CanvasRenderingContext2D context, long sx, long sy, long sw, long sh)' : 'createImageBitmap5',
-  'ImageBitmapFactories.createImageBitmap(HTMLCanvasElement canvas)' : 'createImageBitmap6',
-  'ImageBitmapFactories.createImageBitmap(HTMLCanvasElement canvas, long sx, long sy, long sw, long sh)' : 'createImageBitmap7',
-  'ImageBitmapFactories.createImageBitmap(ImageData data)' : 'createImageBitmap8',
-  'ImageBitmapFactories.createImageBitmap(ImageData data, long sx, long sy, long sw, long sh)' : 'createImageBitmap9',
-  'ImageBitmapFactories.createImageBitmap(ImageBitmap bitmap)' : 'createImageBitmap10',
-  'ImageBitmapFactories.createImageBitmap(ImageBitmap bitmap, long sx, long sy, long sw, long sh)' : 'createImageBitmap11',
-  'ImageBitmapFactories.createImageBitmap(Blob blob)' : 'createImageBitmap12',
-  'ImageBitmapFactories.createImageBitmap(Blob blob, long sx, long sy, long sw, long sh)' : 'createImageBitmap13',
   'RTCDataChannel.send(ArrayBuffer data)': 'sendByteBuffer',
   'RTCDataChannel.send(ArrayBufferView data)': 'sendTypedData',
   'RTCDataChannel.send(Blob data)': 'sendBlob',
   'RTCDataChannel.send(DOMString data)': 'sendString',
-  'SourceBuffer.appendBuffer(ArrayBufferView data)': 'appendBufferView',
+  'SourceBuffer.appendBuffer(ArrayBufferView data)': 'appendTypedData',
   'URL.createObjectURL(MediaSource source)':
       'createObjectUrlFromSource',
   'URL.createObjectURL(WebKitMediaSource source)':
@@ -459,6 +431,8 @@
   'CanvasRenderingContext2D.putImageData',
   'CanvasRenderingContext2D.webkitPutImageDataHD',
   'DataTransferItemList.add',
+  'Document.createElement',
+  'Document.createElementNS',
   'HTMLInputElement.setRangeText',
   'HTMLTextAreaElement.setRangeText',
   'IDBDatabase.transaction',
@@ -468,6 +442,14 @@
   'XMLHttpRequest.send'
 ])
 
+overloaded_and_renamed = monitored.Set(
+    'htmldartgenerator.overloaded_and_renamed', [
+  'WebGLRenderingContext.texImage2D',
+  'WebGLRenderingContext.texSubImage2D',
+  'WebGLRenderingContext.bufferData',
+  'WebGLRenderingContext.bufferSubData',
+])
+
 for member in convert_to_future_members:
   if member in renamed_html_members:
     renamed_html_members[member] = '_' + renamed_html_members[member]
@@ -499,6 +481,7 @@
     'Window.call:blur',
     'Window.call:focus',
     'Window.clientInformation',
+    'Window.createImageBitmap',
     'Window.get:frames',
     'Window.get:length',
     'Window.on:beforeUnload',
@@ -602,6 +585,8 @@
     'Event.returnValue',
     'Event.srcElement',
     'EventSource.URL',
+    'FontFaceSet.load',
+    'FontFaceSet.ready',
     'HTMLAnchorElement.charset',
     'HTMLAnchorElement.coords',
     'HTMLAnchorElement.rev',
@@ -709,9 +694,12 @@
     'HTMLUListElement.compact',
     'HTMLUListElement.type',
     'Location.valueOf',
+    'MessageEvent.ports',
     'MessageEvent.webkitInitMessageEvent',
     'MouseEvent.x',
     'MouseEvent.y',
+    'Navigator.registerServiceWorker',
+    'Navigator.unregisterServiceWorker',
     'Node.compareDocumentPosition',
     'Node.get:DOCUMENT_POSITION_CONTAINED_BY',
     'Node.get:DOCUMENT_POSITION_CONTAINS',
@@ -767,8 +755,9 @@
 })
 
 class HtmlRenamer(object):
-  def __init__(self, database):
+  def __init__(self, database, metadata):
     self._database = database
+    self._metadata = metadata
 
   def RenameInterface(self, interface):
     if 'Callback' in interface.ext_attrs:
@@ -816,10 +805,6 @@
     if self._FindMatch(interface, member, member_prefix, private_html_members):
       if not target_name.startswith('_'):  # e.g. _svgClassName
         target_name = '_' + target_name
-    elif self._FindMatch(interface, member, member_prefix,
-        dom_private_html_members):
-      if not target_name.startswith('$dom_'):  # e.g. $dom_svgClassName
-        target_name = '$dom_' + target_name
 
     if not name and target_name.startswith('webkit'):
       target_name = member[len('webkit'):]
@@ -835,6 +820,11 @@
       return True
     if interface.id in _removed_html_interfaces:
       return True
+    metadata_member = member
+    if member_prefix == 'on:':
+      metadata_member = 'on' + metadata_member.lower()
+    if self._metadata.IsDeprecated(interface, metadata_member):
+      return True
     return False
 
   def ShouldSuppressInterface(self, interface):
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py
index 9c6a6a3..21deb41 100644
--- a/tools/dom/scripts/systemhtml.py
+++ b/tools/dom/scripts/systemhtml.py
@@ -25,7 +25,9 @@
     'AudioContext.createGain',
     'AudioContext.createScriptProcessor',
     'CanvasRenderingContext2D.drawImage',
+    'CanvasRenderingContext2D.fillText',
     'CanvasRenderingContext2D.lineDashOffset',
+    'CanvasRenderingContext2D.setLineDash',
     'Console.memory',
     'ConsoleBase.assertCondition',
     'ConsoleBase.clear',
@@ -78,8 +80,6 @@
     'URL.createObjectUrlFromStream',
     'URL.createObjectUrlFromBlob',
     'URL.revokeObjectURL',
-    'WebGLRenderingContext.texImage2D',
-    'WebGLRenderingContext.texSubImage2D',
     'WheelEvent.deltaMode',
     'WheelEvent.wheelDeltaX',
     'WheelEvent.wheelDeltaY',
diff --git a/tools/dom/scripts/systemnative.py b/tools/dom/scripts/systemnative.py
index 5aa06ee..1684988 100644
--- a/tools/dom/scripts/systemnative.py
+++ b/tools/dom/scripts/systemnative.py
@@ -51,9 +51,13 @@
   ('Navigator', 'vibrate'): 'NavigatorVibration',
   ('Navigator', 'appName'): 'NavigatorID',
   ('Navigator', 'appVersion'): 'NavigatorID',
+  ('Navigator', 'appCodeName'): 'NavigatorID',
   ('Navigator', 'platform'): 'NavigatorID',
+  ('Navigator', 'product'): 'NavigatorID',
   ('Navigator', 'userAgent'): 'NavigatorID',
   ('Navigator', 'onLine'): 'NavigatorOnLine',
+  ('Navigator', 'registerServiceWorker'): 'NavigatorServiceWorker',
+  ('Navigator', 'unregisterServiceWorker'): 'NavigatorServiceWorker',
   ('WorkerGlobalScope', 'crypto'): 'WorkerGlobalScopeCrypto',
   ('WorkerGlobalScope', 'indexedDB'): 'WorkerGlobalScopeIndexedDatabase',
   ('WorkerGlobalScope', 'webkitNotifications'): 'WorkerGlobalScopeNotifications',
@@ -864,7 +868,7 @@
 
     if requires_script_state:
       body_emitter.Emit(
-          '        ScriptState* currentState = ScriptState::current();\n'
+          '        ScriptState* currentState = DartUtilities::currentScriptState();\n'
           '        if (!currentState) {\n'
           '            exception = Dart_NewStringFromCString("Failed to retrieve a script state");\n'
           '            goto fail;\n'
@@ -879,7 +883,7 @@
           '            exception = Dart_NewStringFromCString("Failed to fetch domWindow");\n'
           '            goto fail;\n'
           '        }\n'
-          '        Document* document = domWindow->document();\n')
+          '        Document& document = *domWindow->document();\n')
 
     if needs_receiver:
       body_emitter.Emit(
@@ -891,7 +895,7 @@
       self._cpp_impl_includes.add('"ScriptCallStack.h"')
       body_emitter.Emit(
           '\n'
-          '        ScriptState* currentState = ScriptState::current();\n'
+          '        ScriptState* currentState = DartUtilities::currentScriptState();\n'
           '        if (!currentState) {\n'
           '            exception = Dart_NewStringFromCString("Failed to retrieve a script state");\n'
           '            goto fail;\n'
@@ -914,10 +918,7 @@
           '        Dart_Handle customArgument = Dart_GetNativeArgument(args, $INDEX);\n'
           '        RefPtr<ScriptArguments> scriptArguments(DartUtilities::createScriptArguments(customArgument, exception));\n'
           '        if (!scriptArguments)\n'
-          '            goto fail;\n'
-          '        RefPtr<ScriptCallStack> scriptCallStack(DartUtilities::createScriptCallStack());\n'
-          '        if (!scriptCallStack->size())\n'
-          '            return;\n',
+          '            goto fail;\n',
           INDEX=len(arguments) + 1)
 
     if needs_custom_element_callbacks:
diff --git a/tools/dom/src/EventStreamProvider.dart b/tools/dom/src/EventStreamProvider.dart
index 58c6cde..7f0b364 100644
--- a/tools/dom/src/EventStreamProvider.dart
+++ b/tools/dom/src/EventStreamProvider.dart
@@ -283,13 +283,13 @@
 
   void _tryResume() {
     if (_onData != null && !isPaused) {
-      _target.$dom_addEventListener(_eventType, _onData, _useCapture);
+      _target.addEventListener(_eventType, _onData, _useCapture);
     }
   }
 
   void _unlisten() {
     if (_onData != null) {
-      _target.$dom_removeEventListener(_eventType, _onData, _useCapture);
+      _target.removeEventListener(_eventType, _onData, _useCapture);
     }
   }
 
diff --git a/tools/dom/src/WrappedEvent.dart b/tools/dom/src/WrappedEvent.dart
index b701cef..af64fae 100644
--- a/tools/dom/src/WrappedEvent.dart
+++ b/tools/dom/src/WrappedEvent.dart
@@ -13,11 +13,6 @@
 
   bool get bubbles => wrapped.bubbles;
 
-  bool get cancelBubble => wrapped.bubbles;
-  void set cancelBubble(bool value) {
-    wrapped.cancelBubble = value;
-  }
-
   bool get cancelable => wrapped.cancelable;
 
   DataTransfer get clipboardData => wrapped.clipboardData;
diff --git a/tools/dom/src/dart2js_CustomElementSupport.dart b/tools/dom/src/dart2js_CustomElementSupport.dart
index 6f8aedb..0f941fd 100644
--- a/tools/dom/src/dart2js_CustomElementSupport.dart
+++ b/tools/dom/src/dart2js_CustomElementSupport.dart
@@ -4,8 +4,10 @@
 
 part of dart.dom.html;
 
-_callConstructor(constructor) {
+_callConstructor(constructor, interceptor) {
   return (receiver) {
+    setNativeSubclassDispatchRecord(receiver, interceptor);
+
     return JS('', '#(#)', constructor, receiver);
   };
 }
@@ -62,7 +64,9 @@
     throw new ArgumentError(type);
   }
 
-  var constructor = findConstructorForWebComponentType(type, 'created');
+  var interceptor = JS('=Object', '#.prototype', interceptorClass);
+
+  var constructor = findConstructorForNativeSubclassType(type, 'created');
   if (constructor == null) {
     throw new ArgumentError("$type has no constructor called 'created'");
   }
@@ -75,7 +79,18 @@
   if (baseClassName == null) {
     throw new ArgumentError(type);
   }
-  if (baseClassName == 'Element') baseClassName = 'HTMLElement';
+
+  if (extendsTagName == null) {
+    if (baseClassName != 'HTMLElement') {
+      throw new UnsupportedError('Class must provide extendsTag if base '
+          'native class is not HTMLElement');
+    }
+  } else {
+    if (!JS('bool', '(#.createElement(#) instanceof window[#])',
+        document, extendsTagName, baseClassName)) {
+      throw new UnsupportedError('extendsTag does not match base native class');
+    }
+  }
 
   var baseConstructor = JS('=Object', '#[#]', context, baseClassName);
 
@@ -83,7 +98,7 @@
 
   JS('void', '#.createdCallback = #', properties,
       JS('=Object', '{value: #}',
-          _makeCallbackMethod(_callConstructor(constructor))));
+          _makeCallbackMethod(_callConstructor(constructor, interceptor))));
   JS('void', '#.enteredViewCallback = #', properties,
       JS('=Object', '{value: #}', _makeCallbackMethod(_callEnteredView)));
   JS('void', '#.leftViewCallback = #', properties,
@@ -100,8 +115,6 @@
   var baseProto = JS('=Object', '#.prototype', baseConstructor);
   var proto = JS('=Object', 'Object.create(#, #)', baseProto, properties);
 
-  var interceptor = JS('=Object', '#.prototype', interceptorClass);
-
   setNativeSubclassDispatchRecord(proto, interceptor);
 
   var options = JS('=Object', '{prototype: #}', proto);
diff --git a/tools/dom/src/dart2js_Platform.dart b/tools/dom/src/dart2js_Platform.dart
index ea50a6a..5988011 100644
--- a/tools/dom/src/dart2js_Platform.dart
+++ b/tools/dom/src/dart2js_Platform.dart
@@ -18,17 +18,4 @@
    * error.
    */
   static final supportsSimd = false;
-
-  /**
-   * Upgrade all custom elements in the subtree which have not been upgraded.
-   *
-   * This is needed to cover timing scenarios which the custom element polyfill
-   * does not cover.
-   */
-  static void upgradeCustomElements(Node node) {
-    if (JS('bool', '(#.CustomElements && #.CustomElements.upgradeAll)',
-        window, window)) {
-      JS('', '#.CustomElements.upgradeAll(#)', window, node);
-    }
-  }
 }
diff --git a/tools/dom/src/dartium_Platform.dart b/tools/dom/src/dartium_Platform.dart
index 5ae23c9..a851cca 100644
--- a/tools/dom/src/dartium_Platform.dart
+++ b/tools/dom/src/dartium_Platform.dart
@@ -18,14 +18,4 @@
    * error.
    */
   static final supportsSimd = true;
-
-  /**
-   * Upgrade all custom elements in the subtree which have not been upgraded.
-   *
-   * This is needed to cover timing scenarios which the custom element polyfill
-   * does not cover.
-   */
-  static void upgradeCustomElements(Node node) {
-    // no-op, provided for dart2js polyfill.
-  }
 }
diff --git a/tools/dom/src/native_DOMImplementation.dart b/tools/dom/src/native_DOMImplementation.dart
index e650c6f..51e9ced 100644
--- a/tools/dom/src/native_DOMImplementation.dart
+++ b/tools/dom/src/native_DOMImplementation.dart
@@ -79,6 +79,15 @@
     return result;
   }
 
+  static List captureParsedStackTrace() {
+    try {
+      // Throwing an exception is the only way to generate a stack trace.
+      throw new Exception();
+    } catch (e, stackTrace) {
+      return parseStackTrace(stackTrace);
+    }
+  }
+
   static void populateMap(Map result, List list) {
     for (int i = 0; i < list.length; i += 2) {
       result[list[i]] = list[i + 1];
@@ -156,7 +165,11 @@
    * that does not expect REPL support.
    */
   static const _CONSOLE_API_SUPPORT_HEADER =
-      'with ((this && this.console && this.console._commandLineAPI) || {}) {\n';
+      'with ((console && console._commandLineAPI) || {}) {\n';
+
+  static bool expectsConsoleApi(String expression) {
+    return expression.indexOf(_CONSOLE_API_SUPPORT_HEADER) == 0;;
+  }
 
   /**
    * Takes an [expression] and a list of [local] variable and returns an
@@ -202,7 +215,7 @@
       args[arg] = value;
     }
 
-    if (expression.indexOf(_CONSOLE_API_SUPPORT_HEADER) == 0) {
+    if (expectsConsoleApi(expression)) {
       expression = expression.substring(expression.indexOf('\n') + 1);
       expression = expression.substring(0, expression.lastIndexOf('\n'));
 
@@ -410,9 +423,38 @@
       throw new UnsupportedError("Invalid custom element from $libName.");
     }
     var className = MirrorSystem.getName(cls.simpleName);
-    if (!cls.constructors.containsKey(new Symbol('$className.created'))) {
-      throw new UnsupportedError('Class is missing constructor $className.created');
+    var createdConstructor = cls.constructors[new Symbol('$className.created')];
+    if (createdConstructor == null) {
+      throw new UnsupportedError(
+          'Class is missing constructor $className.created');
     }
+
+    if (createdConstructor.parameters.length > 0) {
+      throw new UnsupportedError(
+          'Constructor $className.created must take zero arguments');
+    }
+
+    Symbol objectName = reflectClass(Object).qualifiedName;
+    bool isRoot(ClassMirror cls) =>
+        cls == null || cls.qualifiedName == objectName;
+    Symbol elementName = reflectClass(HtmlElement).qualifiedName;
+    bool isElement(ClassMirror cls) =>
+        cls != null && cls.qualifiedName == elementName;
+    ClassMirror superClass = cls.superclass;
+    ClassMirror nativeClass = _isBuiltinType(superClass) ? superClass : null;
+    while(!isRoot(superClass) && !isElement(superClass)) {
+      superClass = superClass.superclass;
+      if (nativeClass == null && _isBuiltinType(superClass)) {
+        nativeClass = superClass;
+      }
+    }
+    if (extendsTagName == null) {
+      if (nativeClass.reflectedType != HtmlElement) {
+        throw new UnsupportedError('Class must provide extendsTag if base '
+            'native class is not HTMLElement');
+      }
+    }
+
     _register(document, tag, type, extendsTagName);
   }
 
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index da290f4..394f526 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -53,7 +53,7 @@
     makeLeafDispatchRecord;
 import 'dart:_interceptors' show
     Interceptor, JSExtendableArray, findInterceptorConstructorForType,
-    findConstructorForWebComponentType, getNativeInterceptor,
+    findConstructorForNativeSubclassType, getNativeInterceptor,
     setDispatchProperty, findInterceptorForType;
 import 'dart:_isolate_helper' show IsolateNatives;
 import 'dart:_foreign_helper' show JS;
diff --git a/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate b/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate
index 032c8ae..28da4bb 100644
--- a/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate
+++ b/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate
@@ -22,23 +22,6 @@
   }
 $!MEMBERS
 
-  @deprecated
-  int get clientX => client.x;
-  @deprecated
-  int get clientY => client.y;
-  @deprecated
-  int get offsetX => offset.x;
-  @deprecated
-  int get offsetY => offset.y;
-  @deprecated
-  int get movementX => movement.x;
-  @deprecated
-  int get movementY => movement.y;
-  @deprecated
-  int get screenX => screen.x;
-  @deprecated
-  int get screenY => screen.y;
-
   @DomName('MouseEvent.clientX')
   @DomName('MouseEvent.clientY')
   Point get client => new Point(_clientX, _clientY);
diff --git a/tools/dom/templates/html/dartium/cpp_header.template b/tools/dom/templates/html/dartium/cpp_header.template
index 5dbc8bf..d3e9582 100644
--- a/tools/dom/templates/html/dartium/cpp_header.template
+++ b/tools/dom/templates/html/dartium/cpp_header.template
@@ -9,6 +9,8 @@
 
 #include "bindings/dart/DartDOMWrapper.h"
 $WEBCORE_INCLUDES
+// FIXME: We need this to access the WrapperTypeInfo.
+#include "V8$(INTERFACE).h"
 #include <dart_api.h>
 
 namespace WebCore {
diff --git a/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate b/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate
index 1a5631b..08146ec 100644
--- a/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate
+++ b/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate
@@ -253,11 +253,23 @@
 $endif
 
 $if DART2JS
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @SupportedBrowser(SupportedBrowser.IE, '11')
+  @Unstable()
   @DomName('CanvasRenderingContext2D.lineDashOffset')
+  // TODO(14316): Firefox has this functionality with mozDashOffset, but it
+  // needs to be polyfilled.
   num get lineDashOffset => JS('num',
       '#.lineDashOffset || #.webkitLineDashOffset', this, this);
 
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @SupportedBrowser(SupportedBrowser.IE, '11')
+  @Unstable()
   @DomName('CanvasRenderingContext2D.lineDashOffset')
+  // TODO(14316): Firefox has this functionality with mozDashOffset, but it
+  // needs to be polyfilled.
   void set lineDashOffset(num value) => JS('void',
       'typeof #.lineDashOffset != "undefined" ? #.lineDashOffset = # : '
       '#.webkitLineDashOffset = #', this, this, value, this, value);
@@ -265,5 +277,71 @@
   // TODO(amouravski): Add Dartium native methods for drawImage once we figure
   // out how to not break native bindings.
 $endif
+
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @SupportedBrowser(SupportedBrowser.IE, '11')
+  @Unstable()
+  @DomName('CanvasRenderingContext2D.getLineDash')
+  List<num> getLineDash() {
+    // TODO(14316): Firefox has this functionality with mozDash, but it's a bit
+    // different.
+$if DART2JS
+    if (JS('bool', '!!#.getLineDash', this)) {
+      return JS('List<num>', '#.getLineDash()', this);
+    } else if (JS('bool', '!!#.webkitLineDash', this)) {
+      return JS('List<num>', '#.webkitLineDash', this);
+    } 
+$else
+    var result = _getLineDash();
+    if (result == null) {
+      result = [];
+    }
+    return result;
+$endif
+  }
+
+$if DART2JS
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @SupportedBrowser(SupportedBrowser.IE, '11')
+  @Unstable()
+  @DomName('CanvasRenderingContext2D.setLineDash')
+  void setLineDash(List<num> dash) {
+    // TODO(14316): Firefox has this functionality with mozDash, but it's a bit
+    // different.
+    if (JS('bool', '!!#.setLineDash', this)) {
+      JS('void', '#.setLineDash(#)', this, dash);
+    } else if (JS('bool', '!!#.webkitLineDash', this)) {
+      JS('void', '#.webkitLineDash = #', this, dash);
+    }
+  }
+$endif
+
+$if DART2JS
+
+  /**
+   * Draws text to the canvas.
+   *
+   * The text is drawn starting at coordinates ([x], [y]).
+   * If [maxWidth] is provided and the [text] is computed to be wider than
+   * [maxWidth], then the drawn text is scaled down horizontally to fit.
+   *
+   * The text uses the current [CanvasRenderingContext2D.font] property for font
+   * options, such as typeface and size, and the current
+   * [CanvasRenderingContext2D.fillStyle] for style options such as color.
+   * The current [CanvasRenderingContext2D.textAlign] and
+   * [CanvasRenderingContext2D.textBaseLine] properties are also applied to the
+   * drawn text.
+   */
+  @DomName('CanvasRenderingContext2D.fillText')
+  void fillText(String text, num x, num y, [num maxWidth]) {
+    if (maxWidth != null) {
+      JS('void', '#.fillText(#, #, #, #)', this, text, x, y, maxWidth);
+    } else {
+      JS('void', '#.fillText(#, #, #)', this, text, x, y);
+    }
+  }
+$endif
 }
 
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 4f4241e..bd703e5 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -981,19 +981,6 @@
   }
 
 $if DART2JS
-  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
-$endif
-  Element _templateInstanceRef;
-
-  // Note: only used if `this is! TemplateElement`
-$if DART2JS
-  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
-$endif
-  DocumentFragment _templateContent;
-
-  bool _templateIsDecorated;
-
-$if DART2JS
   @DomName('Element.createShadowRoot')
   @SupportedBrowser(SupportedBrowser.CHROME, '25')
   @Experimental()
@@ -1010,133 +997,6 @@
       JS('ShadowRoot|Null', '#.shadowRoot || #.webkitShadowRoot', this, this);
 $endif
 
-
-  /**
-   * Gets the template this node refers to.
-   * This is only supported if [isTemplate] is true.
-   */
-  @Experimental()
-  Element get ref {
-    _ensureTemplate();
-
-    Element result = null;
-    var refId = attributes['ref'];
-    if (refId != null) {
-      var treeScope = this;
-      while (treeScope.parentNode != null) {
-        treeScope = treeScope.parentNode;
-      }
-
-      // Note: JS code tests that getElementById is present. We can't do that
-      // easily, so instead check for the types known to implement it.
-      if (treeScope is Document ||
-          treeScope is ShadowRoot ||
-          treeScope is svg.SvgSvgElement) {
-
-        result = treeScope.getElementById(refId);
-      }
-    }
-
-    if (result == null) {
-      result = _templateInstanceRef;
-      if (result == null) return this;
-    }
-
-    var nextRef = result.ref;
-    return nextRef != null ? nextRef : result;
-  }
-
-  /**
-   * Gets the content of this template.
-   * This is only supported if [isTemplate] is true.
-   */
-  @Experimental()
-  DocumentFragment get content {
-    _ensureTemplate();
-    return _templateContent;
-  }
-
-  /**
-   * Creates an instance of the template, using the provided model and optional
-   * binding delegate.
-   *
-   * This is only supported if [isTemplate] is true.
-   */
-  @Experimental()
-  DocumentFragment createInstance(model, [BindingDelegate delegate]) {
-    _ensureTemplate();
-    return TemplateElement.mdvPackage(this).createInstance(model, delegate);
-  }
-
-  /**
-   * The data model which is inherited through the tree.
-   * This is only supported if [isTemplate] is true.
-   */
-  @Experimental()
-  get model => TemplateElement.mdvPackage(this).model;
-
-  @Experimental()
-  void set model(value) {
-    _ensureTemplate();
-    TemplateElement.mdvPackage(this).model = value;
-  }
-
-  /**
-   * The binding delegate which is inherited through the tree. It can be used
-   * to configure custom syntax for `{{bindings}}` inside this template.
-   *
-   * This is only supported if [isTemplate] is true.
-   */
-  @Experimental()
-  BindingDelegate get bindingDelegate =>
-      TemplateElement.mdvPackage(this).bindingDelegate;
-
-  @Experimental()
-  void set bindingDelegate(BindingDelegate value) {
-    _ensureTemplate();
-    TemplateElement.mdvPackage(this).bindingDelegate = value;
-  }
-
-  // TODO(jmesserly): const set would be better
-  static const _TABLE_TAGS = const {
-    'caption': null,
-    'col': null,
-    'colgroup': null,
-    'tbody': null,
-    'td': null,
-    'tfoot': null,
-    'th': null,
-    'thead': null,
-    'tr': null,
-  };
-
-  bool get _isAttributeTemplate => attributes.containsKey('template') &&
-      (localName == 'option' || localName == 'optgroup' ||
-       _TABLE_TAGS.containsKey(localName));
-
-  /**
-   * Returns true if this node is a template.
-   *
-   * A node is a template if [tagName] is TEMPLATE, or the node has the
-   * 'template' attribute and this tag supports attribute form for backwards
-   * compatibility with existing HTML parsers. The nodes that can use attribute
-   * form are table elments (THEAD, TBODY, TFOOT, TH, TR, TD, CAPTION, COLGROUP
-   * and COL), OPTION, and OPTGROUP.
-   */
-  // TODO(jmesserly): this is not a public MDV API, but it seems like a useful
-  // place to document which tags our polyfill considers to be templates.
-  // Otherwise I'd be repeating it in several other places.
-  // See if we can replace this with a TemplateMixin.
-  @Experimental()
-  bool get isTemplate => tagName == 'TEMPLATE' || _isAttributeTemplate;
-
-  void _ensureTemplate() {
-    if (!isTemplate) {
-      throw new UnsupportedError('$this is not a template.');
-    }
-    TemplateElement.decorate(this);
-  }
-
   /**
    * Access this element's content position.
    *
@@ -1218,6 +1078,7 @@
    * This method is the Dart equivalent to jQuery's
    * [offset](http://api.jquery.com/offset/) method.
    */
+  @Experimental()
   Point get documentOffset => offsetTo(document.documentElement);
 
   /**
@@ -1231,6 +1092,7 @@
    * element is _not_ an offset parent or transitive offset parent to this
    * element, an [ArgumentError] is thrown.
    */
+  @Experimental()
   Point offsetTo(Element parent) {
     return Element._offsetToHelper(this, parent);
   }
@@ -1375,15 +1237,6 @@
   String get innerHtml => _innerHtml;
 
   /**
-   * For use while transitioning to the safe [innerHtml] or [setInnerHtml].
-   * Unsafe because it opens the app to cross-site scripting vulnerabilities.
-   */
-  @deprecated
-  void set unsafeInnerHtml(String html) {
-    _innerHtml = html;
-  }
-
-  /**
    * This is an ease-of-use accessor for event streams which should only be
    * used when an explicit accessor is not available.
    */
diff --git a/tools/dom/templates/html/impl/impl_EventTarget.darttemplate b/tools/dom/templates/html/impl/impl_EventTarget.darttemplate
index 1630878..5551a1e 100644
--- a/tools/dom/templates/html/impl/impl_EventTarget.darttemplate
+++ b/tools/dom/templates/html/impl/impl_EventTarget.darttemplate
@@ -54,10 +54,32 @@
 class ElementEvents extends Events {
   /* Raw event target. */
   final Element _ptr;
+  static final webkitEvents = {
+    'animationend' : 'webkitAnimationEnd', 
+    'animationiteration' : 'webkitAnimationIteration', 
+    'animationstart' : 'webkitAnimationStart', 
+    'fullscreenchange' : 'webkitfullscreenchange', 
+    'fullscreenerror' : 'webkitfullscreenerror',
+    'keyadded' : 'webkitkeyadded', 
+    'keyerror' : 'webkitkeyerror', 
+    'keymessage' : 'webkitkeymessage', 
+    'needkey' : 'webkitneedkey', 
+    'pointerlockchange' : 'webkitpointerlockchange', 
+    'pointerlockerror' : 'webkitpointerlockerror', 
+    'resourcetimingbufferfull' : 'webkitresourcetimingbufferfull', 
+    'transitionend': 'webkitTransitionEnd',
+    'speechchange' : 'webkitSpeechChange'
+  };
 
   ElementEvents(Element ptr) : this._ptr = ptr, super(ptr);
 
   Stream operator [](String type) {
+    if (webkitEvents.keys.contains(type.toLowerCase())) {
+      if (Device.isWebKit) {
+        return new _ElementEventStreamImpl(
+            _ptr, webkitEvents[type.toLowerCase()], false);
+      }
+    }
     return new _ElementEventStreamImpl(_ptr, type, false);
   }
 }
@@ -65,8 +87,7 @@
 /**
  * Base class for all browser objects that support events.
  *
- * Use the [on] property to add, and remove events (rather than
- * [$dom_addEventListener] and [$dom_removeEventListener]
+ * Use the [on] property to add, and remove events
  * for compile-time type checks and a more concise API.
  */
 $(ANNOTATIONS)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
diff --git a/tools/dom/templates/html/impl/impl_HTMLCanvasElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLCanvasElement.darttemplate
index 03c6da5..474aca9 100644
--- a/tools/dom/templates/html/impl/impl_HTMLCanvasElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLCanvasElement.darttemplate
@@ -14,9 +14,6 @@
   CanvasRenderingContext2D get context2D => getContext('2d');
 $endif
 
-  @deprecated
-  CanvasRenderingContext2D get context2d => this.context2D;
-
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.FIREFOX)
   @Experimental()
diff --git a/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate b/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
index 08e3709..2ff16e3 100644
--- a/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
@@ -105,14 +105,6 @@
     _title = value;
   }
 
-  @DomName('Document.webkitCancelFullScreen')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  void cancelFullScreen() {
-    _webkitCancelFullScreen();
-  }
-
   @DomName('Document.webkitExitFullscreen')
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.SAFARI)
@@ -147,12 +139,6 @@
   @Experimental()
   bool get hidden => _webkitHidden;
 
-  @DomName('Document.webkitIsFullScreen')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental()
-  bool get isFullScreen => _webkitIsFullScreen;
-
   @DomName('Document.webkitPointerLockElement')
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.SAFARI)
@@ -173,7 +159,7 @@
   String get visibilityState => _webkitVisibilityState;
 $endif
 
-  @Experimental
+  @Experimental()
   /**
    * Register a custom subclass of Element to be instantiatable by the DOM.
    *
@@ -252,12 +238,6 @@
   }
 $endif
 
-$if DART2JS
-  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
-$endif
-  // Note: used to polyfill <template>
-  Document _templateContentsOwner;
-
   @DomName('Document.visibilityChange')
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.FIREFOX)
diff --git a/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
index 1ba903c..98c7199 100644
--- a/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
@@ -6,291 +6,10 @@
 
 part of $LIBRARYNAME;
 
-/**
- * Model-Driven Views (MDV)'s native features enables a wide-range of use cases,
- * but (by design) don't attempt to implement a wide array of specialized
- * behaviors.
- *
- * Enabling these features in MDV is a matter of implementing and registering an
- * MDV Custom Syntax. A Custom Syntax is an object which contains one or more
- * delegation functions which implement specialized behavior. This object is
- * registered with MDV via [Element.bindingDelegate]:
- *
- *
- * HTML:
- *     <template bind>
- *       {{ What!Ever('crazy')->thing^^^I+Want(data) }}
- *     </template>
- *
- * Dart:
- *     class MySyntax extends BindingDelegate {
- *       getBinding(model, path, name, node) {
- *         // The magic happens here!
- *       }
- *     }
- *     ...
- *     query('template').bindingDelegate = new MySyntax();
- *     query('template').model = new MyModel();
- *
- * See <https://github.com/polymer-project/mdv/blob/master/docs/syntax.md> for
- * more information about Custom Syntax.
- */
-// TODO(jmesserly): move this type to the MDV package? Two issues: we'd lose
-// type annotation on [Element.bindingDelegate], and "mdv" is normally imported
-// with a prefix.
-@Experimental()
-abstract class BindingDelegate {
-  /**
-   * This syntax method allows for a custom interpretation of the contents of
-   * mustaches (`{{` ... `}}`).
-   *
-   * When a template is inserting an instance, it will invoke this method for
-   * each mustache which is encountered. The function is invoked with four
-   * arguments:
-   *
-   * - [model]: The data context for which this instance is being created.
-   * - [path]: The text contents (trimmed of outer whitespace) of the mustache.
-   * - [name]: The context in which the mustache occurs. Within element
-   *   attributes, this will be the name of the attribute. Within text,
-   *   this will be 'text'.
-   * - [node]: A reference to the node to which this binding will be created.
-   *
-   * If the method wishes to handle binding, it is required to return an object
-   * which has at least a `value` property that can be observed. If it does,
-   * then MDV will call [Node.bind on the node:
-   *
-   *     node.bind(name, retval, 'value');
-   *
-   * If the 'getBinding' does not wish to override the binding, it should return
-   * null.
-   */
-  // TODO(jmesserly): I had to remove type annotations from "name" and "node"
-  // Normally they are String and Node respectively. But sometimes it will pass
-  // (int name, CompoundBinding node). That seems very confusing; we may want
-  // to change this API.
-  getBinding(model, String path, name, node) => null;
-
-  /**
-   * This syntax method allows a syntax to provide an alterate model than the
-   * one the template would otherwise use when producing an instance.
-   *
-   * When a template is about to create an instance, it will invoke this method
-   * The function is invoked with two arguments:
-   *
-   * - [template]: The template element which is about to create and insert an
-   *   instance.
-   * - [model]: The data context for which this instance is being created.
-   *
-   * The template element will always use the return value of `getInstanceModel`
-   * as the model for the new instance. If the syntax does not wish to override
-   * the value, it should simply return the `model` value it was passed.
-   */
-  getInstanceModel(Element template, model) => model;
-}
-
 @Experimental()
 $(ANNOTATIONS)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
 $!MEMBERS
 
-  // For real TemplateElement use the actual DOM .content field instead of
-  // our polyfilled expando.
-  @Experimental()
-  DocumentFragment get content => _content;
-
-
-  /**
-   * The MDV package, if available.
-   *
-   * This can be used to initialize MDV support via:
-   *
-   *     import 'dart:html';
-   *     import 'package:mdv/mdv.dart' as mdv;
-   *     main() {
-   *       mdv.initialize();
-   *     }
-   */
-  static Function mdvPackage = (node) {
-    throw new UnsupportedError("The MDV package is not available. "
-        "You can enable it with `import 'package:mdv/mdv.dart' as mdv;` and "
-        "`mdv.initialize()`");
-  };
-
-  /**
-   * Ensures proper API and content model for template elements.
-   *
-   * [instanceRef] can be used to set the [Element.ref] property of [template],
-   * and use the ref's content will be used as source when createInstance() is
-   * invoked.
-   *
-   * Returns true if this template was just decorated, or false if it was
-   * already decorated.
-   */
-  @Experimental()
-  static bool decorate(Element template, [Element instanceRef]) {
-    // == true check because it starts as a null field.
-    if (template._templateIsDecorated == true) return false;
-
-    _injectStylesheet();
-
-    var templateElement = template;
-    templateElement._templateIsDecorated = true;
-    var isNative = templateElement is TemplateElement;
-    var bootstrapContents = isNative;
-    var liftContents = !isNative;
-    var liftRoot = false;
-
-    if (!isNative && templateElement._isAttributeTemplate) {
-      if (instanceRef != null) {
-        // TODO(jmesserly): this is just an assert in MDV.
-        throw new ArgumentError('instanceRef should not be supplied for '
-            'attribute templates.');
-      }
-      templateElement = _extractTemplateFromAttributeTemplate(template);
-      templateElement._templateIsDecorated = true;
-      isNative = templateElement is TemplateElement;
-      liftRoot = true;
-     }
-
-    if (!isNative) {
-      var doc = _getTemplateContentsOwner(templateElement.document);
-      templateElement._templateContent = doc.createDocumentFragment();
-    }
-
-    if (instanceRef != null) {
-      // template is contained within an instance, its direct content must be
-      // empty
-      templateElement._templateInstanceRef = instanceRef;
-    } else if (liftContents) {
-      _liftNonNativeChildrenIntoContent(templateElement, template, liftRoot);
-    } else if (bootstrapContents) {
-      bootstrap(templateElement.content);
-    }
-
-    return true;
-  }
-
-  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
-  static Document _getTemplateContentsOwner(HtmlDocument 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.lastChild != null) {
-        d.lastChild.remove();
-      }
-      doc._templateContentsOwner = d;
-    }
-    return d;
-  }
-
-  // For non-template browsers, the parser will disallow <template> in certain
-  // locations, so we allow "attribute templates" which combine the template
-  // element with the top-level container node of the content, e.g.
-  //
-  //   <tr template repeat="{{ foo }}"" class="bar"><td>Bar</td></tr>
-  //
-  // becomes
-  //
-  //   <template repeat="{{ foo }}">
-  //   + #document-fragment
-  //     + <tr class="bar">
-  //       + <td>Bar</td>
-  //
-  static Element _extractTemplateFromAttributeTemplate(Element el) {
-    var template = el.document.createElement('template');
-    el.parentNode.insertBefore(template, el);
-
-    for (var name in el.attributes.keys.toList()) {
-      switch (name) {
-        case 'template':
-          el.attributes.remove(name);
-          break;
-        case 'repeat':
-        case 'bind':
-        case 'ref':
-          template.attributes[name] = el.attributes.remove(name);
-          break;
-      }
-    }
-
-    return template;
-  }
-
-  static void _liftNonNativeChildrenIntoContent(Element template, Element el,
-      bool useRoot) {
-
-    var content = template.content;
-    if (useRoot) {
-      content.append(el);
-      return;
-    }
-
-    var child;
-    while ((child = el.firstChild) != null) {
-      content.append(child);
-    }
-  }
-
-  /**
-   * This used to decorate recursively all templates from a given node.
-   *
-   * By default [decorate] will be called on templates lazily when certain
-   * properties such as [model] are accessed, but it can be run eagerly to
-   * decorate an entire tree recursively.
-   */
-  // TODO(rafaelw): Review whether this is the right public API.
-  @Experimental()
-  static void bootstrap(Node content) {
-    void _bootstrap(template) {
-      if (!TemplateElement.decorate(template)) {
-        bootstrap(template.content);
-      }
-    }
-
-    // Need to do this first as the contents may get lifted if |node| is
-    // template.
-    // TODO(jmesserly): content is DocumentFragment or Element
-    var descendents =
-        (content as dynamic).querySelectorAll(_allTemplatesSelectors);
-    if (content is Element && (content as Element).isTemplate) {
-      _bootstrap(content);
-    }
-
-    descendents.forEach(_bootstrap);
-  }
-
-  static final String _allTemplatesSelectors =
-      'template, option[template], optgroup[template], ' +
-      Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", ");
-
-  static bool _initStyles;
-
-  static void _injectStylesheet() {
-    if (_initStyles == true) return;
-    _initStyles = true;
-
-    var style = new StyleElement();
-    style.text = r'''
-template,
-thead[template],
-tbody[template],
-tfoot[template],
-th[template],
-tr[template],
-td[template],
-caption[template],
-colgroup[template],
-col[template],
-option[template] {
-  display: none;
-}''';
-    document.head.append(style);
-  }
-
   /**
    * An override to place the contents into content rather than as child nodes.
    *
diff --git a/tools/dom/templates/html/impl/impl_Node.darttemplate b/tools/dom/templates/html/impl/impl_Node.darttemplate
index 7fa868c..1220467 100644
--- a/tools/dom/templates/html/impl/impl_Node.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Node.darttemplate
@@ -182,27 +182,6 @@
   Node operator[](int index) => _this.childNodes[index];
 }
 
-/** Information about the instantiated template. */
-class TemplateInstance {
-  // TODO(rafaelw): firstNode & lastNode should be read-synchronous
-  // in cases where script has modified the template instance boundary.
-
-  /** The first node of this template instantiation. */
-  final Node firstNode;
-
-  /**
-   * The last node of this template instantiation.
-   * This could be identical to [firstNode] if the template only expanded to a
-   * single node.
-   */
-  final Node lastNode;
-
-  /** The model used to instantiate the template. */
-  final model;
-
-  TemplateInstance(this.firstNode, this.lastNode, this.model);
-}
-
 
 $(ANNOTATIONS)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
 
@@ -280,52 +259,6 @@
    */
   String toString() => nodeValue == null ? super.toString() : nodeValue;
 
-
-  /**
-   * Creates a binding to the attribute [name] to the [path] of the [model].
-   *
-   * This can be overridden by custom elements to provide the binding used in
-   * [Node.bind]. This will only create the binding; it will not add it to
-   * [bindings].
-   *
-   * You should not need to call this directly except from [Node.bind].
-   */
-  @Experimental()
-  createBinding(String name, model, String path) =>
-      TemplateElement.mdvPackage(this).createBinding(name, model, path);
-
-  /**
-   * Binds the attribute [name] to the [path] of the [model].
-   * Path is a String of accessors such as `foo.bar.baz`.
-   * Returns the `NodeBinding` instance.
-   */
-  @Experimental()
-  bind(String name, model, String path) =>
-      TemplateElement.mdvPackage(this).bind(name, model, path);
-
-  /** Unbinds the attribute [name]. */
-  @Experimental()
-  void unbind(String name) {
-    TemplateElement.mdvPackage(this).unbind(name);
-  }
-
-  /** Unbinds all bound attributes. */
-  @Experimental()
-  void unbindAll() {
-    TemplateElement.mdvPackage(this).unbindAll();
-  }
-
-  /** Gets the data bindings that are associated with this node. */
-  @Experimental()
-  Map<String, dynamic> get bindings =>
-      TemplateElement.mdvPackage(this).bindings;
-
-  /** Gets the template instance that instantiated this node, if any. */
-  @Experimental()
-  TemplateInstance get templateInstance =>
-      TemplateElement.mdvPackage(this).templateInstance;
-
-
   /**
    * Use ownerDocument instead.
    */
diff --git a/tools/dom/templates/html/impl/impl_TouchList.darttemplate b/tools/dom/templates/html/impl/impl_TouchList.darttemplate
index d984852..06c7b67 100644
--- a/tools/dom/templates/html/impl/impl_TouchList.darttemplate
+++ b/tools/dom/templates/html/impl/impl_TouchList.darttemplate
@@ -10,6 +10,7 @@
   /// 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.
-  factory $CLASSNAME() => document._createTouchList();
+  // TODO(5760): createTouchList now uses varargs.
+  factory $CLASSNAME() => null;//document._createTouchList();
 $!MEMBERS
 }
diff --git a/tools/dom/templates/html/impl/impl_UIEvent.darttemplate b/tools/dom/templates/html/impl/impl_UIEvent.darttemplate
index 034a510..91e96b2 100644
--- a/tools/dom/templates/html/impl/impl_UIEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_UIEvent.darttemplate
@@ -25,16 +25,6 @@
   }
 $!MEMBERS
 
-  @deprecated
-  int get layerX => layer.x;
-  @deprecated
-  int get layerY => layer.y;
-
-  @deprecated
-  int get pageX => page.x;
-  @deprecated
-  int get pageY => page.y;
-
   @DomName('UIEvent.layerX')
   @DomName('UIEvent.layerY')
   Point get layer => new Point(_layerX, _layerY);
diff --git a/tools/dom/templates/html/impl/impl_WebGLRenderingContext.darttemplate b/tools/dom/templates/html/impl/impl_WebGLRenderingContext.darttemplate
index 3b233f3..d04c3bb 100644
--- a/tools/dom/templates/html/impl/impl_WebGLRenderingContext.darttemplate
+++ b/tools/dom/templates/html/impl/impl_WebGLRenderingContext.darttemplate
@@ -16,14 +16,13 @@
    * To use [texImage2d] with a TypedData object, use [texImage2dTyped].
    *
    */
-  @DomName('WebGLRenderingContext.texImage2D')
 $if DART2JS
   @JSName('texImage2D')
-  void texImage2D(int targetTexture, int levelOfDetail, int internalFormat,
-      int format, int type, data) native;
+  void texImage2DUntyped(int targetTexture, int levelOfDetail, 
+      int internalFormat, int format, int type, data) native;
 $else
-  void texImage2D(int targetTexture, int levelOfDetail, int internalFormat,
-      int format, int type, data) {
+  void texImage2DUntyped(int targetTexture, int levelOfDetail, 
+      int internalFormat, int format, int type, data) {
     if (data is ImageElement) {
       texImage2DImage(targetTexture, levelOfDetail, internalFormat, format,
           type, data);
@@ -51,7 +50,7 @@
 $else
   void texImage2DTyped(int targetTexture, int levelOfDetail, int internalFormat,
       int width, int height, int border, int format, int type, TypedData data) {
-    _texImage2D(targetTexture, levelOfDetail, internalFormat,
+    texImage2D(targetTexture, levelOfDetail, internalFormat,
         width, height, border, format, type, data);
   }
 $endif
@@ -65,15 +64,14 @@
    * To use [texSubImage2d] with a TypedData object, use [texSubImage2dTyped].
    *
    */
-  @DomName('WebGLRenderingContext.texSubImage2D')
 $if DART2JS
   @JSName('texSubImage2D')
-  void texSubImage2D(int targetTexture, int levelOfDetail, int internalFormat,
-      int format, int type, data) native;
+  void texSubImage2DUntyped(int targetTexture, int levelOfDetail,
+      int internalFormat, int format, int type, data) native;
 $else
-  void texSubImage2D(int targetTexture, int levelOfDetail, int internalFormat,
-      int format, int type, data) {
-    _texSubImage2D(targetTexture, levelOfDetail, internalFormat,
+  void texSubImage2DUntyped(int targetTexture, int levelOfDetail, 
+      int internalFormat, int format, int type, data) {
+    texSubImage2D(targetTexture, levelOfDetail, internalFormat,
         format, type, data);
   }
 $endif
@@ -90,7 +88,7 @@
   void texSubImage2DTyped(int targetTexture, int levelOfDetail,
       int internalFormat, int width, int height, int border, int format,
       int type, TypedData data) {
-    _texSubImage2D(targetTexture, levelOfDetail, internalFormat,
+    texSubImage2D(targetTexture, levelOfDetail, internalFormat,
         width, height, border, format, type, data);
   }
 $endif
diff --git a/tools/dom/templates/html/impl/impl_Window.darttemplate b/tools/dom/templates/html/impl/impl_Window.darttemplate
index 7874d5c..a45122a 100644
--- a/tools/dom/templates/html/impl/impl_Window.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Window.darttemplate
@@ -292,21 +292,6 @@
 $endif
 }
 
-/**
- * Event object that is fired before the window is closed.
- *
- * The standard window close behavior can be prevented by setting the
- * [returnValue]. This will display a dialog to the user confirming that they
- * want to close the page.
- */
-abstract class BeforeUnloadEvent implements Event {
-  /**
-   * If set to a non-null value, a dialog will be presented to the user
-   * confirming that they want to close the page.
-   */
-  String returnValue;
-}
-
 class _BeforeUnloadEvent extends _WrappedEvent implements BeforeUnloadEvent {
   String _returnValue;
 
diff --git a/tools/generate_projects.py b/tools/generate_projects.py
deleted file mode 100755
index 8f9d796..0000000
--- a/tools/generate_projects.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-import os
-import sys
-import platform
-
-def NormJoin(path1, path2):
-  return os.path.normpath(os.path.join(path1, path2))
-
-
-def GetProjectGypFile(project_name):
-  project_file = os.path.join(project_name, 'dart-%s.gyp' % project_name)
-  if not os.path.exists(project_file):
-    sys.stderr.write('%s does not exist\n' % project_file)
-    project_file = os.path.join(project_name, 'dart.gyp')
-  return project_file
-
-dart_src = NormJoin(os.path.dirname(sys.argv[0]), os.pardir)
-project_src = sys.argv[1]
-gyp_pylib = os.path.join(dart_src, 'third_party', 'gyp', 'pylib')
-
-if __name__ == '__main__':
-  # If this script is invoked with the -fmake option, we assume that
-  # it is being run automatically via a project Makefile. That can be
-  # problematic (because GYP is really bad at setting up the paths
-  # correctly), so we try to run "gclient runhooks" instead.
-  if '-fmake' in sys.argv:
-    try:
-      sys.exit(os.execvp("gclient", ["gclient", "runhooks"]))
-    except OSError:
-      # Sometimes gclient is not on the PATH. Let the user know that
-      # he must run "gclient runhooks" manually.
-      sys.stderr.write('Error: GYP files are out of date.\n')
-      sys.stderr.write('\n\n*** Please run "gclient runhooks" ***\n\n\n')
-      sys.exit(1)
-
-
-# Add gyp to the imports and if needed get it from the third_party location
-# inside the standalone dart gclient checkout.
-try:
-  import gyp
-except ImportError, e:
-  sys.path.append(os.path.abspath(gyp_pylib))
-  import gyp
-
-
-if __name__ == '__main__':
-  # Make our own location absolute as it is stored in Makefiles.
-  sys.argv[0] = os.path.abspath(sys.argv[0])
-
-  # Add any extra arguments. Needed by compiler/dart.gyp to build v8.
-  args = sys.argv[2:]
-
-  args += ['--depth', project_src]
-  args += ['-I', './tools/gyp/common.gypi']
-
-  if platform.system() == 'Linux':
-    # We need to fiddle with toplevel-dir to work around a GYP bug
-    # that breaks building v8 from compiler/dart.gyp.
-    args += ['--toplevel-dir', os.curdir]
-    args += ['--generator-output', project_src]
-  else:
-    # On at least the Mac, the toplevel-dir should be where the
-    # sources are. Otherwise, Xcode won't show sources correctly.
-    args += ['--toplevel-dir', project_src]
-
-  if sys.platform == 'win32':
-    # Generate Visual Studio 2008 compatible files by default.
-    if not os.environ.get('GYP_MSVS_VERSION'):
-      args.extend(['-G', 'msvs_version=2008'])
-
-  # Change into the dart directory as we want the project to be rooted here.
-  # Also, GYP is very sensitive to exacly from where it is being run.
-  os.chdir(dart_src)
-
-  args += [GetProjectGypFile(project_src)]
-
-  # Generate the projects.
-  sys.exit(gyp.main(args))
diff --git a/tools/gyp/common.gypi b/tools/gyp/common.gypi
deleted file mode 100644
index e7ac207..0000000
--- a/tools/gyp/common.gypi
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-# A set of variables needed to build some of the Chrome based subparts of the
-# Dash project. This is in no way a complete list of variables being defined
-# by Chrome, but just the minimally needed subset.
-
-# Note: this file is similar to all.gypi, but is used when running gyp
-# from subproject directories.  This is deprecated, but still supported.
-{
-  'variables': {
-    'library': 'static_library',
-    'component': 'static_library',
-    'target_arch': 'ia32',
-    # Flag that tells us whether to build native support for dart:io.
-    'dart_io_support': 1,
-  },
-  'conditions': [
-    [ 'OS=="linux"', {
-      'target_defaults': {
-        'ldflags': [ '-pthread', ],
-      },
-    }],
-    [ 'OS=="win"', {
-      'target_defaults': {
-        'msvs_cygwin_dirs': ['<(DEPTH)/../third_party/cygwin'],
-      },
-      'includes': [
-        'msvs.gypi',
-      ],
-    }],
-    [ 'OS=="mac"', {
-      'includes': [
-        'xcode.gypi',
-      ],
-    }],
-  ],
-  'includes': [
-    'configurations.gypi',
-  ],
-}
diff --git a/tools/gyp_dart.py b/tools/gyp_dart.py
index d3f12a8..8bc3984 100644
--- a/tools/gyp_dart.py
+++ b/tools/gyp_dart.py
@@ -18,8 +18,17 @@
   return process.returncode
 
 def main():
+  component = 'all'
+  if len(sys.argv) == 2:
+    component = sys.argv[1]
+
+  component_gyp_files = {
+    'all' : 'dart/dart.gyp',
+    'runtime' : 'dart/runtime/dart-runtime.gyp',
+  }
   args = ['python', 'dart/third_party/gyp/gyp_main.py',
-          '--depth=dart', '-Idart/tools/gyp/all.gypi', 'dart/dart.gyp']
+          '--depth=dart', '-Idart/tools/gyp/all.gypi',
+          component_gyp_files[component]]
 
   if sys.platform == 'win32':
     # Generate Visual Studio 2010 compatible files by default.
diff --git a/tools/make_links.py b/tools/make_links.py
index 66f94e6..1893f2d 100644
--- a/tools/make_links.py
+++ b/tools/make_links.py
@@ -10,12 +10,16 @@
 SOURCE ends with .../lib, the lib suffix is ignored when determining
 the name of the target link.
 
+Before creating any links, the old entries of the TARGET directory will be
+removed.
+
 Usage:
   python tools/make_links.py OPTIONS TARGET SOURCES...
 '''
 
 import optparse
 import os
+import shutil
 import subprocess
 import sys
 import utils
@@ -53,12 +57,23 @@
     if not os.path.exists(dir_name):
       os.mkdir(dir_name)
     open(options.timestamp_file, 'w').close()
-  
+
 
 def main(argv):
   (options, args) = get_options()
   target = os.path.relpath(args[0])
-  if not os.path.exists(target):
+  if os.path.exists(target):
+    # If the packages directory already exists, delete the current links inside
+    # it. This is necessary, otherwise we can end up having links in there
+    # pointing to directories which no longer exist (on incremental builds).
+    for link in os.listdir(target):
+      if utils.GuessOS() == 'win32':
+        # It seems like python on windows is treating pseudo symlinks to
+        # directories as directories.
+        os.rmdir(os.path.join(target, link))
+      else:
+        os.remove(os.path.join(target, link))
+  else:
     os.makedirs(target)
   for source in args[1:]:
     # Assume the source directory is named ".../NAME/lib".
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index c918b77..d62a33e 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -988,7 +988,7 @@
         // If necessary, run the Polymer deploy steps.
         // TODO(jmesserly): this should be generalized for any tests that
         // require Pub deploy, not just polymer.
-        if (customHtml.readAsStringSync().contains('polymer/init.dart')) {
+        if (customHtml.readAsStringSync().contains('<!--polymer-test')) {
           if (compiler != 'none') {
             commands.add(_polymerDeployCommand(
                 customHtmlPath, tempDir, optionsFromFile));
@@ -1191,6 +1191,7 @@
     args..add('package:polymer/deploy.dart')
         ..add('--test')..add(inputFile)
         ..add('--out')..add(outputDir);
+    if (configuration['csp']) args.add('--csp');
 
     return CommandBuilder.instance.getCommand(
         'polymer_deploy', vmFileName, args, configurationDir);