Version 1.2.0-dev.5.0

svn merge -r 32420:32598 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@32601 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..49c312f
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,29 @@
+# Below is a list of people and organizations that have contributed
+# to the Dart project. Names should be added to the list like so:
+#
+#   Name/Organization <email address>
+
+Google Inc.
+
+Ola Martin Bini <ola.bini@gmail.com>
+Michael Haubenwallner <michael.haubenwallner@gmail.com>
+Ladislav Thon <ladicek@gmail.com>
+John Evans <prujohn@gmail.com>
+Lajos Koszti <ajnasz@ajnasz.hu>
+Kevin Moore <kevmoo@j832.com>
+Austin Cummings <austincummings95@gmail.com>
+Alexander Aprelev <aprelev@gmail.com>
+Christopher Stone <chris.stone@gmail.com>
+Kevin Kellogg <kelloggk@gmail.com>
+Matthew Butler <butler.matthew@gmail.com>
+Andy Trevorah <a.trevorah@gmail.com>
+Jingwen Ou <jingweno@gmail.com>
+Chris Strom <chris.eee@gmail.com>
+Adam Singer <financeCoding@gmail.com>
+Chris Buckett <chrisbuckett@gmail.com>
+Thiago Farina <tfarina@chromium.org>
+Sami Ylönen <sami.ylonen@gmail.com>
+David Gomez <irisindigo@gmail.com>
+Nikolaus Graf <nik@blossom.io>
+Alexandre Ardhuin <alexandre.ardhuin@gmail.com>
+Victor Berchet <victor.berchet@gmail.com>
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..7af3211
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,51 @@
+This license applies to all parts of Dart that are not externally
+maintained libraries. The external maintained libraries used by
+Dart are:
+
+7-Zip - in third_party/7zip
+JSCRE - in runtime/third_party/jscre
+Ant - in third_party/apache_ant
+args4j - in third_party/args4j
+bzip2 - in third_party/bzip2
+Commons IO - in third_party/commons-io
+Commons Lang in third_party/commons-lang
+dromaeo - in samples/third_party/dromaeo
+Eclipse - in third_party/eclipse
+gsutil - in third_party/gsutil
+Guava - in third_party/guava
+hamcrest - in third_party/hamcrest
+Httplib2 - in samples/third_party/httplib2
+JSON - in third_party/json
+JUnit - in third_party/junit
+Oauth - in samples/third_party/oauth2client
+weberknecht - in third_party/weberknecht
+fest - in third_party/fest
+mockito - in third_party/mockito
+
+The libraries may have their own licenses; we recommend you read them,
+as their terms may differ from the terms below.
+
+Copyright 2012, the Dart project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+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.
diff --git a/PATENTS b/PATENTS
new file mode 100644
index 0000000..6954196
--- /dev/null
+++ b/PATENTS
@@ -0,0 +1,23 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Dart Project.
+
+Google hereby grants to you a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this
+section) patent license to make, have made, use, offer to sell, sell,
+import, transfer, and otherwise run, modify and propagate the contents
+of this implementation of Dart, where such license applies only to
+those patent claims, both currently owned by Google and acquired in
+the future, licensable by Google that are necessarily infringed by
+this implementation of Dart. This grant does not include claims that
+would be infringed only as a consequence of further modification of
+this implementation. If you or your agent or exclusive licensee
+institute or order or agree to the institution of patent litigation
+against any entity (including a cross-claim or counterclaim in a
+lawsuit) alleging that this implementation of Dart or any code
+incorporated within this implementation of Dart constitutes direct or
+contributory patent infringement, or inducement of patent
+infringement, then any patent rights granted to you under this License
+for this implementation of Dart shall terminate as of the date such
+litigation is filed.
diff --git a/dart.gyp b/dart.gyp
index 0ed89c0..3a4b1ec 100644
--- a/dart.gyp
+++ b/dart.gyp
@@ -40,6 +40,7 @@
         'runtime/dart-runtime.gyp:dart',
         'utils/compiler/compiler.gyp:dart2js',
         'utils/pub/pub.gyp:pub',
+        'dartfmt',
         'analyzer',
       ],
       'actions': [
@@ -54,6 +55,7 @@
             '<(SHARED_INTERMEDIATE_DIR)/utils_wrapper.dart.snapshot',
             '<(SHARED_INTERMEDIATE_DIR)/pub.dart.snapshot',
             '<(PRODUCT_DIR)/dartanalyzer/dartanalyzer.jar',
+            '<(SHARED_INTERMEDIATE_DIR)/dartfmt.dart.snapshot',
             'tools/VERSION'
           ],
           'outputs': [
@@ -84,6 +86,13 @@
       ],
     },
     {
+      'target_name': 'dartfmt',
+      'type': 'none',
+      'dependencies': [
+        'utils/dartfmt/dartfmt.gyp:dartfmt',
+      ],
+    },
+    {
       # This is the target that is built on the dart2dart bots.
       # It must depend on anything that is required by dart2dart
       # tests.
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index 1131798..1ee2375 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -199,7 +199,7 @@
 
 These considerations become even more important if one introduces constructs such as nested classes, which might be considered in future versions of the language.
 
-Good tooling should of course endeavor to inform programmers of such situations (discretely). For example, an identifier that is both inherited and lexically visible could be highlighted (via underlining or colorization). Better yet, tight integration of source control with language aware tools would detect such changes when they occur. 
+Good tooling should of course endeavor to inform programmers of such situations (discreetly). For example, an identifier that is both inherited and lexically visible could be highlighted (via underlining or colorization). Better yet, tight integration of source control with language aware tools would detect such changes when they occur. 
  
 }
 
@@ -4832,7 +4832,7 @@
 
 A Dart program consists of one or more libraries, and may be built out of one or more {\em compilation units}. A compilation unit may be a library or a part (\ref{parts}). 
 
-A library consists of (a possibly empty) set of imports, asset of exports,  and a set of top-level declarations. A top-level declaration is either a class (\ref{classes}), a type alias declaration (\ref{typedef}), a function (\ref{functions}) or a variable declaration (\ref{variables}). The members of a library $L$ are those top level declarations given within a $L$.
+A library consists of (a possibly empty) set of imports, a set of exports, and a set of top-level declarations. A top-level declaration is either a class (\ref{classes}), a type alias declaration (\ref{typedef}), a function (\ref{functions}) or a variable declaration (\ref{variables}). The members of a library $L$ are those top level declarations given within a $L$.
 
  \begin{grammar}
 {\bf topLevelDefinition:}classDefinition;
diff --git a/pkg/analysis_server/lib/http_server.dart b/pkg/analysis_server/lib/http_server.dart
index ecb72d4..3fb08de 100644
--- a/pkg/analysis_server/lib/http_server.dart
+++ b/pkg/analysis_server/lib/http_server.dart
@@ -6,14 +6,13 @@
 
 import 'dart:io';
 
+import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/channel.dart';
+import 'package:analysis_server/src/domain_context.dart';
+import 'package:analysis_server/src/domain_server.dart';
+import 'package:analysis_server/src/get_handler.dart';
 import 'package:args/args.dart';
 
-import 'src/analysis_server.dart';
-import 'src/channel.dart';
-import 'src/domain_context.dart';
-import 'src/domain_server.dart';
-import 'src/get_handler.dart';
-
 /**
  * Instances of the class [HttpServer] implement a simple HTTP server. The
  * primary responsibility of this server is to listen for an UPGRADE request and
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 7fd84f4..1c5e683 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -6,12 +6,11 @@
 
 import 'dart:async';
 
+import 'package:analysis_server/src/analysis_logger.dart';
+import 'package:analysis_server/src/channel.dart';
+import 'package:analysis_server/src/protocol.dart';
 import 'package:analyzer/src/generated/engine.dart';
 
-import 'analysis_logger.dart';
-import 'channel.dart';
-import 'protocol.dart';
-
 /**
  * Instances of the class [AnalysisServer] implement a server that listens on a
  * [CommunicationChannel] for analysis requests and process them.
diff --git a/pkg/analysis_server/lib/src/channel.dart b/pkg/analysis_server/lib/src/channel.dart
index 9def4b4..6a03215 100644
--- a/pkg/analysis_server/lib/src/channel.dart
+++ b/pkg/analysis_server/lib/src/channel.dart
@@ -4,11 +4,10 @@
 
 library channel;
 
-import 'dart:async';
 import 'dart:convert';
 import 'dart:io';
 
-import 'protocol.dart';
+import 'package:analysis_server/src/protocol.dart';
 
 /**
  * The abstract class [CommunicationChannel] defines the behavior of objects
diff --git a/pkg/analysis_server/lib/src/domain_context.dart b/pkg/analysis_server/lib/src/domain_context.dart
index c22fe6f..6e7c6fc 100644
--- a/pkg/analysis_server/lib/src/domain_context.dart
+++ b/pkg/analysis_server/lib/src/domain_context.dart
@@ -4,12 +4,11 @@
 
 library domain.context;
 
+import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/protocol.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 
-import 'analysis_server.dart';
-import 'protocol.dart';
-
 /**
  * Instances of the class [ContextDomainHandler] implement a [RequestHandler]
  * that handles requests in the context domain.
@@ -118,6 +117,8 @@
     ChangeSet changeSet = createChangeSet(changesData);
 
     context.applyChanges(changeSet);
+    Response response = new Response(request.id);
+    return response;
   }
 
   /**
@@ -136,6 +137,8 @@
     AnalysisContext context = getAnalysisContext(request);
 
     context.analysisOptions = createAnalysisOptions(request);
+    Response response = new Response(request.id);
+    return response;
   }
 
   /**
@@ -175,6 +178,8 @@
     List<Source> sources = convertToSources(context.sourceFactory, sourcesData);
 
     context.analysisPriorityOrder = sources;
+    Response response = new Response(request.id);
+    return response;
   }
 
   /**
diff --git a/pkg/analysis_server/lib/src/domain_server.dart b/pkg/analysis_server/lib/src/domain_server.dart
index 23f5bcb..1e37f24 100644
--- a/pkg/analysis_server/lib/src/domain_server.dart
+++ b/pkg/analysis_server/lib/src/domain_server.dart
@@ -4,15 +4,14 @@
 
 library domain.server;
 
+import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/protocol.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_io.dart';
 import 'package:analyzer/src/generated/sdk_io.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 
-import 'analysis_server.dart';
-import 'protocol.dart';
-
 /**
  * Instances of the class [ServerDomainHandler] implement a [RequestHandler]
  * that handles requests in the server domain.
@@ -116,7 +115,7 @@
       // new PackageUriResolver(),
     ]);
     server.contextMap[contextId] = context;
-    
+
     Response response = new Response(request.id);
     response.setResult(CONTEXT_ID_RESULT, contextId);
     return response;
diff --git a/pkg/analysis_server/lib/src/get_handler.dart b/pkg/analysis_server/lib/src/get_handler.dart
index 6bc1d1a..18a7d74 100644
--- a/pkg/analysis_server/lib/src/get_handler.dart
+++ b/pkg/analysis_server/lib/src/get_handler.dart
@@ -4,7 +4,7 @@
 
 import 'package:analyzer/src/generated/engine.dart';
 
-import 'analysis_server.dart';
+import 'package:analysis_server/src/analysis_server.dart';
 
 /**
  * Instances of the class [GetHandler] handle GET requests
diff --git a/pkg/analysis_server/test/mocks.dart b/pkg/analysis_server/test/mocks.dart
index a9416eb..186d6d0 100644
--- a/pkg/analysis_server/test/mocks.dart
+++ b/pkg/analysis_server/test/mocks.dart
@@ -13,5 +13,6 @@
 class MockChannel implements CommunicationChannel {
   dynamic noSuchMethod(Invocation invocation) {
     // Do nothing
+    return null;
   }
 }
diff --git a/pkg/analyzer/bin/analyzer.dart b/pkg/analyzer/bin/analyzer.dart
index 76510c0..19de8ca 100644
--- a/pkg/analyzer/bin/analyzer.dart
+++ b/pkg/analyzer/bin/analyzer.dart
@@ -95,7 +95,7 @@
    * Run the tool in 'batch' mode, receiving command lines through stdin and returning pass/fail
    * status through stdout. This feature is intended for use in unit testing.
    */
-  static ErrorSeverity runAsBatch(List<String> sharedArgs, BatchRunnerHandler handler) {
+  static void runAsBatch(List<String> sharedArgs, BatchRunnerHandler handler) {
     stdout.writeln('>>> BATCH START');
     Stopwatch stopwatch = new Stopwatch();
     stopwatch.start();
@@ -111,7 +111,7 @@
       if (line.isEmpty) {
         var time = stopwatch.elapsedMilliseconds;
         stdout.writeln('>>> BATCH END (${totalTests - testsFailed}/$totalTests) ${time}ms');
-        exit(batchResult.ordinal);
+        exitCode = batchResult.ordinal;
       }
       // prepare aruments
       var args;
diff --git a/pkg/analyzer/bin/formatter.dart b/pkg/analyzer/bin/formatter.dart
index 47a6275..400b309 100755
--- a/pkg/analyzer/bin/formatter.dart
+++ b/pkg/analyzer/bin/formatter.dart
@@ -90,19 +90,19 @@
 }
 
 
-Selection _parseSelection(selectionOption) {
-  if (selectionOption != null) {
-    var units = selectionOption.split(',');
-    if (units.length == 2) {
-      var offset = _toInt(units[0]);
-      var length = _toInt(units[1]);
-      if (offset != null && length != null) {
-        return new Selection(offset, length);
-      }
+Selection _parseSelection(String selectionOption) {
+  if(selectionOption == null) return null;
+
+  var units = selectionOption.split(',');
+  if (units.length == 2) {
+    var offset = _toInt(units[0]);
+    var length = _toInt(units[1]);
+    if (offset != null && length != null) {
+      return new Selection(offset, length);
     }
-    throw new FormatterException('Selections are specified as integer pairs '
-                                 '(e.g., "(offset, length)".');
   }
+  throw new FormatterException('Selections are specified as integer pairs '
+                               '(e.g., "(offset, length)".');
 }
 
 int _toInt(str) => int.parse(str, onError: (_) => null);
diff --git a/pkg/analyzer/lib/src/services/runtime/coverage/coverage_impl.dart b/pkg/analyzer/lib/src/services/runtime/coverage/coverage_impl.dart
index bc1568a..bf245d5 100644
--- a/pkg/analyzer/lib/src/services/runtime/coverage/coverage_impl.dart
+++ b/pkg/analyzer/lib/src/services/runtime/coverage/coverage_impl.dart
@@ -119,7 +119,7 @@
   }
 
   Future sendFile(HttpRequest request, File file) {
-    file.resolveSymbolicLinks().then((fullPath) {
+    return file.resolveSymbolicLinks().then((fullPath) {
       return file.openRead().pipe(request.response);
     });
   }
diff --git a/pkg/barback/lib/barback.dart b/pkg/barback/lib/barback.dart
index e939436..173fb53 100644
--- a/pkg/barback/lib/barback.dart
+++ b/pkg/barback/lib/barback.dart
@@ -4,19 +4,20 @@
 
 library barback;
 
-import 'src/transform.dart';
-import 'src/transformer.dart';
-
 export 'src/asset.dart';
 export 'src/asset_id.dart';
 export 'src/asset_set.dart';
 export 'src/barback.dart';
 export 'src/barback_settings.dart';
+export 'src/base_transform.dart';
 export 'src/build_result.dart';
+export 'src/declaring_transform.dart';
+export 'src/declaring_transformer.dart';
 export 'src/errors.dart' hide flattenAggregateExceptions;
+export 'src/lazy_transformer.dart';
 export 'src/log.dart';
 export 'src/package_provider.dart';
-export 'src/transform.dart' show Transform;
+export 'src/transform.dart';
 export 'src/transform_logger.dart';
 export 'src/transformer.dart';
 export 'src/transformer_group.dart';
diff --git a/pkg/barback/lib/src/asset_cascade.dart b/pkg/barback/lib/src/asset_cascade.dart
index af0b90c..16b4090 100644
--- a/pkg/barback/lib/src/asset_cascade.dart
+++ b/pkg/barback/lib/src/asset_cascade.dart
@@ -151,9 +151,9 @@
       // If the requested asset is available, we can just return it.
       if (node != null && node.state.isAvailable) return node;
 
-      // If there's a build running, that build might generate the asset, so we
-      // wait for it to complete and then try again.
       if (_processDone != null) {
+        // If there's a build running, that build might generate the asset, so
+        // we wait for it to complete and then try again.
         return _processDone.then((_) => getAssetNode(id));
       }
 
@@ -233,6 +233,14 @@
     }
   }
 
+  /// Force all [LazyTransformer]s' transforms in this cascade to begin
+  /// producing concrete assets.
+  void forceAllTransforms() {
+    for (var phase in _phases) {
+      phase.forceAllTransforms();
+    }
+  }
+
   void reportError(BarbackException error) {
     _accumulatedErrors.add(error);
     _errorsController.add(error);
diff --git a/pkg/barback/lib/src/asset_node.dart b/pkg/barback/lib/src/asset_node.dart
index 7ea442a..c4aec84 100644
--- a/pkg/barback/lib/src/asset_node.dart
+++ b/pkg/barback/lib/src/asset_node.dart
@@ -50,6 +50,14 @@
   Asset get asset => _asset;
   Asset _asset;
 
+  /// The callback to be called to notify this asset node's creator that the
+  /// concrete asset should be generated.
+  ///
+  /// This is null for non-lazy asset nodes (see [AssetNodeController.lazy]).
+  /// Once this is called, it's set to null and [this] is no longer considered
+  /// lazy.
+  Function _lazyCallback;
+
   /// A broadcast stream that emits an event whenever the node changes state.
   ///
   /// This stream is synchronous to ensure that when a source asset is modified
@@ -138,7 +146,24 @@
         _asset = asset,
         _state = AssetState.AVAILABLE;
 
-  String toString() => "$state asset $id";
+  AssetNode._lazy(this.id, this._transform, this._origin, this._lazyCallback)
+      : _state = AssetState.DIRTY;
+
+  /// If [this] is lazy, force it to generate a concrete asset; otherwise, do
+  /// nothing.
+  ///
+  /// See [AssetNodeController.lazy].
+  void force() {
+    if (_origin != null) {
+      _origin.force();
+    } else if (_lazyCallback != null) {
+      _lazyCallback();
+      _lazyCallback = null;
+    }
+  }
+
+  String toString() =>
+    "$state${_lazyCallback == null ? '' : ' lazy'} asset $id";
 }
 
 /// The controller for an [AssetNode].
@@ -156,11 +181,26 @@
   AssetNodeController.available(Asset asset, [TransformNode transform])
       : node = new AssetNode._available(asset, transform, null);
 
+  /// Creates a controller for a lazy node.
+  ///
+  /// For the most part, this node works like any other dirty node. However, the
+  /// owner of its controller isn't expected to do the work to make it available
+  /// as soon as possible like they would for a non-lazy node. Instead, when its
+  /// value is needed, [callback] will fire to indicate that it should be made
+  /// available as soon as possible.
+  ///
+  /// [callback] is guaranteed to only fire once.
+  AssetNodeController.lazy(AssetId id, void callback(),
+          [TransformNode transform])
+      : node = new AssetNode._lazy(id, transform, null, callback);
+
   /// Creates a controller for a node whose initial state matches the current
   /// state of [node].
   ///
   /// [AssetNode.origin] of the returned node will automatically be set to
   /// `node.origin`.
+  ///
+  /// If [node] is lazy, the returned node will also be lazy.
   AssetNodeController.from(AssetNode node)
       : node = new AssetNode._(node.id, node.transform, node.origin) {
     if (node.state.isAvailable) {
@@ -175,6 +215,7 @@
     assert(node._state != AssetState.REMOVED);
     node._state = AssetState.DIRTY;
     node._asset = null;
+    node._lazyCallback = null;
     node._stateChangeController.add(AssetState.DIRTY);
   }
 
@@ -186,6 +227,7 @@
     assert(node._state != AssetState.REMOVED);
     node._state = AssetState.REMOVED;
     node._asset = null;
+    node._lazyCallback = null;
     node._stateChangeController.add(AssetState.REMOVED);
   }
 
@@ -199,9 +241,25 @@
     assert(node._state != AssetState.AVAILABLE);
     node._state = AssetState.AVAILABLE;
     node._asset = asset;
+    node._lazyCallback = null;
     node._stateChangeController.add(AssetState.AVAILABLE);
   }
 
+  /// Marks the node as [AssetState.DIRTY] and lazy.
+  ///
+  /// Lazy nodes aren't expected to have their values generated until needed.
+  /// Once it's necessary, [callback] will be called. [callback] is guaranteed
+  /// to be called only once.
+  ///
+  /// See also [AssetNodeController.lazy].
+  void setLazy(void callback()) {
+    assert(node._state != AssetState.REMOVED);
+    node._state = AssetState.DIRTY;
+    node._asset = null;
+    node._lazyCallback = callback;
+    node._stateChangeController.add(AssetState.DIRTY);
+  }
+
   String toString() => "controller for $node";
 }
 
diff --git a/pkg/barback/lib/src/base_transform.dart b/pkg/barback/lib/src/base_transform.dart
new file mode 100644
index 0000000..27dc12a
--- /dev/null
+++ b/pkg/barback/lib/src/base_transform.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2014, 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.base_transform;
+
+import 'dart:async';
+import 'dart:convert';
+
+import 'asset.dart';
+import 'asset_id.dart';
+import 'asset_node.dart';
+import 'errors.dart';
+import 'transform_logger.dart';
+import 'transform_node.dart';
+import 'utils.dart';
+
+/// The base class for the ephemeral transform objects that are passed to
+/// transformers.
+///
+/// This class provides the transformers with inputs, but its up to the
+/// subclasses to provide a means of emitting outputs.
+abstract class BaseTransform {
+  final TransformNode _node;
+  final TransformLogger _logger;
+
+  /// A logger so that the [Transformer] can report build details.
+  TransformLogger get logger => _logger;
+
+  /// Gets the primary input asset.
+  ///
+  /// While a transformation can use multiple input assets, one must be a
+  /// special "primary" asset. This will be the "entrypoint" or "main" input
+  /// file for a transformation.
+  ///
+  /// For example, with a dart2js transform, the primary input would be the
+  /// entrypoint Dart file. All of the other Dart files that that imports
+  /// would be secondary inputs.
+  ///
+  /// This method may fail at runtime if called asynchronously after the
+  /// transform begins running. The primary input may become unavailable while
+  /// this transformer is running due to asset changes earlier in the graph.
+  /// You can ignore the error if this happens: the transformer will be re-run
+  /// automatically for you.
+  Asset get primaryInput {
+    if (_node.primary.state != AssetState.AVAILABLE) {
+      throw new AssetNotFoundException(_node.primary.id);
+    }
+
+    return _node.primary.asset;
+  }
+
+  BaseTransform(this._node, LogFunction logFunction)
+    : _logger = new TransformLogger(logFunction);
+
+  /// Gets the asset for an input [id].
+  ///
+  /// If an input with that ID cannot be found, throws an
+  /// [AssetNotFoundException].
+  Future<Asset> getInput(AssetId id) => _node.getInput(id);
+
+  /// A convenience method to the contents of the input with [id] as a string.
+  ///
+  /// This is equivalent to calling `getInput()` followed by `readAsString()`.
+  ///
+  /// If the asset was created from a [String] the original string is always
+  /// returned and [encoding] is ignored. Otherwise, the binary data of the
+  /// asset is decoded using [encoding], which defaults to [UTF8].
+  Future<String> readInputAsString(AssetId id, {Encoding encoding}) {
+    if (encoding == null) encoding = UTF8;
+    return getInput(id).then((input) => input.readAsString(encoding: encoding));
+  }
+
+  /// A convenience method to the contents of the input with [id].
+  ///
+  /// This is equivalent to calling `getInput()` followed by `read()`.
+  ///
+  /// If the asset was created from a [String], this returns its UTF-8 encoding.
+  Stream<List<int>> readInput(AssetId id) =>
+      futureStream(getInput(id).then((input) => input.read()));
+}
diff --git a/pkg/barback/lib/src/declaring_transform.dart b/pkg/barback/lib/src/declaring_transform.dart
new file mode 100644
index 0000000..3e621d9
--- /dev/null
+++ b/pkg/barback/lib/src/declaring_transform.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2014, 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.declaring_transform;
+
+import 'asset_id.dart';
+import 'base_transform.dart';
+import 'transform_logger.dart';
+import 'transform_node.dart';
+
+/// A transform for [DeclaringTransform]ers that allows them to declare the ids
+/// of the outputs they'll generate without generating the concrete bodies of
+/// those outputs.
+class DeclaringTransform extends BaseTransform {
+  final Set<AssetId> _outputIds;
+
+  DeclaringTransform(TransformNode node, this._outputIds,
+      LogFunction logFunction)
+    : super(node, logFunction);
+
+  /// Stores [id] as the id of an output that will be created by this
+  /// transformation when it's run.
+  ///
+  /// A transformation can declare as many assets as it wants. If
+  /// [DeclaringTransformer.declareOutputs] declareds a given asset id for a
+  /// given input, [Transformer.apply] should emit the corresponding asset as
+  /// well.
+  void declareOutput(AssetId id) {
+    // TODO(nweiz): This should immediately throw if an output with that ID
+    // has already been declared by this transformer.
+    _outputIds.add(id);
+  }
+}
diff --git a/pkg/barback/lib/src/declaring_transformer.dart b/pkg/barback/lib/src/declaring_transformer.dart
new file mode 100644
index 0000000..14a9c4e
--- /dev/null
+++ b/pkg/barback/lib/src/declaring_transformer.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2014, 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.declaring_transformer;
+
+import 'dart:async';
+
+import 'declaring_transform.dart';
+
+/// An interface for [Transformer]s that can cheaply figure out which assets
+/// they'll emit without doing the work of actually creating those assets.
+///
+/// If a transformer implements this interface, that allows barback to perform
+/// optimizations to make the asset graph work more smoothly.
+abstract class DeclaringTransformer {
+  /// Declare which assets would be emitted for the primary input specified by
+  /// [transform].
+  ///
+  /// For the most part, this works like [Transformer.apply]. The difference is
+  /// that instead of emitting [Asset]s, it just emits [AssetId]s through
+  /// [transform.addOutputId].
+  Future declareOutputs(DeclaringTransform transform);
+}
diff --git a/pkg/barback/lib/src/group_runner.dart b/pkg/barback/lib/src/group_runner.dart
index d276796..2e89416 100644
--- a/pkg/barback/lib/src/group_runner.dart
+++ b/pkg/barback/lib/src/group_runner.dart
@@ -66,6 +66,14 @@
     }
   }
 
+  /// Force all [LazyTransformer]s' transforms in this group to begin producing
+  /// concrete assets.
+  void forceAllTransforms() {
+    for (var phase in _phases) {
+      phase.forceAllTransforms();
+    }
+  }
+
   /// Adds a new asset as an input for this group.
   void addInput(AssetNode node) {
     _phases.first.addInput(node);
diff --git a/pkg/barback/lib/src/lazy_transformer.dart b/pkg/barback/lib/src/lazy_transformer.dart
new file mode 100644
index 0000000..67511f8
--- /dev/null
+++ b/pkg/barback/lib/src/lazy_transformer.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2014, 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.lazy_transformer;
+
+import 'declaring_transformer.dart';
+
+/// An interface for [Transformer]s that indicates that the transformer's
+/// outputs shouldn't be generated until requested.
+///
+/// The [declareOutputs] method is used to figure out which assets should be
+/// treated as "lazy." Lazy assets will only be forced to be generated if
+/// they're requested by the user or if they're used by a non-declaring
+/// transformer.
+abstract class LazyTransformer extends DeclaringTransformer {}
diff --git a/pkg/barback/lib/src/package_graph.dart b/pkg/barback/lib/src/package_graph.dart
index ce49459..cf198d9 100644
--- a/pkg/barback/lib/src/package_graph.dart
+++ b/pkg/barback/lib/src/package_graph.dart
@@ -14,7 +14,6 @@
 import 'errors.dart';
 import 'log.dart';
 import 'package_provider.dart';
-import 'pool.dart';
 import 'transformer.dart';
 import 'utils.dart';
 
@@ -139,7 +138,14 @@
   /// If a build is currently in progress, waits until it completes. The
   /// returned future will complete with an error if the build is not
   /// successful.
+  ///
+  /// Any transforms using [LazyTransformer]s will be forced to generate
+  /// concrete outputs, and those outputs will be returned.
   Future<AssetSet> getAllAssets() {
+    for (var cascade in _cascades.values) {
+      cascade.forceAllTransforms();
+    }
+
     if (_cascadeResults.values.contains(null)) {
       // A build is still ongoing, so wait for it to complete and try again.
       return results.first.then((_) => getAllAssets());
diff --git a/pkg/barback/lib/src/phase.dart b/pkg/barback/lib/src/phase.dart
index aa570bf..17d32d8 100644
--- a/pkg/barback/lib/src/phase.dart
+++ b/pkg/barback/lib/src/phase.dart
@@ -145,6 +145,8 @@
   void addInput(AssetNode node) {
     if (_inputs.containsKey(node.id)) _inputs[node.id].remove();
 
+    node.force();
+
     // Each group is one channel along which an asset may be forwarded. Then
     // there's one additional channel for the non-grouped transformers.
     var forwarder = new PhaseForwarder(_groups.length + 1);
@@ -191,7 +193,9 @@
     return newFuture(() {
       if (id.package != cascade.package) return cascade.graph.getAssetNode(id);
       if (!_outputs.containsKey(id)) return null;
-      return _outputs[id].output;
+      var output = _outputs[id].output;
+      output.force();
+      return output;
     });
   }
 
@@ -228,6 +232,18 @@
     }
   }
 
+  /// Force all [LazyTransformer]s' transforms in this phase to begin producing
+  /// concrete assets.
+  void forceAllTransforms() {
+    for (var group in _groups.values) {
+      group.forceAllTransforms();
+    }
+
+    for (var input in _inputs.values) {
+      input.forceAllTransforms();
+    }
+  }
+
   /// Add a new phase after this one with [transformers].
   ///
   /// This may only be called on a phase with no phase following it.
diff --git a/pkg/barback/lib/src/phase_input.dart b/pkg/barback/lib/src/phase_input.dart
index 4937467..3506560 100644
--- a/pkg/barback/lib/src/phase_input.dart
+++ b/pkg/barback/lib/src/phase_input.dart
@@ -150,6 +150,14 @@
     if (_adjustTransformersFuture == null) _adjustTransformers();
   }
 
+  /// Force all [LazyTransformer]s' transforms in this input to begin producing
+  /// concrete assets.
+  void forceAllTransforms() {
+    for (var transform in _transforms) {
+      transform.force();
+    }
+  }
+
   /// Asynchronously determines which transformers can consume [input] as a
   /// primary input and creates transforms for them.
   ///
@@ -199,7 +207,7 @@
         if (!transformers.contains(transform.transformer)) return false;
 
         // TODO(rnystrom): Catch all errors from isPrimary() and redirect to
-        // results.
+        // results (issue 16162).
         return transform.transformer.isPrimary(asset);
       }).then((isPrimary) {
         if (isPrimary) return;
diff --git a/pkg/barback/lib/src/transform.dart b/pkg/barback/lib/src/transform.dart
index 7f0d217..26b718d 100644
--- a/pkg/barback/lib/src/transform.dart
+++ b/pkg/barback/lib/src/transform.dart
@@ -1,35 +1,14 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2014, 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.transform;
 
-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 'errors.dart';
-import 'log.dart';
+import 'base_transform.dart';
 import 'transform_logger.dart';
 import 'transform_node.dart';
-import 'utils.dart';
-
-typedef void LogFunction(AssetId asset, LogLevel level, String message,
-                         Span span);
-
-/// Creates a [Transform] by forwarding to the private constructor.
-///
-/// Lets [TransformNode] create [Transforms] without giving a [Transform]
-/// itself a public constructor, which would be visible to external users.
-/// Unlike the [Transform] class, this function is not exported by barback.dart.
-Transform createTransform(TransformNode node, AssetSet outputs,
-                          LogFunction logFunction) =>
-    new Transform._(node, outputs, logFunction);
 
 /// While a [Transformer] represents a *kind* of transformation, this defines
 /// one specific usage of it on a set of files.
@@ -38,65 +17,11 @@
 /// facilitate communication between the [Transformer] and the code hosting
 /// the transformation. It lets the [Transformer] access inputs and generate
 /// outputs.
-class Transform {
-  final TransformNode _node;
-  final TransformLogger _logger;
+class Transform extends BaseTransform {
   final AssetSet _outputs;
 
-  /// A logger so that the [Transformer] can report build details.
-  TransformLogger get logger => _logger;
-
-  /// Gets the primary input asset.
-  ///
-  /// While a transformation can use multiple input assets, one must be a
-  /// special "primary" asset. This will be the "entrypoint" or "main" input
-  /// file for a transformation.
-  ///
-  /// For example, with a dart2js transform, the primary input would be the
-  /// entrypoint Dart file. All of the other Dart files that that imports
-  /// would be secondary inputs.
-  ///
-  /// This method may fail at runtime if called asynchronously after the
-  /// transform begins running. The primary input may become unavailable while
-  /// this transformer is running due to asset changes earlier in the graph.
-  /// You can ignore the error if this happens: the transformer will be re-run
-  /// automatically for you.
-  Asset get primaryInput {
-    if (_node.primary.state != AssetState.AVAILABLE) {
-      throw new AssetNotFoundException(_node.primary.id);
-    }
-
-    return _node.primary.asset;
-  }
-
-  Transform._(this._node, this._outputs, LogFunction logFunction)
-    : _logger = new TransformLogger(logFunction);
-
-  /// Gets the asset for an input [id].
-  ///
-  /// If an input with that ID cannot be found, throws an
-  /// [AssetNotFoundException].
-  Future<Asset> getInput(AssetId id) => _node.getInput(id);
-
-  /// A convenience method to the contents of the input with [id] as a string.
-  ///
-  /// This is equivalent to calling `getInput()` followed by `readAsString()`.
-  ///
-  /// If the asset was created from a [String] the original string is always
-  /// returned and [encoding] is ignored. Otherwise, the binary data of the
-  /// asset is decoded using [encoding], which defaults to [UTF8].
-  Future<String> readInputAsString(AssetId id, {Encoding encoding}) {
-    if (encoding == null) encoding = UTF8;
-    return getInput(id).then((input) => input.readAsString(encoding: encoding));
-  }
-
-  /// A convenience method to the contents of the input with [id].
-  ///
-  /// This is equivalent to calling `getInput()` followed by `read()`.
-  ///
-  /// If the asset was created from a [String], this returns its UTF-8 encoding.
-  Stream<List<int>> readInput(AssetId id) =>
-      futureStream(getInput(id).then((input) => input.read()));
+  Transform(TransformNode node, this._outputs, LogFunction logFunction)
+    : super(node, logFunction);
 
   /// Stores [output] as the output created by this transformation.
   ///
diff --git a/pkg/barback/lib/src/transform_logger.dart b/pkg/barback/lib/src/transform_logger.dart
index 6067b36..bdac90f 100644
--- a/pkg/barback/lib/src/transform_logger.dart
+++ b/pkg/barback/lib/src/transform_logger.dart
@@ -8,7 +8,9 @@
 
 import 'asset_id.dart';
 import 'log.dart';
-import 'transform.dart';
+
+typedef void LogFunction(AssetId asset, LogLevel level, String message,
+                         Span span);
 
 /// Object used to report warnings and errors encountered while running a
 /// transformer.
diff --git a/pkg/barback/lib/src/transform_node.dart b/pkg/barback/lib/src/transform_node.dart
index 8a79b6c..bba950a 100644
--- a/pkg/barback/lib/src/transform_node.dart
+++ b/pkg/barback/lib/src/transform_node.dart
@@ -12,11 +12,14 @@
 import 'asset_id.dart';
 import 'asset_node.dart';
 import 'asset_set.dart';
+import 'declaring_transform.dart';
 import 'errors.dart';
+import 'lazy_transformer.dart';
 import 'log.dart';
 import 'phase.dart';
 import 'transform.dart';
 import 'transformer.dart';
+import 'utils.dart';
 
 /// Describes a transform on a set of assets and its relationship to the build
 /// dependency graph.
@@ -44,6 +47,9 @@
   bool get isDirty => _isDirty;
   var _isDirty = true;
 
+  /// Whether [transformer] is lazy and this transform has yet to be forced.
+  bool _isLazy;
+
   /// The subscriptions to each input's [AssetNode.onStateChange] stream.
   var _inputSubscriptions = new Map<AssetId, StreamSubscription>();
 
@@ -67,7 +73,10 @@
   Stream<LogEntry> get onLog => _onLogController.stream;
   final _onLogController = new StreamController<LogEntry>.broadcast(sync: true);
 
-  TransformNode(this.phase, this.transformer, this.primary, this._location) {
+  TransformNode(this.phase, Transformer transformer, this.primary,
+      this._location)
+      : transformer = transformer,
+        _isLazy = transformer is LazyTransformer {
     _primarySubscription = primary.onStateChange.listen((state) {
       if (state.isRemoved) {
         remove();
@@ -101,6 +110,16 @@
     }
   }
 
+  /// If [transformer] is lazy, ensures that its concrete outputs will be
+  /// generated.
+  void force() {
+    // TODO(nweiz): we might want to have a timeout after which, if the
+    // transform's outputs have gone unused, we switch it back to lazy mode.
+    if (!_isLazy) return;
+    _isLazy = false;
+    _dirty();
+  }
+
   /// Marks this transform as dirty.
   ///
   /// This causes all of the transform's outputs to be marked as dirty as well.
@@ -119,9 +138,6 @@
   Future<Set<AssetNode>> apply() {
     assert(!_onDirtyController.isClosed);
 
-    var newOutputs = new AssetSet();
-    var transform = createTransform(this, newOutputs, _log);
-
     // Clear all the old input subscriptions. If an input is re-used, we'll
     // re-subscribe.
     for (var subscription in _inputSubscriptions.values) {
@@ -131,25 +147,26 @@
 
     _isDirty = false;
 
-    return transformer.apply(transform).catchError((error, stack) {
+    return syncFuture(() {
+      // TODO(nweiz): If [transformer] is a [DeclaringTransformer] but not a
+      // [LazyTransformer], we can get some mileage out of doing a declarative
+      // first so we know how to hook up the assets.
+      if (_isLazy) return _declareLazy();
+      return _applyImmediate();
+    }).catchError((error, stackTrace) {
       // If the transform became dirty while processing, ignore any errors from
       // it.
-      if (_isDirty) return;
-
-      if (error is! MissingInputException) {
-        error = new TransformerException(info, error, stack);
-      }
-
-      // Catch all transformer errors and pipe them to the results stream.
-      // This is so a broken transformer doesn't take down the whole graph.
-      phase.cascade.reportError(error);
-
-      // Don't allow partial results from a failed transform.
-      newOutputs.clear();
-    }).then((_) {
       if (_isDirty) return new Set();
 
-      return _adjustOutputs(newOutputs);
+      if (error is! MissingInputException) {
+        error = new TransformerException(info, error, stackTrace);
+      }
+
+      // Catch all transformer errors and pipe them to the results stream. This
+      // is so a broken transformer doesn't take down the whole graph.
+      phase.cascade.reportError(error);
+
+      return new Set();
     });
   }
 
@@ -180,40 +197,88 @@
     });
   }
 
-  /// Adjusts the outputs of the transform to reflect the outputs emitted on its
-  /// most recent run.
-  Set<AssetNode> _adjustOutputs(AssetSet newOutputs) {
-    // Any ids that are for a different package are invalid.
-    var invalidIds = newOutputs
-        .map((asset) => asset.id)
-        .where((id) => id.package != phase.cascade.package)
-        .toSet();
-    for (var id in invalidIds) {
-      newOutputs.removeId(id);
-      // TODO(nweiz): report this as a warning rather than a failing error.
-      phase.cascade.reportError(new InvalidOutputException(info, id));
-    }
+  /// Applies the transform so that it produces concrete (as opposed to lazy)
+  /// outputs.
+  Future<Set<AssetNode>> _applyImmediate() {
+    var newOutputs = new AssetSet();
+    var transform = new Transform(this, newOutputs, _log);
 
-    // Remove outputs that used to exist but don't anymore.
-    for (var id in _outputControllers.keys.toList()) {
-      if (newOutputs.containsId(id)) continue;
-      _outputControllers.remove(id).setRemoved();
-    }
+    return syncFuture(() => transformer.apply(transform)).then((_) {
+      if (_isDirty) return new Set();
 
-    var brandNewOutputs = new Set<AssetNode>();
-    // Store any new outputs or new contents for existing outputs.
-    for (var asset in newOutputs) {
-      var controller = _outputControllers[asset.id];
-      if (controller != null) {
-        controller.setAvailable(asset);
-      } else {
-        var controller = new AssetNodeController.available(asset, this);
-        _outputControllers[asset.id] = controller;
-        brandNewOutputs.add(controller.node);
+      // Any ids that are for a different package are invalid.
+      var invalidIds = newOutputs
+          .map((asset) => asset.id)
+          .where((id) => id.package != phase.cascade.package)
+          .toSet();
+      for (var id in invalidIds) {
+        newOutputs.removeId(id);
+        // TODO(nweiz): report this as a warning rather than a failing error.
+        phase.cascade.reportError(new InvalidOutputException(info, id));
       }
-    }
 
-    return brandNewOutputs;
+      // Remove outputs that used to exist but don't anymore.
+      for (var id in _outputControllers.keys.toList()) {
+        if (newOutputs.containsId(id)) continue;
+        _outputControllers.remove(id).setRemoved();
+      }
+
+      var brandNewOutputs = new Set<AssetNode>();
+      // Store any new outputs or new contents for existing outputs.
+      for (var asset in newOutputs) {
+        var controller = _outputControllers[asset.id];
+        if (controller != null) {
+          controller.setAvailable(asset);
+        } else {
+          var controller = new AssetNodeController.available(asset, this);
+          _outputControllers[asset.id] = controller;
+          brandNewOutputs.add(controller.node);
+        }
+      }
+
+      return brandNewOutputs;
+    });
+  }
+
+  /// Applies the transform in declarative mode so that it produces lazy
+  /// outputs.
+  Future<Set<AssetNode>> _declareLazy() {
+    var newIds = new Set();
+    var transform = new DeclaringTransform(this, newIds, _log);
+
+    return syncFuture(() {
+      return (transformer as LazyTransformer).declareOutputs(transform);
+    }).then((_) {
+      if (_isDirty) return new Set();
+
+      var invalidIds =
+          newIds.where((id) => id.package != phase.cascade.package).toSet();
+      for (var id in invalidIds) {
+        newIds.remove(id);
+        // TODO(nweiz): report this as a warning rather than a failing error.
+        phase.cascade.reportError(new InvalidOutputException(info, id));
+      }
+
+      // Remove outputs that used to exist but don't anymore.
+      for (var id in _outputControllers.keys.toList()) {
+        if (newIds.contains(id)) continue;
+        _outputControllers.remove(id).setRemoved();
+      }
+
+      var brandNewOutputs = new Set<AssetNode>();
+      for (var id in newIds) {
+        var controller = _outputControllers[id];
+        if (controller != null) {
+          controller.setLazy(force);
+        } else {
+          var controller = new AssetNodeController.lazy(id, force, this);
+          _outputControllers[id] = controller;
+          brandNewOutputs.add(controller.node);
+        }
+      }
+
+      return brandNewOutputs;
+    });
   }
 
   void _log(AssetId asset, LogLevel level, String message, Span span) {
diff --git a/pkg/barback/lib/src/transformer.dart b/pkg/barback/lib/src/transformer.dart
index e8479f1..6eed17a 100644
--- a/pkg/barback/lib/src/transformer.dart
+++ b/pkg/barback/lib/src/transformer.dart
@@ -15,6 +15,9 @@
 /// Dart2js, a SASS->CSS processor, a CSS spriter, and a tool to concatenate
 /// files are all examples of transformers. To define your own transformation
 /// step, extend (or implement) this class.
+///
+/// If possible, transformers should implement [DeclaringTransformer] as well to
+/// help barback optimize the package graph.
 abstract class Transformer {
   /// Override this to return a space-separated list of file extensions
   /// (with leading `.`) that are allowed for the primary inputs to this
diff --git a/pkg/barback/lib/src/utils.dart b/pkg/barback/lib/src/utils.dart
index f1bcddd..59c9d4b 100644
--- a/pkg/barback/lib/src/utils.dart
+++ b/pkg/barback/lib/src/utils.dart
@@ -140,10 +140,24 @@
 Set unionAll(Iterable<Set> sets) =>
   sets.fold(new Set(), (union, set) => union.union(set));
 
-/// Passes each key/value pair in [map] to [fn] and returns a new [Map] whose
-/// values are the return values of [fn].
-Map mapMapValues(Map map, fn(key, value)) =>
-  new Map.fromIterable(map.keys, value: (key) => fn(key, map[key]));
+/// Creates a new map from [map] with new keys and values.
+///
+/// The return values of [keyFn] are used as the keys and the return values of
+/// [valueFn] are used as the values for the new map.
+Map mapMap(Map map, keyFn(key, value), valueFn(key, value)) =>
+  new Map.fromIterable(map.keys,
+      key: (key) => keyFn(key, map[key]),
+      value: (key) => valueFn(key, map[key]));
+
+/// Creates a new map from [map] with the same keys.
+///
+/// The return values of [fn] are used as the values for the new map.
+Map mapMapValues(Map map, fn(key, value)) => mapMap(map, (key, _) => key, fn);
+
+/// Creates a new map from [map] with the same keys.
+///
+/// The return values of [fn] are used as the keys for the new map.
+Map mapMapKeys(Map map, fn(key, value)) => mapMap(map, fn, (_, value) => value);
 
 /// Returns whether [set1] has exactly the same elements as [set2].
 bool setEquals(Set set1, Set set2) =>
diff --git a/pkg/barback/test/package_graph/lazy_transformer_test.dart b/pkg/barback/test/package_graph/lazy_transformer_test.dart
new file mode 100644
index 0000000..c43c9f1
--- /dev/null
+++ b/pkg/barback/test/package_graph/lazy_transformer_test.dart
@@ -0,0 +1,178 @@
+// Copyright (c) 2014, 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.lazy_asset_test;
+
+import 'package:barback/barback.dart';
+import 'package:barback/src/utils.dart';
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../utils.dart';
+
+main() {
+  initConfig();
+  test("requesting a lazy asset should cause it to be generated", () {
+    initGraph(["app|foo.blub"], {"app": [
+      [new LazyRewriteTransformer("blub", "blab")]
+    ]});
+    updateSources(["app|foo.blub"]);
+    expectAsset("app|foo.blab", "foo.blab");
+    buildShouldSucceed();
+  });
+
+  test("calling getAllAssets should cause a lazy asset to be generated", () {
+    var transformer = new LazyRewriteTransformer("blub", "blab");
+    initGraph(["app|foo.blub"], {"app": [[transformer]]});
+    updateSources(["app|foo.blub"]);
+    expectAllAssets(["app|foo.blab"]);
+    buildShouldSucceed();
+    expect(transformer.numRuns, completion(equals(1)));
+  });
+
+  test("requesting a lazy asset multiple times should only cause it to be "
+      "generated once", () {
+    var transformer = new LazyRewriteTransformer("blub", "blab");
+    initGraph(["app|foo.blub"], {"app": [[transformer]]});
+    updateSources(["app|foo.blub"]);
+    expectAsset("app|foo.blab", "foo.blab");
+    expectAsset("app|foo.blab", "foo.blab");
+    expectAsset("app|foo.blab", "foo.blab");
+    buildShouldSucceed();
+    expect(transformer.numRuns, completion(equals(1)));
+  });
+
+  test("a lazy asset can be consumed by a non-lazy transformer", () {
+    initGraph(["app|foo.blub"], {"app": [
+      [new LazyRewriteTransformer("blub", "blab")],
+      [new RewriteTransformer("blab", "blib")]
+    ]});
+    updateSources(["app|foo.blub"]);
+    expectAsset("app|foo.blib", "foo.blab.blib");
+    buildShouldSucceed();
+  });
+
+  test("a lazy asset isn't eagerly compiled", () {
+    var transformer = new LazyRewriteTransformer("blub", "blab");
+    initGraph(["app|foo.blub"], {"app": [[transformer]]});
+    updateSources(["app|foo.blub"]);
+    buildShouldSucceed();
+    expect(transformer.numRuns, completion(equals(0)));
+  });
+
+  test("a lazy asset emitted by a group isn't eagerly compiled", () {
+    var transformer = new LazyRewriteTransformer("blub", "blab");
+    initGraph(["app|foo.blub"], {"app": [
+      [new TransformerGroup([[transformer]])]
+    ]});
+    updateSources(["app|foo.blub"]);
+    buildShouldSucceed();
+    expect(transformer.numRuns, completion(equals(0)));
+  });
+
+  test("a lazy asset piped into a non-lazy transformer is eagerly compiled",
+      () {
+    var transformer = new LazyRewriteTransformer("blub", "blab");
+    initGraph(["app|foo.blub"], {"app": [
+      [transformer],
+      [new RewriteTransformer("blab", "blib")]
+    ]});
+    updateSources(["app|foo.blub"]);
+    buildShouldSucceed();
+    expect(transformer.numRuns, completion(equals(1)));
+  });
+
+  // TODO(nweiz): enable these once DeclaringTransformers forward laziness
+  // properly (issue 16442).
+  //
+  // test("a lazy asset piped into a declaring transformer isn't eagerly "
+  //     "compiled", () {
+  //   var transformer1 = new LazyRewriteTransformer("blub", "blab");
+  //   var transformer2 = new DeclaringRewriteTransformer("blab", "blib");
+  //   initGraph(["app|foo.blub"], {"app": [
+  //     [transformer1], [transformer2]
+  //   ]});
+  //   updateSources(["app|foo.blub"]);
+  //   buildShouldSucceed();
+  //   expect(transformer1.numRuns, completion(equals(0)));
+  //   expect(transformer2.numRuns, completion(equals(0)));
+  // });
+  //
+  // test("a lazy asset piped into a declaring transformer is compiled "
+  //     "on-demand", () {
+  //   initGraph(["app|foo.blub"], {"app": [
+  //     [new LazyRewriteTransformer("blub", "blab")],
+  //     [new DeclaringRewriteTransformer("blab", "blib")]
+  //   ]});
+  //   updateSources(["app|foo.blub"]);
+  //   expectAsset("app|foo.blib", "foo.blab.blib");
+  //   buildShouldSucceed();
+  // });
+
+  test("a lazy asset works as a cross-package input", () {
+    initGraph({
+      "pkg1|foo.blub": "foo",
+      "pkg2|a.txt": "pkg1|foo.blab"
+    }, {"pkg1": [
+      [new LazyRewriteTransformer("blub", "blab")],
+    ], "pkg2": [
+      [new ManyToOneTransformer("txt")]
+    ]});
+
+    updateSources(["pkg1|foo.blub", "pkg2|a.txt"]);
+    expectAsset("pkg2|a.out", "foo.blab");
+    buildShouldSucceed();
+  });
+
+  test("a lazy transformer can consume secondary inputs lazily", () {
+    initGraph({
+      "app|a.inc": "a",
+      "app|a.txt": "a.inc"
+    }, {"app": [
+      [new LazyManyToOneTransformer("txt")]
+    ]});
+
+    updateSources(["app|a.inc", "app|a.txt"]);
+    expectAsset("app|a.out", "a");
+    buildShouldSucceed();
+  });
+
+  test("once a lazy transformer is materialized, it runs eagerly afterwards",
+      () {
+    var transformer = new LazyRewriteTransformer("blub", "blab");
+    initGraph(["app|foo.blub"], {"app": [[transformer]]});
+
+    updateSources(["app|foo.blub"]);
+    buildShouldSucceed();
+
+    // Request the asset once to force it to be materialized.
+    expectAsset("app|foo.blab", "foo.blab");
+    buildShouldSucceed();
+
+    updateSources(["app|foo.blub"]);
+    buildShouldSucceed();
+
+    expect(transformer.numRuns, completion(equals(2)));
+  });
+
+  test("an error emitted in a lazy transformer's declareOutputs method is "
+      "caught and reported", () {
+    initGraph(["app|foo.txt"], {"app": [
+      [new LazyBadTransformer("app|foo.out")]
+    ]});
+
+    updateSources(["app|foo.txt"]);
+    buildShouldFail([isTransformerException(equals(LazyBadTransformer.ERROR))]);
+  });
+
+  test("an error emitted in a lazy transformer's declareOuputs method prevents "
+      "it from being materialized", () {
+    var transformer = new LazyBadTransformer("app|foo.out");
+    initGraph(["app|foo.txt"], {"app": [[transformer]]});
+
+    updateSources(["app|foo.txt"]);
+    expectNoAsset("app|foo.out");
+    buildShouldFail([isTransformerException(equals(LazyBadTransformer.ERROR))]);
+    expect(transformer.numRuns, completion(equals(0)));
+  });
+}
diff --git a/pkg/barback/test/transformer/lazy_bad.dart b/pkg/barback/test/transformer/lazy_bad.dart
new file mode 100644
index 0000000..4bd07fd
--- /dev/null
+++ b/pkg/barback/test/transformer/lazy_bad.dart
@@ -0,0 +1,40 @@
+// 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.transformer.lazy_bad;
+
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+import 'package:barback/src/utils.dart';
+
+import 'mock.dart';
+
+/// A lazy transformer that throws an exception after [declareOutputs].
+class LazyBadTransformer extends MockTransformer implements LazyTransformer {
+  /// The error [this] throws.
+  static const ERROR = "I am a bad transformer!";
+
+  /// The asset name that [this] should output.
+  final String output;
+
+  LazyBadTransformer(this.output);
+
+  Future<bool> doIsPrimary(Asset asset) => new Future.value(true);
+
+  Future doApply(Transform transform) {
+    return newFuture(() {
+      var id = new AssetId.parse(output);
+      transform.addOutput(new Asset.fromString(id, output));
+    });
+  }
+
+  Future declareOutputs(DeclaringTransform transform) {
+    return newFuture(() {
+      var id = new AssetId.parse(output);
+      transform.declareOutput(id);
+      throw ERROR;
+    });
+  }
+}
diff --git a/pkg/barback/test/transformer/lazy_many_to_one.dart b/pkg/barback/test/transformer/lazy_many_to_one.dart
new file mode 100644
index 0000000..7e1b114
--- /dev/null
+++ b/pkg/barback/test/transformer/lazy_many_to_one.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2014, 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.transformer.lazy_many_to_one;
+
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+
+import 'many_to_one.dart';
+
+/// Like [ManyToOneTransformer], but returns a lazy asset that doesn't perform
+/// the conglomeration until it's materialized.
+class LazyManyToOneTransformer extends ManyToOneTransformer
+    implements LazyTransformer {
+  LazyManyToOneTransformer(String extension)
+      : super(extension);
+
+  Future declareOutputs(DeclaringTransform transform) {
+    transform.declareOutput(transform.primaryInput.id.changeExtension(".out"));
+  }
+}
diff --git a/pkg/barback/test/transformer/lazy_rewrite.dart b/pkg/barback/test/transformer/lazy_rewrite.dart
new file mode 100644
index 0000000..61c00e5
--- /dev/null
+++ b/pkg/barback/test/transformer/lazy_rewrite.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2014, 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.transformer.lazy_rewrite;
+
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+
+import 'rewrite.dart';
+
+/// Like [RewriteTransformer], but returns a lazy asset that doesn't perform the
+/// rewrite until it's materialized.
+class LazyRewriteTransformer extends RewriteTransformer
+    implements LazyTransformer {
+  LazyRewriteTransformer(String from, String to)
+      : super(from, to);
+
+  Future declareOutputs(DeclaringTransform transform) {
+    for (var extension in to.split(" ")) {
+      var id = transform.primaryInput.id.changeExtension(".$extension");
+      transform.declareOutput(id);
+    }
+  }
+}
diff --git a/pkg/barback/test/utils.dart b/pkg/barback/test/utils.dart
index 2f58753..7da5977 100644
--- a/pkg/barback/test/utils.dart
+++ b/pkg/barback/test/utils.dart
@@ -20,6 +20,9 @@
 export 'transformer/check_content.dart';
 export 'transformer/check_content_and_rename.dart';
 export 'transformer/create_asset.dart';
+export 'transformer/lazy_bad.dart';
+export 'transformer/lazy_many_to_one.dart';
+export 'transformer/lazy_rewrite.dart';
 export 'transformer/many_to_one.dart';
 export 'transformer/mock.dart';
 export 'transformer/one_to_many.dart';
@@ -283,22 +286,41 @@
 /// Schedules an expectation that the graph will output all of the given
 /// assets, and no others.
 ///
-/// [assets] is a list of strings that can be parsed to [AssetID]s.
-void expectAllAssets(Iterable<String> assets) {
-  var expected = assets.map((asset) => new AssetId.parse(asset));
+/// [assets] may be an iterable of asset id strings, in which case this asserts
+/// that the graph outputs exactly the assets with those ids. It may also be a
+/// map from asset id strings to asset contents, in which case the contents must
+/// also match.
+void expectAllAssets(assets) {
+  var expected;
+  var expectedString;
+  if (assets is Map) {
+    expected = mapMapKeys(assets, (key, _) => new AssetId.parse(key));
+    expectedString = expected.toString();
+  } else {
+    expected = assets.map((asset) => new AssetId.parse(asset));
+    expectedString = expected.join(', ');
+  }
 
   schedule(() {
     return _barback.getAllAssets().then((actualAssets) {
       var actualIds = actualAssets.map((asset) => asset.id).toSet();
 
-      for (var id in expected) {
-        expect(actualIds, contains(id));
-        actualIds.remove(id);
+      if (expected is Map) {
+        expected.forEach((id, contents) {
+          expect(actualIds, contains(id));
+          actualIds.remove(id);
+          expect(actualAssets[id].readAsString(), completion(equals(contents)));
+        });
+      } else {
+        for (var id in expected) {
+          expect(actualIds, contains(id));
+          actualIds.remove(id);
+        }
       }
 
       expect(actualIds, isEmpty);
     });
-  }, "get all assets, expecting ${expected.join(', ')}");
+  }, "get all assets, expecting $expectedString");
 }
 
 /// Schedules an expectation that [Barback.getAllAssets] will return a [Future]
diff --git a/pkg/collection_helpers/LICENSE b/pkg/collection_helpers/LICENSE
deleted file mode 100644
index ee99930..0000000
--- a/pkg/collection_helpers/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright 2013, the Dart project authors. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-    * Neither the name of Google Inc. nor the names of its
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-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.
diff --git a/pkg/collection_helpers/README.md b/pkg/collection_helpers/README.md
deleted file mode 100644
index fd20bd2..0000000
--- a/pkg/collection_helpers/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-Deprecated helper libraries for working with collections.
-
-The `collection_helpers` package has been split into the
-`collection` package (for most of the library)
-and the `typed_data` package (for typed data buffers).
-
-All further development will happen on those libraries.
-
-Please start using those libraries directly.
diff --git a/pkg/collection_helpers/lib/algorithms.dart b/pkg/collection_helpers/lib/algorithms.dart
deleted file mode 100644
index 85d15ba..0000000
--- a/pkg/collection_helpers/lib/algorithms.dart
+++ /dev/null
@@ -1,8 +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.
-
-@deprecated
-library dart.collection_helpers.algorithms;
-
-export "package:collection/algorithms.dart";
diff --git a/pkg/collection_helpers/lib/all.dart b/pkg/collection_helpers/lib/all.dart
deleted file mode 100644
index a9f6b63..0000000
--- a/pkg/collection_helpers/lib/all.dart
+++ /dev/null
@@ -1,11 +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.
-
-@deprecated
-library dart.collection_helper;
-
-export "algorithms.dart";
-export "equality.dart";
-export "typed_buffers.dart";
-export "wrappers.dart";
diff --git a/pkg/collection_helpers/lib/equality.dart b/pkg/collection_helpers/lib/equality.dart
deleted file mode 100644
index c47d635..0000000
--- a/pkg/collection_helpers/lib/equality.dart
+++ /dev/null
@@ -1,8 +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.
-
-@deprecated
-library dart.collection_helpers.equality;
-
-export "package:collection/equality.dart";
diff --git a/pkg/collection_helpers/lib/typed_buffers.dart b/pkg/collection_helpers/lib/typed_buffers.dart
deleted file mode 100644
index 612e3df..0000000
--- a/pkg/collection_helpers/lib/typed_buffers.dart
+++ /dev/null
@@ -1,8 +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.
-
-@deprecated
-library dart.collection_helpers.typed_buffers;
-
-export "package:typed_data/typed_buffers.dart";
diff --git a/pkg/collection_helpers/lib/wrappers.dart b/pkg/collection_helpers/lib/wrappers.dart
deleted file mode 100644
index d408151..0000000
--- a/pkg/collection_helpers/lib/wrappers.dart
+++ /dev/null
@@ -1,8 +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.
-
-@deprecated
-library dart.collection_helpers.wrappers;
-
-export "package:collection/wrappers.dart";
diff --git a/pkg/collection_helpers/pubspec.yaml b/pkg/collection_helpers/pubspec.yaml
deleted file mode 100644
index 0002f71..0000000
--- a/pkg/collection_helpers/pubspec.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-name: collection_helpers
-version: 0.9.2
-author: Dart Team <misc@dartlang.org>
-description: Discontinued. Use package:collection or package:typed_data.
-homepage: http://www.dartlang.org
-dependencies:
-  collection: "0.9.0"
-  typed_data: "0.9.0"
-environment:
-  sdk: ">=1.0.0 <2.0.0"
diff --git a/pkg/custom_element/REVISION b/pkg/custom_element/REVISION
deleted file mode 100644
index 309f953..0000000
--- a/pkg/custom_element/REVISION
+++ /dev/null
@@ -1,4 +0,0 @@
-sources are from:
-
-https://github.com/Polymer/MutationObservers/commit/a8aa7f9cc35c3ebef152be42f87ec2677a87f55e
-https://github.com/dart-lang/CustomElements/commit/44178138302584392ab51515e2959d8ab925b155
diff --git a/pkg/custom_element/lib/custom-elements.debug.js b/pkg/custom_element/lib/custom-elements.debug.js
deleted file mode 100644
index e3c53e0..0000000
--- a/pkg/custom_element/lib/custom-elements.debug.js
+++ /dev/null
@@ -1,1521 +0,0 @@
-// Copyright (c) 2012 The Polymer Authors. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// 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.
-if (typeof WeakMap === 'undefined') {
-  (function() {
-    var defineProperty = Object.defineProperty;
-    var counter = Date.now() % 1e9;
-
-    var WeakMap = function() {
-      this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__');
-    };
-
-    WeakMap.prototype = {
-      set: function(key, value) {
-        var entry = key[this.name];
-        if (entry && entry[0] === key)
-          entry[1] = value;
-        else
-          defineProperty(key, this.name, {value: [key, value], writable: true});
-      },
-      get: function(key) {
-        var entry;
-        return (entry = key[this.name]) && entry[0] === key ?
-            entry[1] : undefined;
-      },
-      delete: function(key) {
-        this.set(key, undefined);
-      }
-    };
-
-    window.WeakMap = WeakMap;
-  })();
-}
-
-(function(global) {
-
-  var registrationsTable = new WeakMap();
-
-  // We use setImmediate or postMessage for our future callback.
-  var setImmediate = window.msSetImmediate;
-
-  // Use post message to emulate setImmediate.
-  if (!setImmediate) {
-    var setImmediateQueue = [];
-    var sentinel = String(Math.random());
-    window.addEventListener('message', function(e) {
-      if (e.data === sentinel) {
-        var queue = setImmediateQueue;
-        setImmediateQueue = [];
-        queue.forEach(function(func) {
-          func();
-        });
-      }
-    });
-    setImmediate = function(func) {
-      setImmediateQueue.push(func);
-      window.postMessage(sentinel, '*');
-    };
-  }
-
-  // This is used to ensure that we never schedule 2 callas to setImmediate
-  var isScheduled = false;
-
-  // Keep track of observers that needs to be notified next time.
-  var scheduledObservers = [];
-
-  /**
-   * Schedules |dispatchCallback| to be called in the future.
-   * @param {MutationObserver} observer
-   */
-  function scheduleCallback(observer) {
-    scheduledObservers.push(observer);
-    if (!isScheduled) {
-      isScheduled = true;
-      setImmediate(dispatchCallbacks);
-    }
-  }
-
-  function wrapIfNeeded(node) {
-    return window.ShadowDOMPolyfill &&
-        window.ShadowDOMPolyfill.wrapIfNeeded(node) ||
-        node;
-  }
-
-  function dispatchCallbacks() {
-    // http://dom.spec.whatwg.org/#mutation-observers
-
-    isScheduled = false; // Used to allow a new setImmediate call above.
-
-    var observers = scheduledObservers;
-    scheduledObservers = [];
-    // Sort observers based on their creation UID (incremental).
-    observers.sort(function(o1, o2) {
-      return o1.uid_ - o2.uid_;
-    });
-
-    var anyNonEmpty = false;
-    observers.forEach(function(observer) {
-
-      // 2.1, 2.2
-      var queue = observer.takeRecords();
-      // 2.3. Remove all transient registered observers whose observer is mo.
-      removeTransientObserversFor(observer);
-
-      // 2.4
-      if (queue.length) {
-        observer.callback_(queue, observer);
-        anyNonEmpty = true;
-      }
-    });
-
-    // 3.
-    if (anyNonEmpty)
-      dispatchCallbacks();
-  }
-
-  function removeTransientObserversFor(observer) {
-    observer.nodes_.forEach(function(node) {
-      var registrations = registrationsTable.get(node);
-      if (!registrations)
-        return;
-      registrations.forEach(function(registration) {
-        if (registration.observer === observer)
-          registration.removeTransientObservers();
-      });
-    });
-  }
-
-  /**
-   * This function is used for the "For each registered observer observer (with
-   * observer's options as options) in target's list of registered observers,
-   * run these substeps:" and the "For each ancestor ancestor of target, and for
-   * each registered observer observer (with options options) in ancestor's list
-   * of registered observers, run these substeps:" part of the algorithms. The
-   * |options.subtree| is checked to ensure that the callback is called
-   * correctly.
-   *
-   * @param {Node} target
-   * @param {function(MutationObserverInit):MutationRecord} callback
-   */
-  function forEachAncestorAndObserverEnqueueRecord(target, callback) {
-    for (var node = target; node; node = node.parentNode) {
-      var registrations = registrationsTable.get(node);
-
-      if (registrations) {
-        for (var j = 0; j < registrations.length; j++) {
-          var registration = registrations[j];
-          var options = registration.options;
-
-          // Only target ignores subtree.
-          if (node !== target && !options.subtree)
-            continue;
-
-          var record = callback(options);
-          if (record)
-            registration.enqueue(record);
-        }
-      }
-    }
-  }
-
-  var uidCounter = 0;
-
-  /**
-   * The class that maps to the DOM MutationObserver interface.
-   * @param {Function} callback.
-   * @constructor
-   */
-  function JsMutationObserver(callback) {
-    this.callback_ = callback;
-    this.nodes_ = [];
-    this.records_ = [];
-    this.uid_ = ++uidCounter;
-  }
-
-  JsMutationObserver.prototype = {
-    observe: function(target, options) {
-      target = wrapIfNeeded(target);
-
-      // 1.1
-      if (!options.childList && !options.attributes && !options.characterData ||
-
-          // 1.2
-          options.attributeOldValue && !options.attributes ||
-
-          // 1.3
-          options.attributeFilter && options.attributeFilter.length &&
-              !options.attributes ||
-
-          // 1.4
-          options.characterDataOldValue && !options.characterData) {
-
-        throw new SyntaxError();
-      }
-
-      var registrations = registrationsTable.get(target);
-      if (!registrations)
-        registrationsTable.set(target, registrations = []);
-
-      // 2
-      // If target's list of registered observers already includes a registered
-      // observer associated with the context object, replace that registered
-      // observer's options with options.
-      var registration;
-      for (var i = 0; i < registrations.length; i++) {
-        if (registrations[i].observer === this) {
-          registration = registrations[i];
-          registration.removeListeners();
-          registration.options = options;
-          break;
-        }
-      }
-
-      // 3.
-      // Otherwise, add a new registered observer to target's list of registered
-      // observers with the context object as the observer and options as the
-      // options, and add target to context object's list of nodes on which it
-      // is registered.
-      if (!registration) {
-        registration = new Registration(this, target, options);
-        registrations.push(registration);
-        this.nodes_.push(target);
-      }
-
-      registration.addListeners();
-    },
-
-    disconnect: function() {
-      this.nodes_.forEach(function(node) {
-        var registrations = registrationsTable.get(node);
-        for (var i = 0; i < registrations.length; i++) {
-          var registration = registrations[i];
-          if (registration.observer === this) {
-            registration.removeListeners();
-            registrations.splice(i, 1);
-            // Each node can only have one registered observer associated with
-            // this observer.
-            break;
-          }
-        }
-      }, this);
-      this.records_ = [];
-    },
-
-    takeRecords: function() {
-      var copyOfRecords = this.records_;
-      this.records_ = [];
-      return copyOfRecords;
-    }
-  };
-
-  /**
-   * @param {string} type
-   * @param {Node} target
-   * @constructor
-   */
-  function MutationRecord(type, target) {
-    this.type = type;
-    this.target = target;
-    this.addedNodes = [];
-    this.removedNodes = [];
-    this.previousSibling = null;
-    this.nextSibling = null;
-    this.attributeName = null;
-    this.attributeNamespace = null;
-    this.oldValue = null;
-  }
-
-  function copyMutationRecord(original) {
-    var record = new MutationRecord(original.type, original.target);
-    record.addedNodes = original.addedNodes.slice();
-    record.removedNodes = original.removedNodes.slice();
-    record.previousSibling = original.previousSibling;
-    record.nextSibling = original.nextSibling;
-    record.attributeName = original.attributeName;
-    record.attributeNamespace = original.attributeNamespace;
-    record.oldValue = original.oldValue;
-    return record;
-  };
-
-  // We keep track of the two (possibly one) records used in a single mutation.
-  var currentRecord, recordWithOldValue;
-
-  /**
-   * Creates a record without |oldValue| and caches it as |currentRecord| for
-   * later use.
-   * @param {string} oldValue
-   * @return {MutationRecord}
-   */
-  function getRecord(type, target) {
-    return currentRecord = new MutationRecord(type, target);
-  }
-
-  /**
-   * Gets or creates a record with |oldValue| based in the |currentRecord|
-   * @param {string} oldValue
-   * @return {MutationRecord}
-   */
-  function getRecordWithOldValue(oldValue) {
-    if (recordWithOldValue)
-      return recordWithOldValue;
-    recordWithOldValue = copyMutationRecord(currentRecord);
-    recordWithOldValue.oldValue = oldValue;
-    return recordWithOldValue;
-  }
-
-  function clearRecords() {
-    currentRecord = recordWithOldValue = undefined;
-  }
-
-  /**
-   * @param {MutationRecord} record
-   * @return {boolean} Whether the record represents a record from the current
-   * mutation event.
-   */
-  function recordRepresentsCurrentMutation(record) {
-    return record === recordWithOldValue || record === currentRecord;
-  }
-
-  /**
-   * Selects which record, if any, to replace the last record in the queue.
-   * This returns |null| if no record should be replaced.
-   *
-   * @param {MutationRecord} lastRecord
-   * @param {MutationRecord} newRecord
-   * @param {MutationRecord}
-   */
-  function selectRecord(lastRecord, newRecord) {
-    if (lastRecord === newRecord)
-      return lastRecord;
-
-    // Check if the the record we are adding represents the same record. If
-    // so, we keep the one with the oldValue in it.
-    if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord))
-      return recordWithOldValue;
-
-    return null;
-  }
-
-  /**
-   * Class used to represent a registered observer.
-   * @param {MutationObserver} observer
-   * @param {Node} target
-   * @param {MutationObserverInit} options
-   * @constructor
-   */
-  function Registration(observer, target, options) {
-    this.observer = observer;
-    this.target = target;
-    this.options = options;
-    this.transientObservedNodes = [];
-  }
-
-  Registration.prototype = {
-    enqueue: function(record) {
-      var records = this.observer.records_;
-      var length = records.length;
-
-      // There are cases where we replace the last record with the new record.
-      // For example if the record represents the same mutation we need to use
-      // the one with the oldValue. If we get same record (this can happen as we
-      // walk up the tree) we ignore the new record.
-      if (records.length > 0) {
-        var lastRecord = records[length - 1];
-        var recordToReplaceLast = selectRecord(lastRecord, record);
-        if (recordToReplaceLast) {
-          records[length - 1] = recordToReplaceLast;
-          return;
-        }
-      } else {
-        scheduleCallback(this.observer);
-      }
-
-      records[length] = record;
-    },
-
-    addListeners: function() {
-      this.addListeners_(this.target);
-    },
-
-    addListeners_: function(node) {
-      var options = this.options;
-      if (options.attributes)
-        node.addEventListener('DOMAttrModified', this, true);
-
-      if (options.characterData)
-        node.addEventListener('DOMCharacterDataModified', this, true);
-
-      if (options.childList)
-        node.addEventListener('DOMNodeInserted', this, true);
-
-      if (options.childList || options.subtree)
-        node.addEventListener('DOMNodeRemoved', this, true);
-    },
-
-    removeListeners: function() {
-      this.removeListeners_(this.target);
-    },
-
-    removeListeners_: function(node) {
-      var options = this.options;
-      if (options.attributes)
-        node.removeEventListener('DOMAttrModified', this, true);
-
-      if (options.characterData)
-        node.removeEventListener('DOMCharacterDataModified', this, true);
-
-      if (options.childList)
-        node.removeEventListener('DOMNodeInserted', this, true);
-
-      if (options.childList || options.subtree)
-        node.removeEventListener('DOMNodeRemoved', this, true);
-    },
-
-    /**
-     * Adds a transient observer on node. The transient observer gets removed
-     * next time we deliver the change records.
-     * @param {Node} node
-     */
-    addTransientObserver: function(node) {
-      // Don't add transient observers on the target itself. We already have all
-      // the required listeners set up on the target.
-      if (node === this.target)
-        return;
-
-      this.addListeners_(node);
-      this.transientObservedNodes.push(node);
-      var registrations = registrationsTable.get(node);
-      if (!registrations)
-        registrationsTable.set(node, registrations = []);
-
-      // We know that registrations does not contain this because we already
-      // checked if node === this.target.
-      registrations.push(this);
-    },
-
-    removeTransientObservers: function() {
-      var transientObservedNodes = this.transientObservedNodes;
-      this.transientObservedNodes = [];
-
-      transientObservedNodes.forEach(function(node) {
-        // Transient observers are never added to the target.
-        this.removeListeners_(node);
-
-        var registrations = registrationsTable.get(node);
-        for (var i = 0; i < registrations.length; i++) {
-          if (registrations[i] === this) {
-            registrations.splice(i, 1);
-            // Each node can only have one registered observer associated with
-            // this observer.
-            break;
-          }
-        }
-      }, this);
-    },
-
-    handleEvent: function(e) {
-      // Stop propagation since we are managing the propagation manually.
-      // This means that other mutation events on the page will not work
-      // correctly but that is by design.
-      e.stopImmediatePropagation();
-
-      switch (e.type) {
-        case 'DOMAttrModified':
-          // http://dom.spec.whatwg.org/#concept-mo-queue-attributes
-
-          var name = e.attrName;
-          var namespace = e.relatedNode.namespaceURI;
-          var target = e.target;
-
-          // 1.
-          var record = new getRecord('attributes', target);
-          record.attributeName = name;
-          record.attributeNamespace = namespace;
-
-          // 2.
-          var oldValue =
-              e.attrChange === MutationEvent.ADDITION ? null : e.prevValue;
-
-          forEachAncestorAndObserverEnqueueRecord(target, function(options) {
-            // 3.1, 4.2
-            if (!options.attributes)
-              return;
-
-            // 3.2, 4.3
-            if (options.attributeFilter && options.attributeFilter.length &&
-                options.attributeFilter.indexOf(name) === -1 &&
-                options.attributeFilter.indexOf(namespace) === -1) {
-              return;
-            }
-            // 3.3, 4.4
-            if (options.attributeOldValue)
-              return getRecordWithOldValue(oldValue);
-
-            // 3.4, 4.5
-            return record;
-          });
-
-          break;
-
-        case 'DOMCharacterDataModified':
-          // http://dom.spec.whatwg.org/#concept-mo-queue-characterdata
-          var target = e.target;
-
-          // 1.
-          var record = getRecord('characterData', target);
-
-          // 2.
-          var oldValue = e.prevValue;
-
-
-          forEachAncestorAndObserverEnqueueRecord(target, function(options) {
-            // 3.1, 4.2
-            if (!options.characterData)
-              return;
-
-            // 3.2, 4.3
-            if (options.characterDataOldValue)
-              return getRecordWithOldValue(oldValue);
-
-            // 3.3, 4.4
-            return record;
-          });
-
-          break;
-
-        case 'DOMNodeRemoved':
-          this.addTransientObserver(e.target);
-          // Fall through.
-        case 'DOMNodeInserted':
-          // http://dom.spec.whatwg.org/#concept-mo-queue-childlist
-          var target = e.relatedNode;
-          var changedNode = e.target;
-          var addedNodes, removedNodes;
-          if (e.type === 'DOMNodeInserted') {
-            addedNodes = [changedNode];
-            removedNodes = [];
-          } else {
-
-            addedNodes = [];
-            removedNodes = [changedNode];
-          }
-          var previousSibling = changedNode.previousSibling;
-          var nextSibling = changedNode.nextSibling;
-
-          // 1.
-          var record = getRecord('childList', target);
-          record.addedNodes = addedNodes;
-          record.removedNodes = removedNodes;
-          record.previousSibling = previousSibling;
-          record.nextSibling = nextSibling;
-
-          forEachAncestorAndObserverEnqueueRecord(target, function(options) {
-            // 2.1, 3.2
-            if (!options.childList)
-              return;
-
-            // 2.2, 3.3
-            return record;
-          });
-
-      }
-
-      clearRecords();
-    }
-  };
-
-  global.JsMutationObserver = JsMutationObserver;
-
-  if (!global.MutationObserver)
-    global.MutationObserver = JsMutationObserver;
-
-
-})(this);
-
-window.CustomElements = window.CustomElements || {flags:{}};
-(function(scope){

-

-var logFlags = window.logFlags || {};

-var IMPORT_LINK_TYPE = window.HTMLImports ? HTMLImports.IMPORT_LINK_TYPE : 'none';

-

-// walk the subtree rooted at node, applying 'find(element, data)' function

-// to each element

-// if 'find' returns true for 'element', do not search element's subtree

-function findAll(node, find, data) {

-  var e = node.firstElementChild;

-  if (!e) {

-    e = node.firstChild;

-    while (e && e.nodeType !== Node.ELEMENT_NODE) {

-      e = e.nextSibling;

-    }

-  }

-  while (e) {

-    if (find(e, data) !== true) {

-      findAll(e, find, data);

-    }

-    e = e.nextElementSibling;

-  }

-  return null;

-}

-

-// walk all shadowRoots on a given node.

-function forRoots(node, cb) {

-  var root = node.shadowRoot;

-  while(root) {

-    forSubtree(root, cb);

-    root = root.olderShadowRoot;

-  }

-}

-

-// walk the subtree rooted at node, including descent into shadow-roots,

-// applying 'cb' to each element

-function forSubtree(node, cb) {

-  //logFlags.dom && node.childNodes && node.childNodes.length && console.group('subTree: ', node);

-  findAll(node, function(e) {

-    if (cb(e)) {

-      return true;

-    }

-    forRoots(e, cb);

-  });

-  forRoots(node, cb);

-  //logFlags.dom && node.childNodes && node.childNodes.length && console.groupEnd();

-}

-

-// manage lifecycle on added node

-function added(node) {

-  if (upgrade(node)) {

-    insertedNode(node);

-    return true;

-  }

-  inserted(node);

-}

-

-// manage lifecycle on added node's subtree only

-function addedSubtree(node) {

-  forSubtree(node, function(e) {

-    if (added(e)) {

-      return true;

-    }

-  });

-}

-

-// manage lifecycle on added node and it's subtree

-function addedNode(node) {

-  return added(node) || addedSubtree(node);

-}

-

-// upgrade custom elements at node, if applicable

-function upgrade(node) {

-  if (!node.__upgraded__ && node.nodeType === Node.ELEMENT_NODE) {

-    var type = node.getAttribute('is') || node.localName;

-    var definition = scope.registry[type];

-    if (definition) {

-      logFlags.dom && console.group('upgrade:', node.localName);

-      scope.upgrade(node);

-      logFlags.dom && console.groupEnd();

-      return true;

-    }

-  }

-}

-

-function insertedNode(node) {

-  inserted(node);

-  if (inDocument(node)) {

-    forSubtree(node, function(e) {

-      inserted(e);

-    });

-  }

-}

-

-

-// TODO(sorvell): on platforms without MutationObserver, mutations may not be

-// reliable and therefore attached/detached are not reliable.

-// To make these callbacks less likely to fail, we defer all inserts and removes

-// to give a chance for elements to be inserted into dom.

-// This ensures attachedCallback fires for elements that are created and

-// immediately added to dom.

-var hasPolyfillMutations = (!window.MutationObserver ||

-    (window.MutationObserver === window.JsMutationObserver));

-scope.hasPolyfillMutations = hasPolyfillMutations;

-

-var isPendingMutations = false;

-var pendingMutations = [];

-function deferMutation(fn) {

-  pendingMutations.push(fn);

-  if (!isPendingMutations) {

-    isPendingMutations = true;

-    var async = (window.Platform && window.Platform.endOfMicrotask) ||

-        setTimeout;

-    async(takeMutations);

-  }

-}

-

-function takeMutations() {

-  isPendingMutations = false;

-  var $p = pendingMutations;

-  for (var i=0, l=$p.length, p; (i<l) && (p=$p[i]); i++) {

-    p();

-  }

-  pendingMutations = [];

-}

-

-function inserted(element) {

-  if (hasPolyfillMutations) {

-    deferMutation(function() {

-      _inserted(element);

-    });

-  } else {

-    _inserted(element);

-  }

-}

-

-// TODO(sjmiles): if there are descents into trees that can never have inDocument(*) true, fix this

-function _inserted(element) {

-  // TODO(sjmiles): it's possible we were inserted and removed in the space

-  // of one microtask, in which case we won't be 'inDocument' here

-  // But there are other cases where we are testing for inserted without

-  // specific knowledge of mutations, and must test 'inDocument' to determine

-  // whether to call inserted

-  // If we can factor these cases into separate code paths we can have

-  // better diagnostics.

-  // TODO(sjmiles): when logging, do work on all custom elements so we can

-  // track behavior even when callbacks not defined

-  //console.log('inserted: ', element.localName);

-  if (element.attachedCallback || element.detachedCallback || (element.__upgraded__ && logFlags.dom)) {

-    logFlags.dom && console.group('inserted:', element.localName);

-    if (inDocument(element)) {

-      element.__inserted = (element.__inserted || 0) + 1;

-      // if we are in a 'removed' state, bluntly adjust to an 'inserted' state

-      if (element.__inserted < 1) {

-        element.__inserted = 1;

-      }

-      // if we are 'over inserted', squelch the callback

-      if (element.__inserted > 1) {

-        logFlags.dom && console.warn('inserted:', element.localName,

-          'insert/remove count:', element.__inserted)

-      } else if (element.attachedCallback) {

-        logFlags.dom && console.log('inserted:', element.localName);

-        element.attachedCallback();

-      }

-    }

-    logFlags.dom && console.groupEnd();

-  }

-}

-

-function removedNode(node) {

-  removed(node);

-  forSubtree(node, function(e) {

-    removed(e);

-  });

-}

-

-function removed(element) {

-  if (hasPolyfillMutations) {

-    deferMutation(function() {

-      _removed(element);

-    });

-  } else {

-    _removed(element);

-  }

-}

-

-function _removed(element) {

-  // TODO(sjmiles): temporary: do work on all custom elements so we can track

-  // behavior even when callbacks not defined

-  if (element.attachedCallback || element.detachedCallback || (element.__upgraded__ && logFlags.dom)) {

-    logFlags.dom && console.group('removed:', element.localName);

-    if (!inDocument(element)) {

-      element.__inserted = (element.__inserted || 0) - 1;

-      // if we are in a 'inserted' state, bluntly adjust to an 'removed' state

-      if (element.__inserted > 0) {

-        element.__inserted = 0;

-      }

-      // if we are 'over removed', squelch the callback

-      if (element.__inserted < 0) {

-        logFlags.dom && console.warn('removed:', element.localName,

-            'insert/remove count:', element.__inserted)

-      } else if (element.detachedCallback) {

-        element.detachedCallback();

-      }

-    }

-    logFlags.dom && console.groupEnd();

-  }

-}

-

-// SD polyfill intrustion due mainly to the fact that 'document'

-// is not entirely wrapped

-function wrapIfNeeded(node) {

-  return window.ShadowDOMPolyfill ? ShadowDOMPolyfill.wrapIfNeeded(node)

-      : node;

-}

-

-function inDocument(element) {

-  var p = element;

-  var doc = wrapIfNeeded(document);

-  while (p) {

-    if (p == doc) {

-      return true;

-    }

-    p = p.parentNode || p.host;

-  }

-}

-

-function watchShadow(node) {

-  if (node.shadowRoot && !node.shadowRoot.__watched) {

-    logFlags.dom && console.log('watching shadow-root for: ', node.localName);

-    // watch all unwatched roots...

-    var root = node.shadowRoot;

-    while (root) {

-      watchRoot(root);

-      root = root.olderShadowRoot;

-    }

-  }

-}

-

-function watchRoot(root) {

-  if (!root.__watched) {

-    observe(root);

-    root.__watched = true;

-  }

-}

-

-function handler(mutations) {

-  //

-  if (logFlags.dom) {

-    var mx = mutations[0];

-    if (mx && mx.type === 'childList' && mx.addedNodes) {

-        if (mx.addedNodes) {

-          var d = mx.addedNodes[0];

-          while (d && d !== document && !d.host) {

-            d = d.parentNode;

-          }

-          var u = d && (d.URL || d._URL || (d.host && d.host.localName)) || '';

-          u = u.split('/?').shift().split('/').pop();

-        }

-    }

-    console.group('mutations (%d) [%s]', mutations.length, u || '');

-  }

-  //

-  mutations.forEach(function(mx) {

-    //logFlags.dom && console.group('mutation');

-    if (mx.type === 'childList') {

-      forEach(mx.addedNodes, function(n) {

-        //logFlags.dom && console.log(n.localName);

-        if (!n.localName) {

-          return;

-        }

-        // nodes added may need lifecycle management

-        addedNode(n);

-      });

-      // removed nodes may need lifecycle management

-      forEach(mx.removedNodes, function(n) {

-        //logFlags.dom && console.log(n.localName);

-        if (!n.localName) {

-          return;

-        }

-        removedNode(n);

-      });

-    }

-    //logFlags.dom && console.groupEnd();

-  });

-  logFlags.dom && console.groupEnd();

-};

-

-var observer = new MutationObserver(handler);

-

-function takeRecords() {

-  // TODO(sjmiles): ask Raf why we have to call handler ourselves

-  handler(observer.takeRecords());

-  takeMutations();

-}

-

-var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);

-

-function observe(inRoot) {

-  observer.observe(inRoot, {childList: true, subtree: true});

-}

-

-function observeDocument(doc) {

-  observe(doc);

-}

-

-function upgradeDocument(doc) {

-  logFlags.dom && console.group('upgradeDocument: ', (doc.baseURI).split('/').pop());

-  addedNode(doc);

-  logFlags.dom && console.groupEnd();

-}

-

-function upgradeDocumentTree(doc) {

-  doc = wrapIfNeeded(doc);

-  upgradeDocument(doc);

-  //console.log('upgradeDocumentTree: ', (doc.baseURI).split('/').pop());

-  // upgrade contained imported documents

-  var imports = doc.querySelectorAll('link[rel=' + IMPORT_LINK_TYPE + ']');

-  for (var i=0, l=imports.length, n; (i<l) && (n=imports[i]); i++) {

-    if (n.import && n.import.__parsed) {

-      upgradeDocumentTree(n.import);

-    }

-  }

-}

-

-// exports

-scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;

-scope.watchShadow = watchShadow;

-scope.upgradeDocumentTree = upgradeDocumentTree;

-scope.upgradeAll = addedNode;

-scope.upgradeSubtree = addedSubtree;

-

-scope.observeDocument = observeDocument;

-scope.upgradeDocument = upgradeDocument;

-

-scope.takeRecords = takeRecords;

-

-})(window.CustomElements);

-
-/**
- * Implements `document.register`
- * @module CustomElements
-*/
-
-/**
- * Polyfilled extensions to the `document` object.
- * @class Document
-*/
-
-(function(scope) {
-
-// imports
-
-if (!scope) {
-  scope = window.CustomElements = {flags:{}};
-}
-var flags = scope.flags;
-
-// native document.registerElement?
-
-var hasNative = Boolean(document.registerElement);
-// TODO(sorvell): See https://github.com/Polymer/polymer/issues/399
-// we'll address this by defaulting to CE polyfill in the presence of the SD
-// polyfill. This will avoid spamming excess attached/detached callbacks.
-// If there is a compelling need to run CE native with SD polyfill,
-// we'll need to fix this issue.
-var useNative = !flags.register && hasNative && !window.ShadowDOMPolyfill;
-
-if (useNative) {
-
-  // stub
-  var nop = function() {};
-
-  // exports
-  scope.registry = {};
-  scope.upgradeElement = nop;
-
-  scope.watchShadow = nop;
-  scope.upgrade = nop;
-  scope.upgradeAll = nop;
-  scope.upgradeSubtree = nop;
-  scope.observeDocument = nop;
-  scope.upgradeDocument = nop;
-  scope.upgradeDocumentTree = nop;
-  scope.takeRecords = nop;
-
-} else {
-
-  /**
-   * Registers a custom tag name with the document.
-   *
-   * When a registered element is created, a `readyCallback` method is called
-   * in the scope of the element. The `readyCallback` method can be specified on
-   * either `options.prototype` or `options.lifecycle` with the latter taking
-   * precedence.
-   *
-   * @method register
-   * @param {String} name The tag name to register. Must include a dash ('-'),
-   *    for example 'x-component'.
-   * @param {Object} options
-   *    @param {String} [options.extends]
-   *      (_off spec_) Tag name of an element to extend (or blank for a new
-   *      element). This parameter is not part of the specification, but instead
-   *      is a hint for the polyfill because the extendee is difficult to infer.
-   *      Remember that the input prototype must chain to the extended element's
-   *      prototype (or HTMLElement.prototype) regardless of the value of
-   *      `extends`.
-   *    @param {Object} options.prototype The prototype to use for the new
-   *      element. The prototype must inherit from HTMLElement.
-   *    @param {Object} [options.lifecycle]
-   *      Callbacks that fire at important phases in the life of the custom
-   *      element.
-   *
-   * @example
-   *      FancyButton = document.registerElement("fancy-button", {
-   *        extends: 'button',
-   *        prototype: Object.create(HTMLButtonElement.prototype, {
-   *          readyCallback: {
-   *            value: function() {
-   *              console.log("a fancy-button was created",
-   *            }
-   *          }
-   *        })
-   *      });
-   * @return {Function} Constructor for the newly registered type.
-   */
-  function register(name, options) {
-    //console.warn('document.registerElement("' + name + '", ', options, ')');
-    // construct a defintion out of options
-    // TODO(sjmiles): probably should clone options instead of mutating it
-    var definition = options || {};
-    if (!name) {
-      // TODO(sjmiles): replace with more appropriate error (EricB can probably
-      // offer guidance)
-      throw new Error('document.registerElement: first argument `name` must not be empty');
-    }
-    if (name.indexOf('-') < 0) {
-      // TODO(sjmiles): replace with more appropriate error (EricB can probably
-      // offer guidance)
-      throw new Error('document.registerElement: first argument (\'name\') must contain a dash (\'-\'). Argument provided was \'' + String(name) + '\'.');
-    }
-    // elements may only be registered once
-    if (getRegisteredDefinition(name)) {
-      throw new Error('DuplicateDefinitionError: a type with name \'' + String(name) + '\' is already registered');
-    }
-    // must have a prototype, default to an extension of HTMLElement
-    // TODO(sjmiles): probably should throw if no prototype, check spec
-    if (!definition.prototype) {
-      // TODO(sjmiles): replace with more appropriate error (EricB can probably
-      // offer guidance)
-      throw new Error('Options missing required prototype property');
-    }
-    // record name
-    definition.__name = name.toLowerCase();
-    // ensure a lifecycle object so we don't have to null test it
-    definition.lifecycle = definition.lifecycle || {};
-    // build a list of ancestral custom elements (for native base detection)
-    // TODO(sjmiles): we used to need to store this, but current code only
-    // uses it in 'resolveTagName': it should probably be inlined
-    definition.ancestry = ancestry(definition.extends);
-    // extensions of native specializations of HTMLElement require localName
-    // to remain native, and use secondary 'is' specifier for extension type
-    resolveTagName(definition);
-    // some platforms require modifications to the user-supplied prototype
-    // chain
-    resolvePrototypeChain(definition);
-    // overrides to implement attributeChanged callback
-    overrideAttributeApi(definition.prototype);
-    // 7.1.5: Register the DEFINITION with DOCUMENT
-    registerDefinition(definition.__name, definition);
-    // 7.1.7. Run custom element constructor generation algorithm with PROTOTYPE
-    // 7.1.8. Return the output of the previous step.
-    definition.ctor = generateConstructor(definition);
-    definition.ctor.prototype = definition.prototype;
-    // force our .constructor to be our actual constructor
-    definition.prototype.constructor = definition.ctor;
-    // if initial parsing is complete
-    if (scope.ready || scope.performedInitialDocumentUpgrade) {
-      // upgrade any pre-existing nodes of this type
-      scope.upgradeDocumentTree(document);
-    }
-    return definition.ctor;
-  }
-
-  function ancestry(extnds) {
-    var extendee = getRegisteredDefinition(extnds);
-    if (extendee) {
-      return ancestry(extendee.extends).concat([extendee]);
-    }
-    return [];
-  }
-
-  function resolveTagName(definition) {
-    // if we are explicitly extending something, that thing is our
-    // baseTag, unless it represents a custom component
-    var baseTag = definition.extends;
-    // if our ancestry includes custom components, we only have a
-    // baseTag if one of them does
-    for (var i=0, a; (a=definition.ancestry[i]); i++) {
-      baseTag = a.is && a.tag;
-    }
-    // our tag is our baseTag, if it exists, and otherwise just our name
-    definition.tag = baseTag || definition.__name;
-    if (baseTag) {
-      // if there is a base tag, use secondary 'is' specifier
-      definition.is = definition.__name;
-    }
-  }
-
-  function resolvePrototypeChain(definition) {
-    // if we don't support __proto__ we need to locate the native level
-    // prototype for precise mixing in
-    if (!Object.__proto__) {
-      // default prototype
-      var nativePrototype = HTMLElement.prototype;
-      // work out prototype when using type-extension
-      if (definition.is) {
-        var inst = document.createElement(definition.tag);
-        nativePrototype = Object.getPrototypeOf(inst);
-      }
-      // ensure __proto__ reference is installed at each point on the prototype
-      // chain.
-      // NOTE: On platforms without __proto__, a mixin strategy is used instead
-      // of prototype swizzling. In this case, this generated __proto__ provides
-      // limited support for prototype traversal.
-      var proto = definition.prototype, ancestor;
-      while (proto && (proto !== nativePrototype)) {
-        var ancestor = Object.getPrototypeOf(proto);
-        proto.__proto__ = ancestor;
-        proto = ancestor;
-      }
-    }
-    // cache this in case of mixin
-    definition.native = nativePrototype;
-  }
-
-  // SECTION 4
-
-  function instantiate(definition) {
-    // 4.a.1. Create a new object that implements PROTOTYPE
-    // 4.a.2. Let ELEMENT by this new object
-    //
-    // the custom element instantiation algorithm must also ensure that the
-    // output is a valid DOM element with the proper wrapper in place.
-    //
-    return upgrade(domCreateElement(definition.tag), definition);
-  }
-
-  function upgrade(element, definition) {
-    // some definitions specify an 'is' attribute
-    if (definition.is) {
-      element.setAttribute('is', definition.is);
-    }
-    // remove 'unresolved' attr, which is a standin for :unresolved.
-    element.removeAttribute('unresolved');
-    // make 'element' implement definition.prototype
-    implement(element, definition);
-    // flag as upgraded
-    element.__upgraded__ = true;
-    // lifecycle management
-    created(element);
-    // there should never be a shadow root on element at this point
-    // we require child nodes be upgraded before `created`
-    scope.upgradeSubtree(element);
-    // OUTPUT
-    return element;
-  }
-
-  function implement(element, definition) {
-    // prototype swizzling is best
-    if (Object.__proto__) {
-      element.__proto__ = definition.prototype;
-    } else {
-      // where above we can re-acquire inPrototype via
-      // getPrototypeOf(Element), we cannot do so when
-      // we use mixin, so we install a magic reference
-      customMixin(element, definition.prototype, definition.native);
-      element.__proto__ = definition.prototype;
-    }
-  }
-
-  function customMixin(inTarget, inSrc, inNative) {
-    // TODO(sjmiles): 'used' allows us to only copy the 'youngest' version of
-    // any property. This set should be precalculated. We also need to
-    // consider this for supporting 'super'.
-    var used = {};
-    // start with inSrc
-    var p = inSrc;
-    // sometimes the default is HTMLUnknownElement.prototype instead of
-    // HTMLElement.prototype, so we add a test
-    // the idea is to avoid mixing in native prototypes, so adding
-    // the second test is WLOG
-    while (p !== inNative && p !== HTMLUnknownElement.prototype) {
-      var keys = Object.getOwnPropertyNames(p);
-      for (var i=0, k; k=keys[i]; i++) {
-        if (!used[k]) {
-          Object.defineProperty(inTarget, k,
-              Object.getOwnPropertyDescriptor(p, k));
-          used[k] = 1;
-        }
-      }
-      p = Object.getPrototypeOf(p);
-    }
-  }
-
-  function created(element) {
-    // invoke createdCallback
-    if (element.createdCallback) {
-      element.createdCallback();
-    }
-  }
-
-  // attribute watching
-
-  function overrideAttributeApi(prototype) {
-    // overrides to implement callbacks
-    // TODO(sjmiles): should support access via .attributes NamedNodeMap
-    // TODO(sjmiles): preserves user defined overrides, if any
-    if (prototype.setAttribute._polyfilled) {
-      return;
-    }
-    var setAttribute = prototype.setAttribute;
-    prototype.setAttribute = function(name, value) {
-      changeAttribute.call(this, name, value, setAttribute);
-    }
-    var removeAttribute = prototype.removeAttribute;
-    prototype.removeAttribute = function(name) {
-      changeAttribute.call(this, name, null, removeAttribute);
-    }
-    prototype.setAttribute._polyfilled = true;
-  }
-
-  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/
-  // index.html#dfn-attribute-changed-callback
-  function changeAttribute(name, value, operation) {
-    var oldValue = this.getAttribute(name);
-    operation.apply(this, arguments);
-    var newValue = this.getAttribute(name);
-    if (this.attributeChangedCallback
-        && (newValue !== oldValue)) {
-      this.attributeChangedCallback(name, oldValue, newValue);
-    }
-  }
-
-  // element registry (maps tag names to definitions)
-
-  var registry = {};
-
-  function getRegisteredDefinition(name) {
-    if (name) {
-      return registry[name.toLowerCase()];
-    }
-  }
-
-  function registerDefinition(name, definition) {
-    if (registry[name]) {
-      throw new Error('a type with that name is already registered.');
-    }
-    registry[name] = definition;
-  }
-
-  function generateConstructor(definition) {
-    return function() {
-      return instantiate(definition);
-    };
-  }
-
-  function createElement(tag, typeExtension) {
-    // TODO(sjmiles): ignore 'tag' when using 'typeExtension', we could
-    // error check it, or perhaps there should only ever be one argument
-    var definition = getRegisteredDefinition(typeExtension || tag);
-    if (definition) {
-      if (tag == definition.tag && typeExtension == definition.is) {
-        return new definition.ctor();
-      }
-      // Handle empty string for type extension.
-      if (!typeExtension && !definition.is) {
-        return new definition.ctor();
-      }
-    }
-
-    if (typeExtension) {
-      var element = createElement(tag);
-      element.setAttribute('is', typeExtension);
-      return element;
-    }
-    var element = domCreateElement(tag);
-    // Custom tags should be HTMLElements even if not upgraded.
-    if (tag.indexOf('-') >= 0) {
-      implement(element, HTMLElement);
-    }
-    return element;
-  }
-
-  function upgradeElement(element) {
-    if (!element.__upgraded__ && (element.nodeType === Node.ELEMENT_NODE)) {
-      var is = element.getAttribute('is');
-      var definition = registry[is || element.localName];
-      if (definition) {
-        if (is && definition.tag == element.localName) {
-          return upgrade(element, definition);
-        } else if (!is && !definition.extends) {
-          return upgrade(element, definition);
-        }
-      }
-    }
-  }
-
-  function cloneNode(deep) {
-    // call original clone
-    var n = domCloneNode.call(this, deep);
-    // upgrade the element and subtree
-    scope.upgradeAll(n);
-    // return the clone
-    return n;
-  }
-  // capture native createElement before we override it
-
-  var domCreateElement = document.createElement.bind(document);
-
-  // capture native cloneNode before we override it
-
-  var domCloneNode = Node.prototype.cloneNode;
-
-  // exports
-
-  document.registerElement = register;
-  document.createElement = createElement; // override
-  Node.prototype.cloneNode = cloneNode; // override
-
-  scope.registry = registry;
-
-  /**
-   * Upgrade an element to a custom element. Upgrading an element
-   * causes the custom prototype to be applied, an `is` attribute
-   * to be attached (as needed), and invocation of the `readyCallback`.
-   * `upgrade` does nothing if the element is already upgraded, or
-   * if it matches no registered custom tag name.
-   *
-   * @method ugprade
-   * @param {Element} element The element to upgrade.
-   * @return {Element} The upgraded element.
-   */
-  scope.upgrade = upgradeElement;
-}
-
-// bc
-document.register = document.registerElement;
-
-scope.hasNative = hasNative;
-scope.useNative = useNative;
-
-})(window.CustomElements);
-
-(function(scope) {
-
-// import
-
-var IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;
-
-// highlander object for parsing a document tree
-
-var parser = {
-  selectors: [
-    'link[rel=' + IMPORT_LINK_TYPE + ']'
-  ],
-  map: {
-    link: 'parseLink'
-  },
-  parse: function(inDocument) {
-    if (!inDocument.__parsed) {
-      // only parse once
-      inDocument.__parsed = true;
-      // all parsable elements in inDocument (depth-first pre-order traversal)
-      var elts = inDocument.querySelectorAll(parser.selectors);
-      // for each parsable node type, call the mapped parsing method
-      forEach(elts, function(e) {
-        parser[parser.map[e.localName]](e);
-      });
-      // upgrade all upgradeable static elements, anything dynamically
-      // created should be caught by observer
-      CustomElements.upgradeDocument(inDocument);
-      // observe document for dom changes
-      CustomElements.observeDocument(inDocument);
-    }
-  },
-  parseLink: function(linkElt) {
-    // imports
-    if (isDocumentLink(linkElt)) {
-      this.parseImport(linkElt);
-    }
-  },
-  parseImport: function(linkElt) {
-    if (linkElt.import) {
-      parser.parse(linkElt.import);
-    }
-  }
-};
-
-function isDocumentLink(inElt) {
-  return (inElt.localName === 'link'
-      && inElt.getAttribute('rel') === IMPORT_LINK_TYPE);
-}
-
-var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
-
-// exports
-
-scope.parser = parser;
-scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;
-
-})(window.CustomElements);
-(function(scope){
-
-// bootstrap parsing
-function bootstrap() {
-  // parse document
-  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 :
-    setTimeout;
-  async(function() {
-    // set internal 'ready' flag, now document.registerElement will trigger
-    // synchronous upgrades
-    CustomElements.ready = true;
-    // capture blunt profiling data
-    CustomElements.readyTime = Date.now();
-    if (window.HTMLImports) {
-      CustomElements.elapsed = CustomElements.readyTime - HTMLImports.readyTime;
-    }
-    // notify the system that we are bootstrapped
-    document.dispatchEvent(
-      new CustomEvent('WebComponentsReady', {bubbles: true})
-    );
-  });
-}
-
-// CustomEvent shim for IE
-if (typeof window.CustomEvent !== 'function') {
-  window.CustomEvent = function(inType) {
-    var e = document.createEvent('HTMLEvents');
-    e.initEvent(inType, true, true);
-    return e;
-  };
-}
-
-// When loading at readyState complete time (or via flag), boot custom elements
-// immediately.
-// If relevant, HTMLImports must already be loaded.
-if (document.readyState === 'complete' || scope.flags.eager) {
-  bootstrap();
-// When loading at readyState interactive time, bootstrap only if HTMLImports
-// are not pending. Also avoid IE as the semantics of this state are unreliable.
-} else if (document.readyState === 'interactive' && !window.attachEvent &&
-    (!window.HTMLImports || window.HTMLImports.ready)) {
-  bootstrap();
-// When loading at other readyStates, wait for the appropriate DOM event to
-// bootstrap.
-} else {
-  var loadEvent = window.HTMLImports && !HTMLImports.ready ?
-      'HTMLImportsLoaded' : document.readyState == 'loading' ?
-        'DOMContentLoaded' : 'load';
-  window.addEventListener(loadEvent, bootstrap);
-}
-
-})(window.CustomElements);
-
-(function() {
-// Patch to allow custom element and shadow dom to work together, from:
-// https://github.com/Polymer/platform-dev/blob/60ece8c323c5d9325cbfdfd6e8cd180d4f38a3bc/src/patches-shadowdom-polyfill.js
-// include .host reference
-if (HTMLElement.prototype.createShadowRoot) {
-  var originalCreateShadowRoot = HTMLElement.prototype.createShadowRoot;
-  HTMLElement.prototype.createShadowRoot = function() {
-    var root = originalCreateShadowRoot.call(this);
-    root.host = this;
-    CustomElements.watchShadow(this);
-    return root;
-  }
-}
-
-
-// Patch to allow custom elements and shadow dom to work together, from:
-// https://github.com/Polymer/platform-dev/blob/2bb9c56d90f9ac19c2e65cdad368668aff514f14/src/patches-custom-elements.js
-if (window.ShadowDOMPolyfill) {
-
-  // ensure wrapped inputs for these functions
-  var fns = ['upgradeAll', 'upgradeSubtree', 'observeDocument',
-      'upgradeDocument'];
-
-  // cache originals
-  var original = {};
-  fns.forEach(function(fn) {
-    original[fn] = CustomElements[fn];
-  });
-
-  // override
-  fns.forEach(function(fn) {
-    CustomElements[fn] = function(inNode) {
-      return original[fn](window.ShadowDOMPolyfill.wrapIfNeeded(inNode));
-    };
-  });
-
-}
-
-// Patch to make importNode work.
-// https://github.com/Polymer/platform-dev/blob/64a92f273462f04a84abbe2f054294f2b62dbcd6/src/patches-mdv.js
-if (window.CustomElements && !CustomElements.useNative) {
-  var originalImportNode = Document.prototype.importNode;
-  Document.prototype.importNode = function(node, deep) {
-    var imported = originalImportNode.call(this, node, deep);
-    CustomElements.upgradeAll(imported);
-    return imported;
-  }
-}
-
-})();
diff --git a/pkg/custom_element/lib/custom-elements.min.js b/pkg/custom_element/lib/custom-elements.min.js
deleted file mode 100644
index 78b0c76..0000000
--- a/pkg/custom_element/lib/custom-elements.min.js
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2012 The Polymer Authors. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// 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.
-"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}(),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 WeakMap,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,a.MutationObserver||(a.MutationObserver=g)}(this),window.CustomElements=window.CustomElements||{flags:{}},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 A.dom&&console.group("upgrade:",b.localName),a.upgrade(b),A.dom&&console.groupEnd(),!0}}function i(a){l(a),r(a)&&d(a,function(a){l(a)})}function j(a){if(E.push(a),!D){D=!0;var b=window.Platform&&window.Platform.endOfMicrotask||setTimeout;b(k)}}function k(){D=!1;for(var a,b=E,c=0,d=b.length;d>c&&(a=b[c]);c++)a();E=[]}function l(a){C?j(function(){m(a)}):m(a)}function m(a){(a.attachedCallback||a.detachedCallback||a.__upgraded__&&A.dom)&&(A.dom&&console.group("inserted:",a.localName),r(a)&&(a.__inserted=(a.__inserted||0)+1,a.__inserted<1&&(a.__inserted=1),a.__inserted>1?A.dom&&console.warn("inserted:",a.localName,"insert/remove count:",a.__inserted):a.attachedCallback&&(A.dom&&console.log("inserted:",a.localName),a.attachedCallback())),A.dom&&console.groupEnd())}function n(a){o(a),d(a,function(a){o(a)})}function o(a){C?j(function(){p(a)}):p(a)}function p(a){(a.attachedCallback||a.detachedCallback||a.__upgraded__&&A.dom)&&(A.dom&&console.group("removed:",a.localName),r(a)||(a.__inserted=(a.__inserted||0)-1,a.__inserted>0&&(a.__inserted=0),a.__inserted<0?A.dom&&console.warn("removed:",a.localName,"insert/remove count:",a.__inserted):a.detachedCallback&&a.detachedCallback()),A.dom&&console.groupEnd())}function q(a){return window.ShadowDOMPolyfill?ShadowDOMPolyfill.wrapIfNeeded(a):a}function r(a){for(var b=a,c=q(document);b;){if(b==c)return!0;b=b.parentNode||b.host}}function s(a){if(a.shadowRoot&&!a.shadowRoot.__watched){A.dom&&console.log("watching shadow-root for: ",a.localName);for(var b=a.shadowRoot;b;)t(b),b=b.olderShadowRoot}}function t(a){a.__watched||(w(a),a.__watched=!0)}function u(a){if(A.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&&(G(a.addedNodes,function(a){a.localName&&g(a)}),G(a.removedNodes,function(a){a.localName&&n(a)}))}),A.dom&&console.groupEnd()}function v(){u(F.takeRecords()),k()}function w(a){F.observe(a,{childList:!0,subtree:!0})}function x(a){w(a)}function y(a){A.dom&&console.group("upgradeDocument: ",a.baseURI.split("/").pop()),g(a),A.dom&&console.groupEnd()}function z(a){a=q(a),y(a);for(var b,c=a.querySelectorAll("link[rel="+B+"]"),d=0,e=c.length;e>d&&(b=c[d]);d++)b.import&&b.import.__parsed&&z(b.import)}var A=window.logFlags||{},B=window.HTMLImports?HTMLImports.IMPORT_LINK_TYPE:"none",C=!window.MutationObserver||window.MutationObserver===window.JsMutationObserver;a.hasPolyfillMutations=C;var D=!1,E=[],F=new MutationObserver(u),G=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.IMPORT_LINK_TYPE=B,a.watchShadow=s,a.upgradeDocumentTree=z,a.upgradeAll=g,a.upgradeSubtree=f,a.observeDocument=x,a.upgradeDocument=y,a.takeRecords=v}(window.CustomElements),function(a){function b(b,f){var g=f||{};if(!b)throw new Error("document.registerElement: first argument `name` must not be empty");if(b.indexOf("-")<0)throw new Error("document.registerElement: first argument ('name') must contain a dash ('-'). Argument provided was '"+String(b)+"'.");if(m(b))throw new Error("DuplicateDefinitionError: a type with name '"+String(b)+"' is already registered");if(!g.prototype)throw new Error("Options missing required prototype property");return g.__name=b.toLowerCase(),g.lifecycle=g.lifecycle||{},g.ancestry=c(g.extends),d(g),e(g),k(g.prototype),n(g.__name,g),g.ctor=o(g),g.ctor.prototype=g.prototype,g.prototype.constructor=g.ctor,(a.ready||a.performedInitialDocumentUpgrade)&&a.upgradeDocumentTree(document),g.ctor}function c(a){var b=m(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(x(a.tag),a)}function g(b,c){return c.is&&b.setAttribute("is",c.is),b.removeAttribute("unresolved"),h(b,c),b.__upgraded__=!0,j(b),a.upgradeSubtree(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){if(!a.setAttribute._polyfilled){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)},a.setAttribute._polyfilled=!0}}function l(a,b,c){var d=this.getAttribute(a);c.apply(this,arguments);var e=this.getAttribute(a);this.attributeChangedCallback&&e!==d&&this.attributeChangedCallback(a,d,e)}function m(a){return a?w[a.toLowerCase()]:void 0}function n(a,b){if(w[a])throw new Error("a type with that name is already registered.");w[a]=b}function o(a){return function(){return f(a)}}function p(a,b){var c=m(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=p(a);return d.setAttribute("is",b),d}var d=x(a);return a.indexOf("-")>=0&&h(d,HTMLElement),d}function q(a){if(!a.__upgraded__&&a.nodeType===Node.ELEMENT_NODE){var b=a.getAttribute("is"),c=w[b||a.localName];if(c){if(b&&c.tag==a.localName)return g(a,c);if(!b&&!c.extends)return g(a,c)}}}function r(b){var c=y.call(this,b);return a.upgradeAll(c),c}a||(a=window.CustomElements={flags:{}});var s=a.flags,t=Boolean(document.registerElement),u=!s.register&&t&&!window.ShadowDOMPolyfill;if(u){var v=function(){};a.registry={},a.upgradeElement=v,a.watchShadow=v,a.upgrade=v,a.upgradeAll=v,a.upgradeSubtree=v,a.observeDocument=v,a.upgradeDocument=v,a.upgradeDocumentTree=v,a.takeRecords=v}else{var w={},x=document.createElement.bind(document),y=Node.prototype.cloneNode;document.registerElement=b,document.createElement=p,Node.prototype.cloneNode=r,a.registry=w,a.upgrade=q}document.register=document.registerElement,a.hasNative=t,a.useNative=u}(window.CustomElements),function(a){function b(a){return"link"===a.localName&&a.getAttribute("rel")===c}var c=a.IMPORT_LINK_TYPE,d={selectors:["link[rel="+c+"]"],map:{link:"parseLink"},parse:function(a){if(!a.__parsed){a.__parsed=!0;var b=a.querySelectorAll(d.selectors);e(b,function(a){d[d.map[a.localName]](a)}),CustomElements.upgradeDocument(a),CustomElements.observeDocument(a)}},parseLink:function(a){b(a)&&this.parseImport(a)},parseImport:function(a){a.import&&d.parse(a.import)}},e=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.parser=d,a.IMPORT_LINK_TYPE=c}(window.CustomElements),function(a){function b(){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.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.flags.eager)b();else if("interactive"!==document.readyState||window.attachEvent||window.HTMLImports&&!window.HTMLImports.ready){var c=window.HTMLImports&&!HTMLImports.ready?"HTMLImportsLoaded":"loading"==document.readyState?"DOMContentLoaded":"load";window.addEventListener(c,b)}else b()}(window.CustomElements),function(){if(HTMLElement.prototype.createShadowRoot){var a=HTMLElement.prototype.createShadowRoot;HTMLElement.prototype.createShadowRoot=function(){var b=a.call(this);return b.host=this,CustomElements.watchShadow(this),b}}if(window.ShadowDOMPolyfill){var b=["upgradeAll","upgradeSubtree","observeDocument","upgradeDocument"],c={};b.forEach(function(a){c[a]=CustomElements[a]}),b.forEach(function(a){CustomElements[a]=function(b){return c[a](window.ShadowDOMPolyfill.wrapIfNeeded(b))}})}if(window.CustomElements&&!CustomElements.useNative){var d=Document.prototype.importNode;Document.prototype.importNode=function(a,b){var c=d.call(this,a,b);return CustomElements.upgradeAll(c),c}}}();
\ No newline at end of file
diff --git a/pkg/custom_element/lib/custom_element.dart b/pkg/custom_element/lib/custom_element.dart
index ab285ae..5057eb1 100644
--- a/pkg/custom_element/lib/custom_element.dart
+++ b/pkg/custom_element/lib/custom_element.dart
@@ -443,6 +443,9 @@
 
   List<Range> getRegionFlowRanges() => host.getRegionFlowRanges();
 
+  void animate(List<Map> keyframes, [num duration]) =>
+      host.animate(keyframes, duration);
+
   // TODO(jmesserly): rename "created" to "onCreated".
   void onCreated() => created();
 
diff --git a/pkg/custom_element/pubspec.yaml b/pkg/custom_element/pubspec.yaml
index 95a25ea..3568402 100644
--- a/pkg/custom_element/pubspec.yaml
+++ b/pkg/custom_element/pubspec.yaml
@@ -1,11 +1,10 @@
 name: custom_element
-version: 0.9.3
+version: 0.10.0-dev
 author: "Polymer.dart Team <web-ui-dev@dartlang.org>"
 homepage: http://www.dartlang.org/
 description: >
-  Custom Elements let authors define their own elements. Authors associate code
-  with custom tag names, and then use those custom tag names as they would any
-  standard tag.
+  *Deprecated* newer version is in web_components package. This is for backwards
+  compat with polymer.dart 0.4.x (web_ui package)
 dev_dependencies:
   unittest: ">=0.9.0 <0.10.0"
 environment:
diff --git a/pkg/docgen/bin/dartdoc.py b/pkg/docgen/bin/dartdoc.py
index cca0aac..98955df 100644
--- a/pkg/docgen/bin/dartdoc.py
+++ b/pkg/docgen/bin/dartdoc.py
@@ -25,8 +25,7 @@
 DART2JS = join(DART_DIR, 'sdk/bin/dart2js')
 PACKAGE_ROOT = join(dirname(dirname(dirname(DART_EXECUTABLE[:-(len('dart'))]))),
     'packages/')
-EXCLUDED_PACKAGES = ['browser', 'html_import', 'mutation_observer',
-    'pkg.xcodeproj', 'shadow_dom']
+EXCLUDED_PACKAGES = ['browser', 'mutation_observer', 'pkg.xcodeproj']
 APPSERVER_EXECUTABLE = 'dev_appserver.py'
 
 
@@ -87,7 +86,7 @@
 # from the SDK and includes only the ones from pkg. So right now our only option
 # is to do everything in one pass.
   doc_dir = join(DART_DIR, 'pkg')
-  cmd_lst = [DART_EXECUTABLE, 
+  cmd_lst = [DART_EXECUTABLE,
       '--package-root=%s' % PACKAGE_ROOT, 'docgen.dart', '--include-sdk' ]
   cmd_str = ' '.join(AddUserDocgenOptions(cmd_lst, docgen_options, True))
   # Try to run all pkg docs together at once as it's fastest.
diff --git a/pkg/docgen/bin/docgen.dart b/pkg/docgen/bin/docgen.dart
index f1275c5..21ba38a 100644
--- a/pkg/docgen/bin/docgen.dart
+++ b/pkg/docgen/bin/docgen.dart
@@ -13,31 +13,42 @@
 List<String> excludedLibraries = [];
 
 /**
+ * The files/directories that we're being asked to document.
+ */
+List<String> _files;
+
+/**
  * Analyzes Dart files and generates a representation of included libraries,
  * classes, and members.
  */
 void main(List<String> arguments) {
-  var results = _initArgParser().parse(arguments);
-
-  var includeSdk = results['parse-sdk'] || results['include-sdk'];
+  var options = _initArgParser().parse(arguments);
+  _files = options.rest.map(path.normalize).toList();
+  if (_files.isEmpty) _printHelpAndExit();
+  var startPage = options['start-page'];
+  if (_singlePackage(_files) && startPage == null) {
+    startPage = _defaultStartPage;
+    print("Using default options for documenting a single package: "
+        "--start-page=$startPage");
+  }
+  var includeSdk = options['parse-sdk'] || options['include-sdk'];
   var scriptDir = path.dirname(Platform.script.toFilePath());
-  var introduction = includeSdk ? '' : results['introduction'];
-  var files = results.rest.map(path.normalize).toList();
-  if (files.isEmpty) _printHelpAndExit();
-  docgen(files,
-      packageRoot: results['package-root'],
-      outputToYaml: !results['json'],
-      includePrivate: results['include-private'],
+  var introduction = includeSdk ? '' : options['introduction'];
+
+  docgen(_files,
+      packageRoot: options['package-root'],
+      outputToYaml: !options['json'],
+      includePrivate: options['include-private'],
       includeSdk: includeSdk,
-      parseSdk: results['parse-sdk'],
-      append: results['append'] && new Directory(results['out']).existsSync(),
+      parseSdk: options['parse-sdk'],
+      append: options['append'] && new Directory(options['out']).existsSync(),
       introFileName: introduction,
-      out: results['out'],
+      out: options['out'],
       excludeLibraries: excludedLibraries,
-      includeDependentPackages: results['include-dependent-packages'],
-      serve: results['serve'],
-      noDocs: results['no-docs'],
-      startPage: results['startPage']);
+      includeDependentPackages: options['include-dependent-packages'],
+      serve: options['serve'],
+      noDocs: options['no-docs'],
+      startPage: startPage);
 }
 
 /**
@@ -50,6 +61,27 @@
 }
 
 /**
+ * If the user seems to have given us a single package to document, use some
+ * reasonable arguments for what they probably meant.
+ */
+bool _singlePackage(List files) {
+  if (files.length != 1) return false;
+  var pubspec = new File(path.join(files.first, 'pubspec.yaml'));
+  if (!pubspec.existsSync()) return false;
+  return true;
+}
+
+/**
+ * If we've specified just a package and no other command-line options,
+ * use the single package name as the start page.
+ */
+String get _defaultStartPage {
+    var pubspec = new File(path.join(_files.first, 'pubspec.yaml'));
+    if (!pubspec.existsSync()) return null;
+    return Library.packageNameFor(_files.first);
+}
+
+/**
  * Creates parser for docgen command line arguments.
  */
 ArgParser _initArgParser() {
@@ -69,11 +101,13 @@
       help: 'Outputs to JSON. Files are outputted to YAML by default. '
         'If --append is used, it takes the file-format of the previous '
         'run stated in library_list.json ignoring the flag.',
-      negatable: true);
+      negatable: true, defaultsTo: true);
   parser.addFlag('include-private',
       help: 'Flag to include private declarations.', negatable: false);
   parser.addFlag('include-sdk',
-      help: 'Flag to parse SDK Library files.', negatable: false);
+      help: 'Flag to parse SDK Library files.',
+      defaultsTo: true,
+      negatable: true);
   parser.addFlag('parse-sdk',
       help: 'Parses the SDK libraries only.',
       defaultsTo: false, negatable: false);
@@ -101,11 +135,11 @@
       help: 'Assumes we are documenting a single package and are running '
         'in the directory with its pubspec. Includes documentation for all '
         'of its dependent packages.',
-      defaultsTo: false, negatable: false);
-  parser.addOption('startPage',
+      defaultsTo: true, negatable: true);
+  parser.addOption('start-page',
       help: 'By default the viewer will start at the SDK introduction page.'
         'To start at some other page, e.g. for a package, provide the name '
-        'of the package in this argument, e.g. --startPage=intl will make '
+        'of the package in this argument, e.g. --start-page=intl will make '
         'the start page of the viewer be the intl package.',
         defaultsTo: null);
 
diff --git a/pkg/docgen/lib/docgen.dart b/pkg/docgen/lib/docgen.dart
index bb50090..d316780 100644
--- a/pkg/docgen/lib/docgen.dart
+++ b/pkg/docgen/lib/docgen.dart
@@ -147,8 +147,13 @@
   if (libraries.isEmpty) throw new StateError('No Libraries.');
 
   // Finds the root of SDK library based off the location of docgen.
+  // We have two different places to look, depending if we're in a development
+  // repo or in a built SDK, either sdk or dart-sdk respectively
   var root = _Generator._rootDirectory;
   var sdkRoot = path.normalize(path.absolute(path.join(root, 'sdk')));
+  if (!new Directory(sdkRoot).existsSync()) {
+    sdkRoot = path.normalize(path.absolute(path.join(root, 'dart-sdk')));
+  }
   _Generator.logger.info('SDK Root: ${sdkRoot}');
   return _Generator._analyzeLibraries(libraries, sdkRoot,
       packageRoot: packageRoot);
@@ -406,7 +411,7 @@
   static void _writeOutputFiles(libraryMap,
       Iterable<Indexable> filteredEntities, bool outputToYaml, bool append,
       String startPage) {
-    if (startPage != null) libraryMap['startPage'] = startPage;
+    if (startPage != null) libraryMap['start-page'] = startPage;
 
     _writeToFile(JSON.encode(libraryMap), 'library_list.json');
 
@@ -457,14 +462,28 @@
   }
 
   /// Helper accessor to determine the full pathname of the root of the dart
-  /// checkout.
+  /// checkout. We can be in one of three situations:
+  /// 1) Running from pkg/docgen/bin/docgen.dart
+  /// 2) Running from a snapshot in a build,
+  ///   e.g. xcodebuild/ReleaseIA32/dart-sdk/bin
+  /// 3) Running from a built distribution,
+  ///   e.g. ...somename/dart-sdk/bin/snapshots
   static String get _rootDirectory {
     var scriptDir = path.absolute(path.dirname(Platform.script.toFilePath()));
     var root = scriptDir;
-    while(path.basename(root) != 'dart') {
+    var base = path.basename(root);
+    // When we find dart-sdk or sdk we are one level below the root.
+    while (base != 'dart-sdk' && base != 'sdk' && base != 'pkg') {
       root = path.dirname(root);
+      base = path.basename(root);
+      if (root == base) {
+        // We have reached the root of the filesystem without finding anything.
+        throw new FileSystemException(
+            "Cannot find SDK directory starting from ",
+            scriptDir);
+        }
     }
-    return root;
+    return path.dirname(root);
   }
 
   /// Analyzes set of libraries and provides a mirror system which can be used
@@ -572,7 +591,10 @@
   }
 
   /// All of the directories for our dependent packages
+  /// If this is not a package, return an empty list.
   static List<String> _allDependentPackageDirs(String packageDirectory) {
+    var packageName = Library.packageNameFor(packageDirectory);
+    if (packageName == '') return [];
     var dependentsJson = Process.runSync('pub', ['list-package-dirs'],
         workingDirectory: packageDirectory, runInShell: true);
     if (dependentsJson.exitCode != 0) {
@@ -1306,7 +1328,8 @@
         }
     });
     this.functions = _createMethods(_addAll(exported['methods'],
-        dart2js_util.methodsOf(libraryMirror.declarations)).values, this);
+        libraryMirror.declarations.values.where(
+            (mirror) => mirror is MethodMirror)).values, this);
     this.variables = _createVariables(_addAll(exported['variables'],
         dart2js_util.variablesOf(libraryMirror.declarations)).values, this);
   }
@@ -1374,11 +1397,16 @@
   static String _getRootdir(LibraryMirror mirror) =>
       path.dirname(path.dirname(mirror.uri.toFilePath()));
 
-  /// Read a pubspec and return the library name.
+  /// Read a pubspec and return the library name given a [LibraryMirror].
   static String _packageName(LibraryMirror mirror) {
     if (mirror.uri.scheme != 'file') return '';
     var rootdir = _getRootdir(mirror);
-    var pubspecName = path.join(rootdir, 'pubspec.yaml');
+    return packageNameFor(rootdir);
+  }
+
+  /// Read a pubspec and return the library name, given a directory
+  static String packageNameFor(String directoryName) {
+    var pubspecName = path.join(directoryName, 'pubspec.yaml');
     File pubspec = new File(pubspecName);
     if (!pubspec.existsSync()) return '';
     var contents = pubspec.readAsStringSync();
@@ -1425,7 +1453,8 @@
         _addAll(exports['classes'],
             dart2js_util.typesOf(export.targetLibrary.declarations));
         _addAll(exports['methods'],
-            dart2js_util.methodsOf(export.targetLibrary.declarations));
+            export.targetLibrary.declarations.values.where(
+                (mirror) => mirror is MethodMirror));
         _addAll(exports['variables'],
             dart2js_util.variablesOf(export.targetLibrary.declarations));
       }
@@ -1520,10 +1549,16 @@
       // Reading in MDN related json file.
       var root = _Generator._rootDirectory;
       var mdnPath = path.join(root, 'utils/apidoc/mdn/database.json');
-      Indexable._mdn = JSON.decode(new File(mdnPath).readAsStringSync());
+      var mdnFile = new File(mdnPath);
+      if (mdnFile.existsSync()) {
+        Indexable._mdn = JSON.decode(mdnFile.readAsStringSync());
+      } else {
+        _Generator.logger.warning("Cannot find MDN docs expected at $mdnPath");
+        Indexable._mdn = {};
+      }
     }
     var domAnnotation = this.annotations.firstWhere(
-        (e) => e.mirror.qualifiedName == 'metadata.DomName',
+        (e) => e.mirror.qualifiedName == #metadata.DomName,
         orElse: () => null);
     if (domAnnotation == null) return '';
     var domName = domAnnotation.parameters.single;
diff --git a/pkg/html_import/LICENSE b/pkg/html_import/LICENSE
deleted file mode 100644
index 5c60afe..0000000
--- a/pkg/html_import/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright 2014, the Dart project authors. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-    * Neither the name of Google Inc. nor the names of its
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-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.
diff --git a/pkg/html_import/README.md b/pkg/html_import/README.md
deleted file mode 100644
index 066c525..0000000
--- a/pkg/html_import/README.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# HTML Imports polyfill
-
-[HTML Imports][1] are a way to include and reuse HTML documents in other HTML
-documents. As `<script>` tags let authors include external Javascript in their
-pages, imports let authors load full HTML resources.  In particular, imports let
-authors include [Custom Element](https://github.com/Polymer/CustomElements)
-definitions from external URLs.
-
-
-## Getting started
-
-Include the `html_import.debug.js` or `html_import.min.js` (minified) file in
-your project.
-
-    <script src="packages/html_import/html_import.debug.js"></script>
-
-`html_import.debug.js` is the debug loader and uses `document.write` to load
-additional modules.
-
-Use the minified version (`html_import.min.js`) if you need to load the file
-dynamically.
-
-## Basic usage
-
-For HTML imports use the `import` relation on a standard `<link>` tag, for
-example:
-
-    <link rel="import" href="import-file.html">
-
-## Polyfill details
-
-You can read more about how the polyfill is implemented in JavaScript here:
-<https://github.com/Polymer/HTMLImports/tree/master#polyfill-details>
-
-## Getting the source code
-
-This package is built from:
-<https://github.com/Polymer/HTMLImports/tree/master>
-
-You'll need [node.js](http://nodejs.org) to rebuild the JS file. Use
-`npm install` to get dependencies and `grunt` to build.
-
-[1]: https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/imports/index.html
diff --git a/pkg/html_import/lib/html_import.debug.js b/pkg/html_import/lib/html_import.debug.js
deleted file mode 100644
index 08f6438..0000000
--- a/pkg/html_import/lib/html_import.debug.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/* 
- * Copyright 2013 The Polymer Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style
- * license that can be found in the LICENSE file.
- */
-
-(function() {
-  
-var thisFile = 'html_import.debug.js';
-var scopeName = 'HTMLImports';
-var modules = [
-    'src/Parser.js',
-    'src/HTMLImports.js',
-    'src/boot.js'
-];
-
-// export 
-
-window[scopeName] = {
-  entryPointName: thisFile,
-  modules: modules
-};
-
-// bootstrap
-
-var script = document.querySelector('script[src*="' + thisFile + '"]');
-var src = script.attributes.src.value;
-var basePath = src.slice(0, src.indexOf(thisFile));
-
-if (!window.Loader) {
-  var path = basePath + 'tools/loader/loader.js';
-  document.write('<script src="' + path + '"></script>');
-} 
-document.write('<script>Loader.load("' + scopeName + '")</script>');
-  
-})();
diff --git a/pkg/html_import/lib/html_import.min.js b/pkg/html_import/lib/html_import.min.js
deleted file mode 100644
index cd012d0..0000000
--- a/pkg/html_import/lib/html_import.min.js
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2012 The Polymer Authors. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// 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.
-!function(){function a(){HTMLImports.importer.load(document,function(){HTMLImports.parser.parse(document),HTMLImports.readyTime=(new Date).getTime(),document.dispatchEvent(new CustomEvent("HTMLImportsLoaded",{bubbles:!0}))})}"function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a){var b=document.createEvent("HTMLEvents");return b.initEvent(a,!0,!0),b}),"complete"===document.readyState?a():window.addEventListener("DOMContentLoaded",a)}(),function(a){function b(a){return d(a,i)}function c(a){return d(a,j)}function d(a,b){return"link"===a.localName&&a.getAttribute("rel")===b}function e(a){return"script"===a.localName}function f(a,b){var c=a;c instanceof Document||(c=document.implementation.createHTMLDocument(i),c.body.innerHTML=a),c._URL=b;var d=c.createElement("base");return d.setAttribute("href",document.baseURI),c.head.appendChild(d),window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(c),c}a||(a=window.HTMLImports={flags:{}});var g,h=a.xhr,i="import",j="stylesheet",k={documents:{},cache:{},preloadSelectors:["link[rel="+i+"]","element link[rel="+j+"]","template","script[src]:not([type])",'script[src][type="text/javascript"]'].join(","),loader:function(a){return g=new l(k.loaded,a),g.cache=k.cache,g},load:function(a,b){g=k.loader(b),k.preload(a)},preload:function(a){var b=a.querySelectorAll(k.preloadSelectors);b=this.filterMainDocumentNodes(a,b),b=this.extractTemplateNodes(b),g.addNodes(b)},filterMainDocumentNodes:function(a,b){return a===document&&(b=Array.prototype.filter.call(b,function(a){return!e(a)})),b},extractTemplateNodes:function(a){var b=[];return a=Array.prototype.filter.call(a,function(a){if("template"===a.localName){if(a.content){var c=a.content.querySelectorAll("link[rel="+j+"]");c.length&&(b=b.concat(Array.prototype.slice.call(c,0)))}return!1}return!0}),b.length&&(a=a.concat(b)),a},loaded:function(a,d,e){if(b(d)){var g=k.documents[a];g||(g=f(e,a),p.resolvePathsInHTML(g),k.documents[a]=g,k.preload(g)),d.import={href:a,ownerNode:d,content:g},d.content=e=g}d.__resource=e,c(d)&&p.resolvePathsInStylesheet(d)}},l=function(a,b){this.onload=a,this.oncomplete=b,this.inflight=0,this.pending={},this.cache={}};l.prototype={addNodes:function(a){this.inflight+=a.length,q(a,this.require,this),this.checkDone()},require:function(a){var b=p.nodeUrl(a);a.__nodeUrl=b,this.dedupe(b,a)||this.fetch(b,a)},dedupe:function(a,b){return this.pending[a]?(this.pending[a].push(b),!0):this.cache[a]?(this.onload(a,b,g.cache[a]),this.tail(),!0):(this.pending[a]=[b],!1)},fetch:function(a,b){var c=function(c,d){this.receive(a,b,c,d)}.bind(this);h.load(a,c)},receive:function(a,b,c,d){c||(g.cache[a]=d),g.pending[a].forEach(function(b){c||this.onload(a,b,d),this.tail()},this),g.pending[a]=null},tail:function(){--this.inflight,this.checkDone()},checkDone:function(){this.inflight||this.oncomplete()}};var m=["href","src","action"],n="["+m.join("],[")+"]",o="{{.*}}",p={nodeUrl:function(a){return p.resolveUrl(p.getDocumentUrl(document),p.hrefOrSrc(a))},hrefOrSrc:function(a){return a.getAttribute("href")||a.getAttribute("src")},documentUrlFromNode:function(a){return p.getDocumentUrl(a.ownerDocument||a)},getDocumentUrl:function(a){var b=a&&(a._URL||a.impl&&a.impl._URL||a.baseURI||a.URL)||"";return b.split("#")[0]},resolveUrl:function(a,b,c){if(this.isAbsUrl(b))return b;var d=this.compressUrl(this.urlToPath(a)+b);return c&&(d=p.makeRelPath(p.getDocumentUrl(document),d)),d},isAbsUrl:function(a){return/(^data:)|(^http[s]?:)|(^\/)/.test(a)},urlToPath:function(a){var b=a.split("/");return b.pop(),b.push(""),b.join("/")},compressUrl:function(a){for(var b,c=a.split("/"),d=0;d<c.length;d++)b=c[d],".."===b&&(c.splice(d-1,2),d-=2);return c.join("/")},makeRelPath:function(a,b){var c,d;for(c=this.compressUrl(a).split("/"),d=this.compressUrl(b).split("/");c.length&&c[0]===d[0];)c.shift(),d.shift();for(var e=0,f=c.length-1;f>e;e++)d.unshift("..");var g=d.join("/");return g},resolvePathsInHTML:function(a,b){b=b||p.documentUrlFromNode(a),p.resolveAttributes(a,b),p.resolveStyleElts(a,b);var c=a.querySelectorAll("template");c&&q(c,function(a){a.content&&p.resolvePathsInHTML(a.content,b)})},resolvePathsInStylesheet:function(a){var b=p.nodeUrl(a);a.__resource=p.resolveCssText(a.__resource,b)},resolveStyleElts:function(a,b){var c=a.querySelectorAll("style");c&&q(c,function(a){a.textContent=p.resolveCssText(a.textContent,b)})},resolveCssText:function(a,b){return a.replace(/url\([^)]*\)/g,function(a){var c=a.replace(/["']/g,"").slice(4,-1);return c=p.resolveUrl(b,c,!0),"url("+c+")"})},resolveAttributes:function(a,b){var c=a&&a.querySelectorAll(n);c&&q(c,function(a){this.resolveNodeAttributes(a,b)},this)},resolveNodeAttributes:function(a,b){m.forEach(function(c){var d=a.attributes[c];if(d&&d.value&&d.value.search(o)<0){var e=p.resolveUrl(b,d.value,!0);d.value=e}})}};h=h||{async:!0,ok:function(a){return a.status>=200&&a.status<300||304===a.status||0===a.status},load:function(b,c,d){var e=new XMLHttpRequest;return(a.flags.debug||a.flags.bust)&&(b+="?"+Math.random()),e.open("GET",b,h.async),e.addEventListener("readystatechange",function(){4===e.readyState&&c.call(d,!h.ok(e)&&e,e.response,b)}),e.send(),e},loadDocument:function(a,b,c){this.load(a,b,c).responseType="document"}};var q=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.path=p,a.xhr=h,a.importer=k,a.getDocumentUrl=p.getDocumentUrl,a.IMPORT_LINK_TYPE=i}(window.HTMLImports),function(a){function b(a){return"link"===a.localName&&a.getAttribute("rel")===f}function c(a){return a.parentNode&&!d(a)&&!e(a)}function d(a){return a.ownerDocument===document||a.ownerDocument.impl===document}function e(a){return a.parentNode&&"element"===a.parentNode.localName}var f="import",g={selectors:["link[rel="+f+"]","link[rel=stylesheet]","style","script:not([type])",'script[type="text/javascript"]'],map:{link:"parseLink",script:"parseScript",style:"parseGeneric"},parse:function(a){if(!a.__importParsed){a.__importParsed=!0;var b=a.querySelectorAll(g.selectors);h(b,function(a){g[g.map[a.localName]](a)})}},parseLink:function(a){b(a)?a.content&&g.parse(a.content):this.parseGeneric(a)},parseGeneric:function(a){c(a)&&document.head.appendChild(a)},parseScript:function(b){if(c(b)){var d=(b.__resource||b.textContent).trim();if(d){var e=b.__nodeUrl;if(!e){var e=a.path.documentUrlFromNode(b),f="["+Math.floor(1e3*(Math.random()+1))+"]",g=d.match(/Polymer\(['"]([^'"]*)/);f=g&&g[1]||f,e+="/"+f+".js"}d+="\n//# sourceURL="+e+"\n",eval.call(window,d)}}}},h=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.parser=g}(HTMLImports);
diff --git a/pkg/html_import/lib/src/HTMLImports.js b/pkg/html_import/lib/src/HTMLImports.js
deleted file mode 100644
index a77e7165..0000000
--- a/pkg/html_import/lib/src/HTMLImports.js
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * Copyright 2013 The Polymer Authors. 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) {
-
-if (!scope) {
-  scope = window.HTMLImports = {flags:{}};
-}
-
-// imports
-
-var xhr = scope.xhr;
-
-// importer
-
-var IMPORT_LINK_TYPE = 'import';
-var STYLE_LINK_TYPE = 'stylesheet';
-
-// highlander object represents a primary document (the argument to 'load')
-// at the root of a tree of documents
-
-// for any document, importer:
-// - loads any linked documents (with deduping), modifies paths and feeds them back into importer
-// - loads text of external script tags
-// - loads text of external style tags inside of <element>, modifies paths
-
-// when importer 'modifies paths' in a document, this includes
-// - href/src/action in node attributes
-// - paths in inline stylesheets
-// - all content inside templates
-
-// linked style sheets in an import have their own path fixed up when their containing import modifies paths
-// linked style sheets in an <element> are loaded, and the content gets path fixups
-// inline style sheets get path fixups when their containing import modifies paths
-
-var loader;
-
-var importer = {
-  documents: {},
-  cache: {},
-  preloadSelectors: [
-    'link[rel=' + IMPORT_LINK_TYPE + ']',
-    'element link[rel=' + STYLE_LINK_TYPE + ']',
-    'template',
-    'script[src]:not([type])',
-    'script[src][type="text/javascript"]'
-  ].join(','),
-  loader: function(inNext) {
-    // construct a loader instance
-    loader = new Loader(importer.loaded, inNext);
-    // alias the loader cache (for debugging)
-    loader.cache = importer.cache;
-    return loader;
-  },
-  load: function(inDocument, inNext) {
-    // construct a loader instance
-    loader = importer.loader(inNext);
-    // add nodes from document into loader queue
-    importer.preload(inDocument);
-  },
-  preload: function(inDocument) {
-    // all preloadable nodes in inDocument
-    var nodes = inDocument.querySelectorAll(importer.preloadSelectors);
-    // from the main document, only load imports
-    // TODO(sjmiles): do this by altering the selector list instead
-    nodes = this.filterMainDocumentNodes(inDocument, nodes);
-    // extra link nodes from templates, filter templates out of the nodes list
-    nodes = this.extractTemplateNodes(nodes);
-    // add these nodes to loader's queue
-    loader.addNodes(nodes);
-  },
-  filterMainDocumentNodes: function(inDocument, nodes) {
-    if (inDocument === document) {
-      nodes = Array.prototype.filter.call(nodes, function(n) {
-        return !isScript(n);
-      });
-    }
-    return nodes;
-  },
-  extractTemplateNodes: function(nodes) {
-    var extra = [];
-    nodes = Array.prototype.filter.call(nodes, function(n) {
-      if (n.localName === 'template') {
-        if (n.content) {
-          var l$ = n.content.querySelectorAll('link[rel=' + STYLE_LINK_TYPE +
-            ']');
-          if (l$.length) {
-            extra = extra.concat(Array.prototype.slice.call(l$, 0));
-          }
-        }
-        return false;
-      }
-      return true;
-    });
-    if (extra.length) {
-      nodes = nodes.concat(extra);
-    }
-    return nodes;
-  },
-  loaded: function(url, elt, resource) {
-    if (isDocumentLink(elt)) {
-      var document = importer.documents[url];
-      // if we've never seen a document at this url
-      if (!document) {
-        // generate an HTMLDocument from data
-        document = makeDocument(resource, url);
-        // resolve resource paths relative to host document
-        path.resolvePathsInHTML(document);
-        // cache document
-        importer.documents[url] = document;
-        // add nodes from this document to the loader queue
-        importer.preload(document);
-      }
-      // store import record
-      elt.import = {
-        href: url,
-        ownerNode: elt,
-        content: document
-      };
-      // store document resource
-      elt.content = resource = document;
-    }
-    // store generic resource
-    // TODO(sorvell): fails for nodes inside <template>.content
-    // see https://code.google.com/p/chromium/issues/detail?id=249381.
-    elt.__resource = resource;
-    // css path fixups
-    if (isStylesheetLink(elt)) {
-      path.resolvePathsInStylesheet(elt);
-    }
-  }
-};
-
-function isDocumentLink(elt) {
-  return isLinkRel(elt, IMPORT_LINK_TYPE);
-}
-
-function isStylesheetLink(elt) {
-  return isLinkRel(elt, STYLE_LINK_TYPE);
-}
-
-function isLinkRel(elt, rel) {
-  return elt.localName === 'link' && elt.getAttribute('rel') === rel;
-}
-
-function isScript(elt) {
-  return elt.localName === 'script';
-}
-
-function makeDocument(resource, url) {
-  // create a new HTML document
-  var doc = resource;
-  if (!(doc instanceof Document)) {
-    doc = document.implementation.createHTMLDocument(IMPORT_LINK_TYPE);
-    // install html
-    doc.body.innerHTML = resource;
-  }
-  // cache the new document's source url
-  doc._URL = url;
-  // establish a relative path via <base>
-  var base = doc.createElement('base');
-  base.setAttribute('href', document.baseURI);
-  doc.head.appendChild(base);
-  // TODO(sorvell): MDV Polyfill intrusion: boostrap template polyfill
-  if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) {
-    HTMLTemplateElement.bootstrap(doc);
-  }
-  return doc;
-}
-
-var Loader = function(inOnLoad, inOnComplete) {
-  this.onload = inOnLoad;
-  this.oncomplete = inOnComplete;
-  this.inflight = 0;
-  this.pending = {};
-  this.cache = {};
-};
-
-Loader.prototype = {
-  addNodes: function(inNodes) {
-    // number of transactions to complete
-    this.inflight += inNodes.length;
-    // commence transactions
-    forEach(inNodes, this.require, this);
-    // anything to do?
-    this.checkDone();
-  },
-  require: function(inElt) {
-    var url = path.nodeUrl(inElt);
-    // TODO(sjmiles): ad-hoc
-    inElt.__nodeUrl = url;
-    // deduplication
-    if (!this.dedupe(url, inElt)) {
-      // fetch this resource
-      this.fetch(url, inElt);
-    }
-  },
-  dedupe: function(inUrl, inElt) {
-    if (this.pending[inUrl]) {
-      // add to list of nodes waiting for inUrl
-      this.pending[inUrl].push(inElt);
-      // don't need fetch
-      return true;
-    }
-    if (this.cache[inUrl]) {
-      // complete load using cache data
-      this.onload(inUrl, inElt, loader.cache[inUrl]);
-      // finished this transaction
-      this.tail();
-      // don't need fetch
-      return true;
-    }
-    // first node waiting for inUrl
-    this.pending[inUrl] = [inElt];
-    // need fetch (not a dupe)
-    return false;
-  },
-  fetch: function(url, elt) {
-    var receiveXhr = function(err, resource) {
-      this.receive(url, elt, err, resource);
-    }.bind(this);
-    xhr.load(url, receiveXhr);
-    // TODO(sorvell): blocked on 
-    // https://code.google.com/p/chromium/issues/detail?id=257221
-    // xhr'ing for a document makes scripts in imports runnable; otherwise
-    // they are not; however, it requires that we have doctype=html in
-    // the import which is unacceptable. This is only needed on Chrome
-    // to avoid the bug above.
-    /*
-    if (isDocumentLink(elt)) {
-      xhr.loadDocument(url, receiveXhr);
-    } else {
-      xhr.load(url, receiveXhr);
-    }
-    */
-  },
-  receive: function(inUrl, inElt, inErr, inResource) {
-    if (!inErr) {
-      loader.cache[inUrl] = inResource;
-    }
-    loader.pending[inUrl].forEach(function(e) {
-      if (!inErr) {
-        this.onload(inUrl, e, inResource);
-      }
-      this.tail();
-    }, this);
-    loader.pending[inUrl] = null;
-  },
-  tail: function() {
-    --this.inflight;
-    this.checkDone();
-  },
-  checkDone: function() {
-    if (!this.inflight) {
-      this.oncomplete();
-    }
-  }
-};
-
-var URL_ATTRS = ['href', 'src', 'action'];
-var URL_ATTRS_SELECTOR = '[' + URL_ATTRS.join('],[') + ']';
-var URL_TEMPLATE_SEARCH = '{{.*}}';
-
-var path = {
-  nodeUrl: function(inNode) {
-    return path.resolveUrl(path.getDocumentUrl(document), path.hrefOrSrc(inNode));
-  },
-  hrefOrSrc: function(inNode) {
-    return inNode.getAttribute("href") || inNode.getAttribute("src");
-  },
-  documentUrlFromNode: function(inNode) {
-    return path.getDocumentUrl(inNode.ownerDocument || inNode);
-  },
-  getDocumentUrl: function(inDocument) {
-    var url = inDocument &&
-        // TODO(sjmiles): ShadowDOMPolyfill intrusion
-        (inDocument._URL || (inDocument.impl && inDocument.impl._URL)
-            || inDocument.baseURI || inDocument.URL)
-                || '';
-    // take only the left side if there is a #
-    return url.split('#')[0];
-  },
-  resolveUrl: function(inBaseUrl, inUrl, inRelativeToDocument) {
-    if (this.isAbsUrl(inUrl)) {
-      return inUrl;
-    }
-    var url = this.compressUrl(this.urlToPath(inBaseUrl) + inUrl);
-    if (inRelativeToDocument) {
-      url = path.makeRelPath(path.getDocumentUrl(document), url);
-    }
-    return url;
-  },
-  isAbsUrl: function(inUrl) {
-    return /(^data:)|(^http[s]?:)|(^\/)/.test(inUrl);
-  },
-  urlToPath: function(inBaseUrl) {
-    var parts = inBaseUrl.split("/");
-    parts.pop();
-    parts.push('');
-    return parts.join("/");
-  },
-  compressUrl: function(inUrl) {
-    var parts = inUrl.split("/");
-    for (var i=0, p; i<parts.length; i++) {
-      p = parts[i];
-      if (p === "..") {
-        parts.splice(i-1, 2);
-        i -= 2;
-      }
-    }
-    return parts.join("/");
-  },
-  // make a relative path from source to target
-  makeRelPath: function(inSource, inTarget) {
-    var s, t;
-    s = this.compressUrl(inSource).split("/");
-    t = this.compressUrl(inTarget).split("/");
-    while (s.length && s[0] === t[0]){
-      s.shift();
-      t.shift();
-    }
-    for(var i = 0, l = s.length-1; i < l; i++) {
-      t.unshift("..");
-    }
-    var r = t.join("/");
-    return r;
-  },
-  resolvePathsInHTML: function(root, url) {
-    url = url || path.documentUrlFromNode(root)
-    path.resolveAttributes(root, url);
-    path.resolveStyleElts(root, url);
-    // handle template.content
-    var templates = root.querySelectorAll('template');
-    if (templates) {
-      forEach(templates, function(t) {
-        if (t.content) {
-          path.resolvePathsInHTML(t.content, url);
-        }
-      });
-    }
-  },
-  resolvePathsInStylesheet: function(inSheet) {
-    var docUrl = path.nodeUrl(inSheet);
-    inSheet.__resource = path.resolveCssText(inSheet.__resource, docUrl);
-  },
-  resolveStyleElts: function(inRoot, inUrl) {
-    var styles = inRoot.querySelectorAll('style');
-    if (styles) {
-      forEach(styles, function(style) {
-        style.textContent = path.resolveCssText(style.textContent, inUrl);
-      });
-    }
-  },
-  resolveCssText: function(inCssText, inBaseUrl) {
-    return inCssText.replace(/url\([^)]*\)/g, function(inMatch) {
-      // find the url path, ignore quotes in url string
-      var urlPath = inMatch.replace(/["']/g, "").slice(4, -1);
-      urlPath = path.resolveUrl(inBaseUrl, urlPath, true);
-      return "url(" + urlPath + ")";
-    });
-  },
-  resolveAttributes: function(inRoot, inUrl) {
-    // search for attributes that host urls
-    var nodes = inRoot && inRoot.querySelectorAll(URL_ATTRS_SELECTOR);
-    if (nodes) {
-      forEach(nodes, function(n) {
-        this.resolveNodeAttributes(n, inUrl);
-      }, this);
-    }
-  },
-  resolveNodeAttributes: function(inNode, inUrl) {
-    URL_ATTRS.forEach(function(v) {
-      var attr = inNode.attributes[v];
-      if (attr && attr.value &&
-         (attr.value.search(URL_TEMPLATE_SEARCH) < 0)) {
-        var urlPath = path.resolveUrl(inUrl, attr.value, true);
-        attr.value = urlPath;
-      }
-    });
-  }
-};
-
-xhr = xhr || {
-  async: true,
-  ok: function(inRequest) {
-    return (inRequest.status >= 200 && inRequest.status < 300)
-        || (inRequest.status === 304)
-        || (inRequest.status === 0);
-  },
-  load: function(url, next, nextContext) {
-    var request = new XMLHttpRequest();
-    if (scope.flags.debug || scope.flags.bust) {
-      url += '?' + Math.random();
-    }
-    request.open('GET', url, xhr.async);
-    request.addEventListener('readystatechange', function(e) {
-      if (request.readyState === 4) {
-        next.call(nextContext, !xhr.ok(request) && request,
-          request.response, url);
-      }
-    });
-    request.send();
-    return request;
-  },
-  loadDocument: function(url, next, nextContext) {
-    this.load(url, next, nextContext).responseType = 'document';
-  }
-};
-
-var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
-
-// exports
-
-scope.path = path;
-scope.xhr = xhr;
-scope.importer = importer;
-scope.getDocumentUrl = path.getDocumentUrl;
-scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;
-
-})(window.HTMLImports);
diff --git a/pkg/html_import/lib/src/Parser.js b/pkg/html_import/lib/src/Parser.js
deleted file mode 100644
index 2f00e05..0000000
--- a/pkg/html_import/lib/src/Parser.js
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2013 The Polymer Authors. 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) {
-
-var IMPORT_LINK_TYPE = 'import';
-
-// highlander object for parsing a document tree
-
-var importParser = {
-  selectors: [
-    'link[rel=' + IMPORT_LINK_TYPE + ']',
-    'link[rel=stylesheet]',
-    'style',
-    'script:not([type])',
-    'script[type="text/javascript"]'
-  ],
-  map: {
-    link: 'parseLink',
-    script: 'parseScript',
-    style: 'parseGeneric'
-  },
-  parse: function(inDocument) {
-    if (!inDocument.__importParsed) {
-      // only parse once
-      inDocument.__importParsed = true;
-      // all parsable elements in inDocument (depth-first pre-order traversal)
-      var elts = inDocument.querySelectorAll(importParser.selectors);
-      // for each parsable node type, call the mapped parsing method
-      forEach(elts, function(e) {
-        importParser[importParser.map[e.localName]](e);
-      });
-    }
-  },
-  parseLink: function(linkElt) {
-    if (isDocumentLink(linkElt)) {
-      if (linkElt.content) {
-        importParser.parse(linkElt.content);
-      }
-    } else {
-      this.parseGeneric(linkElt);
-    }
-  },
-  parseGeneric: function(elt) {
-    if (needsMainDocumentContext(elt)) {
-      document.head.appendChild(elt);
-    }
-  },
-  parseScript: function(scriptElt) {
-    if (needsMainDocumentContext(scriptElt)) {
-      // acquire code to execute
-      var code = (scriptElt.__resource || scriptElt.textContent).trim();
-      if (code) {
-        // calculate source map hint
-        var moniker = scriptElt.__nodeUrl;
-        if (!moniker) {
-          var moniker = scope.path.documentUrlFromNode(scriptElt);
-          // there could be more than one script this url
-          var tag = '[' + Math.floor((Math.random()+1)*1000) + ']';
-          // TODO(sjmiles): Polymer hack, should be pluggable if we need to allow 
-          // this sort of thing
-          var matches = code.match(/Polymer\(['"]([^'"]*)/);
-          tag = matches && matches[1] || tag;
-          // tag the moniker
-          moniker += '/' + tag + '.js';
-        }
-        // source map hint
-        code += "\n//# sourceURL=" + moniker + "\n";
-        // evaluate the code
-        eval.call(window, code);
-      }
-    }
-  }
-};
-
-var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
-
-function isDocumentLink(elt) {
-  return elt.localName === 'link'
-      && elt.getAttribute('rel') === IMPORT_LINK_TYPE;
-}
-
-function needsMainDocumentContext(node) {
-  // nodes can be moved to the main document:
-  // if they are in a tree but not in the main document and not children of <element>
-  return node.parentNode && !inMainDocument(node) 
-      && !isElementElementChild(node);
-}
-
-function inMainDocument(elt) {
-  return elt.ownerDocument === document ||
-    // TODO(sjmiles): ShadowDOMPolyfill intrusion
-    elt.ownerDocument.impl === document;
-}
-
-function isElementElementChild(elt) {
-  return elt.parentNode && elt.parentNode.localName === 'element';
-}
-
-// exports
-
-scope.parser = importParser;
-
-})(HTMLImports);
\ No newline at end of file
diff --git a/pkg/html_import/lib/src/boot.js b/pkg/html_import/lib/src/boot.js
deleted file mode 100644
index 3ec4897..0000000
--- a/pkg/html_import/lib/src/boot.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2013 The Polymer Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style
- * license that can be found in the LICENSE file.
- */
-(function(){
-
-// bootstrap
-
-// IE shim for CustomEvent
-if (typeof window.CustomEvent !== 'function') {
-  window.CustomEvent = function(inType) {
-     var e = document.createEvent('HTMLEvents');
-     e.initEvent(inType, true, true);
-     return e;
-  };
-}
-
-function bootstrap() {
-  // preload document resource trees
-  HTMLImports.importer.load(document, function() {
-    HTMLImports.parser.parse(document);
-    HTMLImports.readyTime = new Date().getTime();
-    // send HTMLImportsLoaded when finished
-    document.dispatchEvent(
-      new CustomEvent('HTMLImportsLoaded', {bubbles: true})
-    );
-  });
-};
-
-if (document.readyState === 'complete') {
-  bootstrap();
-} else {
-  window.addEventListener('DOMContentLoaded', bootstrap);
-}
-
-})();
diff --git a/pkg/html_import/lib/tools/loader/loader.js b/pkg/html_import/lib/tools/loader/loader.js
deleted file mode 100644
index 1aa3f9c..0000000
--- a/pkg/html_import/lib/tools/loader/loader.js
+++ /dev/null
@@ -1,101 +0,0 @@
-/*

- * Copyright 2013 The Polymer Authors. All rights reserved.

- * Use of this source code is governed by a BSD-style

- * license that can be found in the LICENSE file.

- */

-

-(function() {

-  

-var scope = window.Loader = {};

-var flags = {};

-

-// convert url arguments to flags

-

-if (!flags.noOpts) {

-  location.search.slice(1).split('&').forEach(function(o) {

-    o = o.split('=');

-    o[0] && (flags[o[0]] = o[1] || true);

-  });

-}

-

-// process global logFlags

-

-parseLogFlags(flags);

-

-function load(scopeName) {

-  // imports

-

-  var scope = window[scopeName];

-  var entryPointName = scope.entryPointName;

-  var processFlags = scope.processFlags;

-

-  // acquire attributes and base path from entry point

-

-  var entryPoint = findScript(entryPointName);

-  var base = entryPoint.basePath;

-  

-  // acquire common flags

-  var flags = Loader.flags;

-

-  // convert attributes to flags

-  var flags = Loader.flags;

-  for (var i=0, a; (a=entryPoint.attributes[i]); i++) {

-    if (a.name !== 'src') {

-      flags[a.name] = a.value || true;

-    }

-  }

-

-  // parse log flags into global

-  parseLogFlags(flags);

-

-  // exports

-

-  scope.basePath = base;

-  scope.flags = flags;

-

-  // process flags for dynamic dependencies

-

-  if (processFlags) {

-    processFlags.call(scope, flags);

-  }

-

-  // post-process imports

-

-  var modules = scope.modules || [];

-  var sheets = scope.sheets || [];

-

-  // write script tags for dependencies

-

-  modules.forEach(function(src) {

-    document.write('<script src="' + base + src + '"></script>');

-  });

-

-  // write link tags for styles

-

-  sheets.forEach(function(src) {

-    document.write('<link rel="stylesheet" href="' + base + src + '">');

-  }); 

-}

-

-// utility method

-

-function findScript(fileName) {

-  var script = document.querySelector('script[src*="' + fileName + '"]');

-  var src = script.attributes.src.value;

-  script.basePath = src.slice(0, src.indexOf(fileName));

-  return script;

-}

-

-function parseLogFlags(flags) {

-  var logFlags = window.logFlags = window.logFlags || {};

-  if (flags.log) {

-    flags.log.split(',').forEach(function(f) {

-      logFlags[f] = true;

-    });

-  }

-}

-

-scope.flags = flags;

-scope.load = load;  

-

-})();

diff --git a/pkg/html_import/pubspec.yaml b/pkg/html_import/pubspec.yaml
deleted file mode 100644
index edcaebb..0000000
--- a/pkg/html_import/pubspec.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-name: html_import
-version: 0.9.0
-author: "Polymer.dart Team <web-ui-dev@dartlang.org>"
-homepage: https://github.com/Polymer/HTMLImports/tree/master
-description: >
-  HTML Imports are a way to include and reuse HTML documents in other HTML
-  documents. As <script> tags let authors include external code in their
-  pages, imports let authors load full HTML resources. In particular, imports
-  let authors include Custom Element definitions from external URLs.
-environment:
-  sdk: ">=1.0.0 <2.0.0"
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 83dce91..8edee0d 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -44,6 +44,9 @@
 [ $runtime == jsshell ]
 analyzer/test/generated/element_test: Pass, Slow # Issue 16473
 
+[ $compiler == dart2js && $checked && $runtime == drt && $nocsp ]
+async/test/stream_zip_test: RuntimeError # Issue 16719
+
 [ $runtime == d8 || $runtime == jsshell ]
 unittest/test/unittest_nested_groups_setup_teardown_test: RuntimeError # http://dartbug.com/10109
 stack_trace/test/vm_test: RuntimeError, OK # VM-specific traces
@@ -101,10 +104,9 @@
 typed_data/test/typed_buffers_test: Fail, Crash # No typed_data on IE9.
 polymer/test/instance_attrs_test: Pass, Fail # Issue 14167
 polymer/test/bind_mdv_test: Slow, Pass
+template_binding/test/custom_element_bindings_test: Fail, Timeout # Issue 16717
 
 [ $runtime == safari ]
-fixnum/test/int_64_test: Pass, Fail # Bug in JSC.
-
 # Unexplained errors only occuring on Safari.
 typed_data/test/typed_buffers_test: RuntimeError
 
@@ -357,3 +359,5 @@
 stack_trace/test/trace_test: PubGetError
 stack_trace/test/vm_test: PubGetError
 
+[ $runtime == ie9 ]
+polymer: Pass, Fail, Timeout # Issue 16717
diff --git a/pkg/pkgbuild.status b/pkg/pkgbuild.status
index 8ee3ed75..eeaf35d 100644
--- a/pkg/pkgbuild.status
+++ b/pkg/pkgbuild.status
@@ -12,13 +12,14 @@
 [ $use_repository_packages ]
 pkg/analyzer: PubGetError
 pkg/args: PubGetError
-pkg/async: PubGetError
-pkg/collection: PubGetError
 pkg/stack_trace: PubGetError
+pkg/unittest: PubGetError
 
 [ $use_public_packages ]
 pkg/watcher: PubGetError # Issue 16026
 pkg/template_binding: Pass, PubGetError # Issue 16026
+pkg/polymer: PubGetError # Issue 16026
+pkg/polymer_expressions: PubGetError # Issue 16026
 
 [ $builder_tag == russian ]
 samples/third_party/pop-pop-win: Fail # Issue 16356
diff --git a/pkg/polymer/CHANGELOG.md b/pkg/polymer/CHANGELOG.md
index d732a88..c53ea4cc 100644
--- a/pkg/polymer/CHANGELOG.md
+++ b/pkg/polymer/CHANGELOG.md
@@ -6,6 +6,12 @@
 and template_binding.
 
 #### Pub version 0.10.0-dev
+  * Polymer polyfills are now consolidated in package:web_components, which is
+    identical to platform.js from http://polymer-project.org. This enables
+    interop with elements built in polymer.js.
+  * New feature: `@ObserveProperty('foo bar.baz') myMethod() {...}` will cause
+    myMethod to be called when "foo" or "bar.baz" changes.
+  * Updated for 0.10.0-dev package:observe and package:template_binding changes.
   * Deploy step removes use of mirrors to initialize polymer elements. Mirrors
     are still used for @published and for polymer-expressions.
     **breaking change**: @initMethod and @CustomTag are only supported on
diff --git a/pkg/polymer/lib/builder.dart b/pkg/polymer/lib/builder.dart
index 26813e7..12b8a93 100644
--- a/pkg/polymer/lib/builder.dart
+++ b/pkg/polymer/lib/builder.dart
@@ -237,7 +237,7 @@
 
   /**
    * Run transformers in release mode. For instance, uses the minified versions
-   * of shadow_dom and custom-elements polyfills.
+   * of the web_components polyfill.
    */
   final bool releaseMode;
 
@@ -301,9 +301,8 @@
         'replaces *.dart with *.dart.precompiled.js to comply with \n'
         'Content Security Policy restrictions.')
     ..addFlag('debug', help:
-        'run in debug mode. For example, use the debug versions of the \n'
-        'polyfills (shadow_dom.debug.js and custom-elements.debug.js) \n'
-        'instead of the minified versions.',
+        'run in debug mode. For example, use the debug polyfill \n'
+        'web_components/platform.concat.js instead of the minified one.\n',
         defaultsTo: false)
     ..addFlag('help', abbr: 'h',
         negatable: false, help: 'Displays this help and exit.');
diff --git a/pkg/polymer/lib/deploy.dart b/pkg/polymer/lib/deploy.dart
index d3e41a2..2a4cfb75 100644
--- a/pkg/polymer/lib/deploy.dart
+++ b/pkg/polymer/lib/deploy.dart
@@ -117,9 +117,8 @@
           'leaves "packages/browser/dart.js" to do the replacement at runtime.',
           defaultsTo: true)
       ..addFlag('debug', help:
-          'run in debug mode. For example, use the debug versions of the \n'
-          'polyfills (shadow_dom.debug.js and custom-elements.debug.js) \n'
-          'instead of the minified versions.',
+          'run in debug mode. For example, use the debug polyfill \n'
+          'web_components/platform.concat.js instead of the minified one.\n',
           defaultsTo: false)
       ..addFlag('csp', help:
           'replaces *.dart with *.dart.precompiled.js to comply with \n'
diff --git a/pkg/polymer/lib/polymer.dart b/pkg/polymer/lib/polymer.dart
index 8ccfaff..7aaedc0 100644
--- a/pkg/polymer/lib/polymer.dart
+++ b/pkg/polymer/lib/polymer.dart
@@ -49,7 +49,6 @@
     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:observe/observe.dart';
 import 'package:observe/src/dirty_check.dart' show dirtyCheckZone;
@@ -57,6 +56,7 @@
 import 'package:polymer_expressions/polymer_expressions.dart'
     show PolymerExpressions;
 import 'package:template_binding/template_binding.dart';
+import 'package:web_components/polyfill.dart' show customElementsReady;
 
 import 'deserialize.dart' as deserialize;
 
diff --git a/pkg/polymer/lib/src/boot.dart b/pkg/polymer/lib/src/boot.dart
index 6c2eb79..e0109e8 100644
--- a/pkg/polymer/lib/src/boot.dart
+++ b/pkg/polymer/lib/src/boot.dart
@@ -24,9 +24,7 @@
   _veilElements();
 
   // hookup auto-unveiling
-  Polymer.onReady.then((_) {
-    Polymer.unveilElements();
-  });
+  Polymer.onReady.then((_) => Polymer.unveilElements());
 }
 
 // add polymer styles
diff --git a/pkg/polymer/lib/src/build/import_inliner.dart b/pkg/polymer/lib/src/build/import_inliner.dart
index a66d1bb..126dc1e 100644
--- a/pkg/polymer/lib/src/build/import_inliner.dart
+++ b/pkg/polymer/lib/src/build/import_inliner.dart
@@ -18,6 +18,116 @@
 import 'code_extractor.dart'; // import just for documentation.
 import 'common.dart';
 
+class _HtmlInliner extends PolymerTransformer {
+  final TransformOptions options;
+  final Transform transform;
+  final TransformLogger logger;
+  final AssetId docId;
+  final seen = new Set<AssetId>();
+  final imported = new DocumentFragment();
+  final scriptIds = <AssetId>[];
+
+  _HtmlInliner(this.options, Transform transform)
+      : transform = transform,
+        logger = transform.logger,
+        docId = transform.primaryInput.id;
+
+  Future apply() {
+    seen.add(docId);
+
+    Document document;
+
+    return readPrimaryAsHtml(transform).then((document) =>
+        _visitImports(document, docId).then((importsFound) {
+
+      if (importsFound) {
+        document.body.insertBefore(imported, document.body.firstChild);
+        transform.addOutput(new Asset.fromString(docId, document.outerHtml));
+      } else {
+        transform.addOutput(transform.primaryInput);
+      }
+
+      // We produce a secondary asset with extra information for later phases.
+      transform.addOutput(new Asset.fromString(
+          docId.addExtension('.scriptUrls'),
+          JSON.encode(scriptIds, toEncodable: (id) => id.serialize())));
+    }));
+  }
+
+  /**
+   * Visits imports in [document] and add the imported documents to [documents].
+   * Documents are added in the order they appear, transitive imports are added
+   * first.
+   */
+  Future<bool> _visitImports(Document document, AssetId sourceId) {
+    bool hasImports = false;
+
+    // Note: we need to preserve the import order in the generated output.
+    return Future.forEach(document.querySelectorAll('link'), (Element tag) {
+      if (tag.attributes['rel'] != 'import') return null;
+      var href = tag.attributes['href'];
+      var id = resolve(sourceId, href, transform.logger, tag.sourceSpan);
+      hasImports = true;
+
+      tag.remove();
+      if (id == null || !seen.add(id) ||
+         (id.package == 'polymer' && id.path == 'lib/init.html')) return null;
+
+      return _inlineImport(id);
+    }).then((_) => hasImports);
+  }
+
+  // Loads an asset identified by [id], visits its imports and collects its
+  // html imports. Then inlines it into the main document.
+  Future _inlineImport(AssetId id) =>
+      readAsHtml(id, transform).then((doc) => _visitImports(doc, id).then((_) {
+
+    new _UrlNormalizer(transform, id).visit(doc);
+    _extractScripts(doc);
+
+    // TODO(jmesserly): figure out how this is working in vulcanizer.
+    // Do they produce a <body> tag with a <head> and <body> inside?
+    imported.nodes
+        ..addAll(doc.head.nodes)
+        ..addAll(doc.body.nodes);
+  }));
+
+  /**
+   * 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.
+   */
+  void _extractScripts(Document document) {
+    bool first = true;
+    for (var script in document.querySelectorAll('script')) {
+      if (script.attributes['type'] == 'application/dart') {
+        script.remove();
+
+        // only one Dart script per document is supported in Dartium.
+        if (first) {
+          first = false;
+
+          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', span: script.sourceSpan);
+            continue;
+          }
+          scriptIds.add(resolve(docId, src, logger, script.sourceSpan));
+
+        } else {
+          // TODO(jmesserly): remove this when we are running linter.
+          logger.warning('more than one Dart script per HTML '
+              'document is not supported. Script will be ignored.',
+              span: script.sourceSpan);
+        }
+      }
+    }
+  }
+}
+
 /**
  * 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
@@ -27,7 +137,7 @@
  * support script tags with inlined code, use this transformer after running
  * [InlineCodeExtractor] on an earlier phase.
  */
-class ImportInliner extends Transformer with PolymerTransformer {
+class ImportInliner extends Transformer {
   final TransformOptions options;
 
   ImportInliner(this.options);
@@ -36,122 +146,11 @@
   Future<bool> isPrimary(Asset input) =>
       new Future.value(options.isHtmlEntryPoint(input.id));
 
-  Future apply(Transform transform) {
-    var logger = transform.logger;
-    var seen = new Set<AssetId>();
-    var documents = [];
-    var id = transform.primaryInput.id;
-    seen.add(id);
-    return readPrimaryAsHtml(transform).then((document) {
-      var future = _visitImports(document, id, transform, seen, documents);
-      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;
-        }
-
-        // 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 fragment = new DocumentFragment();
-        for (var importedDoc in documents) {
-          bool first = true;
-          for (var e in importedDoc.queryAll('script')) {
-            if (e.attributes['type'] == 'application/dart') {
-              e.remove();
-
-              // only one Dart script per document is supported in Dartium.
-              if (first) {
-                first = false;
-                scripts.add(e);
-              } else {
-                // TODO(jmesserly): remove this when we are running linter.
-                logger.warning('more than one Dart script per HTML document is '
-                    'not supported. Script will be ignored.',
-                    span: e.sourceSpan);
-              }
-            }
-          }
-
-          // TODO(jmesserly): should we merge the head too?
-          fragment.nodes.addAll(importedDoc.body.nodes);
-        }
-
-        document.body.insertBefore(fragment, document.body.firstChild);
-
-        for (var tag in document.queryAll('link')) {
-          if (tag.attributes['rel'] == 'import') tag.remove();
-        }
-
-        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', span: script.sourceSpan);
-            continue;
-          }
-          scriptIds.add(resolve(id, src, logger, script.sourceSpan));
-        }
-        transform.addOutput(new Asset.fromString(secondaryId,
-            JSON.encode(scriptIds, toEncodable: (id) => id.serialize())));
-      });
-    });
-  }
-
-  /**
-   * Visits imports in [document] and add their polymer-element and script tags
-   * to [elements], unless they have already been [seen]. Elements are added in
-   * the order they appear, transitive imports are added first.
-   */
-  Future<bool> _visitImports(Document document, AssetId sourceId,
-      Transform transform, Set<AssetId> seen, List<Document> documents) {
-    var importIds = [];
-    bool hasImports = false;
-    for (var tag in document.queryAll('link')) {
-      if (tag.attributes['rel'] != 'import') continue;
-      var href = tag.attributes['href'];
-      var id = resolve(sourceId, href, transform.logger, tag.sourceSpan);
-      hasImports = true;
-      if (id == null || seen.contains(id) ||
-         (id.package == 'polymer' && id.path == 'lib/init.html')) continue;
-      importIds.add(id);
-    }
-
-    if (importIds.isEmpty) return new Future.value(hasImports);
-
-    // Note: we need to preserve the import order in the generated output.
-    return Future.forEach(importIds, (id) {
-      if (seen.contains(id)) return new Future.value(null);
-      seen.add(id);
-      return _collectImportedDocuments(id, transform, seen, documents);
-    }).then((_) => true);
-  }
-
-  /**
-   * Loads an asset identified by [id], visits its imports and collects it's
-   * polymer-element definitions and script tags.
-   */
-  Future _collectImportedDocuments(AssetId id, Transform transform,
-      Set<AssetId> seen, List documents) {
-    return readAsHtml(id, transform).then((document) {
-      return _visitImports(document, id, transform, seen, documents).then((_) {
-        new _UrlNormalizer(transform, id).visit(document);
-        documents.add(document);
-      });
-    });
-  }
+  Future apply(Transform transform) =>
+      new _HtmlInliner(options, transform).apply();
 }
 
+
 /** Internally adjusts urls in the html that we are about to inline. */
 class _UrlNormalizer extends TreeVisitor {
   final Transform transform;
diff --git a/pkg/polymer/lib/src/build/linter.dart b/pkg/polymer/lib/src/build/linter.dart
index 07e0153..b553ff0 100644
--- a/pkg/polymer/lib/src/build/linter.dart
+++ b/pkg/polymer/lib/src/build/linter.dart
@@ -414,7 +414,7 @@
           span: node.attributeSpans[name]);
     }
 
-    if (value.contains('.') || value.contains('(')) {
+    if (value.contains('(')) {
       _logger.warning('Invalid event handler body "$value". Declare a method '
           'in your custom element "void handlerName(event, detail, target)" '
           'and use the form $name="handlerName".',
diff --git a/pkg/polymer/lib/src/build/polyfill_injector.dart b/pkg/polymer/lib/src/build/polyfill_injector.dart
index fefc148..02b9fd1 100644
--- a/pkg/polymer/lib/src/build/polyfill_injector.dart
+++ b/pkg/polymer/lib/src/build/polyfill_injector.dart
@@ -16,8 +16,7 @@
 /**
  * Ensures that any scripts and polyfills needed to run a polymer application
  * 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).
+ * script tag that loads the polyfills and interop.js (used for 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.
@@ -33,22 +32,19 @@
 
   Future apply(Transform transform) {
     return readPrimaryAsHtml(transform).then((document) {
-      bool shadowDomFound = false;
+      bool webComponentsFound = false;
       bool jsInteropFound = false;
-      bool customElementFound = false;
       Element dartJs;
       final dartScripts = <Element>[];
 
-      for (var tag in document.queryAll('script')) {
+      for (var tag in document.querySelectorAll('script')) {
         var src = tag.attributes['src'];
         if (src != null) {
           var last = src.split('/').last;
           if (last == 'interop.js') {
             jsInteropFound = true;
-          } else if (_shadowDomJS.hasMatch(last)) {
-            shadowDomFound = true;
-          } else if (_customElementJS.hasMatch(last)) {
-            customElementFound = true;
+          } else if (_webComponentsJS.hasMatch(last)) {
+            webComponentsFound = true;
           } else if (last == 'dart.js') {
             dartJs = tag;
           }
@@ -89,31 +85,27 @@
               '<script src="packages/browser/dart.js"></script>'));
       }
 
-      _addScript(urlSegment) {
+      _addScriptFirst(urlSegment) {
         document.head.nodes.insert(0, parseFragment(
               '<script src="packages/$urlSegment"></script>\n'));
       }
 
       // JS interop code is required for Polymer CSS shimming.
-      if (!jsInteropFound) _addScript('browser/interop.js');
+      if (!jsInteropFound) _addScriptFirst('browser/interop.js');
 
-      // TODO(sigmund): enable using .min.js. This currently fails in checked
-      // mode because of bugs in dart2js mirrors (dartbug.com/14720).
-      // var suffix = options.releaseMode ? '.min.js' : '.debug.js';
-      var suffix = '.debug.js';
-      if (!customElementFound) {
-        _addScript('custom_element/custom-elements$suffix');
+      var suffix = options.releaseMode ? '.js' : '.concat.js';
+      if (!webComponentsFound) {
+        _addScriptFirst('web_components/dart_support.js');
+
+        // platform.js should come before all other scripts.
+        _addScriptFirst('web_components/platform$suffix');
       }
 
-      // This polyfill needs to be the first one on the head
-      if (!shadowDomFound) _addScript('shadow_dom/shadow_dom$suffix');
-
       transform.addOutput(
           new Asset.fromString(transform.primaryInput.id, document.outerHtml));
     });
   }
 }
 
-final _shadowDomJS = new RegExp(r'shadow_dom\..*\.js', caseSensitive: false);
-final _customElementJS = new RegExp(r'custom-elements\..*\.js',
+final _webComponentsJS = new RegExp(r'platform.*\.js',
     caseSensitive: false);
diff --git a/pkg/polymer/lib/src/build/runner.dart b/pkg/polymer/lib/src/build/runner.dart
index af71282..41c65aa 100644
--- a/pkg/polymer/lib/src/build/runner.dart
+++ b/pkg/polymer/lib/src/build/runner.dart
@@ -117,10 +117,10 @@
 // TODO(sigmund): consider computing this list by recursively parsing
 // pubspec.yaml files in the `Options.packageDirs`.
 final Set<String> _polymerPackageDependencies = [
-    'analyzer', 'args', 'barback', 'browser', 'custom_element', 'html5lib',
-    'html_import', 'js', 'logging', 'mutation_observer', 'observe', 'path'
-    'polymer_expressions', 'serialization', 'shadow_dom', 'source_maps',
-    'stack_trace', 'template_binding', 'unittest', 'unmodifiable_collection',
+    'analyzer', 'args', 'barback', 'browser', 'html5lib',
+    'js', 'logging', 'mutation_observer', 'observe', 'path'
+    'polymer_expressions', 'serialization', 'source_maps',
+    'stack_trace', 'template_binding', 'unittest', 'web_components',
     'yaml'].toSet();
 
 /** Return the relative path of each file under [subDir] in [package]. */
diff --git a/pkg/polymer/lib/src/declaration.dart b/pkg/polymer/lib/src/declaration.dart
index d120340..9201767 100644
--- a/pkg/polymer/lib/src/declaration.dart
+++ b/pkg/polymer/lib/src/declaration.dart
@@ -658,12 +658,16 @@
   var href = sheet.href;
   if (href == '') href = sheet.attributes["href"];
 
+  // TODO(jmesserly): our build is not doing the right thing for
+  // link rel=stylesheet, see http://dartbug.com/16648
   if (js.context != null && js.context.hasProperty('HTMLImports')) {
     var jsSheet = new js.JsObject.fromBrowserObject(sheet);
     var resource = jsSheet['__resource'];
     if (resource != null) return resource;
-    _sheetLog.fine('failed to get stylesheet text href="$href"');
-    return '';
+    // TODO(jmesserly): figure out why HTMLImports is failing to load these.
+    // Falling back to sync XHR is no good.
+    // _sheetLog.fine('failed to get stylesheet text href="$href"');
+    // return '';
   }
   // TODO(jmesserly): it seems like polymer-js is always polyfilling
   // HTMLImports, because their code depends on "__resource" to work.
diff --git a/pkg/polymer/pubspec.yaml b/pkg/polymer/pubspec.yaml
index 15475869..08e2b6a 100644
--- a/pkg/polymer/pubspec.yaml
+++ b/pkg/polymer/pubspec.yaml
@@ -11,16 +11,14 @@
   args: ">=0.9.0 <0.10.0"
   barback: ">=0.9.0 <0.12.0"
   browser: ">=0.9.0 <0.10.0"
-  custom_element: ">=0.9.1+1 <0.10.0"
-  html5lib: ">=0.9.1 <0.10.0"
-  html_import: ">=0.9.0 <0.10.0"
+  html5lib: ">=0.9.2-dev <0.10.0"
   logging: ">=0.9.0 <0.10.0"
-  observe: ">=0.9.1 <0.10.0"
+  observe: ">=0.10.0-dev <0.11.0"
   path: ">=0.9.0 <2.0.0"
-  polymer_expressions: ">=0.9.1 <0.10.0"
-  shadow_dom: ">=0.9.1 <0.10.0"
+  polymer_expressions: ">=0.10.0-dev <0.11.0"
   source_maps: ">=0.9.0 <0.10.0"
-  template_binding: ">=0.9.0 <0.10.0"
+  template_binding: ">=0.10.0-dev <0.11.0"
+  web_components: ">=0.3.0 <0.4.0"
   yaml: ">=0.9.0 <0.10.0"
 transformers:
 - observe:
diff --git a/pkg/polymer/test/bind_mdv_test.dart b/pkg/polymer/test/bind_mdv_test.dart
index 3323b0c..a47bfc2 100644
--- a/pkg/polymer/test/bind_mdv_test.dart
+++ b/pkg/polymer/test/bind_mdv_test.dart
@@ -6,16 +6,16 @@
 
 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:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
+import 'package:web_components/polyfill.dart';
 
 main() {
   useHtmlConfiguration();
 
-  var registered = loadCustomElementPolyfill().then((_) {
+  var registered = customElementsReady.then((_) {
     document.register('my-div', MyDivElement);
   });
 
diff --git a/pkg/polymer/test/bind_mdv_test.html b/pkg/polymer/test/bind_mdv_test.html
new file mode 100644
index 0000000..444bf7e
--- /dev/null
+++ b/pkg/polymer/test/bind_mdv_test.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> bind_mdv_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/platform.concat.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running bind_mdv_test </h1>
+  <script type="text/javascript"
+      src="/packages/unittest/test_controller.js"></script>
+  <script type="text/javascript"
+      src="/packages/browser/interop.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/pkg/polymer/test/build/all_phases_test.dart b/pkg/polymer/test/build/all_phases_test.dart
index 3f84593..6633eb1 100644
--- a/pkg/polymer/test/build/all_phases_test.dart
+++ b/pkg/polymer/test/build/all_phases_test.dart
@@ -37,8 +37,7 @@
     }, {
       'a|web/test.html':
           '<!DOCTYPE html><html><head>'
-          '$SHADOW_DOM_TAG'
-          '$CUSTOM_ELEMENT_TAG'
+          '$WEB_COMPONENTS_TAG'
           '$INTEROP_TAG'
           '<script src="test.html_bootstrap.dart.js"></script>'
           '</head><body></body></html>',
@@ -64,8 +63,7 @@
     }, {
       'a|web/test.html':
           '<!DOCTYPE html><html><head>'
-          '$SHADOW_DOM_TAG'
-          '$CUSTOM_ELEMENT_TAG'
+          '$WEB_COMPONENTS_TAG'
           '$INTEROP_TAG'
           '<script src="test.html_bootstrap.dart.js"></script>'
           '</head><body></body></html>',
@@ -103,8 +101,7 @@
     }, {
       'a|web/test.html':
           '<!DOCTYPE html><html><head>'
-          '$SHADOW_DOM_TAG'
-          '$CUSTOM_ELEMENT_TAG'
+          '$WEB_COMPONENTS_TAG'
           '$INTEROP_TAG'
           '<script src="test.html_bootstrap.dart.js"></script>'
           '</head><body>'
@@ -142,8 +139,7 @@
     }, {
       'a|web/index.html':
           '<!DOCTYPE html><html><head>'
-          '$SHADOW_DOM_TAG'
-          '$CUSTOM_ELEMENT_TAG'
+          '$WEB_COMPONENTS_TAG'
           '$INTEROP_TAG'
           '</head><body><polymer-element>1</polymer-element>'
           '<script src="index.html_bootstrap.dart.js"></script>'
diff --git a/pkg/polymer/test/build/common.dart b/pkg/polymer/test/build/common.dart
index d38fb3d..a4d9ba2 100644
--- a/pkg/polymer/test/build/common.dart
+++ b/pkg/polymer/test/build/common.dart
@@ -131,13 +131,10 @@
   });
 }
 
-// TODO(jmesserly): this is .debug to workaround issue 14720.
-const SHADOW_DOM_TAG =
-    '<script src="packages/shadow_dom/shadow_dom.debug.js"></script>\n';
+const WEB_COMPONENTS_TAG =
+    '<script src="packages/web_components/platform.js"></script>\n'
+    '<script src="packages/web_components/dart_support.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">'
-    '</script>\n';
diff --git a/pkg/polymer/test/build/polyfill_injector_test.dart b/pkg/polymer/test/build/polyfill_injector_test.dart
index 8a28739..7e0f95e 100644
--- a/pkg/polymer/test/build/polyfill_injector_test.dart
+++ b/pkg/polymer/test/build/polyfill_injector_test.dart
@@ -51,7 +51,7 @@
     }, {
       'a|web/test.html':
           '<!DOCTYPE html><html><head>'
-          '$SHADOW_DOM_TAG$CUSTOM_ELEMENT_TAG$INTEROP_TAG'
+          '$WEB_COMPONENTS_TAG$INTEROP_TAG'
           '</head><body>'
           '<script ${type}src="a.dart$ext"></script>'
           '$dartJsTag'
@@ -61,8 +61,7 @@
   testPhases('interop/shadow dom already present', phases, {
       'a|web/test.html':
           '<!DOCTYPE html><html><head>'
-          '$SHADOW_DOM_TAG'
-          '$CUSTOM_ELEMENT_TAG'
+          '$WEB_COMPONENTS_TAG'
           '$INTEROP_TAG'
           '</head><body>'
           '<script type="application/dart" src="a.dart"></script>'
@@ -70,8 +69,7 @@
     }, {
       'a|web/test.html':
           '<!DOCTYPE html><html><head>'
-          '$SHADOW_DOM_TAG'
-          '$CUSTOM_ELEMENT_TAG'
+          '$WEB_COMPONENTS_TAG'
           '$INTEROP_TAG'
           '</head><body>'
           '<script ${type}src="a.dart$ext"></script>'
diff --git a/pkg/polymer/test/noscript_test.dart b/pkg/polymer/test/noscript_test.dart
index d638713..bdbcb6f 100644
--- a/pkg/polymer/test/noscript_test.dart
+++ b/pkg/polymer/test/noscript_test.dart
@@ -2,18 +2,32 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:async';
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:unittest/html_config.dart';
 import 'package:polymer/polymer.dart';
 import 'package:template_binding/template_binding.dart';
 
-main() {
-  initPolymer();
-  useHtmlConfiguration();
-  templateBind(querySelector("#a")).model = "foo";
+Future<List<MutationRecord>> onMutation(Node node) {
+  var completer = new Completer();
+  new MutationObserver((mutations, observer) {
+    observer.disconnect();
+    completer.complete(mutations);
+  })..observe(node, childList: true, subtree: true);
+  return completer.future;
+}
 
-  setUp(() => Polymer.onReady);
+main() => initPolymer().run(() {
+  useHtmlConfiguration();
+
+  var ready = Polymer.onReady.then((_) {
+    var a = querySelector("#a");
+    templateBind(a).model = "foo";
+    return onMutation(a.parent);
+  });
+
+  setUp(() => ready);
 
   test('template found with multiple noscript declarations', () {
     expect(querySelector('x-a') is PolymerElement, isTrue);
@@ -28,4 +42,4 @@
     expect(querySelector('x-d') is PolymerElement, isTrue);
     expect(querySelector('x-d').shadowRoot.nodes.first.text, 'd');
   });
-}
+});
diff --git a/pkg/polymer/test/run.sh b/pkg/polymer/test/run.sh
deleted file mode 100755
index 62497be..0000000
--- a/pkg/polymer/test/run.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-# 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.
-
-# Usage: run from a Dart SVN checkout after building.
-
-# bail on error
-set -e
-
-# Note: test.dart needs to be run from the root of the Dart checkout
-DIR=$( cd $( dirname "${BASH_SOURCE[0]}" ) && pwd )
-pushd $DIR/../../.. > /dev/null
-
-echo "*** Running unit tests for Polymer.dart and its dependencies."
-
-SUITES="pkg/polymer samples/third_party/todomvc"
-
-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"
-$CMD
-
-echo -e "All tests pass"
diff --git a/pkg/polymer_expressions/pubspec.yaml b/pkg/polymer_expressions/pubspec.yaml
index 5b80ae9..d996a3b 100644
--- a/pkg/polymer_expressions/pubspec.yaml
+++ b/pkg/polymer_expressions/pubspec.yaml
@@ -1,12 +1,12 @@
 name: polymer_expressions
-version: 0.9.1
+version: 0.10.0-dev
 author: Web UI Authors <html-dev@dartlang.org>
 description: An expressive custom binding syntax for MDV templates
 homepage: http://www.dartlang.org/polymer-dart/
 dependencies:
   browser: ">=0.9.0 <0.10.0"
   observe: ">=0.9.0 <0.10.0"
-  template_binding: ">=0.9.0 <0.10.0"
+  template_binding: ">=0.10.0-dev <0.11.0"
 dev_dependencies:
   unittest: ">=0.9.0 <0.10.0"
   benchmark_harness: ">=1.0.0 <2.0.0"
diff --git a/pkg/sequence_zip/LICENSE b/pkg/sequence_zip/LICENSE
deleted file mode 100644
index ee99930..0000000
--- a/pkg/sequence_zip/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright 2013, the Dart project authors. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-    * Neither the name of Google Inc. nor the names of its
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-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.
diff --git a/pkg/sequence_zip/lib/iterable_zip.dart b/pkg/sequence_zip/lib/iterable_zip.dart
deleted file mode 100644
index dd4e5cb..0000000
--- a/pkg/sequence_zip/lib/iterable_zip.dart
+++ /dev/null
@@ -1,9 +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.
-
-/** Please use `package:collection/iterable_zip.dart` instead. */
-@deprecated
-library iterable_zip;
-
-export "package:collection/iterable_zip.dart";
diff --git a/pkg/sequence_zip/lib/sequence_zip.dart b/pkg/sequence_zip/lib/sequence_zip.dart
deleted file mode 100644
index 8824e46..0000000
--- a/pkg/sequence_zip/lib/sequence_zip.dart
+++ /dev/null
@@ -1,13 +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.
-
-/**
- * Please use the libraries `package:collection/iterable_zip.dart` for iterable zipping
- * or `package:async/stream_zip.dart` for stream zipping.
- */
-@deprecated
-library sequence_zip;
-
-export "iterable_zip.dart";
-export "stream_zip.dart";
diff --git a/pkg/sequence_zip/lib/stream_zip.dart b/pkg/sequence_zip/lib/stream_zip.dart
deleted file mode 100644
index 78b7a3a..0000000
--- a/pkg/sequence_zip/lib/stream_zip.dart
+++ /dev/null
@@ -1,9 +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.
-
-/** Please use `package:async/stream_zip.dart` instead. */
-@deprecated
-library stream_zip;
-
-export "package:async/stream_zip.dart";
\ No newline at end of file
diff --git a/pkg/sequence_zip/pubspec.yaml b/pkg/sequence_zip/pubspec.yaml
deleted file mode 100644
index 961e43a..0000000
--- a/pkg/sequence_zip/pubspec.yaml
+++ /dev/null
@@ -1,14 +0,0 @@
-name: sequence_zip
-version: 0.9.1
-author: Dart Team <misc@dartlang.org>
-homepage: http://www.dartlang.org
-description: >
-  "Zip" functionality on iterables and streams.
-  This package has been discontinued.
-  The zip functionality for iterables is in `package:collection/iterable_zip.dart`
-  and the zip functionality for streams is in `package:async/stream_zip.dart`.
-dependencies:
-  collection: "0.9.0"
-  async: "0.9.0"
-environment:
-  sdk: ">=0.8.10+6 <2.0.0"
diff --git a/pkg/shadow_dom/README.md b/pkg/shadow_dom/README.md
deleted file mode 100644
index 9c2c1c2..0000000
--- a/pkg/shadow_dom/README.md
+++ /dev/null
@@ -1,100 +0,0 @@
-# Shadow DOM polyfill
-
-Shadow DOM is designed to provide encapsulation by hiding DOM subtrees under
-shadow roots. It provides a method of establishing and maintaining functional
-boundaries between DOM trees and how these trees interact with each other within
-a document, thus enabling better functional encapsulation within the DOM. See
-the
-[W3C specification](https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html)
-for details.
-
-## Getting started
-
-Include the polyfill in your HTML `<head>` to enable Shadow DOM:
-
-```html
-    <script src="packages/shadow_dom/shadow_dom.debug.js"></script>
-```
-
-You can also use a minified version for deployment:
-
-```html
-    <script src="packages/shadow_dom/shadow_dom.min.js"></script>
-```
-
-Because it does extensive DOM patching, it should be included **before** other
-script tags.
-
-## Useful resources
-
-- [What the Heck is Shadow DOM?](http://glazkov.com/2011/01/14/what-the-heck-is-shadow-dom/)
-- [Web Components Explained - Shadow DOM](https://dvcs.w3.org/hg/webcomponents/raw-file/57f8cfc4a7dc/explainer/index.html#shadow-dom-section)
-- [HTML5Rocks - Shadow DOM 101](http://www.html5rocks.com/tutorials/webcomponents/shadowdom/)
-- [HTML5Rocks - Shadow DOM 201: CSS and Styling](http://www.html5rocks.com/tutorials/webcomponents/shadowdom-201/)
-- [HTML5Rocks - Shadow DOM 301: Advanced Concepts & DOM APIs](http://www.html5rocks.com/tutorials/webcomponents/shadowdom-301/)
-
-## Learn the tech
-
-### Basic usage
-
-```dart
-var el = new DivElement();
-var shadow = el.createShadowRoot();
-shadow.innerHtml = '<content select="h1"></content>';
-```
-
-### Shadow DOM subtrees
-
-Shadow DOM allows a single node to express three subtrees: _light DOM_, _shadow DOM_, and _composed DOM_.
-
-A component user supplies the light DOM; the node has a (hidden) shadow DOM; and the composed DOM is what is actually rendered in the browser. At render time, the light DOM is merged with the shadow DOM to produce the composed DOM. For example:
-
-**Light DOM**
-
-```html
-<my-custom-element>
-  <!-- everything in here is my-custom-element's light DOM -->
-  <q>Hello World</q>
-</my-custom-element>
-```
-
-**Shadow DOM**
-
-```html
-<!-- shadow-root is attached to my-custom-element, but is not a child -->
-<shadow-root>
-  <!-- everything in here is my-custom-element's shadow DOM -->
-  <span>People say: <content></content></span>
-</shadow-root>
-```
-
-**Composed (rendered) DOM**
-
-```html
-<!-- rendered DOM -->
-<my-custom-element>
-  <span>People say: <q>Hello World</q></span>
-</my-custom-element>
-```
-
-The following is true about this example:
-
-* The light DOM that belongs to `<my-custom-element>` is visible to the user as its normal subtree. It can expressed by `.childNodes`, `.nodes`, `.innerHtml` or any other property or method that gives you information about a node's subtree.
-* Nodes in light DOM or shadow DOM express parent and sibling relationships that match their respective tree structures; the relationships that exist in the rendered tree are not expressed anywhere in DOM.
-
-So, while in the final rendered tree `<span>` is a child of `<my-custom-element>` and the parent of `<q>`, interrogating those nodes will tell you that the `<span>` is a child of `<shadow-root>` and `<q>` is a child of `<my-custom-element>`, and that those two nodes are unrelated.
-
-In this way, the user can manipulate light DOM or shadow DOM directly as regular DOM subtrees, and let the system take care of keeping the render tree synchronized.
-
-## Polyfill details
-
-You can read more about how the polyfill is implemented in JavaScript here:
-<https://github.com/polymer/ShadowDOM#polyfill-details>.
-
-## Getting the source code
-
-This package is built from:
-<https://github.com/dart-lang/ShadowDOM/tree/conditional_shadowdom>
-
-You'll need [node.js](http://nodejs.org) to rebuild the JS file. Use `npm install` to
-get dependencies and `grunt` to build.
diff --git a/pkg/shadow_dom/REVISIONS b/pkg/shadow_dom/REVISIONS
deleted file mode 100644
index 6b8b65f..0000000
--- a/pkg/shadow_dom/REVISIONS
+++ /dev/null
@@ -1,5 +0,0 @@
- 
-  ShadowDOM is at revision 3d48070b83678bcf10ee45e1604ace2c80f26a15 
-  observe-js is at revision 0152d542350239563d0f2cad39d22d3254bd6c2a 
-  WeakMap is at revision a0947a9a0f58f5733f464755c3b86de624b00a5d 
-  platform-dev is at revision 1cc5f8d38cdc93ea994e28463f3381b873f28ea7
diff --git a/pkg/shadow_dom/lib/shadow_dom.debug.js b/pkg/shadow_dom/lib/shadow_dom.debug.js
deleted file mode 100644
index f411852..0000000
--- a/pkg/shadow_dom/lib/shadow_dom.debug.js
+++ /dev/null
@@ -1,7551 +0,0 @@
-if (!HTMLElement.prototype.createShadowRoot
-    || window.__forceShadowDomPolyfill) {
-
-/*
- * Copyright 2013 The Polymer Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style
- * license that can be found in the LICENSE file.
- */
-(function() {
-  // TODO(jmesserly): fix dart:html to use unprefixed name
-  if (Element.prototype.webkitCreateShadowRoot) {
-    Element.prototype.webkitCreateShadowRoot = function() {
-      return window.ShadowDOMPolyfill.wrapIfNeeded(this).createShadowRoot();
-    };
-  }
-})();
-
-// Copyright 2012 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-(function(global) {
-  'use strict';
-
-  var PROP_ADD_TYPE = 'add';
-  var PROP_UPDATE_TYPE = 'update';
-  var PROP_RECONFIGURE_TYPE = 'reconfigure';
-  var PROP_DELETE_TYPE = 'delete';
-  var ARRAY_SPLICE_TYPE = 'splice';
-
-  // Detect and do basic sanity checking on Object/Array.observe.
-  function detectObjectObserve() {
-    if (typeof Object.observe !== 'function' ||
-        typeof Array.observe !== 'function') {
-      return false;
-    }
-
-    var records = [];
-
-    function callback(recs) {
-      records = recs;
-    }
-
-    var test = {};
-    Object.observe(test, callback);
-    test.id = 1;
-    test.id = 2;
-    delete test.id;
-    Object.deliverChangeRecords(callback);
-    if (records.length !== 3)
-      return false;
-
-    // TODO(rafaelw): Remove this when new change record type names make it to
-    // chrome release.
-    if (records[0].type == 'new' &&
-        records[1].type == 'updated' &&
-        records[2].type == 'deleted') {
-      PROP_ADD_TYPE = 'new';
-      PROP_UPDATE_TYPE = 'updated';
-      PROP_RECONFIGURE_TYPE = 'reconfigured';
-      PROP_DELETE_TYPE = 'deleted';
-    } else if (records[0].type != 'add' ||
-               records[1].type != 'update' ||
-               records[2].type != 'delete') {
-      console.error('Unexpected change record names for Object.observe. ' +
-                    'Using dirty-checking instead');
-      return false;
-    }
-    Object.unobserve(test, callback);
-
-    test = [0];
-    Array.observe(test, callback);
-    test[1] = 1;
-    test.length = 0;
-    Object.deliverChangeRecords(callback);
-    if (records.length != 2)
-      return false;
-    if (records[0].type != ARRAY_SPLICE_TYPE ||
-        records[1].type != ARRAY_SPLICE_TYPE) {
-      return false;
-    }
-    Array.unobserve(test, callback);
-
-    return true;
-  }
-
-  var hasObserve = detectObjectObserve();
-
-  function detectEval() {
-    // don't test for eval if document has CSP securityPolicy object and we can see that
-    // eval is not supported. This avoids an error message in console even when the exception
-    // is caught
-    if (global.document &&
-        'securityPolicy' in global.document &&
-        !global.document.securityPolicy.allowsEval) {
-      return false;
-    }
-
-    try {
-      var f = new Function('', 'return true;');
-      return f();
-    } catch (ex) {
-      return false;
-    }
-  }
-
-  var hasEval = detectEval();
-
-  function isIndex(s) {
-    return +s === s >>> 0;
-  }
-
-  function toNumber(s) {
-    return +s;
-  }
-
-  function isObject(obj) {
-    return obj === Object(obj);
-  }
-
-  var numberIsNaN = global.Number.isNaN || function isNaN(value) {
-    return typeof value === 'number' && global.isNaN(value);
-  }
-
-  function areSameValue(left, right) {
-    if (left === right)
-      return left !== 0 || 1 / left === 1 / right;
-    if (numberIsNaN(left) && numberIsNaN(right))
-      return true;
-
-    return left !== left && right !== right;
-  }
-
-  var createObject = ('__proto__' in {}) ?
-    function(obj) { return obj; } :
-    function(obj) {
-      var proto = obj.__proto__;
-      if (!proto)
-        return obj;
-      var newObject = Object.create(proto);
-      Object.getOwnPropertyNames(obj).forEach(function(name) {
-        Object.defineProperty(newObject, name,
-                             Object.getOwnPropertyDescriptor(obj, name));
-      });
-      return newObject;
-    };
-
-  var identStart = '[\$_a-zA-Z]';
-  var identPart = '[\$_a-zA-Z0-9]';
-  var ident = identStart + '+' + identPart + '*';
-  var elementIndex = '(?:[0-9]|[1-9]+[0-9]+)';
-  var identOrElementIndex = '(?:' + ident + '|' + elementIndex + ')';
-  var path = '(?:' + identOrElementIndex + ')(?:\\s*\\.\\s*' + identOrElementIndex + ')*';
-  var pathRegExp = new RegExp('^' + path + '$');
-
-  function isPathValid(s) {
-    if (typeof s != 'string')
-      return false;
-    s = s.trim();
-
-    if (s == '')
-      return true;
-
-    if (s[0] == '.')
-      return false;
-
-    return pathRegExp.test(s);
-  }
-
-  var constructorIsPrivate = {};
-
-  function Path(s, privateToken) {
-    if (privateToken !== constructorIsPrivate)
-      throw Error('Use Path.get to retrieve path objects');
-
-    if (s.trim() == '')
-      return this;
-
-    if (isIndex(s)) {
-      this.push(s);
-      return this;
-    }
-
-    s.split(/\s*\.\s*/).filter(function(part) {
-      return part;
-    }).forEach(function(part) {
-      this.push(part);
-    }, this);
-
-    if (hasEval && this.length) {
-      this.getValueFrom = this.compiledGetValueFromFn();
-    }
-  }
-
-  // TODO(rafaelw): Make simple LRU cache
-  var pathCache = {};
-
-  function getPath(pathString) {
-    if (pathString instanceof Path)
-      return pathString;
-
-    if (pathString == null)
-      pathString = '';
-
-    if (typeof pathString !== 'string')
-      pathString = String(pathString);
-
-    var path = pathCache[pathString];
-    if (path)
-      return path;
-    if (!isPathValid(pathString))
-      return invalidPath;
-    var path = new Path(pathString, constructorIsPrivate);
-    pathCache[pathString] = path;
-    return path;
-  }
-
-  Path.get = getPath;
-
-  Path.prototype = createObject({
-    __proto__: [],
-    valid: true,
-
-    toString: function() {
-      return this.join('.');
-    },
-
-    getValueFrom: function(obj, directObserver) {
-      for (var i = 0; i < this.length; i++) {
-        if (obj == null)
-          return;
-        obj = obj[this[i]];
-      }
-      return obj;
-    },
-
-    iterateObjects: function(obj, observe) {
-      for (var i = 0; i < this.length; i++) {
-        if (i)
-          obj = obj[this[i - 1]];
-        if (!obj)
-          return;
-        observe(obj);
-      }
-    },
-
-    compiledGetValueFromFn: function() {
-      var accessors = this.map(function(ident) {
-        return isIndex(ident) ? '["' + ident + '"]' : '.' + ident;
-      });
-
-      var str = '';
-      var pathString = 'obj';
-      str += 'if (obj != null';
-      var i = 0;
-      for (; i < (this.length - 1); i++) {
-        var ident = this[i];
-        pathString += accessors[i];
-        str += ' &&\n     ' + pathString + ' != null';
-      }
-      str += ')\n';
-
-      pathString += accessors[i];
-
-      str += '  return ' + pathString + ';\nelse\n  return undefined;';
-      return new Function('obj', str);
-    },
-
-    setValueFrom: function(obj, value) {
-      if (!this.length)
-        return false;
-
-      for (var i = 0; i < this.length - 1; i++) {
-        if (!isObject(obj))
-          return false;
-        obj = obj[this[i]];
-      }
-
-      if (!isObject(obj))
-        return false;
-
-      obj[this[i]] = value;
-      return true;
-    }
-  });
-
-  var invalidPath = new Path('', constructorIsPrivate);
-  invalidPath.valid = false;
-  invalidPath.getValueFrom = invalidPath.setValueFrom = function() {};
-
-  var MAX_DIRTY_CHECK_CYCLES = 1000;
-
-  function dirtyCheck(observer) {
-    var cycles = 0;
-    while (cycles < MAX_DIRTY_CHECK_CYCLES && observer.check_()) {
-      cycles++;
-    }
-    if (global.testingExposeCycleCount)
-      global.dirtyCheckCycleCount = cycles;
-
-    return cycles > 0;
-  }
-
-  function objectIsEmpty(object) {
-    for (var prop in object)
-      return false;
-    return true;
-  }
-
-  function diffIsEmpty(diff) {
-    return objectIsEmpty(diff.added) &&
-           objectIsEmpty(diff.removed) &&
-           objectIsEmpty(diff.changed);
-  }
-
-  function diffObjectFromOldObject(object, oldObject) {
-    var added = {};
-    var removed = {};
-    var changed = {};
-    var oldObjectHas = {};
-
-    for (var prop in oldObject) {
-      var newValue = object[prop];
-
-      if (newValue !== undefined && newValue === oldObject[prop])
-        continue;
-
-      if (!(prop in object)) {
-        removed[prop] = undefined;
-        continue;
-      }
-
-      if (newValue !== oldObject[prop])
-        changed[prop] = newValue;
-    }
-
-    for (var prop in object) {
-      if (prop in oldObject)
-        continue;
-
-      added[prop] = object[prop];
-    }
-
-    if (Array.isArray(object) && object.length !== oldObject.length)
-      changed.length = object.length;
-
-    return {
-      added: added,
-      removed: removed,
-      changed: changed
-    };
-  }
-
-  var eomTasks = [];
-  function runEOMTasks() {
-    if (!eomTasks.length)
-      return false;
-
-    for (var i = 0; i < eomTasks.length; i++) {
-      eomTasks[i]();
-    }
-    eomTasks.length = 0;
-    return true;
-  }
-
-  var runEOM = hasObserve ? (function(){
-    var eomObj = { pingPong: true };
-    var eomRunScheduled = false;
-
-    Object.observe(eomObj, function() {
-      runEOMTasks();
-      eomRunScheduled = false;
-    });
-
-    return function(fn) {
-      eomTasks.push(fn);
-      if (!eomRunScheduled) {
-        eomRunScheduled = true;
-        eomObj.pingPong = !eomObj.pingPong;
-      }
-    };
-  })() :
-  (function() {
-    return function(fn) {
-      eomTasks.push(fn);
-    };
-  })();
-
-  var observedObjectCache = [];
-
-  function newObservedObject() {
-    var observer;
-    var object;
-    var discardRecords = false;
-    var first = true;
-
-    function callback(records) {
-      if (observer && observer.state_ === OPENED && !discardRecords)
-        observer.check_(records);
-    }
-
-    return {
-      open: function(obs) {
-        if (observer)
-          throw Error('ObservedObject in use');
-
-        if (!first)
-          Object.deliverChangeRecords(callback);
-
-        observer = obs;
-        first = false;
-      },
-      observe: function(obj, arrayObserve) {
-        object = obj;
-        if (arrayObserve)
-          Array.observe(object, callback);
-        else
-          Object.observe(object, callback);
-      },
-      deliver: function(discard) {
-        discardRecords = discard;
-        Object.deliverChangeRecords(callback);
-        discardRecords = false;
-      },
-      close: function() {
-        observer = undefined;
-        Object.unobserve(object, callback);
-        observedObjectCache.push(this);
-      }
-    };
-  }
-
-  function getObservedObject(observer, object, arrayObserve) {
-    var dir = observedObjectCache.pop() || newObservedObject();
-    dir.open(observer);
-    dir.observe(object, arrayObserve);
-    return dir;
-  }
-
-  var emptyArray = [];
-  var observedSetCache = [];
-
-  function newObservedSet() {
-    var observers = [];
-    var observerCount = 0;
-    var objects = [];
-    var toRemove = emptyArray;
-    var resetNeeded = false;
-    var resetScheduled = false;
-
-    function observe(obj) {
-      if (!isObject(obj))
-        return;
-
-      var index = toRemove.indexOf(obj);
-      if (index >= 0) {
-        toRemove[index] = undefined;
-        objects.push(obj);
-      } else if (objects.indexOf(obj) < 0) {
-        objects.push(obj);
-        Object.observe(obj, callback);
-      }
-
-      observe(Object.getPrototypeOf(obj));
-    }
-
-    function reset() {
-      resetScheduled = false;
-      if (!resetNeeded)
-        return;
-
-      var objs = toRemove === emptyArray ? [] : toRemove;
-      toRemove = objects;
-      objects = objs;
-
-      var observer;
-      for (var id in observers) {
-        observer = observers[id];
-        if (!observer || observer.state_ != OPENED)
-          continue;
-
-        observer.iterateObjects_(observe);
-      }
-
-      for (var i = 0; i < toRemove.length; i++) {
-        var obj = toRemove[i];
-        if (obj)
-          Object.unobserve(obj, callback);
-      }
-
-      toRemove.length = 0;
-    }
-
-    function scheduleReset() {
-      if (resetScheduled)
-        return;
-
-      resetNeeded = true;
-      resetScheduled = true;
-      runEOM(reset);
-    }
-
-    function callback() {
-      var observer;
-
-      for (var id in observers) {
-        observer = observers[id];
-        if (!observer || observer.state_ != OPENED)
-          continue;
-
-        observer.check_();
-      }
-
-      scheduleReset();
-    }
-
-    var record = {
-      object: undefined,
-      objects: objects,
-      open: function(obs) {
-        observers[obs.id_] = obs;
-        observerCount++;
-        obs.iterateObjects_(observe);
-      },
-      close: function(obs) {
-        var anyLeft = false;
-
-        observers[obs.id_] = undefined;
-        observerCount--;
-
-        if (observerCount) {
-          scheduleReset();
-          return;
-        }
-        resetNeeded = false;
-
-        for (var i = 0; i < objects.length; i++) {
-          Object.unobserve(objects[i], callback);
-          Observer.unobservedCount++;
-        }
-
-        observers.length = 0;
-        objects.length = 0;
-        observedSetCache.push(this);
-      },
-      reset: scheduleReset
-    };
-
-    return record;
-  }
-
-  var lastObservedSet;
-
-  function getObservedSet(observer, obj) {
-    if (!lastObservedSet || lastObservedSet.object !== obj) {
-      lastObservedSet = observedSetCache.pop() || newObservedSet();
-      lastObservedSet.object = obj;
-    }
-    lastObservedSet.open(observer);
-    return lastObservedSet;
-  }
-
-  var UNOPENED = 0;
-  var OPENED = 1;
-  var CLOSED = 2;
-  var RESETTING = 3;
-
-  var nextObserverId = 1;
-
-  function Observer() {
-    this.state_ = UNOPENED;
-    this.callback_ = undefined;
-    this.target_ = undefined; // TODO(rafaelw): Should be WeakRef
-    this.directObserver_ = undefined;
-    this.value_ = undefined;
-    this.id_ = nextObserverId++;
-  }
-
-  Observer.prototype = {
-    open: function(callback, target) {
-      if (this.state_ != UNOPENED)
-        throw Error('Observer has already been opened.');
-
-      addToAll(this);
-      this.callback_ = callback;
-      this.target_ = target;
-      this.state_ = OPENED;
-      this.connect_();
-      return this.value_;
-    },
-
-    close: function() {
-      if (this.state_ != OPENED)
-        return;
-
-      removeFromAll(this);
-      this.state_ = CLOSED;
-      this.disconnect_();
-      this.value_ = undefined;
-      this.callback_ = undefined;
-      this.target_ = undefined;
-    },
-
-    deliver: function() {
-      if (this.state_ != OPENED)
-        return;
-
-      dirtyCheck(this);
-    },
-
-    report_: function(changes) {
-      try {
-        this.callback_.apply(this.target_, changes);
-      } catch (ex) {
-        Observer._errorThrownDuringCallback = true;
-        console.error('Exception caught during observer callback: ' +
-                       (ex.stack || ex));
-      }
-    },
-
-    discardChanges: function() {
-      this.check_(undefined, true);
-      return this.value_;
-    }
-  }
-
-  var collectObservers = !hasObserve;
-  var allObservers;
-  Observer._allObserversCount = 0;
-
-  if (collectObservers) {
-    allObservers = [];
-  }
-
-  function addToAll(observer) {
-    Observer._allObserversCount++;
-    if (!collectObservers)
-      return;
-
-    allObservers.push(observer);
-  }
-
-  function removeFromAll(observer) {
-    Observer._allObserversCount--;
-  }
-
-  var runningMicrotaskCheckpoint = false;
-
-  var hasDebugForceFullDelivery = typeof Object.deliverAllChangeRecords == 'function';
-
-  global.Platform = global.Platform || {};
-
-  global.Platform.performMicrotaskCheckpoint = function() {
-    if (runningMicrotaskCheckpoint)
-      return;
-
-    if (hasDebugForceFullDelivery) {
-      Object.deliverAllChangeRecords();
-      return;
-    }
-
-    if (!collectObservers)
-      return;
-
-    runningMicrotaskCheckpoint = true;
-
-    var cycles = 0;
-    var anyChanged, toCheck;
-
-    do {
-      cycles++;
-      toCheck = allObservers;
-      allObservers = [];
-      anyChanged = false;
-
-      for (var i = 0; i < toCheck.length; i++) {
-        var observer = toCheck[i];
-        if (observer.state_ != OPENED)
-          continue;
-
-        if (observer.check_())
-          anyChanged = true;
-
-        allObservers.push(observer);
-      }
-      if (runEOMTasks())
-        anyChanged = true;
-    } while (cycles < MAX_DIRTY_CHECK_CYCLES && anyChanged);
-
-    if (global.testingExposeCycleCount)
-      global.dirtyCheckCycleCount = cycles;
-
-    runningMicrotaskCheckpoint = false;
-  };
-
-  if (collectObservers) {
-    global.Platform.clearObservers = function() {
-      allObservers = [];
-    };
-  }
-
-  function ObjectObserver(object) {
-    Observer.call(this);
-    this.value_ = object;
-    this.oldObject_ = undefined;
-  }
-
-  ObjectObserver.prototype = createObject({
-    __proto__: Observer.prototype,
-
-    arrayObserve: false,
-
-    connect_: function(callback, target) {
-      if (hasObserve) {
-        this.directObserver_ = getObservedObject(this, this.value_,
-                                                 this.arrayObserve);
-      } else {
-        this.oldObject_ = this.copyObject(this.value_);
-      }
-
-    },
-
-    copyObject: function(object) {
-      var copy = Array.isArray(object) ? [] : {};
-      for (var prop in object) {
-        copy[prop] = object[prop];
-      };
-      if (Array.isArray(object))
-        copy.length = object.length;
-      return copy;
-    },
-
-    check_: function(changeRecords, skipChanges) {
-      var diff;
-      var oldValues;
-      if (hasObserve) {
-        if (!changeRecords)
-          return false;
-
-        oldValues = {};
-        diff = diffObjectFromChangeRecords(this.value_, changeRecords,
-                                           oldValues);
-      } else {
-        oldValues = this.oldObject_;
-        diff = diffObjectFromOldObject(this.value_, this.oldObject_);
-      }
-
-      if (diffIsEmpty(diff))
-        return false;
-
-      if (!hasObserve)
-        this.oldObject_ = this.copyObject(this.value_);
-
-      this.report_([
-        diff.added || {},
-        diff.removed || {},
-        diff.changed || {},
-        function(property) {
-          return oldValues[property];
-        }
-      ]);
-
-      return true;
-    },
-
-    disconnect_: function() {
-      if (hasObserve) {
-        this.directObserver_.close();
-        this.directObserver_ = undefined;
-      } else {
-        this.oldObject_ = undefined;
-      }
-    },
-
-    deliver: function() {
-      if (this.state_ != OPENED)
-        return;
-
-      if (hasObserve)
-        this.directObserver_.deliver(false);
-      else
-        dirtyCheck(this);
-    },
-
-    discardChanges: function() {
-      if (this.directObserver_)
-        this.directObserver_.deliver(true);
-      else
-        this.oldObject_ = this.copyObject(this.value_);
-
-      return this.value_;
-    }
-  });
-
-  function ArrayObserver(array) {
-    if (!Array.isArray(array))
-      throw Error('Provided object is not an Array');
-    ObjectObserver.call(this, array);
-  }
-
-  ArrayObserver.prototype = createObject({
-
-    __proto__: ObjectObserver.prototype,
-
-    arrayObserve: true,
-
-    copyObject: function(arr) {
-      return arr.slice();
-    },
-
-    check_: function(changeRecords) {
-      var splices;
-      if (hasObserve) {
-        if (!changeRecords)
-          return false;
-        splices = projectArraySplices(this.value_, changeRecords);
-      } else {
-        splices = calcSplices(this.value_, 0, this.value_.length,
-                              this.oldObject_, 0, this.oldObject_.length);
-      }
-
-      if (!splices || !splices.length)
-        return false;
-
-      if (!hasObserve)
-        this.oldObject_ = this.copyObject(this.value_);
-
-      this.report_([splices]);
-      return true;
-    }
-  });
-
-  ArrayObserver.applySplices = function(previous, current, splices) {
-    splices.forEach(function(splice) {
-      var spliceArgs = [splice.index, splice.removed.length];
-      var addIndex = splice.index;
-      while (addIndex < splice.index + splice.addedCount) {
-        spliceArgs.push(current[addIndex]);
-        addIndex++;
-      }
-
-      Array.prototype.splice.apply(previous, spliceArgs);
-    });
-  };
-
-  function PathObserver(object, path) {
-    Observer.call(this);
-
-    this.object_ = object;
-    this.path_ = path instanceof Path ? path : getPath(path);
-    this.directObserver_ = undefined;
-  }
-
-  PathObserver.prototype = createObject({
-    __proto__: Observer.prototype,
-
-    connect_: function() {
-      if (hasObserve)
-        this.directObserver_ = getObservedSet(this, this.object_);
-
-      this.check_(undefined, true);
-    },
-
-    disconnect_: function() {
-      this.value_ = undefined;
-
-      if (this.directObserver_) {
-        this.directObserver_.close(this);
-        this.directObserver_ = undefined;
-      }
-    },
-
-    iterateObjects_: function(observe) {
-      this.path_.iterateObjects(this.object_, observe);
-    },
-
-    check_: function(changeRecords, skipChanges) {
-      var oldValue = this.value_;
-      this.value_ = this.path_.getValueFrom(this.object_);
-      if (skipChanges || areSameValue(this.value_, oldValue))
-        return false;
-
-      this.report_([this.value_, oldValue]);
-      return true;
-    },
-
-    setValue: function(newValue) {
-      if (this.path_)
-        this.path_.setValueFrom(this.object_, newValue);
-    }
-  });
-
-  function CompoundObserver() {
-    Observer.call(this);
-
-    this.value_ = [];
-    this.directObserver_ = undefined;
-    this.observed_ = [];
-  }
-
-  var observerSentinel = {};
-
-  CompoundObserver.prototype = createObject({
-    __proto__: Observer.prototype,
-
-    connect_: function() {
-      this.check_(undefined, true);
-
-      if (!hasObserve)
-        return;
-
-      var object;
-      var needsDirectObserver = false;
-      for (var i = 0; i < this.observed_.length; i += 2) {
-        object = this.observed_[i]
-        if (object !== observerSentinel) {
-          needsDirectObserver = true;
-          break;
-        }
-      }
-
-      if (this.directObserver_) {
-        if (needsDirectObserver) {
-          this.directObserver_.reset();
-          return;
-        }
-        this.directObserver_.close();
-        this.directObserver_ = undefined;
-        return;
-      }
-
-      if (needsDirectObserver)
-        this.directObserver_ = getObservedSet(this, object);
-    },
-
-    closeObservers_: function() {
-      for (var i = 0; i < this.observed_.length; i += 2) {
-        if (this.observed_[i] === observerSentinel)
-          this.observed_[i + 1].close();
-      }
-      this.observed_.length = 0;
-    },
-
-    disconnect_: function() {
-      this.value_ = undefined;
-
-      if (this.directObserver_) {
-        this.directObserver_.close(this);
-        this.directObserver_ = undefined;
-      }
-
-      this.closeObservers_();
-    },
-
-    addPath: function(object, path) {
-      if (this.state_ != UNOPENED && this.state_ != RESETTING)
-        throw Error('Cannot add paths once started.');
-
-      this.observed_.push(object, path instanceof Path ? path : getPath(path));
-    },
-
-    addObserver: function(observer) {
-      if (this.state_ != UNOPENED && this.state_ != RESETTING)
-        throw Error('Cannot add observers once started.');
-
-      observer.open(this.deliver, this);
-      this.observed_.push(observerSentinel, observer);
-    },
-
-    startReset: function() {
-      if (this.state_ != OPENED)
-        throw Error('Can only reset while open');
-
-      this.state_ = RESETTING;
-      this.closeObservers_();
-    },
-
-    finishReset: function() {
-      if (this.state_ != RESETTING)
-        throw Error('Can only finishReset after startReset');
-      this.state_ = OPENED;
-      this.connect_();
-
-      return this.value_;
-    },
-
-    iterateObjects_: function(observe) {
-      var object;
-      for (var i = 0; i < this.observed_.length; i += 2) {
-        object = this.observed_[i]
-        if (object !== observerSentinel)
-          this.observed_[i + 1].iterateObjects(object, observe)
-      }
-    },
-
-    check_: function(changeRecords, skipChanges) {
-      var oldValues;
-      for (var i = 0; i < this.observed_.length; i += 2) {
-        var pathOrObserver = this.observed_[i+1];
-        var object = this.observed_[i];
-        var value = object === observerSentinel ?
-            pathOrObserver.discardChanges() :
-            pathOrObserver.getValueFrom(object)
-
-        if (skipChanges) {
-          this.value_[i / 2] = value;
-          continue;
-        }
-
-        if (areSameValue(value, this.value_[i / 2]))
-          continue;
-
-        oldValues = oldValues || [];
-        oldValues[i / 2] = this.value_[i / 2];
-        this.value_[i / 2] = value;
-      }
-
-      if (!oldValues)
-        return false;
-
-      // TODO(rafaelw): Having observed_ as the third callback arg here is
-      // pretty lame API. Fix.
-      this.report_([this.value_, oldValues, this.observed_]);
-      return true;
-    }
-  });
-
-  function identFn(value) { return value; }
-
-  function ObserverTransform(observable, getValueFn, setValueFn,
-                             dontPassThroughSet) {
-    this.callback_ = undefined;
-    this.target_ = undefined;
-    this.value_ = undefined;
-    this.observable_ = observable;
-    this.getValueFn_ = getValueFn || identFn;
-    this.setValueFn_ = setValueFn || identFn;
-    // TODO(rafaelw): This is a temporary hack. PolymerExpressions needs this
-    // at the moment because of a bug in it's dependency tracking.
-    this.dontPassThroughSet_ = dontPassThroughSet;
-  }
-
-  ObserverTransform.prototype = {
-    open: function(callback, target) {
-      this.callback_ = callback;
-      this.target_ = target;
-      this.value_ =
-          this.getValueFn_(this.observable_.open(this.observedCallback_, this));
-      return this.value_;
-    },
-
-    observedCallback_: function(value) {
-      value = this.getValueFn_(value);
-      if (areSameValue(value, this.value_))
-        return;
-      var oldValue = this.value_;
-      this.value_ = value;
-      this.callback_.call(this.target_, this.value_, oldValue);
-    },
-
-    discardChanges: function() {
-      this.value_ = this.getValueFn_(this.observable_.discardChanges());
-      return this.value_;
-    },
-
-    deliver: function() {
-      return this.observable_.deliver();
-    },
-
-    setValue: function(value) {
-      value = this.setValueFn_(value);
-      if (!this.dontPassThroughSet_ && this.observable_.setValue)
-        return this.observable_.setValue(value);
-    },
-
-    close: function() {
-      if (this.observable_)
-        this.observable_.close();
-      this.callback_ = undefined;
-      this.target_ = undefined;
-      this.observable_ = undefined;
-      this.value_ = undefined;
-      this.getValueFn_ = undefined;
-      this.setValueFn_ = undefined;
-    }
-  }
-
-  var expectedRecordTypes = {};
-  expectedRecordTypes[PROP_ADD_TYPE] = true;
-  expectedRecordTypes[PROP_UPDATE_TYPE] = true;
-  expectedRecordTypes[PROP_DELETE_TYPE] = true;
-
-  function notifyFunction(object, name) {
-    if (typeof Object.observe !== 'function')
-      return;
-
-    var notifier = Object.getNotifier(object);
-    return function(type, oldValue) {
-      var changeRecord = {
-        object: object,
-        type: type,
-        name: name
-      };
-      if (arguments.length === 2)
-        changeRecord.oldValue = oldValue;
-      notifier.notify(changeRecord);
-    }
-  }
-
-  Observer.defineComputedProperty = function(target, name, observable) {
-    var notify = notifyFunction(target, name);
-    var value = observable.open(function(newValue, oldValue) {
-      value = newValue;
-      if (notify)
-        notify(PROP_UPDATE_TYPE, oldValue);
-    });
-
-    Object.defineProperty(target, name, {
-      get: function() {
-        observable.deliver();
-        return value;
-      },
-      set: function(newValue) {
-        observable.setValue(newValue);
-        return newValue;
-      },
-      configurable: true
-    });
-
-    return {
-      close: function() {
-        observable.close();
-        Object.defineProperty(target, name, {
-          value: value,
-          writable: true,
-          configurable: true
-        });
-      }
-    };
-  }
-
-  function diffObjectFromChangeRecords(object, changeRecords, oldValues) {
-    var added = {};
-    var removed = {};
-
-    for (var i = 0; i < changeRecords.length; i++) {
-      var record = changeRecords[i];
-      if (!expectedRecordTypes[record.type]) {
-        console.error('Unknown changeRecord type: ' + record.type);
-        console.error(record);
-        continue;
-      }
-
-      if (!(record.name in oldValues))
-        oldValues[record.name] = record.oldValue;
-
-      if (record.type == PROP_UPDATE_TYPE)
-        continue;
-
-      if (record.type == PROP_ADD_TYPE) {
-        if (record.name in removed)
-          delete removed[record.name];
-        else
-          added[record.name] = true;
-
-        continue;
-      }
-
-      // type = 'delete'
-      if (record.name in added) {
-        delete added[record.name];
-        delete oldValues[record.name];
-      } else {
-        removed[record.name] = true;
-      }
-    }
-
-    for (var prop in added)
-      added[prop] = object[prop];
-
-    for (var prop in removed)
-      removed[prop] = undefined;
-
-    var changed = {};
-    for (var prop in oldValues) {
-      if (prop in added || prop in removed)
-        continue;
-
-      var newValue = object[prop];
-      if (oldValues[prop] !== newValue)
-        changed[prop] = newValue;
-    }
-
-    return {
-      added: added,
-      removed: removed,
-      changed: changed
-    };
-  }
-
-  function newSplice(index, removed, addedCount) {
-    return {
-      index: index,
-      removed: removed,
-      addedCount: addedCount
-    };
-  }
-
-  var EDIT_LEAVE = 0;
-  var EDIT_UPDATE = 1;
-  var EDIT_ADD = 2;
-  var EDIT_DELETE = 3;
-
-  function ArraySplice() {}
-
-  ArraySplice.prototype = {
-
-    // Note: This function is *based* on the computation of the Levenshtein
-    // "edit" distance. The one change is that "updates" are treated as two
-    // edits - not one. With Array splices, an update is really a delete
-    // followed by an add. By retaining this, we optimize for "keeping" the
-    // maximum array items in the original array. For example:
-    //
-    //   'xxxx123' -> '123yyyy'
-    //
-    // With 1-edit updates, the shortest path would be just to update all seven
-    // characters. With 2-edit updates, we delete 4, leave 3, and add 4. This
-    // leaves the substring '123' intact.
-    calcEditDistances: function(current, currentStart, currentEnd,
-                                old, oldStart, oldEnd) {
-      // "Deletion" columns
-      var rowCount = oldEnd - oldStart + 1;
-      var columnCount = currentEnd - currentStart + 1;
-      var distances = new Array(rowCount);
-
-      // "Addition" rows. Initialize null column.
-      for (var i = 0; i < rowCount; i++) {
-        distances[i] = new Array(columnCount);
-        distances[i][0] = i;
-      }
-
-      // Initialize null row
-      for (var j = 0; j < columnCount; j++)
-        distances[0][j] = j;
-
-      for (var i = 1; i < rowCount; i++) {
-        for (var j = 1; j < columnCount; j++) {
-          if (this.equals(current[currentStart + j - 1], old[oldStart + i - 1]))
-            distances[i][j] = distances[i - 1][j - 1];
-          else {
-            var north = distances[i - 1][j] + 1;
-            var west = distances[i][j - 1] + 1;
-            distances[i][j] = north < west ? north : west;
-          }
-        }
-      }
-
-      return distances;
-    },
-
-    // This starts at the final weight, and walks "backward" by finding
-    // the minimum previous weight recursively until the origin of the weight
-    // matrix.
-    spliceOperationsFromEditDistances: function(distances) {
-      var i = distances.length - 1;
-      var j = distances[0].length - 1;
-      var current = distances[i][j];
-      var edits = [];
-      while (i > 0 || j > 0) {
-        if (i == 0) {
-          edits.push(EDIT_ADD);
-          j--;
-          continue;
-        }
-        if (j == 0) {
-          edits.push(EDIT_DELETE);
-          i--;
-          continue;
-        }
-        var northWest = distances[i - 1][j - 1];
-        var west = distances[i - 1][j];
-        var north = distances[i][j - 1];
-
-        var min;
-        if (west < north)
-          min = west < northWest ? west : northWest;
-        else
-          min = north < northWest ? north : northWest;
-
-        if (min == northWest) {
-          if (northWest == current) {
-            edits.push(EDIT_LEAVE);
-          } else {
-            edits.push(EDIT_UPDATE);
-            current = northWest;
-          }
-          i--;
-          j--;
-        } else if (min == west) {
-          edits.push(EDIT_DELETE);
-          i--;
-          current = west;
-        } else {
-          edits.push(EDIT_ADD);
-          j--;
-          current = north;
-        }
-      }
-
-      edits.reverse();
-      return edits;
-    },
-
-    /**
-     * Splice Projection functions:
-     *
-     * A splice map is a representation of how a previous array of items
-     * was transformed into a new array of items. Conceptually it is a list of
-     * tuples of
-     *
-     *   <index, removed, addedCount>
-     *
-     * which are kept in ascending index order of. The tuple represents that at
-     * the |index|, |removed| sequence of items were removed, and counting forward
-     * from |index|, |addedCount| items were added.
-     */
-
-    /**
-     * Lacking individual splice mutation information, the minimal set of
-     * splices can be synthesized given the previous state and final state of an
-     * array. The basic approach is to calculate the edit distance matrix and
-     * choose the shortest path through it.
-     *
-     * Complexity: O(l * p)
-     *   l: The length of the current array
-     *   p: The length of the old array
-     */
-    calcSplices: function(current, currentStart, currentEnd,
-                          old, oldStart, oldEnd) {
-      var prefixCount = 0;
-      var suffixCount = 0;
-
-      var minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart);
-      if (currentStart == 0 && oldStart == 0)
-        prefixCount = this.sharedPrefix(current, old, minLength);
-
-      if (currentEnd == current.length && oldEnd == old.length)
-        suffixCount = this.sharedSuffix(current, old, minLength - prefixCount);
-
-      currentStart += prefixCount;
-      oldStart += prefixCount;
-      currentEnd -= suffixCount;
-      oldEnd -= suffixCount;
-
-      if (currentEnd - currentStart == 0 && oldEnd - oldStart == 0)
-        return [];
-
-      if (currentStart == currentEnd) {
-        var splice = newSplice(currentStart, [], 0);
-        while (oldStart < oldEnd)
-          splice.removed.push(old[oldStart++]);
-
-        return [ splice ];
-      } else if (oldStart == oldEnd)
-        return [ newSplice(currentStart, [], currentEnd - currentStart) ];
-
-      var ops = this.spliceOperationsFromEditDistances(
-          this.calcEditDistances(current, currentStart, currentEnd,
-                                 old, oldStart, oldEnd));
-
-      var splice = undefined;
-      var splices = [];
-      var index = currentStart;
-      var oldIndex = oldStart;
-      for (var i = 0; i < ops.length; i++) {
-        switch(ops[i]) {
-          case EDIT_LEAVE:
-            if (splice) {
-              splices.push(splice);
-              splice = undefined;
-            }
-
-            index++;
-            oldIndex++;
-            break;
-          case EDIT_UPDATE:
-            if (!splice)
-              splice = newSplice(index, [], 0);
-
-            splice.addedCount++;
-            index++;
-
-            splice.removed.push(old[oldIndex]);
-            oldIndex++;
-            break;
-          case EDIT_ADD:
-            if (!splice)
-              splice = newSplice(index, [], 0);
-
-            splice.addedCount++;
-            index++;
-            break;
-          case EDIT_DELETE:
-            if (!splice)
-              splice = newSplice(index, [], 0);
-
-            splice.removed.push(old[oldIndex]);
-            oldIndex++;
-            break;
-        }
-      }
-
-      if (splice) {
-        splices.push(splice);
-      }
-      return splices;
-    },
-
-    sharedPrefix: function(current, old, searchLength) {
-      for (var i = 0; i < searchLength; i++)
-        if (!this.equals(current[i], old[i]))
-          return i;
-      return searchLength;
-    },
-
-    sharedSuffix: function(current, old, searchLength) {
-      var index1 = current.length;
-      var index2 = old.length;
-      var count = 0;
-      while (count < searchLength && this.equals(current[--index1], old[--index2]))
-        count++;
-
-      return count;
-    },
-
-    calculateSplices: function(current, previous) {
-      return this.calcSplices(current, 0, current.length, previous, 0,
-                              previous.length);
-    },
-
-    equals: function(currentValue, previousValue) {
-      return currentValue === previousValue;
-    }
-  };
-
-  var arraySplice = new ArraySplice();
-
-  function calcSplices(current, currentStart, currentEnd,
-                       old, oldStart, oldEnd) {
-    return arraySplice.calcSplices(current, currentStart, currentEnd,
-                                   old, oldStart, oldEnd);
-  }
-
-  function intersect(start1, end1, start2, end2) {
-    // Disjoint
-    if (end1 < start2 || end2 < start1)
-      return -1;
-
-    // Adjacent
-    if (end1 == start2 || end2 == start1)
-      return 0;
-
-    // Non-zero intersect, span1 first
-    if (start1 < start2) {
-      if (end1 < end2)
-        return end1 - start2; // Overlap
-      else
-        return end2 - start2; // Contained
-    } else {
-      // Non-zero intersect, span2 first
-      if (end2 < end1)
-        return end2 - start1; // Overlap
-      else
-        return end1 - start1; // Contained
-    }
-  }
-
-  function mergeSplice(splices, index, removed, addedCount) {
-
-    var splice = newSplice(index, removed, addedCount);
-
-    var inserted = false;
-    var insertionOffset = 0;
-
-    for (var i = 0; i < splices.length; i++) {
-      var current = splices[i];
-      current.index += insertionOffset;
-
-      if (inserted)
-        continue;
-
-      var intersectCount = intersect(splice.index,
-                                     splice.index + splice.removed.length,
-                                     current.index,
-                                     current.index + current.addedCount);
-
-      if (intersectCount >= 0) {
-        // Merge the two splices
-
-        splices.splice(i, 1);
-        i--;
-
-        insertionOffset -= current.addedCount - current.removed.length;
-
-        splice.addedCount += current.addedCount - intersectCount;
-        var deleteCount = splice.removed.length +
-                          current.removed.length - intersectCount;
-
-        if (!splice.addedCount && !deleteCount) {
-          // merged splice is a noop. discard.
-          inserted = true;
-        } else {
-          var removed = current.removed;
-
-          if (splice.index < current.index) {
-            // some prefix of splice.removed is prepended to current.removed.
-            var prepend = splice.removed.slice(0, current.index - splice.index);
-            Array.prototype.push.apply(prepend, removed);
-            removed = prepend;
-          }
-
-          if (splice.index + splice.removed.length > current.index + current.addedCount) {
-            // some suffix of splice.removed is appended to current.removed.
-            var append = splice.removed.slice(current.index + current.addedCount - splice.index);
-            Array.prototype.push.apply(removed, append);
-          }
-
-          splice.removed = removed;
-          if (current.index < splice.index) {
-            splice.index = current.index;
-          }
-        }
-      } else if (splice.index < current.index) {
-        // Insert splice here.
-
-        inserted = true;
-
-        splices.splice(i, 0, splice);
-        i++;
-
-        var offset = splice.addedCount - splice.removed.length
-        current.index += offset;
-        insertionOffset += offset;
-      }
-    }
-
-    if (!inserted)
-      splices.push(splice);
-  }
-
-  function createInitialSplices(array, changeRecords) {
-    var splices = [];
-
-    for (var i = 0; i < changeRecords.length; i++) {
-      var record = changeRecords[i];
-      switch(record.type) {
-        case ARRAY_SPLICE_TYPE:
-          mergeSplice(splices, record.index, record.removed.slice(), record.addedCount);
-          break;
-        case PROP_ADD_TYPE:
-        case PROP_UPDATE_TYPE:
-        case PROP_DELETE_TYPE:
-          if (!isIndex(record.name))
-            continue;
-          var index = toNumber(record.name);
-          if (index < 0)
-            continue;
-          mergeSplice(splices, index, [record.oldValue], 1);
-          break;
-        default:
-          console.error('Unexpected record type: ' + JSON.stringify(record));
-          break;
-      }
-    }
-
-    return splices;
-  }
-
-  function projectArraySplices(array, changeRecords) {
-    var splices = [];
-
-    createInitialSplices(array, changeRecords).forEach(function(splice) {
-      if (splice.addedCount == 1 && splice.removed.length == 1) {
-        if (splice.removed[0] !== array[splice.index])
-          splices.push(splice);
-
-        return
-      };
-
-      splices = splices.concat(calcSplices(array, splice.index, splice.index + splice.addedCount,
-                                           splice.removed, 0, splice.removed.length));
-    });
-
-    return splices;
-  }
-
-  global.Observer = Observer;
-  global.Observer.runEOM_ = runEOM;
-  global.Observer.hasObjectObserve = hasObserve;
-  global.ArrayObserver = ArrayObserver;
-  global.ArrayObserver.calculateSplices = function(current, previous) {
-    return arraySplice.calculateSplices(current, previous);
-  };
-
-  global.ArraySplice = ArraySplice;
-  global.ObjectObserver = ObjectObserver;
-  global.PathObserver = PathObserver;
-  global.CompoundObserver = CompoundObserver;
-  global.Path = Path;
-  global.ObserverTransform = ObserverTransform;
-
-  // TODO(rafaelw): Only needed for testing until new change record names
-  // make it to release.
-  global.Observer.changeRecordTypes = {
-    add: PROP_ADD_TYPE,
-    update: PROP_UPDATE_TYPE,
-    reconfigure: PROP_RECONFIGURE_TYPE,
-    'delete': PROP_DELETE_TYPE,
-    splice: ARRAY_SPLICE_TYPE
-  };
-})(typeof global !== 'undefined' && global && typeof module !== 'undefined' && module ? global : this || window);
-
-/*
- * Copyright 2012 The Polymer Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style
- * license that can be found in the LICENSE file.
- */
-
-if (typeof WeakMap === 'undefined') {
-  (function() {
-    var defineProperty = Object.defineProperty;
-    var counter = Date.now() % 1e9;
-
-    var WeakMap = function() {
-      this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__');
-    };
-
-    WeakMap.prototype = {
-      set: function(key, value) {
-        var entry = key[this.name];
-        if (entry && entry[0] === key)
-          entry[1] = value;
-        else
-          defineProperty(key, this.name, {value: [key, value], writable: true});
-      },
-      get: function(key) {
-        var entry;
-        return (entry = key[this.name]) && entry[0] === key ?
-            entry[1] : undefined;
-      },
-      delete: function(key) {
-        this.set(key, undefined);
-      }
-    };
-
-    window.WeakMap = WeakMap;
-  })();
-}
-
-// Copyright 2012 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-window.ShadowDOMPolyfill = {};
-
-(function(scope) {
-  'use strict';
-
-  var constructorTable = new WeakMap();
-  var nativePrototypeTable = new WeakMap();
-  var wrappers = Object.create(null);
-
-  // Don't test for eval if document has CSP securityPolicy object and we can
-  // see that eval is not supported. This avoids an error message in console
-  // even when the exception is caught
-  var hasEval = !('securityPolicy' in document) ||
-      document.securityPolicy.allowsEval;
-  if (hasEval) {
-    try {
-      var f = new Function('', 'return true;');
-      hasEval = f();
-    } catch (ex) {
-      hasEval = false;
-    }
-  }
-
-  function assert(b) {
-    if (!b)
-      throw new Error('Assertion failed');
-  };
-
-  var defineProperty = Object.defineProperty;
-  var getOwnPropertyNames = Object.getOwnPropertyNames;
-  var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
-
-  function mixin(to, from) {
-    getOwnPropertyNames(from).forEach(function(name) {
-      defineProperty(to, name, getOwnPropertyDescriptor(from, name));
-    });
-    return to;
-  };
-
-  function mixinStatics(to, from) {
-    getOwnPropertyNames(from).forEach(function(name) {
-      switch (name) {
-        case 'arguments':
-        case 'caller':
-        case 'length':
-        case 'name':
-        case 'prototype':
-        case 'toString':
-          return;
-      }
-      defineProperty(to, name, getOwnPropertyDescriptor(from, name));
-    });
-    return to;
-  };
-
-  function oneOf(object, propertyNames) {
-    for (var i = 0; i < propertyNames.length; i++) {
-      if (propertyNames[i] in object)
-        return propertyNames[i];
-    }
-  }
-
-  // Mozilla's old DOM bindings are bretty busted:
-  // https://bugzilla.mozilla.org/show_bug.cgi?id=855844
-  // Make sure they are create before we start modifying things.
-  getOwnPropertyNames(window);
-
-  function getWrapperConstructor(node) {
-    var nativePrototype = node.__proto__ || Object.getPrototypeOf(node);
-    var wrapperConstructor = constructorTable.get(nativePrototype);
-    if (wrapperConstructor)
-      return wrapperConstructor;
-
-    var parentWrapperConstructor = getWrapperConstructor(nativePrototype);
-
-    var GeneratedWrapper = createWrapperConstructor(parentWrapperConstructor);
-    registerInternal(nativePrototype, GeneratedWrapper, node);
-
-    return GeneratedWrapper;
-  }
-
-  function addForwardingProperties(nativePrototype, wrapperPrototype) {
-    installProperty(nativePrototype, wrapperPrototype, true);
-  }
-
-  function registerInstanceProperties(wrapperPrototype, instanceObject) {
-    installProperty(instanceObject, wrapperPrototype, false);
-  }
-
-  var isFirefox = /Firefox/.test(navigator.userAgent);
-
-  // This is used as a fallback when getting the descriptor fails in
-  // installProperty.
-  var dummyDescriptor = {
-    get: function() {},
-    set: function(v) {},
-    configurable: true,
-    enumerable: true
-  };
-
-  function isEventHandlerName(name) {
-    return /^on[a-z]+$/.test(name);
-  }
-
-  function isIdentifierName(name) {
-    return /^\w[a-zA-Z_0-9]*$/.test(name);
-  }
-
-  function getGetter(name) {
-    return hasEval && isIdentifierName(name) ?
-        new Function('return this.impl.' + name) :
-        function() { return this.impl[name]; };
-  }
-
-  function getSetter(name) {
-    return hasEval && isIdentifierName(name) ?
-        new Function('v', 'this.impl.' + name + ' = v') :
-        function(v) { this.impl[name] = v; };
-  }
-
-  function getMethod(name) {
-    return hasEval && isIdentifierName(name) ?
-        new Function('return this.impl.' + name +
-                     '.apply(this.impl, arguments)') :
-        function() { return this.impl[name].apply(this.impl, arguments); };
-  }
-
-  function getDescriptor(source, name) {
-    try {
-      return Object.getOwnPropertyDescriptor(source, name);
-    } catch (ex) {
-      // JSC and V8 both use data properties instead of accessors which can
-      // cause getting the property desciptor to throw an exception.
-      // https://bugs.webkit.org/show_bug.cgi?id=49739
-      return dummyDescriptor;
-    }
-  }
-
-  function installProperty(source, target, allowMethod, opt_blacklist) {
-    var names = getOwnPropertyNames(source);
-    for (var i = 0; i < names.length; i++) {
-      var name = names[i];
-      if (name === 'polymerBlackList_')
-        continue;
-
-      if (name in target)
-        continue;
-
-      if (source.polymerBlackList_ && source.polymerBlackList_[name])
-        continue;
-
-      if (isFirefox) {
-        // Tickle Firefox's old bindings.
-        source.__lookupGetter__(name);
-      }
-      var descriptor = getDescriptor(source, name);
-      var getter, setter;
-      if (allowMethod && typeof descriptor.value === 'function') {
-        target[name] = getMethod(name);
-        continue;
-      }
-
-      var isEvent = isEventHandlerName(name);
-      if (isEvent)
-        getter = scope.getEventHandlerGetter(name);
-      else
-        getter = getGetter(name);
-
-      if (descriptor.writable || descriptor.set) {
-        if (isEvent)
-          setter = scope.getEventHandlerSetter(name);
-        else
-          setter = getSetter(name);
-      }
-
-      defineProperty(target, name, {
-        get: getter,
-        set: setter,
-        configurable: descriptor.configurable,
-        enumerable: descriptor.enumerable
-      });
-    }
-  }
-
-  /**
-   * @param {Function} nativeConstructor
-   * @param {Function} wrapperConstructor
-   * @param {Object=} opt_instance If present, this is used to extract
-   *     properties from an instance object.
-   */
-  function register(nativeConstructor, wrapperConstructor, opt_instance) {
-    var nativePrototype = nativeConstructor.prototype;
-    registerInternal(nativePrototype, wrapperConstructor, opt_instance);
-    mixinStatics(wrapperConstructor, nativeConstructor);
-  }
-
-  function registerInternal(nativePrototype, wrapperConstructor, opt_instance) {
-    var wrapperPrototype = wrapperConstructor.prototype;
-    assert(constructorTable.get(nativePrototype) === undefined);
-
-    constructorTable.set(nativePrototype, wrapperConstructor);
-    nativePrototypeTable.set(wrapperPrototype, nativePrototype);
-
-    addForwardingProperties(nativePrototype, wrapperPrototype);
-    if (opt_instance)
-      registerInstanceProperties(wrapperPrototype, opt_instance);
-    defineProperty(wrapperPrototype, 'constructor', {
-      value: wrapperConstructor,
-      configurable: true,
-      enumerable: false,
-      writable: true
-    });
-  }
-
-  function isWrapperFor(wrapperConstructor, nativeConstructor) {
-    return constructorTable.get(nativeConstructor.prototype) ===
-        wrapperConstructor;
-  }
-
-  /**
-   * Creates a generic wrapper constructor based on |object| and its
-   * constructor.
-   * @param {Node} object
-   * @return {Function} The generated constructor.
-   */
-  function registerObject(object) {
-    var nativePrototype = Object.getPrototypeOf(object);
-
-    var superWrapperConstructor = getWrapperConstructor(nativePrototype);
-    var GeneratedWrapper = createWrapperConstructor(superWrapperConstructor);
-    registerInternal(nativePrototype, GeneratedWrapper, object);
-
-    return GeneratedWrapper;
-  }
-
-  function createWrapperConstructor(superWrapperConstructor) {
-    function GeneratedWrapper(node) {
-      superWrapperConstructor.call(this, node);
-    }
-    GeneratedWrapper.prototype =
-        Object.create(superWrapperConstructor.prototype);
-    GeneratedWrapper.prototype.constructor = GeneratedWrapper;
-
-    return GeneratedWrapper;
-  }
-
-  var OriginalDOMImplementation = window.DOMImplementation;
-  var OriginalEventTarget = window.EventTarget;
-  var OriginalEvent = window.Event;
-  var OriginalNode = window.Node;
-  var OriginalWindow = window.Window;
-  var OriginalRange = window.Range;
-  var OriginalCanvasRenderingContext2D = window.CanvasRenderingContext2D;
-  var OriginalWebGLRenderingContext = window.WebGLRenderingContext;
-  var OriginalSVGElementInstance = window.SVGElementInstance;
-
-  function isWrapper(object) {
-    return object instanceof wrappers.EventTarget ||
-           object instanceof wrappers.Event ||
-           object instanceof wrappers.Range ||
-           object instanceof wrappers.DOMImplementation ||
-           object instanceof wrappers.CanvasRenderingContext2D ||
-           wrappers.WebGLRenderingContext &&
-               object instanceof wrappers.WebGLRenderingContext;
-  }
-
-  function isNative(object) {
-    return OriginalEventTarget && object instanceof OriginalEventTarget ||
-           object instanceof OriginalNode ||
-           object instanceof OriginalEvent ||
-           object instanceof OriginalWindow ||
-           object instanceof OriginalRange ||
-           object instanceof OriginalDOMImplementation ||
-           object instanceof OriginalCanvasRenderingContext2D ||
-           OriginalWebGLRenderingContext &&
-               object instanceof OriginalWebGLRenderingContext ||
-           OriginalSVGElementInstance &&
-               object instanceof OriginalSVGElementInstance;
-  }
-
-  /**
-   * Wraps a node in a WrapperNode. If there already exists a wrapper for the
-   * |node| that wrapper is returned instead.
-   * @param {Node} node
-   * @return {WrapperNode}
-   */
-  function wrap(impl) {
-    if (impl === null)
-      return null;
-
-    assert(isNative(impl));
-    return impl.polymerWrapper_ ||
-        (impl.polymerWrapper_ = new (getWrapperConstructor(impl))(impl));
-  }
-
-  /**
-   * Unwraps a wrapper and returns the node it is wrapping.
-   * @param {WrapperNode} wrapper
-   * @return {Node}
-   */
-  function unwrap(wrapper) {
-    if (wrapper === null)
-      return null;
-    assert(isWrapper(wrapper));
-    return wrapper.impl;
-  }
-
-  /**
-   * Unwraps object if it is a wrapper.
-   * @param {Object} object
-   * @return {Object} The native implementation object.
-   */
-  function unwrapIfNeeded(object) {
-    return object && isWrapper(object) ? unwrap(object) : object;
-  }
-
-  /**
-   * Wraps object if it is not a wrapper.
-   * @param {Object} object
-   * @return {Object} The wrapper for object.
-   */
-  function wrapIfNeeded(object) {
-    return object && !isWrapper(object) ? wrap(object) : object;
-  }
-
-  /**
-   * Overrides the current wrapper (if any) for node.
-   * @param {Node} node
-   * @param {WrapperNode=} wrapper If left out the wrapper will be created as
-   *     needed next time someone wraps the node.
-   */
-  function rewrap(node, wrapper) {
-    if (wrapper === null)
-      return;
-    assert(isNative(node));
-    assert(wrapper === undefined || isWrapper(wrapper));
-    node.polymerWrapper_ = wrapper;
-  }
-
-  function defineGetter(constructor, name, getter) {
-    defineProperty(constructor.prototype, name, {
-      get: getter,
-      configurable: true,
-      enumerable: true
-    });
-  }
-
-  function defineWrapGetter(constructor, name) {
-    defineGetter(constructor, name, function() {
-      return wrap(this.impl[name]);
-    });
-  }
-
-  /**
-   * Forwards existing methods on the native object to the wrapper methods.
-   * This does not wrap any of the arguments or the return value since the
-   * wrapper implementation already takes care of that.
-   * @param {Array.<Function>} constructors
-   * @parem {Array.<string>} names
-   */
-  function forwardMethodsToWrapper(constructors, names) {
-    constructors.forEach(function(constructor) {
-      names.forEach(function(name) {
-        constructor.prototype[name] = function() {
-          var w = wrapIfNeeded(this);
-          return w[name].apply(w, arguments);
-        };
-      });
-    });
-  }
-
-  scope.assert = assert;
-  scope.constructorTable = constructorTable;
-  scope.defineGetter = defineGetter;
-  scope.defineWrapGetter = defineWrapGetter;
-  scope.forwardMethodsToWrapper = forwardMethodsToWrapper;
-  scope.isWrapper = isWrapper;
-  scope.isWrapperFor = isWrapperFor;
-  scope.mixin = mixin;
-  scope.nativePrototypeTable = nativePrototypeTable;
-  scope.oneOf = oneOf;
-  scope.registerObject = registerObject;
-  scope.registerWrapper = register;
-  scope.rewrap = rewrap;
-  scope.unwrap = unwrap;
-  scope.unwrapIfNeeded = unwrapIfNeeded;
-  scope.wrap = wrap;
-  scope.wrapIfNeeded = wrapIfNeeded;
-  scope.wrappers = wrappers;
-
-})(window.ShadowDOMPolyfill);
-
-/*
- * Copyright 2013 The Polymer Authors. All rights reserved.
- * Use of this source code is goverened by a BSD-style
- * license that can be found in the LICENSE file.
- */
-
-(function(context) {
-  'use strict';
-
-  var OriginalMutationObserver = window.MutationObserver;
-  var callbacks = [];
-  var pending = false;
-  var timerFunc;
-
-  function handle() {
-    pending = false;
-    var copies = callbacks.slice(0);
-    callbacks = [];
-    for (var i = 0; i < copies.length; i++) {
-      (0, copies[i])();
-    }
-  }
-
-  if (OriginalMutationObserver) {
-    var counter = 1;
-    var observer = new OriginalMutationObserver(handle);
-    var textNode = document.createTextNode(counter);
-    observer.observe(textNode, {characterData: true});
-
-    timerFunc = function() {
-      counter = (counter + 1) % 2;
-      textNode.data = counter;
-    };
-
-  } else {
-    timerFunc = window.setImmediate || window.setTimeout;
-  }
-
-  function setEndOfMicrotask(func) {
-    callbacks.push(func);
-    if (pending)
-      return;
-    pending = true;
-    timerFunc(handle, 0);
-  }
-
-  context.setEndOfMicrotask = setEndOfMicrotask;
-
-})(window.ShadowDOMPolyfill);
-
-/*
- * Copyright 2013 The Polymer Authors. All rights reserved.
- * Use of this source code is goverened by a BSD-style
- * license that can be found in the LICENSE file.
- */
-
-(function(scope) {
-  'use strict';
-
-  var setEndOfMicrotask = scope.setEndOfMicrotask
-  var wrapIfNeeded = scope.wrapIfNeeded
-  var wrappers = scope.wrappers;
-
-  var registrationsTable = new WeakMap();
-  var globalMutationObservers = [];
-  var isScheduled = false;
-
-  function scheduleCallback(observer) {
-    if (isScheduled)
-      return;
-    setEndOfMicrotask(notifyObservers);
-    isScheduled = true;
-  }
-
-  // http://dom.spec.whatwg.org/#mutation-observers
-  function notifyObservers() {
-    isScheduled = false;
-
-    do {
-      var notifyList = globalMutationObservers.slice();
-      var anyNonEmpty = false;
-      for (var i = 0; i < notifyList.length; i++) {
-        var mo = notifyList[i];
-        var queue = mo.takeRecords();
-        removeTransientObserversFor(mo);
-        if (queue.length) {
-          mo.callback_(queue, mo);
-          anyNonEmpty = true;
-        }
-      }
-    } while (anyNonEmpty);
-  }
-
-  /**
-   * @param {string} type
-   * @param {Node} target
-   * @constructor
-   */
-  function MutationRecord(type, target) {
-    this.type = type;
-    this.target = target;
-    this.addedNodes = new wrappers.NodeList();
-    this.removedNodes = new wrappers.NodeList();
-    this.previousSibling = null;
-    this.nextSibling = null;
-    this.attributeName = null;
-    this.attributeNamespace = null;
-    this.oldValue = null;
-  }
-
-  /**
-   * Registers transient observers to ancestor and its ancesors for the node
-   * which was removed.
-   * @param {!Node} ancestor
-   * @param {!Node} node
-   */
-  function registerTransientObservers(ancestor, node) {
-    for (; ancestor; ancestor = ancestor.parentNode) {
-      var registrations = registrationsTable.get(ancestor);
-      if (!registrations)
-        continue;
-      for (var i = 0; i < registrations.length; i++) {
-        var registration = registrations[i];
-        if (registration.options.subtree)
-          registration.addTransientObserver(node);
-      }
-    }
-  }
-
-  function removeTransientObserversFor(observer) {
-    for (var i = 0; i < observer.nodes_.length; i++) {
-      var node = observer.nodes_[i];
-      var registrations = registrationsTable.get(node);
-      if (!registrations)
-        return;
-      for (var j = 0; j < registrations.length; j++) {
-        var registration = registrations[j];
-        if (registration.observer === observer)
-          registration.removeTransientObservers();
-      }
-    }
-  }
-
-  // http://dom.spec.whatwg.org/#queue-a-mutation-record
-  function enqueueMutation(target, type, data) {
-    // 1.
-    var interestedObservers = Object.create(null);
-    var associatedStrings = Object.create(null);
-
-    // 2.
-    for (var node = target; node; node = node.parentNode) {
-      // 3.
-      var registrations = registrationsTable.get(node);
-      if (!registrations)
-        continue;
-      for (var j = 0; j < registrations.length; j++) {
-        var registration = registrations[j];
-        var options = registration.options;
-        // 1.
-        if (node !== target && !options.subtree)
-          continue;
-
-        // 2.
-        if (type === 'attributes' && !options.attributes)
-          continue;
-
-        // 3. If type is "attributes", options's attributeFilter is present, and
-        // either options's attributeFilter does not contain name or namespace
-        // is non-null, continue.
-        if (type === 'attributes' && options.attributeFilter &&
-            (data.namespace !== null ||
-             options.attributeFilter.indexOf(data.name) === -1)) {
-          continue;
-        }
-
-        // 4.
-        if (type === 'characterData' && !options.characterData)
-          continue;
-
-        // 5.
-        if (type === 'childList' && !options.childList)
-          continue;
-
-        // 6.
-        var observer = registration.observer;
-        interestedObservers[observer.uid_] = observer;
-
-        // 7. If either type is "attributes" and options's attributeOldValue is
-        // true, or type is "characterData" and options's characterDataOldValue
-        // is true, set the paired string of registered observer's observer in
-        // interested observers to oldValue.
-        if (type === 'attributes' && options.attributeOldValue ||
-            type === 'characterData' && options.characterDataOldValue) {
-          associatedStrings[observer.uid_] = data.oldValue;
-        }
-      }
-    }
-
-    var anyRecordsEnqueued = false;
-
-    // 4.
-    for (var uid in interestedObservers) {
-      var observer = interestedObservers[uid];
-      var record = new MutationRecord(type, target);
-
-      // 2.
-      if ('name' in data && 'namespace' in data) {
-        record.attributeName = data.name;
-        record.attributeNamespace = data.namespace;
-      }
-
-      // 3.
-      if (data.addedNodes)
-        record.addedNodes = data.addedNodes;
-
-      // 4.
-      if (data.removedNodes)
-        record.removedNodes = data.removedNodes;
-
-      // 5.
-      if (data.previousSibling)
-        record.previousSibling = data.previousSibling;
-
-      // 6.
-      if (data.nextSibling)
-        record.nextSibling = data.nextSibling;
-
-      // 7.
-      if (associatedStrings[uid] !== undefined)
-        record.oldValue = associatedStrings[uid];
-
-      // 8.
-      observer.records_.push(record);
-
-      anyRecordsEnqueued = true;
-    }
-
-    if (anyRecordsEnqueued)
-      scheduleCallback();
-  }
-
-  var slice = Array.prototype.slice;
-
-  /**
-   * @param {!Object} options
-   * @constructor
-   */
-  function MutationObserverOptions(options) {
-    this.childList = !!options.childList;
-    this.subtree = !!options.subtree;
-
-    // 1. If either options' attributeOldValue or attributeFilter is present
-    // and options' attributes is omitted, set options' attributes to true.
-    if (!('attributes' in options) &&
-        ('attributeOldValue' in options || 'attributeFilter' in options)) {
-      this.attributes = true;
-    } else {
-      this.attributes = !!options.attributes;
-    }
-
-    // 2. If options' characterDataOldValue is present and options'
-    // characterData is omitted, set options' characterData to true.
-    if ('characterDataOldValue' in options && !('characterData' in options))
-      this.characterData = true;
-    else
-      this.characterData = !!options.characterData;
-
-    // 3. & 4.
-    if (!this.attributes &&
-        (options.attributeOldValue || 'attributeFilter' in options) ||
-        // 5.
-        !this.characterData && options.characterDataOldValue) {
-      throw new TypeError();
-    }
-
-    this.characterData = !!options.characterData;
-    this.attributeOldValue = !!options.attributeOldValue;
-    this.characterDataOldValue = !!options.characterDataOldValue;
-    if ('attributeFilter' in options) {
-      if (options.attributeFilter == null ||
-          typeof options.attributeFilter !== 'object') {
-        throw new TypeError();
-      }
-      this.attributeFilter = slice.call(options.attributeFilter);
-    } else {
-      this.attributeFilter = null;
-    }
-  }
-
-  var uidCounter = 0;
-
-  /**
-   * The class that maps to the DOM MutationObserver interface.
-   * @param {Function} callback.
-   * @constructor
-   */
-  function MutationObserver(callback) {
-    this.callback_ = callback;
-    this.nodes_ = [];
-    this.records_ = [];
-    this.uid_ = ++uidCounter;
-
-    // This will leak. There is no way to implement this without WeakRefs :'(
-    globalMutationObservers.push(this);
-  }
-
-  MutationObserver.prototype = {
-    // http://dom.spec.whatwg.org/#dom-mutationobserver-observe
-    observe: function(target, options) {
-      target = wrapIfNeeded(target);
-
-      var newOptions = new MutationObserverOptions(options);
-
-      // 6.
-      var registration;
-      var registrations = registrationsTable.get(target);
-      if (!registrations)
-        registrationsTable.set(target, registrations = []);
-
-      for (var i = 0; i < registrations.length; i++) {
-        if (registrations[i].observer === this) {
-          registration = registrations[i];
-          // 6.1.
-          registration.removeTransientObservers();
-          // 6.2.
-          registration.options = newOptions;
-        }
-      }
-
-      // 7.
-      if (!registration) {
-        registration = new Registration(this, target, newOptions);
-        registrations.push(registration);
-        this.nodes_.push(target);
-      }
-    },
-
-    // http://dom.spec.whatwg.org/#dom-mutationobserver-disconnect
-    disconnect: function() {
-      this.nodes_.forEach(function(node) {
-        var registrations = registrationsTable.get(node);
-        for (var i = 0; i < registrations.length; i++) {
-          var registration = registrations[i];
-          if (registration.observer === this) {
-            registrations.splice(i, 1);
-            // Each node can only have one registered observer associated with
-            // this observer.
-            break;
-          }
-        }
-      }, this);
-      this.records_ = [];
-    },
-
-    takeRecords: function() {
-      var copyOfRecords = this.records_;
-      this.records_ = [];
-      return copyOfRecords;
-    }
-  };
-
-  /**
-   * Class used to represent a registered observer.
-   * @param {MutationObserver} observer
-   * @param {Node} target
-   * @param {MutationObserverOptions} options
-   * @constructor
-   */
-  function Registration(observer, target, options) {
-    this.observer = observer;
-    this.target = target;
-    this.options = options;
-    this.transientObservedNodes = [];
-  }
-
-  Registration.prototype = {
-    /**
-     * Adds a transient observer on node. The transient observer gets removed
-     * next time we deliver the change records.
-     * @param {Node} node
-     */
-    addTransientObserver: function(node) {
-      // Don't add transient observers on the target itself. We already have all
-      // the required listeners set up on the target.
-      if (node === this.target)
-        return;
-
-      this.transientObservedNodes.push(node);
-      var registrations = registrationsTable.get(node);
-      if (!registrations)
-        registrationsTable.set(node, registrations = []);
-
-      // We know that registrations does not contain this because we already
-      // checked if node === this.target.
-      registrations.push(this);
-    },
-
-    removeTransientObservers: function() {
-      var transientObservedNodes = this.transientObservedNodes;
-      this.transientObservedNodes = [];
-
-      for (var i = 0; i < transientObservedNodes.length; i++) {
-        var node = transientObservedNodes[i];
-        var registrations = registrationsTable.get(node);
-        for (var j = 0; j < registrations.length; j++) {
-          if (registrations[j] === this) {
-            registrations.splice(j, 1);
-            // Each node can only have one registered observer associated with
-            // this observer.
-            break;
-          }
-        }
-      }
-    }
-  };
-
-  scope.enqueueMutation = enqueueMutation;
-  scope.registerTransientObservers = registerTransientObservers;
-  scope.wrappers.MutationObserver = MutationObserver;
-  scope.wrappers.MutationRecord = MutationRecord;
-
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var forwardMethodsToWrapper = scope.forwardMethodsToWrapper;
-  var mixin = scope.mixin;
-  var registerWrapper = scope.registerWrapper;
-  var unwrap = scope.unwrap;
-  var wrap = scope.wrap;
-  var wrappers = scope.wrappers;
-
-  var wrappedFuns = new WeakMap();
-  var listenersTable = new WeakMap();
-  var handledEventsTable = new WeakMap();
-  var currentlyDispatchingEvents = new WeakMap();
-  var targetTable = new WeakMap();
-  var currentTargetTable = new WeakMap();
-  var relatedTargetTable = new WeakMap();
-  var eventPhaseTable = new WeakMap();
-  var stopPropagationTable = new WeakMap();
-  var stopImmediatePropagationTable = new WeakMap();
-  var eventHandlersTable = new WeakMap();
-  var eventPathTable = new WeakMap();
-
-  function isShadowRoot(node) {
-    return node instanceof wrappers.ShadowRoot;
-  }
-
-  function isInsertionPoint(node) {
-    var localName = node.localName;
-    return localName === 'content' || localName === 'shadow';
-  }
-
-  function isShadowHost(node) {
-    return !!node.shadowRoot;
-  }
-
-  function getEventParent(node) {
-    var dv;
-    return node.parentNode || (dv = node.defaultView) && wrap(dv) || null;
-  }
-
-  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-adjusted-parent
-  function calculateParents(node, context, ancestors) {
-    if (ancestors.length)
-      return ancestors.shift();
-
-    // 1.
-    if (isShadowRoot(node))
-      return getInsertionParent(node) || node.host;
-
-    // 2.
-    var eventParents = scope.eventParentsTable.get(node);
-    if (eventParents) {
-      // Copy over the remaining event parents for next iteration.
-      for (var i = 1; i < eventParents.length; i++) {
-        ancestors[i - 1] = eventParents[i];
-      }
-      return eventParents[0];
-    }
-
-    // 3.
-    if (context && isInsertionPoint(node)) {
-      var parentNode = node.parentNode;
-      if (parentNode && isShadowHost(parentNode)) {
-        var trees = scope.getShadowTrees(parentNode);
-        var p = getInsertionParent(context);
-        for (var i = 0; i < trees.length; i++) {
-          if (trees[i].contains(p))
-            return p;
-        }
-      }
-    }
-
-    return getEventParent(node);
-  }
-
-  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#event-retargeting
-  function retarget(node) {
-    var stack = [];  // 1.
-    var ancestor = node;  // 2.
-    var targets = [];
-    var ancestors = [];
-    while (ancestor) {  // 3.
-      var context = null;  // 3.2.
-      // TODO(arv): Change order of these. If the stack is empty we always end
-      // up pushing ancestor, no matter what.
-      if (isInsertionPoint(ancestor)) {  // 3.1.
-        context = topMostNotInsertionPoint(stack);  // 3.1.1.
-        var top = stack[stack.length - 1] || ancestor;  // 3.1.2.
-        stack.push(top);
-      } else if (!stack.length) {
-        stack.push(ancestor);  // 3.3.
-      }
-      var target = stack[stack.length - 1];  // 3.4.
-      targets.push({target: target, currentTarget: ancestor});  // 3.5.
-      if (isShadowRoot(ancestor))  // 3.6.
-        stack.pop();  // 3.6.1.
-
-      ancestor = calculateParents(ancestor, context, ancestors);  // 3.7.
-    }
-    return targets;
-  }
-
-  function topMostNotInsertionPoint(stack) {
-    for (var i = stack.length - 1; i >= 0; i--) {
-      if (!isInsertionPoint(stack[i]))
-        return stack[i];
-    }
-    return null;
-  }
-
-  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-adjusted-related-target
-  function adjustRelatedTarget(target, related) {
-    var ancestors = [];
-    while (target) {  // 3.
-      var stack = [];  // 3.1.
-      var ancestor = related;  // 3.2.
-      var last = undefined;  // 3.3. Needs to be reset every iteration.
-      while (ancestor) {
-        var context = null;
-        if (!stack.length) {
-          stack.push(ancestor);
-        } else {
-          if (isInsertionPoint(ancestor)) {  // 3.4.3.
-            context = topMostNotInsertionPoint(stack);
-            // isDistributed is more general than checking whether last is
-            // assigned into ancestor.
-            if (isDistributed(last)) {  // 3.4.3.2.
-              var head = stack[stack.length - 1];
-              stack.push(head);
-            }
-          }
-        }
-
-        if (inSameTree(ancestor, target))  // 3.4.4.
-          return stack[stack.length - 1];
-
-        if (isShadowRoot(ancestor))  // 3.4.5.
-          stack.pop();
-
-        last = ancestor;  // 3.4.6.
-        ancestor = calculateParents(ancestor, context, ancestors);  // 3.4.7.
-      }
-      if (isShadowRoot(target))  // 3.5.
-        target = target.host;
-      else
-        target = target.parentNode;  // 3.6.
-    }
-  }
-
-  function getInsertionParent(node) {
-    return scope.insertionParentTable.get(node);
-  }
-
-  function isDistributed(node) {
-    return getInsertionParent(node);
-  }
-
-  function rootOfNode(node) {
-    var p;
-    while (p = node.parentNode) {
-      node = p;
-    }
-    return node;
-  }
-
-  function inSameTree(a, b) {
-    return rootOfNode(a) === rootOfNode(b);
-  }
-
-  function enclosedBy(a, b) {
-    if (a === b)
-      return true;
-    if (a instanceof wrappers.ShadowRoot)
-      return enclosedBy(rootOfNode(a.host), b);
-    return false;
-  }
-
-
-  function dispatchOriginalEvent(originalEvent) {
-    // Make sure this event is only dispatched once.
-    if (handledEventsTable.get(originalEvent))
-      return;
-    handledEventsTable.set(originalEvent, true);
-
-    return dispatchEvent(wrap(originalEvent), wrap(originalEvent.target));
-  }
-
-  function dispatchEvent(event, originalWrapperTarget) {
-    if (currentlyDispatchingEvents.get(event))
-      throw new Error('InvalidStateError')
-    currentlyDispatchingEvents.set(event, true);
-
-    // Render to ensure that the event path is correct.
-    scope.renderAllPending();
-    var eventPath = retarget(originalWrapperTarget);
-
-    // For window load events the load event is dispatched at the window but
-    // the target is set to the document.
-    //
-    // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#the-end
-    //
-    // TODO(arv): Find a less hacky way to do this.
-    if (event.type === 'load' &&
-        eventPath.length === 2 &&
-        eventPath[0].target instanceof wrappers.Document) {
-      eventPath.shift();
-    }
-
-    eventPathTable.set(event, eventPath);
-
-    if (dispatchCapturing(event, eventPath)) {
-      if (dispatchAtTarget(event, eventPath)) {
-        dispatchBubbling(event, eventPath);
-      }
-    }
-
-    eventPhaseTable.set(event, Event.NONE);
-    currentTargetTable.delete(event, null);
-    currentlyDispatchingEvents.delete(event);
-
-    return event.defaultPrevented;
-  }
-
-  function dispatchCapturing(event, eventPath) {
-    var phase;
-
-    for (var i = eventPath.length - 1; i > 0; i--) {
-      var target = eventPath[i].target;
-      var currentTarget = eventPath[i].currentTarget;
-      if (target === currentTarget)
-        continue;
-
-      phase = Event.CAPTURING_PHASE;
-      if (!invoke(eventPath[i], event, phase))
-        return false;
-    }
-
-    return true;
-  }
-
-  function dispatchAtTarget(event, eventPath) {
-    var phase = Event.AT_TARGET;
-    return invoke(eventPath[0], event, phase);
-  }
-
-  function dispatchBubbling(event, eventPath) {
-    var bubbles = event.bubbles;
-    var phase;
-
-    for (var i = 1; i < eventPath.length; i++) {
-      var target = eventPath[i].target;
-      var currentTarget = eventPath[i].currentTarget;
-      if (target === currentTarget)
-        phase = Event.AT_TARGET;
-      else if (bubbles && !stopImmediatePropagationTable.get(event))
-        phase = Event.BUBBLING_PHASE;
-      else
-        continue;
-
-      if (!invoke(eventPath[i], event, phase))
-        return;
-    }
-  }
-
-  function invoke(tuple, event, phase) {
-    var target = tuple.target;
-    var currentTarget = tuple.currentTarget;
-
-    var listeners = listenersTable.get(currentTarget);
-    if (!listeners)
-      return true;
-
-    if ('relatedTarget' in event) {
-      var originalEvent = unwrap(event);
-      // X-Tag sets relatedTarget on a CustomEvent. If they do that there is no
-      // way to have relatedTarget return the adjusted target but worse is that
-      // the originalEvent might not have a relatedTarget so we hit an assert
-      // when we try to wrap it.
-      if (originalEvent.relatedTarget) {
-        var relatedTarget = wrap(originalEvent.relatedTarget);
-
-        var adjusted = adjustRelatedTarget(currentTarget, relatedTarget);
-        if (adjusted === target)
-          return true;
-
-        relatedTargetTable.set(event, adjusted);
-      }
-    }
-
-    eventPhaseTable.set(event, phase);
-    var type = event.type;
-
-    var anyRemoved = false;
-    targetTable.set(event, target);
-    currentTargetTable.set(event, currentTarget);
-
-    for (var i = 0; i < listeners.length; i++) {
-      var listener = listeners[i];
-      if (listener.removed) {
-        anyRemoved = true;
-        continue;
-      }
-
-      if (listener.type !== type ||
-          !listener.capture && phase === Event.CAPTURING_PHASE ||
-          listener.capture && phase === Event.BUBBLING_PHASE) {
-        continue;
-      }
-
-      try {
-        if (typeof listener.handler === 'function')
-          listener.handler.call(currentTarget, event);
-        else
-          listener.handler.handleEvent(event);
-
-        if (stopImmediatePropagationTable.get(event))
-          return false;
-
-      } catch (ex) {
-        if (window.onerror)
-          window.onerror(ex.message);
-        else
-          console.error(ex, ex.stack);
-      }
-    }
-
-    if (anyRemoved) {
-      var copy = listeners.slice();
-      listeners.length = 0;
-      for (var i = 0; i < copy.length; i++) {
-        if (!copy[i].removed)
-          listeners.push(copy[i]);
-      }
-    }
-
-    return !stopPropagationTable.get(event);
-  }
-
-  function Listener(type, handler, capture) {
-    this.type = type;
-    this.handler = handler;
-    this.capture = Boolean(capture);
-  }
-  Listener.prototype = {
-    equals: function(that) {
-      return this.handler === that.handler && this.type === that.type &&
-          this.capture === that.capture;
-    },
-    get removed() {
-      return this.handler === null;
-    },
-    remove: function() {
-      this.handler = null;
-    }
-  };
-
-  var OriginalEvent = window.Event;
-  OriginalEvent.prototype.polymerBlackList_ = {
-    returnValue: true,
-    // TODO(arv): keyLocation is part of KeyboardEvent but Firefox does not
-    // support constructable KeyboardEvent so we keep it here for now.
-    keyLocation: true
-  };
-
-  /**
-   * Creates a new Event wrapper or wraps an existin native Event object.
-   * @param {string|Event} type
-   * @param {Object=} options
-   * @constructor
-   */
-  function Event(type, options) {
-    if (type instanceof OriginalEvent)
-      this.impl = type;
-    else
-      return wrap(constructEvent(OriginalEvent, 'Event', type, options));
-  }
-  Event.prototype = {
-    get target() {
-      return targetTable.get(this);
-    },
-    get currentTarget() {
-      return currentTargetTable.get(this);
-    },
-    get eventPhase() {
-      return eventPhaseTable.get(this);
-    },
-    get path() {
-      var nodeList = new wrappers.NodeList();
-      var eventPath = eventPathTable.get(this);
-      if (eventPath) {
-        var index = 0;
-        var lastIndex = eventPath.length - 1;
-        var baseRoot = rootOfNode(currentTargetTable.get(this));
-
-        for (var i = 0; i <= lastIndex; i++) {
-          var currentTarget = eventPath[i].currentTarget;
-          var currentRoot = rootOfNode(currentTarget);
-          if (enclosedBy(baseRoot, currentRoot) &&
-              // Make sure we do not add Window to the path.
-              (i !== lastIndex || currentTarget instanceof wrappers.Node)) {
-            nodeList[index++] = currentTarget;
-          }
-        }
-        nodeList.length = index;
-      }
-      return nodeList;
-    },
-    stopPropagation: function() {
-      stopPropagationTable.set(this, true);
-    },
-    stopImmediatePropagation: function() {
-      stopPropagationTable.set(this, true);
-      stopImmediatePropagationTable.set(this, true);
-    }
-  };
-  registerWrapper(OriginalEvent, Event, document.createEvent('Event'));
-
-  function unwrapOptions(options) {
-    if (!options || !options.relatedTarget)
-      return options;
-    return Object.create(options, {
-      relatedTarget: {value: unwrap(options.relatedTarget)}
-    });
-  }
-
-  function registerGenericEvent(name, SuperEvent, prototype) {
-    var OriginalEvent = window[name];
-    var GenericEvent = function(type, options) {
-      if (type instanceof OriginalEvent)
-        this.impl = type;
-      else
-        return wrap(constructEvent(OriginalEvent, name, type, options));
-    };
-    GenericEvent.prototype = Object.create(SuperEvent.prototype);
-    if (prototype)
-      mixin(GenericEvent.prototype, prototype);
-    if (OriginalEvent) {
-      // - Old versions of Safari fails on new FocusEvent (and others?).
-      // - IE does not support event constructors.
-      // - createEvent('FocusEvent') throws in Firefox.
-      // => Try the best practice solution first and fallback to the old way
-      // if needed.
-      try {
-        registerWrapper(OriginalEvent, GenericEvent, new OriginalEvent('temp'));
-      } catch (ex) {
-        registerWrapper(OriginalEvent, GenericEvent,
-                        document.createEvent(name));
-      }
-    }
-    return GenericEvent;
-  }
-
-  var UIEvent = registerGenericEvent('UIEvent', Event);
-  var CustomEvent = registerGenericEvent('CustomEvent', Event);
-
-  var relatedTargetProto = {
-    get relatedTarget() {
-      return relatedTargetTable.get(this) || wrap(unwrap(this).relatedTarget);
-    }
-  };
-
-  function getInitFunction(name, relatedTargetIndex) {
-    return function() {
-      arguments[relatedTargetIndex] = unwrap(arguments[relatedTargetIndex]);
-      var impl = unwrap(this);
-      impl[name].apply(impl, arguments);
-    };
-  }
-
-  var mouseEventProto = mixin({
-    initMouseEvent: getInitFunction('initMouseEvent', 14)
-  }, relatedTargetProto);
-
-  var focusEventProto = mixin({
-    initFocusEvent: getInitFunction('initFocusEvent', 5)
-  }, relatedTargetProto);
-
-  var MouseEvent = registerGenericEvent('MouseEvent', UIEvent, mouseEventProto);
-  var FocusEvent = registerGenericEvent('FocusEvent', UIEvent, focusEventProto);
-
-  // In case the browser does not support event constructors we polyfill that
-  // by calling `createEvent('Foo')` and `initFooEvent` where the arguments to
-  // `initFooEvent` are derived from the registered default event init dict.
-  var defaultInitDicts = Object.create(null);
-
-  var supportsEventConstructors = (function() {
-    try {
-      new window.FocusEvent('focus');
-    } catch (ex) {
-      return false;
-    }
-    return true;
-  })();
-
-  /**
-   * Constructs a new native event.
-   */
-  function constructEvent(OriginalEvent, name, type, options) {
-    if (supportsEventConstructors)
-      return new OriginalEvent(type, unwrapOptions(options));
-
-    // Create the arguments from the default dictionary.
-    var event = unwrap(document.createEvent(name));
-    var defaultDict = defaultInitDicts[name];
-    var args = [type];
-    Object.keys(defaultDict).forEach(function(key) {
-      var v = options != null && key in options ?
-          options[key] : defaultDict[key];
-      if (key === 'relatedTarget')
-        v = unwrap(v);
-      args.push(v);
-    });
-    event['init' + name].apply(event, args);
-    return event;
-  }
-
-  if (!supportsEventConstructors) {
-    var configureEventConstructor = function(name, initDict, superName) {
-      if (superName) {
-        var superDict = defaultInitDicts[superName];
-        initDict = mixin(mixin({}, superDict), initDict);
-      }
-
-      defaultInitDicts[name] = initDict;
-    };
-
-    // The order of the default event init dictionary keys is important, the
-    // arguments to initFooEvent is derived from that.
-    configureEventConstructor('Event', {bubbles: false, cancelable: false});
-    configureEventConstructor('CustomEvent', {detail: null}, 'Event');
-    configureEventConstructor('UIEvent', {view: null, detail: 0}, 'Event');
-    configureEventConstructor('MouseEvent', {
-      screenX: 0,
-      screenY: 0,
-      clientX: 0,
-      clientY: 0,
-      ctrlKey: false,
-      altKey: false,
-      shiftKey: false,
-      metaKey: false,
-      button: 0,
-      relatedTarget: null
-    }, 'UIEvent');
-    configureEventConstructor('FocusEvent', {relatedTarget: null}, 'UIEvent');
-  }
-
-  function BeforeUnloadEvent(impl) {
-    Event.call(this);
-  }
-  BeforeUnloadEvent.prototype = Object.create(Event.prototype);
-  mixin(BeforeUnloadEvent.prototype, {
-    get returnValue() {
-      return this.impl.returnValue;
-    },
-    set returnValue(v) {
-      this.impl.returnValue = v;
-    }
-  });
-
-  function isValidListener(fun) {
-    if (typeof fun === 'function')
-      return true;
-    return fun && fun.handleEvent;
-  }
-
-  function isMutationEvent(type) {
-    switch (type) {
-      case 'DOMAttrModified':
-      case 'DOMAttributeNameChanged':
-      case 'DOMCharacterDataModified':
-      case 'DOMElementNameChanged':
-      case 'DOMNodeInserted':
-      case 'DOMNodeInsertedIntoDocument':
-      case 'DOMNodeRemoved':
-      case 'DOMNodeRemovedFromDocument':
-      case 'DOMSubtreeModified':
-        return true;
-    }
-    return false;
-  }
-
-  var OriginalEventTarget = window.EventTarget;
-
-  /**
-   * This represents a wrapper for an EventTarget.
-   * @param {!EventTarget} impl The original event target.
-   * @constructor
-   */
-  function EventTarget(impl) {
-    this.impl = impl;
-  }
-
-  // Node and Window have different internal type checks in WebKit so we cannot
-  // use the same method as the original function.
-  var methodNames = [
-    'addEventListener',
-    'removeEventListener',
-    'dispatchEvent'
-  ];
-
-  [Node, Window].forEach(function(constructor) {
-    var p = constructor.prototype;
-    methodNames.forEach(function(name) {
-      Object.defineProperty(p, name + '_', {value: p[name]});
-    });
-  });
-
-  function getTargetToListenAt(wrapper) {
-    if (wrapper instanceof wrappers.ShadowRoot)
-      wrapper = wrapper.host;
-    return unwrap(wrapper);
-  }
-
-  EventTarget.prototype = {
-    addEventListener: function(type, fun, capture) {
-      if (!isValidListener(fun) || isMutationEvent(type))
-        return;
-
-      var listener = new Listener(type, fun, capture);
-      var listeners = listenersTable.get(this);
-      if (!listeners) {
-        listeners = [];
-        listenersTable.set(this, listeners);
-      } else {
-        // Might have a duplicate.
-        for (var i = 0; i < listeners.length; i++) {
-          if (listener.equals(listeners[i]))
-            return;
-        }
-      }
-
-      listeners.push(listener);
-
-      var target = getTargetToListenAt(this);
-      target.addEventListener_(type, dispatchOriginalEvent, true);
-    },
-    removeEventListener: function(type, fun, capture) {
-      capture = Boolean(capture);
-      var listeners = listenersTable.get(this);
-      if (!listeners)
-        return;
-      var count = 0, found = false;
-      for (var i = 0; i < listeners.length; i++) {
-        if (listeners[i].type === type && listeners[i].capture === capture) {
-          count++;
-          if (listeners[i].handler === fun) {
-            found = true;
-            listeners[i].remove();
-          }
-        }
-      }
-
-      if (found && count === 1) {
-        var target = getTargetToListenAt(this);
-        target.removeEventListener_(type, dispatchOriginalEvent, true);
-      }
-    },
-    dispatchEvent: function(event) {
-      // We want to use the native dispatchEvent because it triggers the default
-      // actions (like checking a checkbox). However, if there are no listeners
-      // in the composed tree then there are no events that will trigger and
-      // listeners in the non composed tree that are part of the event path are
-      // not notified.
-      //
-      // If we find out that there are no listeners in the composed tree we add
-      // a temporary listener to the target which makes us get called back even
-      // in that case.
-
-      var nativeEvent = unwrap(event);
-      var eventType = nativeEvent.type;
-
-      // Allow dispatching the same event again. This is safe because if user
-      // code calls this during an existing dispatch of the same event the
-      // native dispatchEvent throws (that is required by the spec).
-      handledEventsTable.set(nativeEvent, false);
-
-      // Force rendering since we prefer native dispatch and that works on the
-      // composed tree.
-      scope.renderAllPending();
-
-      var tempListener;
-      if (!hasListenerInAncestors(this, eventType)) {
-        tempListener = function() {};
-        this.addEventListener(eventType, tempListener, true);
-      }
-
-      try {
-        return unwrap(this).dispatchEvent_(nativeEvent);
-      } finally {
-        if (tempListener)
-          this.removeEventListener(eventType, tempListener, true);
-      }
-    }
-  };
-
-  function hasListener(node, type) {
-    var listeners = listenersTable.get(node);
-    if (listeners) {
-      for (var i = 0; i < listeners.length; i++) {
-        if (!listeners[i].removed && listeners[i].type === type)
-          return true;
-      }
-    }
-    return false;
-  }
-
-  function hasListenerInAncestors(target, type) {
-    for (var node = unwrap(target); node; node = node.parentNode) {
-      if (hasListener(wrap(node), type))
-        return true;
-    }
-    return false;
-  }
-
-  if (OriginalEventTarget)
-    registerWrapper(OriginalEventTarget, EventTarget);
-
-  function wrapEventTargetMethods(constructors) {
-    forwardMethodsToWrapper(constructors, methodNames);
-  }
-
-  var originalElementFromPoint = document.elementFromPoint;
-
-  function elementFromPoint(self, document, x, y) {
-    scope.renderAllPending();
-
-    var element = wrap(originalElementFromPoint.call(document.impl, x, y));
-    var targets = retarget(element, this)
-    for (var i = 0; i < targets.length; i++) {
-      var target = targets[i];
-      if (target.currentTarget === self)
-        return target.target;
-    }
-    return null;
-  }
-
-  /**
-   * Returns a function that is to be used as a getter for `onfoo` properties.
-   * @param {string} name
-   * @return {Function}
-   */
-  function getEventHandlerGetter(name) {
-    return function() {
-      var inlineEventHandlers = eventHandlersTable.get(this);
-      return inlineEventHandlers && inlineEventHandlers[name] &&
-          inlineEventHandlers[name].value || null;
-     };
-  }
-
-  /**
-   * Returns a function that is to be used as a setter for `onfoo` properties.
-   * @param {string} name
-   * @return {Function}
-   */
-  function getEventHandlerSetter(name) {
-    var eventType = name.slice(2);
-    return function(value) {
-      var inlineEventHandlers = eventHandlersTable.get(this);
-      if (!inlineEventHandlers) {
-        inlineEventHandlers = Object.create(null);
-        eventHandlersTable.set(this, inlineEventHandlers);
-      }
-
-      var old = inlineEventHandlers[name];
-      if (old)
-        this.removeEventListener(eventType, old.wrapped, false);
-
-      if (typeof value === 'function') {
-        var wrapped = function(e) {
-          var rv = value.call(this, e);
-          if (rv === false)
-            e.preventDefault();
-          else if (name === 'onbeforeunload' && typeof rv === 'string')
-            e.returnValue = rv;
-          // mouseover uses true for preventDefault but preventDefault for
-          // mouseover is ignored by browsers these day.
-        };
-
-        this.addEventListener(eventType, wrapped, false);
-        inlineEventHandlers[name] = {
-          value: value,
-          wrapped: wrapped
-        };
-      }
-    };
-  }
-
-  scope.adjustRelatedTarget = adjustRelatedTarget;
-  scope.elementFromPoint = elementFromPoint;
-  scope.getEventHandlerGetter = getEventHandlerGetter;
-  scope.getEventHandlerSetter = getEventHandlerSetter;
-  scope.wrapEventTargetMethods = wrapEventTargetMethods;
-  scope.wrappers.BeforeUnloadEvent = BeforeUnloadEvent;
-  scope.wrappers.CustomEvent = CustomEvent;
-  scope.wrappers.Event = Event;
-  scope.wrappers.EventTarget = EventTarget;
-  scope.wrappers.FocusEvent = FocusEvent;
-  scope.wrappers.MouseEvent = MouseEvent;
-  scope.wrappers.UIEvent = UIEvent;
-
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2012 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var wrap = scope.wrap;
-
-  function nonEnum(obj, prop) {
-    Object.defineProperty(obj, prop, {enumerable: false});
-  }
-
-  function NodeList() {
-    this.length = 0;
-    nonEnum(this, 'length');
-  }
-  NodeList.prototype = {
-    item: function(index) {
-      return this[index];
-    }
-  };
-  nonEnum(NodeList.prototype, 'item');
-
-  function wrapNodeList(list) {
-    if (list == null)
-      return list;
-    var wrapperList = new NodeList();
-    for (var i = 0, length = list.length; i < length; i++) {
-      wrapperList[i] = wrap(list[i]);
-    }
-    wrapperList.length = length;
-    return wrapperList;
-  }
-
-  function addWrapNodeListMethod(wrapperConstructor, name) {
-    wrapperConstructor.prototype[name] = function() {
-      return wrapNodeList(this.impl[name].apply(this.impl, arguments));
-    };
-  }
-
-  scope.wrappers.NodeList = NodeList;
-  scope.addWrapNodeListMethod = addWrapNodeListMethod;
-  scope.wrapNodeList = wrapNodeList;
-
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2012 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var EventTarget = scope.wrappers.EventTarget;
-  var NodeList = scope.wrappers.NodeList;
-  var assert = scope.assert;
-  var defineWrapGetter = scope.defineWrapGetter;
-  var enqueueMutation = scope.enqueueMutation;
-  var isWrapper = scope.isWrapper;
-  var mixin = scope.mixin;
-  var registerTransientObservers = scope.registerTransientObservers;
-  var registerWrapper = scope.registerWrapper;
-  var unwrap = scope.unwrap;
-  var wrap = scope.wrap;
-  var wrapIfNeeded = scope.wrapIfNeeded;
-
-  function assertIsNodeWrapper(node) {
-    assert(node instanceof Node);
-  }
-
-  function createOneElementNodeList(node) {
-    var nodes = new NodeList();
-    nodes[0] = node;
-    nodes.length = 1;
-    return nodes;
-  }
-
-  var surpressMutations = false;
-
-  /**
-   * Called before node is inserted into a node to enqueue its removal from its
-   * old parent.
-   * @param {!Node} node The node that is about to be removed.
-   * @param {!Node} parent The parent node that the node is being removed from.
-   * @param {!NodeList} nodes The collected nodes.
-   */
-  function enqueueRemovalForInsertedNodes(node, parent, nodes) {
-    enqueueMutation(parent, 'childList', {
-      removedNodes: nodes,
-      previousSibling: node.previousSibling,
-      nextSibling: node.nextSibling
-    });
-  }
-
-  function enqueueRemovalForInsertedDocumentFragment(df, nodes) {
-    enqueueMutation(df, 'childList', {
-      removedNodes: nodes
-    });
-  }
-
-  /**
-   * Collects nodes from a DocumentFragment or a Node for removal followed
-   * by an insertion.
-   *
-   * This updates the internal pointers for node, previousNode and nextNode.
-   */
-  function collectNodes(node, parentNode, previousNode, nextNode) {
-    if (node instanceof DocumentFragment) {
-      var nodes = collectNodesForDocumentFragment(node);
-
-      // The extra loop is to work around bugs with DocumentFragments in IE.
-      surpressMutations = true;
-      for (var i = nodes.length - 1; i >= 0; i--) {
-        node.removeChild(nodes[i]);
-        nodes[i].parentNode_ = parentNode;
-      }
-      surpressMutations = false;
-
-      for (var i = 0; i < nodes.length; i++) {
-        nodes[i].previousSibling_ = nodes[i - 1] || previousNode;
-        nodes[i].nextSibling_ = nodes[i + 1] || nextNode;
-      }
-
-      if (previousNode)
-        previousNode.nextSibling_ = nodes[0];
-      if (nextNode)
-        nextNode.previousSibling_ = nodes[nodes.length - 1];
-
-      return nodes;
-    }
-
-    var nodes = createOneElementNodeList(node);
-    var oldParent = node.parentNode;
-    if (oldParent) {
-      // This will enqueue the mutation record for the removal as needed.
-      oldParent.removeChild(node);
-    }
-
-    node.parentNode_ = parentNode;
-    node.previousSibling_ = previousNode;
-    node.nextSibling_ = nextNode;
-    if (previousNode)
-      previousNode.nextSibling_ = node;
-    if (nextNode)
-      nextNode.previousSibling_ = node;
-
-    return nodes;
-  }
-
-  function collectNodesNative(node) {
-    if (node instanceof DocumentFragment)
-      return collectNodesForDocumentFragment(node);
-
-    var nodes = createOneElementNodeList(node);
-    var oldParent = node.parentNode;
-    if (oldParent)
-      enqueueRemovalForInsertedNodes(node, oldParent, nodes);
-    return nodes;
-  }
-
-  function collectNodesForDocumentFragment(node) {
-    var nodes = new NodeList();
-    var i = 0;
-    for (var child = node.firstChild; child; child = child.nextSibling) {
-      nodes[i++] = child;
-    }
-    nodes.length = i;
-    enqueueRemovalForInsertedDocumentFragment(node, nodes);
-    return nodes;
-  }
-
-  function snapshotNodeList(nodeList) {
-    // NodeLists are not live at the moment so just return the same object.
-    return nodeList;
-  }
-
-  // http://dom.spec.whatwg.org/#node-is-inserted
-  function nodeWasAdded(node) {
-    node.nodeIsInserted_();
-  }
-
-  function nodesWereAdded(nodes) {
-    for (var i = 0; i < nodes.length; i++) {
-      nodeWasAdded(nodes[i]);
-    }
-  }
-
-  // http://dom.spec.whatwg.org/#node-is-removed
-  function nodeWasRemoved(node) {
-    // Nothing at this point in time.
-  }
-
-  function nodesWereRemoved(nodes) {
-    // Nothing at this point in time.
-  }
-
-  function ensureSameOwnerDocument(parent, child) {
-    var ownerDoc = parent.nodeType === Node.DOCUMENT_NODE ?
-        parent : parent.ownerDocument;
-    if (ownerDoc !== child.ownerDocument)
-      ownerDoc.adoptNode(child);
-  }
-
-  function adoptNodesIfNeeded(owner, nodes) {
-    if (!nodes.length)
-      return;
-
-    var ownerDoc = owner.ownerDocument;
-
-    // All nodes have the same ownerDocument when we get here.
-    if (ownerDoc === nodes[0].ownerDocument)
-      return;
-
-    for (var i = 0; i < nodes.length; i++) {
-      scope.adoptNodeNoRemove(nodes[i], ownerDoc);
-    }
-  }
-
-  function unwrapNodesForInsertion(owner, nodes) {
-    adoptNodesIfNeeded(owner, nodes);
-    var length = nodes.length;
-
-    if (length === 1)
-      return unwrap(nodes[0]);
-
-    var df = unwrap(owner.ownerDocument.createDocumentFragment());
-    for (var i = 0; i < length; i++) {
-      df.appendChild(unwrap(nodes[i]));
-    }
-    return df;
-  }
-
-  function clearChildNodes(wrapper) {
-    if (wrapper.firstChild_ !== undefined) {
-      var child = wrapper.firstChild_;
-      while (child) {
-        var tmp = child;
-        child = child.nextSibling_;
-        tmp.parentNode_ = tmp.previousSibling_ = tmp.nextSibling_ = undefined;
-      }
-    }
-    wrapper.firstChild_ = wrapper.lastChild_ = undefined;
-  }
-
-  function removeAllChildNodes(wrapper) {
-    if (wrapper.invalidateShadowRenderer()) {
-      var childWrapper = wrapper.firstChild;
-      while (childWrapper) {
-        assert(childWrapper.parentNode === wrapper);
-        var nextSibling = childWrapper.nextSibling;
-        var childNode = unwrap(childWrapper);
-        var parentNode = childNode.parentNode;
-        if (parentNode)
-          originalRemoveChild.call(parentNode, childNode);
-        childWrapper.previousSibling_ = childWrapper.nextSibling_ =
-            childWrapper.parentNode_ = null;
-        childWrapper = nextSibling;
-      }
-      wrapper.firstChild_ = wrapper.lastChild_ = null;
-    } else {
-      var node = unwrap(wrapper);
-      var child = node.firstChild;
-      var nextSibling;
-      while (child) {
-        nextSibling = child.nextSibling;
-        originalRemoveChild.call(node, child);
-        child = nextSibling;
-      }
-    }
-  }
-
-  function invalidateParent(node) {
-    var p = node.parentNode;
-    return p && p.invalidateShadowRenderer();
-  }
-
-  function cleanupNodes(nodes) {
-    for (var i = 0, n; i < nodes.length; i++) {
-      n = nodes[i];
-      n.parentNode.removeChild(n);
-    }
-  }
-
-  var OriginalNode = window.Node;
-
-  /**
-   * This represents a wrapper of a native DOM node.
-   * @param {!Node} original The original DOM node, aka, the visual DOM node.
-   * @constructor
-   * @extends {EventTarget}
-   */
-  function Node(original) {
-    assert(original instanceof OriginalNode);
-
-    EventTarget.call(this, original);
-
-    // These properties are used to override the visual references with the
-    // logical ones. If the value is undefined it means that the logical is the
-    // same as the visual.
-
-    /**
-     * @type {Node|undefined}
-     * @private
-     */
-    this.parentNode_ = undefined;
-
-    /**
-     * @type {Node|undefined}
-     * @private
-     */
-    this.firstChild_ = undefined;
-
-    /**
-     * @type {Node|undefined}
-     * @private
-     */
-    this.lastChild_ = undefined;
-
-    /**
-     * @type {Node|undefined}
-     * @private
-     */
-    this.nextSibling_ = undefined;
-
-    /**
-     * @type {Node|undefined}
-     * @private
-     */
-    this.previousSibling_ = undefined;
-  }
-
-  var OriginalDocumentFragment = window.DocumentFragment;
-  var originalAppendChild = OriginalNode.prototype.appendChild;
-  var originalCompareDocumentPosition =
-      OriginalNode.prototype.compareDocumentPosition;
-  var originalInsertBefore = OriginalNode.prototype.insertBefore;
-  var originalRemoveChild = OriginalNode.prototype.removeChild;
-  var originalReplaceChild = OriginalNode.prototype.replaceChild;
-
-  var isIe = /Trident/.test(navigator.userAgent);
-
-  var removeChildOriginalHelper = isIe ?
-      function(parent, child) {
-        try {
-          originalRemoveChild.call(parent, child);
-        } catch (ex) {
-          if (!(parent instanceof OriginalDocumentFragment))
-            throw ex;
-        }
-      } :
-      function(parent, child) {
-        originalRemoveChild.call(parent, child);
-      };
-
-  Node.prototype = Object.create(EventTarget.prototype);
-  mixin(Node.prototype, {
-    appendChild: function(childWrapper) {
-      return this.insertBefore(childWrapper, null);
-    },
-
-    insertBefore: function(childWrapper, refWrapper) {
-      assertIsNodeWrapper(childWrapper);
-
-      var refNode;
-      if (refWrapper) {
-        if (isWrapper(refWrapper)) {
-          refNode = unwrap(refWrapper);
-        } else {
-          refNode = refWrapper;
-          refWrapper = wrap(refNode);
-        }
-      } else {
-        refWrapper = null;
-        refNode = null;
-      }
-
-      refWrapper && assert(refWrapper.parentNode === this);
-
-      var nodes;
-      var previousNode =
-          refWrapper ? refWrapper.previousSibling : this.lastChild;
-
-      var useNative = !this.invalidateShadowRenderer() &&
-                      !invalidateParent(childWrapper);
-
-      if (useNative)
-        nodes = collectNodesNative(childWrapper);
-      else
-        nodes = collectNodes(childWrapper, this, previousNode, refWrapper);
-
-      if (useNative) {
-        ensureSameOwnerDocument(this, childWrapper);
-        clearChildNodes(this);
-        originalInsertBefore.call(this.impl, unwrap(childWrapper), refNode);
-      } else {
-        if (!previousNode)
-          this.firstChild_ = nodes[0];
-        if (!refWrapper)
-          this.lastChild_ = nodes[nodes.length - 1];
-
-        var parentNode = refNode ? refNode.parentNode : this.impl;
-
-        // insertBefore refWrapper no matter what the parent is?
-        if (parentNode) {
-          originalInsertBefore.call(parentNode,
-              unwrapNodesForInsertion(this, nodes), refNode);
-        } else {
-          adoptNodesIfNeeded(this, nodes);
-        }
-      }
-
-      enqueueMutation(this, 'childList', {
-        addedNodes: nodes,
-        nextSibling: refWrapper,
-        previousSibling: previousNode
-      });
-
-      nodesWereAdded(nodes);
-
-      return childWrapper;
-    },
-
-    removeChild: function(childWrapper) {
-      assertIsNodeWrapper(childWrapper);
-      if (childWrapper.parentNode !== this) {
-        // IE has invalid DOM trees at times.
-        var found = false;
-        var childNodes = this.childNodes;
-        for (var ieChild = this.firstChild; ieChild;
-             ieChild = ieChild.nextSibling) {
-          if (ieChild === childWrapper) {
-            found = true;
-            break;
-          }
-        }
-        if (!found) {
-          // TODO(arv): DOMException
-          throw new Error('NotFoundError');
-        }
-      }
-
-      var childNode = unwrap(childWrapper);
-      var childWrapperNextSibling = childWrapper.nextSibling;
-      var childWrapperPreviousSibling = childWrapper.previousSibling;
-
-      if (this.invalidateShadowRenderer()) {
-        // We need to remove the real node from the DOM before updating the
-        // pointers. This is so that that mutation event is dispatched before
-        // the pointers have changed.
-        var thisFirstChild = this.firstChild;
-        var thisLastChild = this.lastChild;
-
-        var parentNode = childNode.parentNode;
-        if (parentNode)
-          removeChildOriginalHelper(parentNode, childNode);
-
-        if (thisFirstChild === childWrapper)
-          this.firstChild_ = childWrapperNextSibling;
-        if (thisLastChild === childWrapper)
-          this.lastChild_ = childWrapperPreviousSibling;
-        if (childWrapperPreviousSibling)
-          childWrapperPreviousSibling.nextSibling_ = childWrapperNextSibling;
-        if (childWrapperNextSibling) {
-          childWrapperNextSibling.previousSibling_ =
-              childWrapperPreviousSibling;
-        }
-
-        childWrapper.previousSibling_ = childWrapper.nextSibling_ =
-            childWrapper.parentNode_ = undefined;
-      } else {
-        clearChildNodes(this);
-        removeChildOriginalHelper(this.impl, childNode);
-      }
-
-      if (!surpressMutations) {
-        enqueueMutation(this, 'childList', {
-          removedNodes: createOneElementNodeList(childWrapper),
-          nextSibling: childWrapperNextSibling,
-          previousSibling: childWrapperPreviousSibling
-        });
-      }
-
-      registerTransientObservers(this, childWrapper);
-
-      return childWrapper;
-    },
-
-    replaceChild: function(newChildWrapper, oldChildWrapper) {
-      assertIsNodeWrapper(newChildWrapper);
-
-      var oldChildNode;
-      if (isWrapper(oldChildWrapper)) {
-        oldChildNode = unwrap(oldChildWrapper);
-      } else {
-        oldChildNode = oldChildWrapper;
-        oldChildWrapper = wrap(oldChildNode);
-      }
-
-      if (oldChildWrapper.parentNode !== this) {
-        // TODO(arv): DOMException
-        throw new Error('NotFoundError');
-      }
-
-      var nextNode = oldChildWrapper.nextSibling;
-      var previousNode = oldChildWrapper.previousSibling;
-      var nodes;
-
-      var useNative = !this.invalidateShadowRenderer() &&
-                      !invalidateParent(newChildWrapper);
-
-      if (useNative) {
-        nodes = collectNodesNative(newChildWrapper);
-      } else {
-        if (nextNode === newChildWrapper)
-          nextNode = newChildWrapper.nextSibling;
-        nodes = collectNodes(newChildWrapper, this, previousNode, nextNode);
-      }
-
-      if (!useNative) {
-        if (this.firstChild === oldChildWrapper)
-          this.firstChild_ = nodes[0];
-        if (this.lastChild === oldChildWrapper)
-          this.lastChild_ = nodes[nodes.length - 1];
-
-        oldChildWrapper.previousSibling_ = oldChildWrapper.nextSibling_ =
-            oldChildWrapper.parentNode_ = undefined;
-
-        // replaceChild no matter what the parent is?
-        if (oldChildNode.parentNode) {
-          originalReplaceChild.call(
-              oldChildNode.parentNode,
-              unwrapNodesForInsertion(this, nodes),
-              oldChildNode);
-        }
-      } else {
-        ensureSameOwnerDocument(this, newChildWrapper);
-        clearChildNodes(this);
-        originalReplaceChild.call(this.impl, unwrap(newChildWrapper),
-                                  oldChildNode);
-      }
-
-      enqueueMutation(this, 'childList', {
-        addedNodes: nodes,
-        removedNodes: createOneElementNodeList(oldChildWrapper),
-        nextSibling: nextNode,
-        previousSibling: previousNode
-      });
-
-      nodeWasRemoved(oldChildWrapper);
-      nodesWereAdded(nodes);
-
-      return oldChildWrapper;
-    },
-
-    /**
-     * Called after a node was inserted. Subclasses override this to invalidate
-     * the renderer as needed.
-     * @private
-     */
-    nodeIsInserted_: function() {
-      for (var child = this.firstChild; child; child = child.nextSibling) {
-        child.nodeIsInserted_();
-      }
-    },
-
-    hasChildNodes: function() {
-      return this.firstChild !== null;
-    },
-
-    /** @type {Node} */
-    get parentNode() {
-      // If the parentNode has not been overridden, use the original parentNode.
-      return this.parentNode_ !== undefined ?
-          this.parentNode_ : wrap(this.impl.parentNode);
-    },
-
-    /** @type {Node} */
-    get firstChild() {
-      return this.firstChild_ !== undefined ?
-          this.firstChild_ : wrap(this.impl.firstChild);
-    },
-
-    /** @type {Node} */
-    get lastChild() {
-      return this.lastChild_ !== undefined ?
-          this.lastChild_ : wrap(this.impl.lastChild);
-    },
-
-    /** @type {Node} */
-    get nextSibling() {
-      return this.nextSibling_ !== undefined ?
-          this.nextSibling_ : wrap(this.impl.nextSibling);
-    },
-
-    /** @type {Node} */
-    get previousSibling() {
-      return this.previousSibling_ !== undefined ?
-          this.previousSibling_ : wrap(this.impl.previousSibling);
-    },
-
-    get parentElement() {
-      var p = this.parentNode;
-      while (p && p.nodeType !== Node.ELEMENT_NODE) {
-        p = p.parentNode;
-      }
-      return p;
-    },
-
-    get textContent() {
-      // TODO(arv): This should fallback to this.impl.textContent if there
-      // are no shadow trees below or above the context node.
-      var s = '';
-      for (var child = this.firstChild; child; child = child.nextSibling) {
-        if (child.nodeType != Node.COMMENT_NODE) {
-          s += child.textContent;
-        }
-      }
-      return s;
-    },
-    set textContent(textContent) {
-      var removedNodes = snapshotNodeList(this.childNodes);
-
-      if (this.invalidateShadowRenderer()) {
-        removeAllChildNodes(this);
-        if (textContent !== '') {
-          var textNode = this.impl.ownerDocument.createTextNode(textContent);
-          this.appendChild(textNode);
-        }
-      } else {
-        clearChildNodes(this);
-        this.impl.textContent = textContent;
-      }
-
-      var addedNodes = snapshotNodeList(this.childNodes);
-
-      enqueueMutation(this, 'childList', {
-        addedNodes: addedNodes,
-        removedNodes: removedNodes
-      });
-
-      nodesWereRemoved(removedNodes);
-      nodesWereAdded(addedNodes);
-    },
-
-    get childNodes() {
-      var wrapperList = new NodeList();
-      var i = 0;
-      for (var child = this.firstChild; child; child = child.nextSibling) {
-        wrapperList[i++] = child;
-      }
-      wrapperList.length = i;
-      return wrapperList;
-    },
-
-    cloneNode: function(deep) {
-      var clone = wrap(this.impl.cloneNode(false));
-      if (deep) {
-        for (var child = this.firstChild; child; child = child.nextSibling) {
-          clone.appendChild(child.cloneNode(true));
-        }
-      }
-      // TODO(arv): Some HTML elements also clone other data like value.
-      return clone;
-    },
-
-    contains: function(child) {
-      if (!child)
-        return false;
-
-      child = wrapIfNeeded(child);
-
-      // TODO(arv): Optimize using ownerDocument etc.
-      if (child === this)
-        return true;
-      var parentNode = child.parentNode;
-      if (!parentNode)
-        return false;
-      return this.contains(parentNode);
-    },
-
-    compareDocumentPosition: function(otherNode) {
-      // This only wraps, it therefore only operates on the composed DOM and not
-      // the logical DOM.
-      return originalCompareDocumentPosition.call(this.impl, unwrap(otherNode));
-    },
-
-    normalize: function() {
-      var nodes = snapshotNodeList(this.childNodes);
-      var remNodes = [];
-      var s = '';
-      var modNode;
-
-      for (var i = 0, n; i < nodes.length; i++) {
-        n = nodes[i];
-        if (n.nodeType === Node.TEXT_NODE) {
-          if (!modNode && !n.data.length)
-            this.removeNode(n);
-          else if (!modNode)
-            modNode = n;
-          else {
-            s += n.data;
-            remNodes.push(n);
-          }
-        } else {
-          if (modNode && remNodes.length) {
-            modNode.data += s;
-            cleanUpNodes(remNodes);
-          }
-          remNodes = [];
-          s = '';
-          modNode = null;
-          if (n.childNodes.length)
-            n.normalize();
-        }
-      }
-
-      // handle case where >1 text nodes are the last children
-      if (modNode && remNodes.length) {
-        modNode.data += s;
-        cleanupNodes(remNodes);
-      }
-    }
-  });
-
-  defineWrapGetter(Node, 'ownerDocument');
-
-  // We use a DocumentFragment as a base and then delete the properties of
-  // DocumentFragment.prototype from the wrapper Node. Since delete makes
-  // objects slow in some JS engines we recreate the prototype object.
-  registerWrapper(OriginalNode, Node, document.createDocumentFragment());
-  delete Node.prototype.querySelector;
-  delete Node.prototype.querySelectorAll;
-  Node.prototype = mixin(Object.create(EventTarget.prototype), Node.prototype);
-
-  scope.nodeWasAdded = nodeWasAdded;
-  scope.nodeWasRemoved = nodeWasRemoved;
-  scope.nodesWereAdded = nodesWereAdded;
-  scope.nodesWereRemoved = nodesWereRemoved;
-  scope.snapshotNodeList = snapshotNodeList;
-  scope.wrappers.Node = Node;
-
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. 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) {
-  'use strict';
-
-  function findOne(node, selector) {
-    var m, el = node.firstElementChild;
-    while (el) {
-      if (el.matches(selector))
-        return el;
-      m = findOne(el, selector);
-      if (m)
-        return m;
-      el = el.nextElementSibling;
-    }
-    return null;
-  }
-
-  function findAll(node, selector, results) {
-    var el = node.firstElementChild;
-    while (el) {
-      if (el.matches(selector))
-        results[results.length++] = el;
-      findAll(el, selector, results);
-      el = el.nextElementSibling;
-    }
-    return results;
-  }
-
-  // find and findAll will only match Simple Selectors,
-  // Structural Pseudo Classes are not guarenteed to be correct
-  // http://www.w3.org/TR/css3-selectors/#simple-selectors
-
-  var SelectorsInterface = {
-    querySelector: function(selector) {
-      return findOne(this, selector);
-    },
-    querySelectorAll: function(selector) {
-      return findAll(this, selector, new NodeList())
-    }
-  };
-
-  var GetElementsByInterface = {
-    getElementsByTagName: function(tagName) {
-      // TODO(arv): Check tagName?
-      return this.querySelectorAll(tagName);
-    },
-    getElementsByClassName: function(className) {
-      // TODO(arv): Check className?
-      return this.querySelectorAll('.' + className);
-    },
-    getElementsByTagNameNS: function(ns, tagName) {
-      if (ns === '*')
-        return this.getElementsByTagName(tagName);
-
-      // TODO(arv): Check tagName?
-      var result = new NodeList;
-      var els = this.getElementsByTagName(tagName);
-      for (var i = 0, j = 0; i < els.length; i++) {
-        if (els[i].namespaceURI === ns)
-          result[j++] = els[i];
-      }
-      result.length = j;
-      return result;
-    }
-  };
-
-  scope.GetElementsByInterface = GetElementsByInterface;
-  scope.SelectorsInterface = SelectorsInterface;
-
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var NodeList = scope.wrappers.NodeList;
-
-  function forwardElement(node) {
-    while (node && node.nodeType !== Node.ELEMENT_NODE) {
-      node = node.nextSibling;
-    }
-    return node;
-  }
-
-  function backwardsElement(node) {
-    while (node && node.nodeType !== Node.ELEMENT_NODE) {
-      node = node.previousSibling;
-    }
-    return node;
-  }
-
-  var ParentNodeInterface = {
-    get firstElementChild() {
-      return forwardElement(this.firstChild);
-    },
-
-    get lastElementChild() {
-      return backwardsElement(this.lastChild);
-    },
-
-    get childElementCount() {
-      var count = 0;
-      for (var child = this.firstElementChild;
-           child;
-           child = child.nextElementSibling) {
-        count++;
-      }
-      return count;
-    },
-
-    get children() {
-      var wrapperList = new NodeList();
-      var i = 0;
-      for (var child = this.firstElementChild;
-           child;
-           child = child.nextElementSibling) {
-        wrapperList[i++] = child;
-      }
-      wrapperList.length = i;
-      return wrapperList;
-    }
-  };
-
-  var ChildNodeInterface = {
-    get nextElementSibling() {
-      return forwardElement(this.nextSibling);
-    },
-
-    get previousElementSibling() {
-      return backwardsElement(this.previousSibling);
-    }
-  };
-
-  scope.ChildNodeInterface = ChildNodeInterface;
-  scope.ParentNodeInterface = ParentNodeInterface;
-
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var ChildNodeInterface = scope.ChildNodeInterface;
-  var Node = scope.wrappers.Node;
-  var enqueueMutation = scope.enqueueMutation;
-  var mixin = scope.mixin;
-  var registerWrapper = scope.registerWrapper;
-
-  var OriginalCharacterData = window.CharacterData;
-
-  function CharacterData(node) {
-    Node.call(this, node);
-  }
-  CharacterData.prototype = Object.create(Node.prototype);
-  mixin(CharacterData.prototype, {
-    get textContent() {
-      return this.data;
-    },
-    set textContent(value) {
-      this.data = value;
-    },
-    get data() {
-      return this.impl.data;
-    },
-    set data(value) {
-      var oldValue = this.impl.data;
-      enqueueMutation(this, 'characterData', {
-        oldValue: oldValue
-      });
-      this.impl.data = value;
-    }
-  });
-
-  mixin(CharacterData.prototype, ChildNodeInterface);
-
-  registerWrapper(OriginalCharacterData, CharacterData,
-                  document.createTextNode(''));
-
-  scope.wrappers.CharacterData = CharacterData;
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2014 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var CharacterData = scope.wrappers.CharacterData;
-  var enqueueMutation = scope.enqueueMutation;
-  var mixin = scope.mixin;
-  var registerWrapper = scope.registerWrapper;
-
-  function toUInt32(x) {
-    return x >>> 0;
-  }
-
-  var OriginalText = window.Text;
-
-  function Text(node) {
-    CharacterData.call(this, node);
-  }
-  Text.prototype = Object.create(CharacterData.prototype);
-  mixin(Text.prototype, {
-    splitText: function(offset) {
-      offset = toUInt32(offset);
-      var s = this.data;
-      if (offset > s.length)
-        throw new Error('IndexSizeError');
-      var head = s.slice(0, offset);
-      var tail = s.slice(offset);
-      this.data = head;
-      var newTextNode = this.ownerDocument.createTextNode(tail);
-      if (this.parentNode)
-        this.parentNode.insertBefore(newTextNode, this.nextSibling);
-      return newTextNode;
-    }
-  });
-
-  registerWrapper(OriginalText, Text, document.createTextNode(''));
-
-  scope.wrappers.Text = Text;
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var ChildNodeInterface = scope.ChildNodeInterface;
-  var GetElementsByInterface = scope.GetElementsByInterface;
-  var Node = scope.wrappers.Node;
-  var ParentNodeInterface = scope.ParentNodeInterface;
-  var SelectorsInterface = scope.SelectorsInterface;
-  var addWrapNodeListMethod = scope.addWrapNodeListMethod;
-  var enqueueMutation = scope.enqueueMutation;
-  var mixin = scope.mixin;
-  var oneOf = scope.oneOf;
-  var registerWrapper = scope.registerWrapper;
-  var wrappers = scope.wrappers;
-
-  var OriginalElement = window.Element;
-
-  var matchesNames = [
-    'matches',  // needs to come first.
-    'mozMatchesSelector',
-    'msMatchesSelector',
-    'webkitMatchesSelector',
-  ].filter(function(name) {
-    return OriginalElement.prototype[name];
-  });
-
-  var matchesName = matchesNames[0];
-
-  var originalMatches = OriginalElement.prototype[matchesName];
-
-  function invalidateRendererBasedOnAttribute(element, name) {
-    // Only invalidate if parent node is a shadow host.
-    var p = element.parentNode;
-    if (!p || !p.shadowRoot)
-      return;
-
-    var renderer = scope.getRendererForHost(p);
-    if (renderer.dependsOnAttribute(name))
-      renderer.invalidate();
-  }
-
-  function enqueAttributeChange(element, name, oldValue) {
-    // This is not fully spec compliant. We should use localName (which might
-    // have a different case than name) and the namespace (which requires us
-    // to get the Attr object).
-    enqueueMutation(element, 'attributes', {
-      name: name,
-      namespace: null,
-      oldValue: oldValue
-    });
-  }
-
-  function Element(node) {
-    Node.call(this, node);
-  }
-  Element.prototype = Object.create(Node.prototype);
-  mixin(Element.prototype, {
-    createShadowRoot: function() {
-      var newShadowRoot = new wrappers.ShadowRoot(this);
-      this.impl.polymerShadowRoot_ = newShadowRoot;
-
-      var renderer = scope.getRendererForHost(this);
-      renderer.invalidate();
-
-      return newShadowRoot;
-    },
-
-    get shadowRoot() {
-      return this.impl.polymerShadowRoot_ || null;
-    },
-
-    setAttribute: function(name, value) {
-      var oldValue = this.impl.getAttribute(name);
-      this.impl.setAttribute(name, value);
-      enqueAttributeChange(this, name, oldValue);
-      invalidateRendererBasedOnAttribute(this, name);
-    },
-
-    removeAttribute: function(name) {
-      var oldValue = this.impl.getAttribute(name);
-      this.impl.removeAttribute(name);
-      enqueAttributeChange(this, name, oldValue);
-      invalidateRendererBasedOnAttribute(this, name);
-    },
-
-    matches: function(selector) {
-      return originalMatches.call(this.impl, selector);
-    }
-  });
-
-  matchesNames.forEach(function(name) {
-    if (name !== 'matches') {
-      Element.prototype[name] = function(selector) {
-        return this.matches(selector);
-      };
-    }
-  });
-
-  if (OriginalElement.prototype.webkitCreateShadowRoot) {
-    Element.prototype.webkitCreateShadowRoot =
-        Element.prototype.createShadowRoot;
-  }
-
-  /**
-   * Useful for generating the accessor pair for a property that reflects an
-   * attribute.
-   */
-  function setterDirtiesAttribute(prototype, propertyName, opt_attrName) {
-    var attrName = opt_attrName || propertyName;
-    Object.defineProperty(prototype, propertyName, {
-      get: function() {
-        return this.impl[propertyName];
-      },
-      set: function(v) {
-        this.impl[propertyName] = v;
-        invalidateRendererBasedOnAttribute(this, attrName);
-      },
-      configurable: true,
-      enumerable: true
-    });
-  }
-
-  setterDirtiesAttribute(Element.prototype, 'id');
-  setterDirtiesAttribute(Element.prototype, 'className', 'class');
-
-  mixin(Element.prototype, ChildNodeInterface);
-  mixin(Element.prototype, GetElementsByInterface);
-  mixin(Element.prototype, ParentNodeInterface);
-  mixin(Element.prototype, SelectorsInterface);
-
-  registerWrapper(OriginalElement, Element,
-                  document.createElementNS(null, 'x'));
-
-  // TODO(arv): Export setterDirtiesAttribute and apply it to more bindings
-  // that reflect attributes.
-  scope.matchesNames = matchesNames;
-  scope.wrappers.Element = Element;
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var Element = scope.wrappers.Element;
-  var defineGetter = scope.defineGetter;
-  var enqueueMutation = scope.enqueueMutation;
-  var mixin = scope.mixin;
-  var nodesWereAdded = scope.nodesWereAdded;
-  var nodesWereRemoved = scope.nodesWereRemoved;
-  var registerWrapper = scope.registerWrapper;
-  var snapshotNodeList = scope.snapshotNodeList;
-  var unwrap = scope.unwrap;
-  var wrap = scope.wrap;
-
-  /////////////////////////////////////////////////////////////////////////////
-  // innerHTML and outerHTML
-
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#escapingString
-  var escapeAttrRegExp = /[&\u00A0"]/g;
-  var escapeDataRegExp = /[&\u00A0<>]/g;
-
-  function escapeReplace(c) {
-    switch (c) {
-      case '&':
-        return '&amp;';
-      case '<':
-        return '&lt;';
-      case '>':
-        return '&gt;';
-      case '"':
-        return '&quot;'
-      case '\u00A0':
-        return '&nbsp;';
-    }
-  }
-
-  function escapeAttr(s) {
-    return s.replace(escapeAttrRegExp, escapeReplace);
-  }
-
-  function escapeData(s) {
-    return s.replace(escapeDataRegExp, escapeReplace);
-  }
-
-  function makeSet(arr) {
-    var set = {};
-    for (var i = 0; i < arr.length; i++) {
-      set[arr[i]] = true;
-    }
-    return set;
-  }
-
-  // http://www.whatwg.org/specs/web-apps/current-work/#void-elements
-  var voidElements = makeSet([
-    'area',
-    'base',
-    'br',
-    'col',
-    'command',
-    'embed',
-    'hr',
-    'img',
-    'input',
-    'keygen',
-    'link',
-    'meta',
-    'param',
-    'source',
-    'track',
-    'wbr'
-  ]);
-
-  var plaintextParents = makeSet([
-    'style',
-    'script',
-    'xmp',
-    'iframe',
-    'noembed',
-    'noframes',
-    'plaintext',
-    'noscript'
-  ]);
-
-  function getOuterHTML(node, parentNode) {
-    switch (node.nodeType) {
-      case Node.ELEMENT_NODE:
-        var tagName = node.tagName.toLowerCase();
-        var s = '<' + tagName;
-        var attrs = node.attributes;
-        for (var i = 0, attr; attr = attrs[i]; i++) {
-          s += ' ' + attr.name + '="' + escapeAttr(attr.value) + '"';
-        }
-        s += '>';
-        if (voidElements[tagName])
-          return s;
-
-        return s + getInnerHTML(node) + '</' + tagName + '>';
-
-      case Node.TEXT_NODE:
-        var data = node.data;
-        if (parentNode && plaintextParents[parentNode.localName])
-          return data;
-        return escapeData(data);
-
-      case Node.COMMENT_NODE:
-        return '<!--' + node.data + '-->';
-
-      default:
-        console.error(node);
-        throw new Error('not implemented');
-    }
-  }
-
-  function getInnerHTML(node) {
-    var s = '';
-    for (var child = node.firstChild; child; child = child.nextSibling) {
-      s += getOuterHTML(child, node);
-    }
-    return s;
-  }
-
-  function setInnerHTML(node, value, opt_tagName) {
-    var tagName = opt_tagName || 'div';
-    node.textContent = '';
-    var tempElement = unwrap(node.ownerDocument.createElement(tagName));
-    tempElement.innerHTML = value;
-    var firstChild;
-    while (firstChild = tempElement.firstChild) {
-      node.appendChild(wrap(firstChild));
-    }
-  }
-
-  // IE11 does not have MSIE in the user agent string.
-  var oldIe = /MSIE/.test(navigator.userAgent);
-
-  var OriginalHTMLElement = window.HTMLElement;
-
-  function HTMLElement(node) {
-    Element.call(this, node);
-  }
-  HTMLElement.prototype = Object.create(Element.prototype);
-  mixin(HTMLElement.prototype, {
-    get innerHTML() {
-      // TODO(arv): This should fallback to this.impl.innerHTML if there
-      // are no shadow trees below or above the context node.
-      return getInnerHTML(this);
-    },
-    set innerHTML(value) {
-      // IE9 does not handle set innerHTML correctly on plaintextParents. It
-      // creates element children. For example
-      //
-      //   scriptElement.innerHTML = '<a>test</a>'
-      //
-      // Creates a single HTMLAnchorElement child.
-      if (oldIe && plaintextParents[this.localName]) {
-        this.textContent = value;
-        return;
-      }
-
-      var removedNodes = snapshotNodeList(this.childNodes);
-
-      if (this.invalidateShadowRenderer())
-        setInnerHTML(this, value, this.tagName);
-      else
-        this.impl.innerHTML = value;
-      var addedNodes = snapshotNodeList(this.childNodes);
-
-      enqueueMutation(this, 'childList', {
-        addedNodes: addedNodes,
-        removedNodes: removedNodes
-      });
-
-      nodesWereRemoved(removedNodes);
-      nodesWereAdded(addedNodes);
-    },
-
-    get outerHTML() {
-      return getOuterHTML(this, this.parentNode);
-    },
-    set outerHTML(value) {
-      var p = this.parentNode;
-      if (p) {
-        p.invalidateShadowRenderer();
-        var df = frag(p, value);
-        p.replaceChild(df, this);
-      }
-    },
-
-    insertAdjacentHTML: function(position, text) {
-      var contextElement, refNode;
-      switch (String(position).toLowerCase()) {
-        case 'beforebegin':
-          contextElement = this.parentNode;
-          refNode = this;
-          break;
-        case 'afterend':
-          contextElement = this.parentNode;
-          refNode = this.nextSibling;
-          break;
-        case 'afterbegin':
-          contextElement = this;
-          refNode = this.firstChild;
-          break;
-        case 'beforeend':
-          contextElement = this;
-          refNode = null;
-          break;
-        default:
-          return;
-      }
-
-      var df = frag(contextElement, text);
-      contextElement.insertBefore(df, refNode);
-    }
-  });
-
-  function frag(contextElement, html) {
-    // TODO(arv): This does not work with SVG and other non HTML elements.
-    var p = unwrap(contextElement.cloneNode(false));
-    p.innerHTML = html;
-    var df = unwrap(document.createDocumentFragment());
-    var c;
-    while (c = p.firstChild) {
-      df.appendChild(c);
-    }
-    return wrap(df);
-  }
-
-  function getter(name) {
-    return function() {
-      scope.renderAllPending();
-      return this.impl[name];
-    };
-  }
-
-  function getterRequiresRendering(name) {
-    defineGetter(HTMLElement, name, getter(name));
-  }
-
-  [
-    'clientHeight',
-    'clientLeft',
-    'clientTop',
-    'clientWidth',
-    'offsetHeight',
-    'offsetLeft',
-    'offsetTop',
-    'offsetWidth',
-    'scrollHeight',
-    'scrollWidth',
-  ].forEach(getterRequiresRendering);
-
-  function getterAndSetterRequiresRendering(name) {
-    Object.defineProperty(HTMLElement.prototype, name, {
-      get: getter(name),
-      set: function(v) {
-        scope.renderAllPending();
-        this.impl[name] = v;
-      },
-      configurable: true,
-      enumerable: true
-    });
-  }
-
-  [
-    'scrollLeft',
-    'scrollTop',
-  ].forEach(getterAndSetterRequiresRendering);
-
-  function methodRequiresRendering(name) {
-    Object.defineProperty(HTMLElement.prototype, name, {
-      value: function() {
-        scope.renderAllPending();
-        return this.impl[name].apply(this.impl, arguments);
-      },
-      configurable: true,
-      enumerable: true
-    });
-  }
-
-  [
-    'getBoundingClientRect',
-    'getClientRects',
-    'scrollIntoView'
-  ].forEach(methodRequiresRendering);
-
-  // HTMLElement is abstract so we use a subclass that has no members.
-  registerWrapper(OriginalHTMLElement, HTMLElement,
-                  document.createElement('b'));
-
-  scope.wrappers.HTMLElement = HTMLElement;
-
-  // TODO: Find a better way to share these two with WrapperShadowRoot.
-  scope.getInnerHTML = getInnerHTML;
-  scope.setInnerHTML = setInnerHTML
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var HTMLElement = scope.wrappers.HTMLElement;
-  var mixin = scope.mixin;
-  var registerWrapper = scope.registerWrapper;
-  var wrap = scope.wrap;
-
-  var OriginalHTMLCanvasElement = window.HTMLCanvasElement;
-
-  function HTMLCanvasElement(node) {
-    HTMLElement.call(this, node);
-  }
-  HTMLCanvasElement.prototype = Object.create(HTMLElement.prototype);
-
-  mixin(HTMLCanvasElement.prototype, {
-    getContext: function() {
-      var context = this.impl.getContext.apply(this.impl, arguments);
-      return context && wrap(context);
-    }
-  });
-
-  registerWrapper(OriginalHTMLCanvasElement, HTMLCanvasElement,
-                  document.createElement('canvas'));
-
-  scope.wrappers.HTMLCanvasElement = HTMLCanvasElement;
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var HTMLElement = scope.wrappers.HTMLElement;
-  var mixin = scope.mixin;
-  var registerWrapper = scope.registerWrapper;
-
-  var OriginalHTMLContentElement = window.HTMLContentElement;
-
-  function HTMLContentElement(node) {
-    HTMLElement.call(this, node);
-  }
-  HTMLContentElement.prototype = Object.create(HTMLElement.prototype);
-  mixin(HTMLContentElement.prototype, {
-    get select() {
-      return this.getAttribute('select');
-    },
-    set select(value) {
-      this.setAttribute('select', value);
-    },
-
-    setAttribute: function(n, v) {
-      HTMLElement.prototype.setAttribute.call(this, n, v);
-      if (String(n).toLowerCase() === 'select')
-        this.invalidateShadowRenderer(true);
-    }
-
-    // getDistributedNodes is added in ShadowRenderer
-
-    // TODO: attribute boolean resetStyleInheritance;
-  });
-
-  if (OriginalHTMLContentElement)
-    registerWrapper(OriginalHTMLContentElement, HTMLContentElement);
-
-  scope.wrappers.HTMLContentElement = HTMLContentElement;
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var HTMLElement = scope.wrappers.HTMLElement;
-  var registerWrapper = scope.registerWrapper;
-  var unwrap = scope.unwrap;
-  var rewrap = scope.rewrap;
-
-  var OriginalHTMLImageElement = window.HTMLImageElement;
-
-  function HTMLImageElement(node) {
-    HTMLElement.call(this, node);
-  }
-  HTMLImageElement.prototype = Object.create(HTMLElement.prototype);
-
-  registerWrapper(OriginalHTMLImageElement, HTMLImageElement,
-                  document.createElement('img'));
-
-  function Image(width, height) {
-    if (!(this instanceof Image)) {
-      throw new TypeError(
-          'DOM object constructor cannot be called as a function.');
-    }
-
-    var node = unwrap(document.createElement('img'));
-    HTMLElement.call(this, node);
-    rewrap(node, this);
-
-    if (width !== undefined)
-      node.width = width;
-    if (height !== undefined)
-      node.height = height;
-  }
-
-  Image.prototype = HTMLImageElement.prototype;
-
-  scope.wrappers.HTMLImageElement = HTMLImageElement;
-  scope.wrappers.Image = Image;
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var HTMLElement = scope.wrappers.HTMLElement;
-  var mixin = scope.mixin;
-  var registerWrapper = scope.registerWrapper;
-
-  var OriginalHTMLShadowElement = window.HTMLShadowElement;
-
-  function HTMLShadowElement(node) {
-    HTMLElement.call(this, node);
-  }
-  HTMLShadowElement.prototype = Object.create(HTMLElement.prototype);
-  mixin(HTMLShadowElement.prototype, {
-    // TODO: attribute boolean resetStyleInheritance;
-  });
-
-  if (OriginalHTMLShadowElement)
-    registerWrapper(OriginalHTMLShadowElement, HTMLShadowElement);
-
-  scope.wrappers.HTMLShadowElement = HTMLShadowElement;
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var HTMLElement = scope.wrappers.HTMLElement;
-  var getInnerHTML = scope.getInnerHTML;
-  var mixin = scope.mixin;
-  var registerWrapper = scope.registerWrapper;
-  var setInnerHTML = scope.setInnerHTML;
-  var unwrap = scope.unwrap;
-  var wrap = scope.wrap;
-
-  var contentTable = new WeakMap();
-  var templateContentsOwnerTable = new WeakMap();
-
-  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
-  function getTemplateContentsOwner(doc) {
-    if (!doc.defaultView)
-      return doc;
-    var d = templateContentsOwnerTable.get(doc);
-    if (!d) {
-      // TODO(arv): This should either be a Document or HTMLDocument depending
-      // on doc.
-      d = doc.implementation.createHTMLDocument('');
-      while (d.lastChild) {
-        d.removeChild(d.lastChild);
-      }
-      templateContentsOwnerTable.set(doc, d);
-    }
-    return d;
-  }
-
-  function extractContent(templateElement) {
-    // templateElement is not a wrapper here.
-    var doc = getTemplateContentsOwner(templateElement.ownerDocument);
-    var df = unwrap(doc.createDocumentFragment());
-    var child;
-    while (child = templateElement.firstChild) {
-      df.appendChild(child);
-    }
-    return df;
-  }
-
-  var OriginalHTMLTemplateElement = window.HTMLTemplateElement;
-
-  function HTMLTemplateElement(node) {
-    HTMLElement.call(this, node);
-    if (!OriginalHTMLTemplateElement) {
-      var content = extractContent(node);
-      contentTable.set(this, wrap(content));
-    }
-  }
-  HTMLTemplateElement.prototype = Object.create(HTMLElement.prototype);
-
-  mixin(HTMLTemplateElement.prototype, {
-    get content() {
-      if (OriginalHTMLTemplateElement)
-        return wrap(this.impl.content);
-      return contentTable.get(this);
-    },
-
-    get innerHTML() {
-      return getInnerHTML(this.content);
-    },
-    set innerHTML(value) {
-      setInnerHTML(this.content, value);
-    }
-
-    // TODO(arv): cloneNode needs to clone content.
-
-  });
-
-  if (OriginalHTMLTemplateElement)
-    registerWrapper(OriginalHTMLTemplateElement, HTMLTemplateElement);
-
-  scope.wrappers.HTMLTemplateElement = HTMLTemplateElement;
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var HTMLElement = scope.wrappers.HTMLElement;
-  var registerWrapper = scope.registerWrapper;
-
-  var OriginalHTMLMediaElement = window.HTMLMediaElement;
-
-  function HTMLMediaElement(node) {
-    HTMLElement.call(this, node);
-  }
-  HTMLMediaElement.prototype = Object.create(HTMLElement.prototype);
-
-  registerWrapper(OriginalHTMLMediaElement, HTMLMediaElement,
-                  document.createElement('audio'));
-
-  scope.wrappers.HTMLMediaElement = HTMLMediaElement;
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var HTMLMediaElement = scope.wrappers.HTMLMediaElement;
-  var registerWrapper = scope.registerWrapper;
-  var unwrap = scope.unwrap;
-  var rewrap = scope.rewrap;
-
-  var OriginalHTMLAudioElement = window.HTMLAudioElement;
-
-  function HTMLAudioElement(node) {
-    HTMLMediaElement.call(this, node);
-  }
-  HTMLAudioElement.prototype = Object.create(HTMLMediaElement.prototype);
-
-  registerWrapper(OriginalHTMLAudioElement, HTMLAudioElement,
-                  document.createElement('audio'));
-
-  function Audio(src) {
-    if (!(this instanceof Audio)) {
-      throw new TypeError(
-          'DOM object constructor cannot be called as a function.');
-    }
-
-    var node = unwrap(document.createElement('audio'));
-    HTMLMediaElement.call(this, node);
-    rewrap(node, this);
-
-    node.setAttribute('preload', 'auto');
-    if (src !== undefined)
-      node.setAttribute('src', src);
-  }
-
-  Audio.prototype = HTMLAudioElement.prototype;
-
-  scope.wrappers.HTMLAudioElement = HTMLAudioElement;
-  scope.wrappers.Audio = Audio;
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var HTMLElement = scope.wrappers.HTMLElement;
-  var mixin = scope.mixin;
-  var registerWrapper = scope.registerWrapper;
-  var rewrap = scope.rewrap;
-  var unwrap = scope.unwrap;
-  var wrap = scope.wrap;
-
-  var OriginalHTMLOptionElement = window.HTMLOptionElement;
-
-  function trimText(s) {
-    return s.replace(/\s+/g, ' ').trim();
-  }
-
-  function HTMLOptionElement(node) {
-    HTMLElement.call(this, node);
-  }
-  HTMLOptionElement.prototype = Object.create(HTMLElement.prototype);
-  mixin(HTMLOptionElement.prototype, {
-    get text() {
-      return trimText(this.textContent);
-    },
-    set text(value) {
-      this.textContent = trimText(String(value));
-    },
-    get form() {
-      return wrap(unwrap(this).form);
-    }
-  });
-
-  registerWrapper(OriginalHTMLOptionElement, HTMLOptionElement,
-                  document.createElement('option'));
-
-  function Option(text, value, defaultSelected, selected) {
-    if (!(this instanceof Option)) {
-      throw new TypeError(
-          'DOM object constructor cannot be called as a function.');
-    }
-
-    var node = unwrap(document.createElement('option'));
-    HTMLElement.call(this, node);
-    rewrap(node, this);
-
-    if (text !== undefined)
-      node.text = text;
-    if (value !== undefined)
-      node.setAttribute('value', value);
-    if (defaultSelected === true)
-      node.setAttribute('selected', '');
-    node.selected = selected === true;
-  }
-
-  Option.prototype = HTMLOptionElement.prototype;
-
-  scope.wrappers.HTMLOptionElement = HTMLOptionElement;
-  scope.wrappers.Option = Option;
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var HTMLContentElement = scope.wrappers.HTMLContentElement;
-  var HTMLElement = scope.wrappers.HTMLElement;
-  var HTMLShadowElement = scope.wrappers.HTMLShadowElement;
-  var HTMLTemplateElement = scope.wrappers.HTMLTemplateElement;
-  var mixin = scope.mixin;
-  var registerWrapper = scope.registerWrapper;
-
-  var OriginalHTMLUnknownElement = window.HTMLUnknownElement;
-
-  function HTMLUnknownElement(node) {
-    switch (node.localName) {
-      case 'content':
-        return new HTMLContentElement(node);
-      case 'shadow':
-        return new HTMLShadowElement(node);
-      case 'template':
-        return new HTMLTemplateElement(node);
-    }
-    HTMLElement.call(this, node);
-  }
-  HTMLUnknownElement.prototype = Object.create(HTMLElement.prototype);
-  registerWrapper(OriginalHTMLUnknownElement, HTMLUnknownElement);
-  scope.wrappers.HTMLUnknownElement = HTMLUnknownElement;
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2014 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var registerObject = scope.registerObject;
-
-  var SVG_NS = 'http://www.w3.org/2000/svg';
-  var svgTitleElement = document.createElementNS(SVG_NS, 'title');
-  var SVGTitleElement = registerObject(svgTitleElement);
-  var SVGElement = Object.getPrototypeOf(SVGTitleElement.prototype).constructor;
-
-  scope.wrappers.SVGElement = SVGElement;
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2014 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var mixin = scope.mixin;
-  var registerWrapper = scope.registerWrapper;
-  var unwrap = scope.unwrap;
-  var wrap = scope.wrap;
-
-  var OriginalSVGUseElement = window.SVGUseElement;
-
-  // IE uses SVGElement as parent interface, SVG2 (Blink & Gecko) uses
-  // SVGGraphicsElement. Use the <g> element to get the right prototype.
-
-  var SVG_NS = 'http://www.w3.org/2000/svg';
-  var gWrapper = wrap(document.createElementNS(SVG_NS, 'g'));
-  var useElement = document.createElementNS(SVG_NS, 'use');
-  var SVGGElement = gWrapper.constructor;
-  var parentInterfacePrototype = Object.getPrototypeOf(SVGGElement.prototype);
-  var parentInterface = parentInterfacePrototype.constructor;
-
-  function SVGUseElement(impl) {
-    parentInterface.call(this, impl);
-  }
-
-  SVGUseElement.prototype = Object.create(parentInterfacePrototype);
-
-  // Firefox does not expose instanceRoot.
-  if ('instanceRoot' in useElement) {
-    mixin(SVGUseElement.prototype, {
-      get instanceRoot() {
-        return wrap(unwrap(this).instanceRoot);
-      },
-      get animatedInstanceRoot() {
-        return wrap(unwrap(this).animatedInstanceRoot);
-      },
-    });
-  }
-
-  registerWrapper(OriginalSVGUseElement, SVGUseElement, useElement);
-
-  scope.wrappers.SVGUseElement = SVGUseElement;
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2014 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var EventTarget = scope.wrappers.EventTarget;
-  var mixin = scope.mixin;
-  var registerWrapper = scope.registerWrapper;
-  var wrap = scope.wrap;
-
-  var OriginalSVGElementInstance = window.SVGElementInstance;
-  if (!OriginalSVGElementInstance)
-    return;
-
-  function SVGElementInstance(impl) {
-    EventTarget.call(this, impl);
-  }
-
-  SVGElementInstance.prototype = Object.create(EventTarget.prototype);
-  mixin(SVGElementInstance.prototype, {
-    /** @type {SVGElement} */
-    get correspondingElement() {
-      return wrap(this.impl.correspondingElement);
-    },
-
-    /** @type {SVGUseElement} */
-    get correspondingUseElement() {
-      return wrap(this.impl.correspondingUseElement);
-    },
-
-    /** @type {SVGElementInstance} */
-    get parentNode() {
-      return wrap(this.impl.parentNode);
-    },
-
-    /** @type {SVGElementInstanceList} */
-    get childNodes() {
-      throw new Error('Not implemented');
-    },
-
-    /** @type {SVGElementInstance} */
-    get firstChild() {
-      return wrap(this.impl.firstChild);
-    },
-
-    /** @type {SVGElementInstance} */
-    get lastChild() {
-      return wrap(this.impl.lastChild);
-    },
-
-    /** @type {SVGElementInstance} */
-    get previousSibling() {
-      return wrap(this.impl.previousSibling);
-    },
-
-    /** @type {SVGElementInstance} */
-    get nextSibling() {
-      return wrap(this.impl.nextSibling);
-    }
-  });
-
-  registerWrapper(OriginalSVGElementInstance, SVGElementInstance);
-
-  scope.wrappers.SVGElementInstance = SVGElementInstance;
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var mixin = scope.mixin;
-  var registerWrapper = scope.registerWrapper;
-  var unwrap = scope.unwrap;
-  var unwrapIfNeeded = scope.unwrapIfNeeded;
-  var wrap = scope.wrap;
-
-  var OriginalCanvasRenderingContext2D = window.CanvasRenderingContext2D;
-
-  function CanvasRenderingContext2D(impl) {
-    this.impl = impl;
-  }
-
-  mixin(CanvasRenderingContext2D.prototype, {
-    get canvas() {
-      return wrap(this.impl.canvas);
-    },
-
-    drawImage: function() {
-      arguments[0] = unwrapIfNeeded(arguments[0]);
-      this.impl.drawImage.apply(this.impl, arguments);
-    },
-
-    createPattern: function() {
-      arguments[0] = unwrap(arguments[0]);
-      return this.impl.createPattern.apply(this.impl, arguments);
-    }
-  });
-
-  registerWrapper(OriginalCanvasRenderingContext2D, CanvasRenderingContext2D,
-                  document.createElement('canvas').getContext('2d'));
-
-  scope.wrappers.CanvasRenderingContext2D = CanvasRenderingContext2D;
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var mixin = scope.mixin;
-  var registerWrapper = scope.registerWrapper;
-  var unwrapIfNeeded = scope.unwrapIfNeeded;
-  var wrap = scope.wrap;
-
-  var OriginalWebGLRenderingContext = window.WebGLRenderingContext;
-
-  // IE10 does not have WebGL.
-  if (!OriginalWebGLRenderingContext)
-    return;
-
-  function WebGLRenderingContext(impl) {
-    this.impl = impl;
-  }
-
-  mixin(WebGLRenderingContext.prototype, {
-    get canvas() {
-      return wrap(this.impl.canvas);
-    },
-
-    texImage2D: function() {
-      arguments[5] = unwrapIfNeeded(arguments[5]);
-      this.impl.texImage2D.apply(this.impl, arguments);
-    },
-
-    texSubImage2D: function() {
-      arguments[6] = unwrapIfNeeded(arguments[6]);
-      this.impl.texSubImage2D.apply(this.impl, arguments);
-    }
-  });
-
-  // Blink/WebKit has broken DOM bindings. Usually we would create an instance
-  // of the object and pass it into registerWrapper as a "blueprint" but
-  // creating WebGL contexts is expensive and might fail so we use a dummy
-  // object with dummy instance properties for these broken browsers.
-  var instanceProperties = /WebKit/.test(navigator.userAgent) ?
-      {drawingBufferHeight: null, drawingBufferWidth: null} : {};
-
-  registerWrapper(OriginalWebGLRenderingContext, WebGLRenderingContext,
-      instanceProperties);
-
-  scope.wrappers.WebGLRenderingContext = WebGLRenderingContext;
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var registerWrapper = scope.registerWrapper;
-  var unwrap = scope.unwrap;
-  var unwrapIfNeeded = scope.unwrapIfNeeded;
-  var wrap = scope.wrap;
-
-  var OriginalRange = window.Range;
-
-  function Range(impl) {
-    this.impl = impl;
-  }
-  Range.prototype = {
-    get startContainer() {
-      return wrap(this.impl.startContainer);
-    },
-    get endContainer() {
-      return wrap(this.impl.endContainer);
-    },
-    get commonAncestorContainer() {
-      return wrap(this.impl.commonAncestorContainer);
-    },
-    setStart: function(refNode,offset) {
-      this.impl.setStart(unwrapIfNeeded(refNode), offset);
-    },
-    setEnd: function(refNode,offset) {
-      this.impl.setEnd(unwrapIfNeeded(refNode), offset);
-    },
-    setStartBefore: function(refNode) {
-      this.impl.setStartBefore(unwrapIfNeeded(refNode));
-    },
-    setStartAfter: function(refNode) {
-      this.impl.setStartAfter(unwrapIfNeeded(refNode));
-    },
-    setEndBefore: function(refNode) {
-      this.impl.setEndBefore(unwrapIfNeeded(refNode));
-    },
-    setEndAfter: function(refNode) {
-      this.impl.setEndAfter(unwrapIfNeeded(refNode));
-    },
-    selectNode: function(refNode) {
-      this.impl.selectNode(unwrapIfNeeded(refNode));
-    },
-    selectNodeContents: function(refNode) {
-      this.impl.selectNodeContents(unwrapIfNeeded(refNode));
-    },
-    compareBoundaryPoints: function(how, sourceRange) {
-      return this.impl.compareBoundaryPoints(how, unwrap(sourceRange));
-    },
-    extractContents: function() {
-      return wrap(this.impl.extractContents());
-    },
-    cloneContents: function() {
-      return wrap(this.impl.cloneContents());
-    },
-    insertNode: function(node) {
-      this.impl.insertNode(unwrapIfNeeded(node));
-    },
-    surroundContents: function(newParent) {
-      this.impl.surroundContents(unwrapIfNeeded(newParent));
-    },
-    cloneRange: function() {
-      return wrap(this.impl.cloneRange());
-    },
-    isPointInRange: function(node, offset) {
-      return this.impl.isPointInRange(unwrapIfNeeded(node), offset);
-    },
-    comparePoint: function(node, offset) {
-      return this.impl.comparePoint(unwrapIfNeeded(node), offset);
-    },
-    intersectsNode: function(node) {
-      return this.impl.intersectsNode(unwrapIfNeeded(node));
-    },
-    toString: function() {
-      return this.impl.toString();
-    }
-  };
-
-  // IE9 does not have createContextualFragment.
-  if (OriginalRange.prototype.createContextualFragment) {
-    Range.prototype.createContextualFragment = function(html) {
-      return wrap(this.impl.createContextualFragment(html));
-    };
-  }
-
-  registerWrapper(window.Range, Range, document.createRange());
-
-  scope.wrappers.Range = Range;
-
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var GetElementsByInterface = scope.GetElementsByInterface;
-  var ParentNodeInterface = scope.ParentNodeInterface;
-  var SelectorsInterface = scope.SelectorsInterface;
-  var mixin = scope.mixin;
-  var registerObject = scope.registerObject;
-
-  var DocumentFragment = registerObject(document.createDocumentFragment());
-  mixin(DocumentFragment.prototype, ParentNodeInterface);
-  mixin(DocumentFragment.prototype, SelectorsInterface);
-  mixin(DocumentFragment.prototype, GetElementsByInterface);
-
-  var Comment = registerObject(document.createComment(''));
-
-  scope.wrappers.Comment = Comment;
-  scope.wrappers.DocumentFragment = DocumentFragment;
-
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var DocumentFragment = scope.wrappers.DocumentFragment;
-  var elementFromPoint = scope.elementFromPoint;
-  var getInnerHTML = scope.getInnerHTML;
-  var mixin = scope.mixin;
-  var rewrap = scope.rewrap;
-  var setInnerHTML = scope.setInnerHTML;
-  var unwrap = scope.unwrap;
-
-  var shadowHostTable = new WeakMap();
-  var nextOlderShadowTreeTable = new WeakMap();
-
-  var spaceCharRe = /[ \t\n\r\f]/;
-
-  function ShadowRoot(hostWrapper) {
-    var node = unwrap(hostWrapper.impl.ownerDocument.createDocumentFragment());
-    DocumentFragment.call(this, node);
-
-    // createDocumentFragment associates the node with a wrapper
-    // DocumentFragment instance. Override that.
-    rewrap(node, this);
-
-    var oldShadowRoot = hostWrapper.shadowRoot;
-    nextOlderShadowTreeTable.set(this, oldShadowRoot);
-
-    shadowHostTable.set(this, hostWrapper);
-  }
-  ShadowRoot.prototype = Object.create(DocumentFragment.prototype);
-  mixin(ShadowRoot.prototype, {
-    get innerHTML() {
-      return getInnerHTML(this);
-    },
-    set innerHTML(value) {
-      setInnerHTML(this, value);
-      this.invalidateShadowRenderer();
-    },
-
-    get olderShadowRoot() {
-      return nextOlderShadowTreeTable.get(this) || null;
-    },
-
-    get host() {
-      return shadowHostTable.get(this) || null;
-    },
-
-    invalidateShadowRenderer: function() {
-      return shadowHostTable.get(this).invalidateShadowRenderer();
-    },
-
-    elementFromPoint: function(x, y) {
-      return elementFromPoint(this, this.ownerDocument, x, y);
-    },
-
-    getElementById: function(id) {
-      if (spaceCharRe.test(id))
-        return null;
-      return this.querySelector('[id="' + id + '"]');
-    }
-  });
-
-  scope.wrappers.ShadowRoot = ShadowRoot;
-
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. 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) {
-  'use strict';
-
-  var Element = scope.wrappers.Element;
-  var HTMLContentElement = scope.wrappers.HTMLContentElement;
-  var HTMLShadowElement = scope.wrappers.HTMLShadowElement;
-  var Node = scope.wrappers.Node;
-  var ShadowRoot = scope.wrappers.ShadowRoot;
-  var assert = scope.assert;
-  var mixin = scope.mixin;
-  var oneOf = scope.oneOf;
-  var unwrap = scope.unwrap;
-  var wrap = scope.wrap;
-
-  /**
-   * Updates the fields of a wrapper to a snapshot of the logical DOM as needed.
-   * Up means parentNode
-   * Sideways means previous and next sibling.
-   * @param {!Node} wrapper
-   */
-  function updateWrapperUpAndSideways(wrapper) {
-    wrapper.previousSibling_ = wrapper.previousSibling;
-    wrapper.nextSibling_ = wrapper.nextSibling;
-    wrapper.parentNode_ = wrapper.parentNode;
-  }
-
-  /**
-   * Updates the fields of a wrapper to a snapshot of the logical DOM as needed.
-   * Down means first and last child
-   * @param {!Node} wrapper
-   */
-  function updateWrapperDown(wrapper) {
-    wrapper.firstChild_ = wrapper.firstChild;
-    wrapper.lastChild_ = wrapper.lastChild;
-  }
-
-  function updateAllChildNodes(parentNodeWrapper) {
-    assert(parentNodeWrapper instanceof Node);
-    for (var childWrapper = parentNodeWrapper.firstChild;
-         childWrapper;
-         childWrapper = childWrapper.nextSibling) {
-      updateWrapperUpAndSideways(childWrapper);
-    }
-    updateWrapperDown(parentNodeWrapper);
-  }
-
-  function insertBefore(parentNodeWrapper, newChildWrapper, refChildWrapper) {
-    var parentNode = unwrap(parentNodeWrapper);
-    var newChild = unwrap(newChildWrapper);
-    var refChild = refChildWrapper ? unwrap(refChildWrapper) : null;
-
-    remove(newChildWrapper);
-    updateWrapperUpAndSideways(newChildWrapper);
-
-    if (!refChildWrapper) {
-      parentNodeWrapper.lastChild_ = parentNodeWrapper.lastChild;
-      if (parentNodeWrapper.lastChild === parentNodeWrapper.firstChild)
-        parentNodeWrapper.firstChild_ = parentNodeWrapper.firstChild;
-
-      var lastChildWrapper = wrap(parentNode.lastChild);
-      if (lastChildWrapper)
-        lastChildWrapper.nextSibling_ = lastChildWrapper.nextSibling;
-    } else {
-      if (parentNodeWrapper.firstChild === refChildWrapper)
-        parentNodeWrapper.firstChild_ = refChildWrapper;
-
-      refChildWrapper.previousSibling_ = refChildWrapper.previousSibling;
-    }
-
-    parentNode.insertBefore(newChild, refChild);
-  }
-
-  function remove(nodeWrapper) {
-    var node = unwrap(nodeWrapper)
-    var parentNode = node.parentNode;
-    if (!parentNode)
-      return;
-
-    var parentNodeWrapper = wrap(parentNode);
-    updateWrapperUpAndSideways(nodeWrapper);
-
-    if (nodeWrapper.previousSibling)
-      nodeWrapper.previousSibling.nextSibling_ = nodeWrapper;
-    if (nodeWrapper.nextSibling)
-      nodeWrapper.nextSibling.previousSibling_ = nodeWrapper;
-
-    if (parentNodeWrapper.lastChild === nodeWrapper)
-      parentNodeWrapper.lastChild_ = nodeWrapper;
-    if (parentNodeWrapper.firstChild === nodeWrapper)
-      parentNodeWrapper.firstChild_ = nodeWrapper;
-
-    parentNode.removeChild(node);
-  }
-
-  var distributedChildNodesTable = new WeakMap();
-  var eventParentsTable = new WeakMap();
-  var insertionParentTable = new WeakMap();
-  var rendererForHostTable = new WeakMap();
-
-  function distributeChildToInsertionPoint(child, insertionPoint) {
-    getDistributedChildNodes(insertionPoint).push(child);
-    assignToInsertionPoint(child, insertionPoint);
-
-    var eventParents = eventParentsTable.get(child);
-    if (!eventParents)
-      eventParentsTable.set(child, eventParents = []);
-    eventParents.push(insertionPoint);
-  }
-
-  function resetDistributedChildNodes(insertionPoint) {
-    distributedChildNodesTable.set(insertionPoint, []);
-  }
-
-  function getDistributedChildNodes(insertionPoint) {
-    return distributedChildNodesTable.get(insertionPoint);
-  }
-
-  function getChildNodesSnapshot(node) {
-    var result = [], i = 0;
-    for (var child = node.firstChild; child; child = child.nextSibling) {
-      result[i++] = child;
-    }
-    return result;
-  }
-
-  /**
-   * Visits all nodes in the tree that fulfils the |predicate|. If the |visitor|
-   * function returns |false| the traversal is aborted.
-   * @param {!Node} tree
-   * @param {function(!Node) : boolean} predicate
-   * @param {function(!Node) : *} visitor
-   */
-  function visit(tree, predicate, visitor) {
-    // This operates on logical DOM.
-    for (var node = tree.firstChild; node; node = node.nextSibling) {
-      if (predicate(node)) {
-        if (visitor(node) === false)
-          return;
-      } else {
-        visit(node, predicate, visitor);
-      }
-    }
-  }
-
-  // Matching Insertion Points
-  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#matching-insertion-points
-
-  // TODO(arv): Verify this... I don't remember why I picked this regexp.
-  var selectorMatchRegExp = /^[*.:#[a-zA-Z_|]/;
-
-  var allowedPseudoRegExp = 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('|') + ')');
-
-
-  /**
-   * @param {Element} node
-   * @oaram {Element} point The insertion point element.
-   * @return {boolean} Whether the node matches the insertion point.
-   */
-  function matchesCriteria(node, point) {
-    var select = point.getAttribute('select');
-    if (!select)
-      return true;
-
-    // Here we know the select attribute is a non empty string.
-    select = select.trim();
-    if (!select)
-      return true;
-
-    if (!(node instanceof Element))
-      return false;
-
-    // The native matches function in IE9 does not correctly work with elements
-    // that are not in the document.
-    // TODO(arv): Implement matching in JS.
-    // https://github.com/Polymer/ShadowDOM/issues/361
-    if (select === '*' || select === node.localName)
-      return true;
-
-    // TODO(arv): This does not seem right. Need to check for a simple selector.
-    if (!selectorMatchRegExp.test(select))
-      return false;
-
-    // TODO(arv): This no longer matches the spec.
-    if (select[0] === ':' && !allowedPseudoRegExp.test(select))
-      return false;
-
-    try {
-      return node.matches(select);
-    } catch (ex) {
-      // Invalid selector.
-      return false;
-    }
-  }
-
-  var request = oneOf(window, [
-    'requestAnimationFrame',
-    'mozRequestAnimationFrame',
-    'webkitRequestAnimationFrame',
-    'setTimeout'
-  ]);
-
-  var pendingDirtyRenderers = [];
-  var renderTimer;
-
-  function renderAllPending() {
-    for (var i = 0; i < pendingDirtyRenderers.length; i++) {
-      pendingDirtyRenderers[i].render();
-    }
-    pendingDirtyRenderers = [];
-  }
-
-  function handleRequestAnimationFrame() {
-    renderTimer = null;
-    renderAllPending();
-  }
-
-  /**
-   * Returns existing shadow renderer for a host or creates it if it is needed.
-   * @params {!Element} host
-   * @return {!ShadowRenderer}
-   */
-  function getRendererForHost(host) {
-    var renderer = rendererForHostTable.get(host);
-    if (!renderer) {
-      renderer = new ShadowRenderer(host);
-      rendererForHostTable.set(host, renderer);
-    }
-    return renderer;
-  }
-
-  function getShadowRootAncestor(node) {
-    for (; node; node = node.parentNode) {
-      if (node instanceof ShadowRoot)
-        return node;
-    }
-    return null;
-  }
-
-  function getRendererForShadowRoot(shadowRoot) {
-    return getRendererForHost(shadowRoot.host);
-  }
-
-  var spliceDiff = new ArraySplice();
-  spliceDiff.equals = function(renderNode, rawNode) {
-    return unwrap(renderNode.node) === rawNode;
-  };
-
-  /**
-   * RenderNode is used as an in memory "render tree". When we render the
-   * composed tree we create a tree of RenderNodes, then we diff this against
-   * the real DOM tree and make minimal changes as needed.
-   */
-  function RenderNode(node) {
-    this.skip = false;
-    this.node = node;
-    this.childNodes = [];
-  }
-
-  RenderNode.prototype = {
-    append: function(node) {
-      var rv = new RenderNode(node);
-      this.childNodes.push(rv);
-      return rv;
-    },
-
-    sync: function(opt_added) {
-      if (this.skip)
-        return;
-
-      var nodeWrapper = this.node;
-      // plain array of RenderNodes
-      var newChildren = this.childNodes;
-      // plain array of real nodes.
-      var oldChildren = getChildNodesSnapshot(unwrap(nodeWrapper));
-      var added = opt_added || new WeakMap();
-
-      var splices = spliceDiff.calculateSplices(newChildren, oldChildren);
-
-      var newIndex = 0, oldIndex = 0;
-      var lastIndex = 0;
-      for (var i = 0; i < splices.length; i++) {
-        var splice = splices[i];
-        for (; lastIndex < splice.index; lastIndex++) {
-          oldIndex++;
-          newChildren[newIndex++].sync(added);
-        }
-
-        var removedCount = splice.removed.length;
-        for (var j = 0; j < removedCount; j++) {
-          var wrapper = wrap(oldChildren[oldIndex++]);
-          if (!added.get(wrapper))
-            remove(wrapper);
-        }
-
-        var addedCount = splice.addedCount;
-        var refNode = oldChildren[oldIndex] && wrap(oldChildren[oldIndex]);
-        for (var j = 0; j < addedCount; j++) {
-          var newChildRenderNode = newChildren[newIndex++];
-          var newChildWrapper = newChildRenderNode.node;
-          insertBefore(nodeWrapper, newChildWrapper, refNode);
-
-          // Keep track of added so that we do not remove the node after it
-          // has been added.
-          added.set(newChildWrapper, true);
-
-          newChildRenderNode.sync(added);
-        }
-
-        lastIndex += addedCount;
-      }
-
-      for (var i = lastIndex; i < newChildren.length; i++) {
-        newChildren[i].sync(added);
-      }
-    }
-  };
-
-  function ShadowRenderer(host) {
-    this.host = host;
-    this.dirty = false;
-    this.invalidateAttributes();
-    this.associateNode(host);
-  }
-
-  ShadowRenderer.prototype = {
-
-    // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#rendering-shadow-trees
-    render: function(opt_renderNode) {
-      if (!this.dirty)
-        return;
-
-      this.invalidateAttributes();
-      this.treeComposition();
-
-      var host = this.host;
-      var shadowRoot = host.shadowRoot;
-
-      this.associateNode(host);
-      var topMostRenderer = !renderNode;
-      var renderNode = opt_renderNode || new RenderNode(host);
-
-      for (var node = shadowRoot.firstChild; node; node = node.nextSibling) {
-        this.renderNode(shadowRoot, renderNode, node, false);
-      }
-
-      if (topMostRenderer)
-        renderNode.sync();
-
-      this.dirty = false;
-    },
-
-    invalidate: function() {
-      if (!this.dirty) {
-        this.dirty = true;
-        pendingDirtyRenderers.push(this);
-        if (renderTimer)
-          return;
-        renderTimer = window[request](handleRequestAnimationFrame, 0);
-      }
-    },
-
-    renderNode: function(shadowRoot, renderNode, node, isNested) {
-      if (isShadowHost(node)) {
-        renderNode = renderNode.append(node);
-        var renderer = getRendererForHost(node);
-        renderer.dirty = true;  // Need to rerender due to reprojection.
-        renderer.render(renderNode);
-      } else if (isInsertionPoint(node)) {
-        this.renderInsertionPoint(shadowRoot, renderNode, node, isNested);
-      } else if (isShadowInsertionPoint(node)) {
-        this.renderShadowInsertionPoint(shadowRoot, renderNode, node);
-      } else {
-        this.renderAsAnyDomTree(shadowRoot, renderNode, node, isNested);
-      }
-    },
-
-    renderAsAnyDomTree: function(shadowRoot, renderNode, node, isNested) {
-      renderNode = renderNode.append(node);
-
-      if (isShadowHost(node)) {
-        var renderer = getRendererForHost(node);
-        renderNode.skip = !renderer.dirty;
-        renderer.render(renderNode);
-      } else {
-        for (var child = node.firstChild; child; child = child.nextSibling) {
-          this.renderNode(shadowRoot, renderNode, child, isNested);
-        }
-      }
-    },
-
-    renderInsertionPoint: function(shadowRoot, renderNode, insertionPoint,
-                                   isNested) {
-      var distributedChildNodes = getDistributedChildNodes(insertionPoint);
-      if (distributedChildNodes.length) {
-        this.associateNode(insertionPoint);
-
-        for (var i = 0; i < distributedChildNodes.length; i++) {
-          var child = distributedChildNodes[i];
-          if (isInsertionPoint(child) && isNested)
-            this.renderInsertionPoint(shadowRoot, renderNode, child, isNested);
-          else
-            this.renderAsAnyDomTree(shadowRoot, renderNode, child, isNested);
-        }
-      } else {
-        this.renderFallbackContent(shadowRoot, renderNode, insertionPoint);
-      }
-      this.associateNode(insertionPoint.parentNode);
-    },
-
-    renderShadowInsertionPoint: function(shadowRoot, renderNode,
-                                         shadowInsertionPoint) {
-      var nextOlderTree = shadowRoot.olderShadowRoot;
-      if (nextOlderTree) {
-        assignToInsertionPoint(nextOlderTree, shadowInsertionPoint);
-        this.associateNode(shadowInsertionPoint.parentNode);
-        for (var node = nextOlderTree.firstChild;
-             node;
-             node = node.nextSibling) {
-          this.renderNode(nextOlderTree, renderNode, node, true);
-        }
-      } else {
-        this.renderFallbackContent(shadowRoot, renderNode,
-                                   shadowInsertionPoint);
-      }
-    },
-
-    renderFallbackContent: function(shadowRoot, renderNode, fallbackHost) {
-      this.associateNode(fallbackHost);
-      this.associateNode(fallbackHost.parentNode);
-      for (var node = fallbackHost.firstChild; node; node = node.nextSibling) {
-        this.renderAsAnyDomTree(shadowRoot, renderNode, node, false);
-      }
-    },
-
-    /**
-     * Invalidates the attributes used to keep track of which attributes may
-     * cause the renderer to be invalidated.
-     */
-    invalidateAttributes: function() {
-      this.attributes = Object.create(null);
-    },
-
-    /**
-     * Parses the selector and makes this renderer dependent on the attribute
-     * being used in the selector.
-     * @param {string} selector
-     */
-    updateDependentAttributes: function(selector) {
-      if (!selector)
-        return;
-
-      var attributes = this.attributes;
-
-      // .class
-      if (/\.\w+/.test(selector))
-        attributes['class'] = true;
-
-      // #id
-      if (/#\w+/.test(selector))
-        attributes['id'] = true;
-
-      selector.replace(/\[\s*([^\s=\|~\]]+)/g, function(_, name) {
-        attributes[name] = true;
-      });
-
-      // Pseudo selectors have been removed from the spec.
-    },
-
-    dependsOnAttribute: function(name) {
-      return this.attributes[name];
-    },
-
-    // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-distribution-algorithm
-    distribute: function(tree, pool) {
-      var self = this;
-
-      visit(tree, isActiveInsertionPoint,
-          function(insertionPoint) {
-            resetDistributedChildNodes(insertionPoint);
-            self.updateDependentAttributes(
-                insertionPoint.getAttribute('select'));
-
-            for (var i = 0; i < pool.length; i++) {  // 1.2
-              var node = pool[i];  // 1.2.1
-              if (node === undefined)  // removed
-                continue;
-              if (matchesCriteria(node, insertionPoint)) {  // 1.2.2
-                distributeChildToInsertionPoint(node, insertionPoint);  // 1.2.2.1
-                pool[i] = undefined;  // 1.2.2.2
-              }
-            }
-          });
-    },
-
-    // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-tree-composition
-    treeComposition: function () {
-      var shadowHost = this.host;
-      var tree = shadowHost.shadowRoot;  // 1.
-      var pool = [];  // 2.
-
-      for (var child = shadowHost.firstChild;
-           child;
-           child = child.nextSibling) {  // 3.
-        if (isInsertionPoint(child)) {  // 3.2.
-          var reprojected = getDistributedChildNodes(child);  // 3.2.1.
-          // if reprojected is undef... reset it?
-          if (!reprojected || !reprojected.length)  // 3.2.2.
-            reprojected = getChildNodesSnapshot(child);
-          pool.push.apply(pool, reprojected);  // 3.2.3.
-        } else {
-          pool.push(child); // 3.3.
-        }
-      }
-
-      var shadowInsertionPoint, point;
-      while (tree) {  // 4.
-        // 4.1.
-        shadowInsertionPoint = undefined;  // Reset every iteration.
-        visit(tree, isActiveShadowInsertionPoint, function(point) {
-          shadowInsertionPoint = point;
-          return false;
-        });
-        point = shadowInsertionPoint;
-
-        this.distribute(tree, pool);  // 4.2.
-        if (point) {  // 4.3.
-          var nextOlderTree = tree.olderShadowRoot;  // 4.3.1.
-          if (!nextOlderTree) {
-            break;  // 4.3.1.1.
-          } else {
-            tree = nextOlderTree;  // 4.3.2.2.
-            assignToInsertionPoint(tree, point);  // 4.3.2.2.
-            continue;  // 4.3.2.3.
-          }
-        } else {
-          break;  // 4.4.
-        }
-      }
-    },
-
-    associateNode: function(node) {
-      node.impl.polymerShadowRenderer_ = this;
-    }
-  };
-
-  function isInsertionPoint(node) {
-    // Should this include <shadow>?
-    return node instanceof HTMLContentElement;
-  }
-
-  function isActiveInsertionPoint(node) {
-    // <content> inside another <content> or <shadow> is considered inactive.
-    return node instanceof HTMLContentElement;
-  }
-
-  function isShadowInsertionPoint(node) {
-    return node instanceof HTMLShadowElement;
-  }
-
-  function isActiveShadowInsertionPoint(node) {
-    // <shadow> inside another <content> or <shadow> is considered inactive.
-    return node instanceof HTMLShadowElement;
-  }
-
-  function isShadowHost(shadowHost) {
-    return shadowHost.shadowRoot;
-  }
-
-  function getShadowTrees(host) {
-    var trees = [];
-
-    for (var tree = host.shadowRoot; tree; tree = tree.olderShadowRoot) {
-      trees.push(tree);
-    }
-    return trees;
-  }
-
-  function assignToInsertionPoint(tree, point) {
-    insertionParentTable.set(tree, point);
-  }
-
-  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#rendering-shadow-trees
-  function render(host) {
-    new ShadowRenderer(host).render();
-  };
-
-  // Need to rerender shadow host when:
-  //
-  // - a direct child to the ShadowRoot is added or removed
-  // - a direct child to the host is added or removed
-  // - a new shadow root is created
-  // - a direct child to a content/shadow element is added or removed
-  // - a sibling to a content/shadow element is added or removed
-  // - content[select] is changed
-  // - an attribute in a direct child to a host is modified
-
-  /**
-   * This gets called when a node was added or removed to it.
-   */
-  Node.prototype.invalidateShadowRenderer = function(force) {
-    var renderer = this.impl.polymerShadowRenderer_;
-    if (renderer) {
-      renderer.invalidate();
-      return true;
-    }
-
-    return false;
-  };
-
-  HTMLContentElement.prototype.getDistributedNodes = function() {
-    // TODO(arv): We should only rerender the dirty ancestor renderers (from
-    // the root and down).
-    renderAllPending();
-    return getDistributedChildNodes(this);
-  };
-
-  HTMLShadowElement.prototype.nodeIsInserted_ =
-  HTMLContentElement.prototype.nodeIsInserted_ = function() {
-    // Invalidate old renderer if any.
-    this.invalidateShadowRenderer();
-
-    var shadowRoot = getShadowRootAncestor(this);
-    var renderer;
-    if (shadowRoot)
-      renderer = getRendererForShadowRoot(shadowRoot);
-    this.impl.polymerShadowRenderer_ = renderer;
-    if (renderer)
-      renderer.invalidate();
-  };
-
-  scope.eventParentsTable = eventParentsTable;
-  scope.getRendererForHost = getRendererForHost;
-  scope.getShadowTrees = getShadowTrees;
-  scope.insertionParentTable = insertionParentTable;
-  scope.renderAllPending = renderAllPending;
-
-  // Exposed for testing
-  scope.visual = {
-    insertBefore: insertBefore,
-    remove: remove,
-  };
-
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var HTMLElement = scope.wrappers.HTMLElement;
-  var assert = scope.assert;
-  var mixin = scope.mixin;
-  var registerWrapper = scope.registerWrapper;
-  var unwrap = scope.unwrap;
-  var wrap = scope.wrap;
-
-  var elementsWithFormProperty = [
-    'HTMLButtonElement',
-    'HTMLFieldSetElement',
-    'HTMLInputElement',
-    'HTMLKeygenElement',
-    'HTMLLabelElement',
-    'HTMLLegendElement',
-    'HTMLObjectElement',
-    // HTMLOptionElement is handled in HTMLOptionElement.js
-    'HTMLOutputElement',
-    'HTMLSelectElement',
-    'HTMLTextAreaElement',
-  ];
-
-  function createWrapperConstructor(name) {
-    if (!window[name])
-      return;
-
-    // Ensure we are not overriding an already existing constructor.
-    assert(!scope.wrappers[name]);
-
-    var GeneratedWrapper = function(node) {
-      // At this point all of them extend HTMLElement.
-      HTMLElement.call(this, node);
-    }
-    GeneratedWrapper.prototype = Object.create(HTMLElement.prototype);
-    mixin(GeneratedWrapper.prototype, {
-      get form() {
-        return wrap(unwrap(this).form);
-      },
-    });
-
-    registerWrapper(window[name], GeneratedWrapper,
-        document.createElement(name.slice(4, -7)));
-    scope.wrappers[name] = GeneratedWrapper;
-  }
-
-  elementsWithFormProperty.forEach(createWrapperConstructor);
-
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2014 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var registerWrapper = scope.registerWrapper;
-  var unwrap = scope.unwrap;
-  var unwrapIfNeeded = scope.unwrapIfNeeded;
-  var wrap = scope.wrap;
-
-  var OriginalSelection = window.Selection;
-
-  function Selection(impl) {
-    this.impl = impl;
-  }
-  Selection.prototype = {
-    get anchorNode() {
-      return wrap(this.impl.anchorNode);
-    },
-    get focusNode() {
-      return wrap(this.impl.focusNode);
-    },
-    addRange: function(range) {
-      this.impl.addRange(unwrap(range));
-    },
-    collapse: function(node, index) {
-      this.impl.collapse(unwrapIfNeeded(node), index);
-    },
-    containsNode: function(node, allowPartial) {
-      return this.impl.containsNode(unwrapIfNeeded(node), allowPartial);
-    },
-    extend: function(node, offset) {
-      this.impl.extend(unwrapIfNeeded(node), offset);
-    },
-    getRangeAt: function(index) {
-      return wrap(this.impl.getRangeAt(index));
-    },
-    removeRange: function(range) {
-      this.impl.removeRange(unwrap(range));
-    },
-    selectAllChildren: function(node) {
-      this.impl.selectAllChildren(unwrapIfNeeded(node));
-    },
-    toString: function() {
-      return this.impl.toString();
-    }
-  };
-
-  // WebKit extensions. Not implemented.
-  // readonly attribute Node baseNode;
-  // readonly attribute long baseOffset;
-  // readonly attribute Node extentNode;
-  // readonly attribute long extentOffset;
-  // [RaisesException] void setBaseAndExtent([Default=Undefined] optional Node baseNode,
-  //                       [Default=Undefined] optional long baseOffset,
-  //                       [Default=Undefined] optional Node extentNode,
-  //                       [Default=Undefined] optional long extentOffset);
-  // [RaisesException, ImplementedAs=collapse] void setPosition([Default=Undefined] optional Node node,
-  //                  [Default=Undefined] optional long offset);
-
-  registerWrapper(window.Selection, Selection, window.getSelection());
-
-  scope.wrappers.Selection = Selection;
-
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var GetElementsByInterface = scope.GetElementsByInterface;
-  var Node = scope.wrappers.Node;
-  var ParentNodeInterface = scope.ParentNodeInterface;
-  var Selection = scope.wrappers.Selection;
-  var SelectorsInterface = scope.SelectorsInterface;
-  var ShadowRoot = scope.wrappers.ShadowRoot;
-  var defineWrapGetter = scope.defineWrapGetter;
-  var elementFromPoint = scope.elementFromPoint;
-  var forwardMethodsToWrapper = scope.forwardMethodsToWrapper;
-  var matchesNames = scope.matchesNames;
-  var mixin = scope.mixin;
-  var registerWrapper = scope.registerWrapper;
-  var renderAllPending = scope.renderAllPending;
-  var rewrap = scope.rewrap;
-  var unwrap = scope.unwrap;
-  var wrap = scope.wrap;
-  var wrapEventTargetMethods = scope.wrapEventTargetMethods;
-  var wrapNodeList = scope.wrapNodeList;
-
-  var implementationTable = new WeakMap();
-
-  function Document(node) {
-    Node.call(this, node);
-  }
-  Document.prototype = Object.create(Node.prototype);
-
-  defineWrapGetter(Document, 'documentElement');
-
-  // Conceptually both body and head can be in a shadow but suporting that seems
-  // overkill at this point.
-  defineWrapGetter(Document, 'body');
-  defineWrapGetter(Document, 'head');
-
-  // document cannot be overridden so we override a bunch of its methods
-  // directly on the instance.
-
-  function wrapMethod(name) {
-    var original = document[name];
-    Document.prototype[name] = function() {
-      return wrap(original.apply(this.impl, arguments));
-    };
-  }
-
-  [
-    'createComment',
-    'createDocumentFragment',
-    'createElement',
-    'createElementNS',
-    'createEvent',
-    'createEventNS',
-    'createRange',
-    'createTextNode',
-    'getElementById'
-  ].forEach(wrapMethod);
-
-  var originalAdoptNode = document.adoptNode;
-
-  function adoptNodeNoRemove(node, doc) {
-    originalAdoptNode.call(doc.impl, unwrap(node));
-    adoptSubtree(node, doc);
-  }
-
-  function adoptSubtree(node, doc) {
-    if (node.shadowRoot)
-      doc.adoptNode(node.shadowRoot);
-    if (node instanceof ShadowRoot)
-      adoptOlderShadowRoots(node, doc);
-    for (var child = node.firstChild; child; child = child.nextSibling) {
-      adoptSubtree(child, doc);
-    }
-  }
-
-  function adoptOlderShadowRoots(shadowRoot, doc) {
-    var oldShadowRoot = shadowRoot.olderShadowRoot;
-    if (oldShadowRoot)
-      doc.adoptNode(oldShadowRoot);
-  }
-
-  var originalImportNode = document.importNode;
-  var originalGetSelection = document.getSelection;
-
-  mixin(Document.prototype, {
-    adoptNode: function(node) {
-      if (node.parentNode)
-        node.parentNode.removeChild(node);
-      adoptNodeNoRemove(node, this);
-      return node;
-    },
-    elementFromPoint: function(x, y) {
-      return elementFromPoint(this, this, x, y);
-    },
-    importNode: function(node, deep) {
-      // We need to manually walk the tree to ensure we do not include rendered
-      // shadow trees.
-      var clone = wrap(originalImportNode.call(this.impl, unwrap(node), false));
-      if (deep) {
-        for (var child = node.firstChild; child; child = child.nextSibling) {
-          clone.appendChild(this.importNode(child, true));
-        }
-      }
-      return clone;
-    },
-    getSelection: function() {
-      renderAllPending();
-      return new Selection(originalGetSelection.call(unwrap(this)));
-    }
-  });
-
-  if (document.registerElement) {
-    var originalRegisterElement = document.registerElement;
-    Document.prototype.registerElement = function(tagName, object) {
-      var prototype = object.prototype;
-
-      // If we already used the object as a prototype for another custom
-      // element.
-      if (scope.nativePrototypeTable.get(prototype)) {
-        // TODO(arv): DOMException
-        throw new Error('NotSupportedError');
-      }
-
-      // Find first object on the prototype chain that already have a native
-      // prototype. Keep track of all the objects before that so we can create
-      // a similar structure for the native case.
-      var proto = Object.getPrototypeOf(prototype);
-      var nativePrototype;
-      var prototypes = [];
-      while (proto) {
-        nativePrototype = scope.nativePrototypeTable.get(proto);
-        if (nativePrototype)
-          break;
-        prototypes.push(proto);
-        proto = Object.getPrototypeOf(proto);
-      }
-
-      if (!nativePrototype) {
-        // TODO(arv): DOMException
-        throw new Error('NotSupportedError');
-      }
-
-      // This works by creating a new prototype object that is empty, but has
-      // the native prototype as its proto. The original prototype object
-      // passed into register is used as the wrapper prototype.
-
-      var newPrototype = Object.create(nativePrototype);
-      for (var i = prototypes.length - 1; i >= 0; i--) {
-        newPrototype = Object.create(newPrototype);
-      }
-
-      // Add callbacks if present.
-      // Names are taken from:
-      //   https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.cpp&sq=package:chromium&type=cs&l=156
-      // and not from the spec since the spec is out of date.
-      [
-        'createdCallback',
-        'attachedCallback',
-        'detachedCallback',
-        'attributeChangedCallback',
-      ].forEach(function(name) {
-        var f = prototype[name];
-        if (!f)
-          return;
-        newPrototype[name] = function() {
-          // if this element has been wrapped prior to registration,
-          // the wrapper is stale; in this case rewrap
-          if (!(wrap(this) instanceof CustomElementConstructor)) {
-            rewrap(this);
-          }
-          f.apply(wrap(this), arguments);
-        };
-      });
-
-      var p = {prototype: newPrototype};
-      if (object.extends)
-        p.extends = object.extends;
-
-      function CustomElementConstructor(node) {
-        if (!node) {
-          if (object.extends) {
-            return document.createElement(object.extends, tagName);
-          } else {
-            return document.createElement(tagName);
-          }
-        }
-        this.impl = node;
-      }
-      CustomElementConstructor.prototype = prototype;
-      CustomElementConstructor.prototype.constructor = CustomElementConstructor;
-
-      scope.constructorTable.set(newPrototype, CustomElementConstructor);
-      scope.nativePrototypeTable.set(prototype, newPrototype);
-
-      // registration is synchronous so do it last
-      var nativeConstructor = originalRegisterElement.call(unwrap(this),
-          tagName, p);
-      return CustomElementConstructor;
-    };
-
-    forwardMethodsToWrapper([
-      window.HTMLDocument || window.Document,  // Gecko adds these to HTMLDocument
-    ], [
-      'registerElement',
-    ]);
-  }
-
-  // We also override some of the methods on document.body and document.head
-  // for convenience.
-  forwardMethodsToWrapper([
-    window.HTMLBodyElement,
-    window.HTMLDocument || window.Document,  // Gecko adds these to HTMLDocument
-    window.HTMLHeadElement,
-    window.HTMLHtmlElement,
-  ], [
-    'appendChild',
-    'compareDocumentPosition',
-    'contains',
-    'getElementsByClassName',
-    'getElementsByTagName',
-    'getElementsByTagNameNS',
-    'insertBefore',
-    'querySelector',
-    'querySelectorAll',
-    'removeChild',
-    'replaceChild',
-  ].concat(matchesNames));
-
-  forwardMethodsToWrapper([
-    window.HTMLDocument || window.Document,  // Gecko adds these to HTMLDocument
-  ], [
-    'adoptNode',
-    'importNode',
-    'contains',
-    'createComment',
-    'createDocumentFragment',
-    'createElement',
-    'createElementNS',
-    'createEvent',
-    'createEventNS',
-    'createRange',
-    'createTextNode',
-    'elementFromPoint',
-    'getElementById',
-    'getSelection',
-  ]);
-
-  mixin(Document.prototype, GetElementsByInterface);
-  mixin(Document.prototype, ParentNodeInterface);
-  mixin(Document.prototype, SelectorsInterface);
-
-  mixin(Document.prototype, {
-    get implementation() {
-      var implementation = implementationTable.get(this);
-      if (implementation)
-        return implementation;
-      implementation =
-          new DOMImplementation(unwrap(this).implementation);
-      implementationTable.set(this, implementation);
-      return implementation;
-    }
-  });
-
-  registerWrapper(window.Document, Document,
-      document.implementation.createHTMLDocument(''));
-
-  // Both WebKit and Gecko uses HTMLDocument for document. HTML5/DOM only has
-  // one Document interface and IE implements the standard correctly.
-  if (window.HTMLDocument)
-    registerWrapper(window.HTMLDocument, Document);
-
-  wrapEventTargetMethods([
-    window.HTMLBodyElement,
-    window.HTMLDocument || window.Document,  // Gecko adds these to HTMLDocument
-    window.HTMLHeadElement,
-  ]);
-
-  function DOMImplementation(impl) {
-    this.impl = impl;
-  }
-
-  function wrapImplMethod(constructor, name) {
-    var original = document.implementation[name];
-    constructor.prototype[name] = function() {
-      return wrap(original.apply(this.impl, arguments));
-    };
-  }
-
-  function forwardImplMethod(constructor, name) {
-    var original = document.implementation[name];
-    constructor.prototype[name] = function() {
-      return original.apply(this.impl, arguments);
-    };
-  }
-
-  wrapImplMethod(DOMImplementation, 'createDocumentType');
-  wrapImplMethod(DOMImplementation, 'createDocument');
-  wrapImplMethod(DOMImplementation, 'createHTMLDocument');
-  forwardImplMethod(DOMImplementation, 'hasFeature');
-
-  registerWrapper(window.DOMImplementation, DOMImplementation);
-
-  forwardMethodsToWrapper([
-    window.DOMImplementation,
-  ], [
-    'createDocumentType',
-    'createDocument',
-    'createHTMLDocument',
-    'hasFeature',
-  ]);
-
-  scope.adoptNodeNoRemove = adoptNodeNoRemove;
-  scope.wrappers.DOMImplementation = DOMImplementation;
-  scope.wrappers.Document = Document;
-
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var EventTarget = scope.wrappers.EventTarget;
-  var Selection = scope.wrappers.Selection;
-  var mixin = scope.mixin;
-  var registerWrapper = scope.registerWrapper;
-  var renderAllPending = scope.renderAllPending;
-  var unwrap = scope.unwrap;
-  var unwrapIfNeeded = scope.unwrapIfNeeded;
-  var wrap = scope.wrap;
-
-  var OriginalWindow = window.Window;
-  var originalGetComputedStyle = window.getComputedStyle;
-  var originalGetSelection = window.getSelection;
-
-  function Window(impl) {
-    EventTarget.call(this, impl);
-  }
-  Window.prototype = Object.create(EventTarget.prototype);
-
-  OriginalWindow.prototype.getComputedStyle = function(el, pseudo) {
-    return wrap(this || window).getComputedStyle(unwrapIfNeeded(el), pseudo);
-  };
-
-  OriginalWindow.prototype.getSelection = function() {
-    return wrap(this || window).getSelection();
-  };
-
-  // Work around for https://bugzilla.mozilla.org/show_bug.cgi?id=943065
-  delete window.getComputedStyle;
-  delete window.getSelection;
-
-  ['addEventListener', 'removeEventListener', 'dispatchEvent'].forEach(
-      function(name) {
-        OriginalWindow.prototype[name] = function() {
-          var w = wrap(this || window);
-          return w[name].apply(w, arguments);
-        };
-
-        // Work around for https://bugzilla.mozilla.org/show_bug.cgi?id=943065
-        delete window[name];
-      });
-
-  mixin(Window.prototype, {
-    getComputedStyle: function(el, pseudo) {
-      renderAllPending();
-      return originalGetComputedStyle.call(unwrap(this), unwrapIfNeeded(el),
-                                           pseudo);
-    },
-    getSelection: function() {
-      renderAllPending();
-      return new Selection(originalGetSelection.call(unwrap(this)));
-    },
-  });
-
-  registerWrapper(OriginalWindow, Window);
-
-  scope.wrappers.Window = Window;
-
-})(window.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
-  'use strict';
-
-  var isWrapperFor = scope.isWrapperFor;
-
-  // This is a list of the elements we currently override the global constructor
-  // for.
-  var elements = {
-    'a': 'HTMLAnchorElement',
-
-    // Do not create an applet element by default since it shows a warning in
-    // IE.
-    // https://github.com/Polymer/polymer/issues/217
-    // 'applet': 'HTMLAppletElement',
-
-    'area': 'HTMLAreaElement',
-    'br': 'HTMLBRElement',
-    'base': 'HTMLBaseElement',
-    'body': 'HTMLBodyElement',
-    'button': 'HTMLButtonElement',
-    // 'command': 'HTMLCommandElement',  // Not fully implemented in Gecko.
-    'dl': 'HTMLDListElement',
-    'datalist': 'HTMLDataListElement',
-    'data': 'HTMLDataElement',
-    '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',
-    'marquee': 'HTMLMarqueeElement',
-    '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',
-    'time': 'HTMLTimeElement',
-    'caption': 'HTMLTableCaptionElement',
-    // WebKit and Moz are wrong:
-    // https://bugs.webkit.org/show_bug.cgi?id=111469
-    // https://bugzilla.mozilla.org/show_bug.cgi?id=848096
-    // 'td': 'HTMLTableCellElement',
-    'col': 'HTMLTableColElement',
-    'table': 'HTMLTableElement',
-    'tr': 'HTMLTableRowElement',
-    'thead': 'HTMLTableSectionElement',
-    'tbody': 'HTMLTableSectionElement',
-    'textarea': 'HTMLTextAreaElement',
-    'track': 'HTMLTrackElement',
-    'title': 'HTMLTitleElement',
-    'ul': 'HTMLUListElement',
-    'video': 'HTMLVideoElement',
-  };
-
-  function overrideConstructor(tagName) {
-    var nativeConstructorName = elements[tagName];
-    var nativeConstructor = window[nativeConstructorName];
-    if (!nativeConstructor)
-      return;
-    var element = document.createElement(tagName);
-    var wrapperConstructor = element.constructor;
-    window[nativeConstructorName] = wrapperConstructor;
-  }
-
-  Object.keys(elements).forEach(overrideConstructor);
-
-  Object.getOwnPropertyNames(scope.wrappers).forEach(function(name) {
-    window[name] = scope.wrappers[name]
-  });
-
-  // Export for testing.
-  scope.knownElements = elements;
-
-})(window.ShadowDOMPolyfill);
-
-/*
- * Copyright 2013 The Polymer Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style
- * license that can be found in the LICENSE file.
- */
-(function() {
-  var ShadowDOMPolyfill = window.ShadowDOMPolyfill;
-  var wrap = ShadowDOMPolyfill.wrap;
-
-  // patch in prefixed name
-  Object.defineProperties(HTMLElement.prototype, {
-    //TODO(sjmiles): review accessor alias with Arv
-    webkitShadowRoot: {
-      get: function() {
-        return this.shadowRoot;
-      }
-    }
-  });
-
-  // ShadowCSS needs this:
-  window.wrap = window.ShadowDOMPolyfill.wrap;
-  window.unwrap = window.ShadowDOMPolyfill.unwrap;
-
-  //TODO(sjmiles): review method alias with Arv
-  HTMLElement.prototype.webkitCreateShadowRoot =
-      HTMLElement.prototype.createShadowRoot;
-
-  // TODO(jmesserly): we need to wrap document somehow (a dart:html hook?)
-  window.dartExperimentalFixupGetTag = function(originalGetTag) {
-    var NodeList = ShadowDOMPolyfill.wrappers.NodeList;
-    var ShadowRoot = ShadowDOMPolyfill.wrappers.ShadowRoot;
-    var unwrapIfNeeded = ShadowDOMPolyfill.unwrapIfNeeded;
-    function getTag(obj) {
-      // TODO(jmesserly): do we still need these?
-      if (obj instanceof NodeList) return 'NodeList';
-      if (obj instanceof ShadowRoot) return 'ShadowRoot';
-      if (window.MutationRecord && (obj instanceof MutationRecord))
-          return 'MutationRecord';
-      if (window.MutationObserver && (obj instanceof MutationObserver))
-          return 'MutationObserver';
-
-      // TODO(jmesserly): this prevents incorrect interaction between ShadowDOM
-      // and dart:html's <template> polyfill. Essentially, ShadowDOM is
-      // polyfilling native template, but our Dart polyfill fails to detect this
-      // because the unwrapped node is an HTMLUnknownElement, leading it to
-      // think the node has no content.
-      if (obj instanceof HTMLTemplateElement) return 'HTMLTemplateElement';
-
-      var unwrapped = unwrapIfNeeded(obj);
-      if (obj !== unwrapped) {
-        // Fix up class names for Firefox.
-        // For some of them (like HTMLFormElement and HTMLInputElement),
-        // the "constructor" property of the unwrapped nodes points at the
-        // same constructor as the wrapper.
-        var ctor = obj.constructor
-        if (ctor === unwrapped.constructor) {
-          var name = ctor._ShadowDOMPolyfill$cacheTag_;
-          if (!name) {
-            name = Object.prototype.toString.call(unwrapped);
-            name = name.substring(8, name.length - 1);
-            ctor._ShadowDOMPolyfill$cacheTag_ = name;
-          }
-          return name;
-        }
-
-        obj = unwrapped;
-      }
-      return originalGetTag(obj);
-    }
-
-    return getTag;
-  };
-})();
-
-// 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.
-
-var Platform = {};
-
-/*
- * Copyright 2012 The Polymer Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style
- * license that can be found in the LICENSE file.
- */
-
-/*
-  This is a limited shim for ShadowDOM css styling.
-  https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#styles
-  
-  The intention here is to support only the styling features which can be 
-  relatively simply implemented. The goal is to allow users to avoid the 
-  most obvious pitfalls and do so without compromising performance significantly. 
-  For ShadowDOM styling that's not covered here, a set of best practices
-  can be provided that should allow users to accomplish more complex styling.
-
-  The following is a list of specific ShadowDOM styling features and a brief
-  discussion of the approach used to shim.
-
-  Shimmed features:
-
-  * @host: ShadowDOM allows styling of the shadowRoot's host element using the 
-  @host rule. To shim this feature, the @host styles are reformatted and 
-  prefixed with a given scope name and promoted to a document level stylesheet.
-  For example, given a scope name of .foo, a rule like this:
-  
-    @host {
-      * {
-        background: red;
-      }
-    }
-  
-  becomes:
-  
-    .foo {
-      background: red;
-    }
-  
-  * encapsultion: Styles defined within ShadowDOM, apply only to 
-  dom inside the ShadowDOM. Polymer uses one of two techniques to imlement
-  this feature.
-  
-  By default, rules are prefixed with the host element tag name 
-  as a descendant selector. This ensures styling does not leak out of the 'top'
-  of the element's ShadowDOM. For example,
-
-  div {
-      font-weight: bold;
-    }
-  
-  becomes:
-
-  x-foo div {
-      font-weight: bold;
-    }
-  
-  becomes:
-
-
-  Alternatively, if Platform.ShadowCSS.strictStyling is set to true then 
-  selectors are scoped by adding an attribute selector suffix to each
-  simple selector that contains the host element tag name. Each element 
-  in the element's ShadowDOM template is also given the scope attribute. 
-  Thus, these rules match only elements that have the scope attribute.
-  For example, given a scope name of x-foo, a rule like this:
-  
-    div {
-      font-weight: bold;
-    }
-  
-  becomes:
-  
-    div[x-foo] {
-      font-weight: bold;
-    }
-
-  Note that elements that are dynamically added to a scope must have the scope
-  selector added to them manually.
-
-  * ::pseudo: These rules are converted to rules that take advantage of the
-  pseudo attribute. For example, a shadowRoot like this inside an x-foo
-
-    <div pseudo="x-special">Special</div>
-
-  with a rule like this:
-
-    x-foo::x-special { ... }
-
-  becomes:
-
-    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
-  shadowRoot should not cross the ShadowDOM boundary and should not apply
-  inside a shadowRoot.
-
-  This styling behavior is not emulated. Some possible ways to do this that 
-  were rejected due to complexity and/or performance concerns include: (1) reset
-  every possible property for every possible selector for a given scope name;
-  (2) re-implement css in javascript.
-  
-  As an alternative, users should make sure to use selectors
-  specific to the scope in which they are working.
-  
-  * ::distributed: This behavior is not emulated. It's often not necessary
-  to style the contents of a specific insertion point and instead, descendants
-  of the host element can be styled selectively. Users can also create an 
-  extra node around an insertion point and style that node's contents
-  via descendent selectors. For example, with a shadowRoot like this:
-  
-    <style>
-      content::-webkit-distributed(div) {
-        background: red;
-      }
-    </style>
-    <content></content>
-  
-  could become:
-  
-    <style>
-      / *@polyfill .content-container div * / 
-      content::-webkit-distributed(div) {
-        background: red;
-      }
-    </style>
-    <div class="content-container">
-      <content></content>
-    </div>
-  
-  Note the use of @polyfill in the comment above a ShadowDOM specific style
-  declaration. This is a directive to the styling shim to use the selector 
-  in comments in lieu of the next selector when running under polyfill.
-*/
-(function(scope) {
-
-var loader = scope.loader;
-
-var ShadowCSS = {
-  strictStyling: false,
-  registry: {},
-  // 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 */ and /* @polyfill-rule */
-  // 4. shim @host and scoping
-  shimStyling: function(root, name, extendsName) {
-    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);
-    }
-    var cssText = this.stylesToShimmedCssText(def.rootStyles, def.scopeStyles,
-        name, typeExtension);
-    // 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);
-  },
-  // apply @polyfill rules + @host and scope shimming
-  stylesToShimmedCssText: function(rootStyles, scopeStyles, name,
-      typeExtension) {
-    name = name || '';
-    // insert @polyfill and @polyfill-rule rules into style elements
-    // scoping process takes care of shimming these
-    this.insertPolyfillDirectives(rootStyles);
-    this.insertPolyfillRules(rootStyles);
-    var cssText = this.shimAtHost(scopeStyles, name, typeExtension) +
-        this.shimScoping(scopeStyles, name, typeExtension);
-    // note: we only need to do rootStyles since these are unscoped.
-    cssText += this.extractPolyfillUnscopedRules(rootStyles);
-    return cssText;
-  },
-  registerDefinition: function(root, name, extendsName) {
-    var def = this.registry[name] = {
-      root: root,
-      name: name,
-      extendsName: extendsName
-    }
-    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 && (!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.
-      Array.prototype.forEach.call(root.querySelectorAll('*'),
-          function(node) {
-            node.setAttribute(name, '');
-          });
-      // and template contents too
-      Array.prototype.forEach.call(root.querySelectorAll('template'),
-          function(template) {
-            this.applyScopeToContent(template.content, name);
-          },
-          this);
-    }
-  },
-  /*
-   * Process styles to convert native ShadowDOM rules that will trip
-   * up the css parser; we rely on decorating the stylesheet with comments.
-   * 
-   * For example, we convert this rule:
-   * 
-   * (comment start) @polyfill :host menu-item (comment end)
-   * shadow::-webkit-distributed(menu-item) {
-   * 
-   * to this:
-   * 
-   * scopeName menu-item {
-   *
-  **/
-  insertPolyfillDirectives: function(styles) {
-    if (styles) {
-      Array.prototype.forEach.call(styles, function(s) {
-        s.textContent = this.insertPolyfillDirectivesInCssText(s.textContent);
-      }, this);
-    }
-  },
-  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);
-    }
-  },
-  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;
-  },
-  // form: @host { .foo { declarations } }
-  // becomes: scopeName.foo { declarations }
-  shimAtHost: function(styles, name, typeExtension) {
-    if (styles) {
-      return this.convertAtHostStyles(styles, name, typeExtension);
-    }
-  },
-  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),
-        this.makeScopeMatcher(name, typeExtension)));
-    return cssText;
-  },
-  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, 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, typeExtension ? is + '$1$3' :
-            name + '$1$3');
-      // selector: .foo -> name.foo (OR) [bar] -> name[bar]
-      } else if (p.match(hostFixableRe)) {
-        p = typeExtension ? is + p : name + p;
-      }
-      r.push(p);
-    }, this);
-    return r.join(', ');
-  },
-  // consider styles that do not include component name in the selector to be
-  // unscoped and in need of promotion; 
-  // for convenience, also consider keyframe rules this way.
-  findAtHostRules: function(cssRules, matcher) {
-    return Array.prototype.filter.call(cssRules, 
-      this.isHostRule.bind(this, matcher));
-  },
-  isHostRule: function(matcher, cssRule) {
-    return (cssRule.selectorText && cssRule.selectorText.match(matcher)) ||
-      (cssRule.cssRules && this.findAtHostRules(cssRule.cssRules, matcher).length) ||
-      (cssRule.type == CSSRule.WEBKIT_KEYFRAMES_RULE);
-  },
-  /* Ensure styles are scoped. Pseudo-scoping takes a rule like:
-   * 
-   *  .foo {... } 
-   *  
-   *  and converts this to
-   *  
-   *  scopeName .foo { ... }
-  */
-  shimScoping: function(styles, name, typeExtension) {
-    if (styles) {
-      return this.convertScopedStyles(styles, name, typeExtension);
-    }
-  },
-  convertScopedStyles: function(styles, name, typeExtension) {
-    var cssText = stylesToCssText(styles).replace(hostRuleRe, '');
-    cssText = this.insertPolyfillHostInCssText(cssText);
-    cssText = this.convertColonHost(cssText);
-    cssText = this.convertColonAncestor(cssText);
-    // TODO(sorvell): deprecated, remove
-    cssText = this.convertPseudos(cssText);
-    // TODO(sorvell): deprecated, remove
-    cssText = this.convertParts(cssText);
-    cssText = this.convertCombinators(cssText);
-    var rules = cssToRules(cssText);
-    if (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
-  */
-  convertColonHost: function(cssText) {
-    return this.convertColonRule(cssText, cssColonHostRe,
-        this.colonHostPartReplacer);
-  },
-  /*
-   * convert a rule like :ancestor(.foo) > .bar { }
-   *
-   * to
-   *
-   * scopeName.foo > .bar, .foo scopeName > .bar { }
-   * 
-   * and
-   *
-   * :ancestor(.foo:host) .bar { ... }
-   * 
-   * to
-   * 
-   * scopeName.foo .bar { ... }
-  */
-  convertColonAncestor: function(cssText) {
-    return this.convertColonRule(cssText, cssColonAncestorRe,
-        this.colonAncestorPartReplacer);
-  },
-  convertColonRule: function(cssText, regExp, partReplacer) {
-    // p1 = :host, p2 = contents of (), p3 rest of rule
-    return cssText.replace(regExp, function(m, p1, p2, p3) {
-      p1 = polyfillHostNoCombinator;
-      if (p2) {
-        var parts = p2.split(','), r = [];
-        for (var i=0, l=parts.length, p; (i<l) && (p=parts[i]); i++) {
-          p = p.trim();
-          r.push(partReplacer(p1, p, p3));
-        }
-        return r.join(',');
-      } else {
-        return p1 + p3;
-      }
-    });
-  },
-  colonAncestorPartReplacer: function(host, part, suffix) {
-    if (part.match(polyfillHost)) {
-      return this.colonHostPartReplacer(host, part, suffix);
-    } else {
-      return host + part + suffix + ', ' + part + ' ' + host + suffix;
-    }
-  },
-  colonHostPartReplacer: function(host, part, suffix) {
-    return host + part.replace(polyfillHost, '') + suffix;
-  },
-  /*
-   * Convert ^ and ^^ combinators by replacing with space.
-  */
-  convertCombinators: function(cssText) {
-    return cssText.replace(/\^\^/g, ' ').replace(/\^/g, ' ');
-  },
-  // change a selector like 'div' to 'name div'
-  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, typeExtension, 
-          this.strictStyling) + ' {\n\t';
-        cssText += this.propertiesFromRule(rule) + '\n}\n\n';
-      } else if (rule.media) {
-        cssText += '@media ' + rule.media.mediaText + ' {\n';
-        cssText += this.scopeRules(rule.cssRules, name, typeExtension);
-        cssText += '\n}\n\n';
-      } else if (rule.cssText) {
-        cssText += rule.cssText + '\n\n';
-      }
-    }, this);
-    return cssText;
-  },
-  scopeSelector: function(selector, name, typeExtension, strict) {
-    var r = [], parts = selector.split(',');
-    parts.forEach(function(p) {
-      p = p.trim();
-      if (this.selectorNeedsScoping(p, name, typeExtension)) {
-        p = (strict && !p.match(polyfillHostNoCombinator)) ? 
-            this.applyStrictSelectorScope(p, name) :
-            this.applySimpleSelectorScope(p, name, typeExtension);
-      }
-      r.push(p);
-    }, this);
-    return r.join(', ');
-  },
-  selectorNeedsScoping: function(selector, name, typeExtension) {
-    var re = this.makeScopeMatcher(name, typeExtension);
-    return !selector.match(re);
-  },
-  makeScopeMatcher: function(name, typeExtension) {
-    var matchScope = typeExtension ? '\\[is=[\'"]?' + name + '[\'"]?\\]' : name;
-    return new RegExp('^(' + matchScope + ')' + selectorReSuffix, 'm');
-  },
-  // scope via name and [is=name]
-  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]
-  applyStrictSelectorScope: function(selector, name) {
-    var splits = [' ', '>', '+', '~'],
-      scoped = selector,
-      attrName = '[' + name + ']';
-    splits.forEach(function(sep) {
-      var parts = scoped.split(sep);
-      scoped = parts.map(function(p) {
-        // 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')
-        }
-        return p;
-      }).join(sep);
-    });
-    return scoped;
-  },
-  insertPolyfillHostInCssText: function(selector) {
-    return selector.replace(hostRe, polyfillHost).replace(colonHostRe,
-        polyfillHost).replace(colonAncestorRe, polyfillAncestor);
-  },
-  propertiesFromRule: function(rule) {
-    // TODO(sorvell): Safari cssom incorrectly removes quotes from the content
-    // property. (https://bugs.webkit.org/show_bug.cgi?id=118045)
-    if (rule.style.content && !rule.style.content.match(/['"]+/)) {
-      return rule.style.cssText.replace(/content:[^;]*;/g, 'content: \'' + 
-          rule.style.content + '\';');
-    }
-    return rule.style.cssText;
-  }
-};
-
-var hostRuleRe = /@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim,
-    selectorRe = /([^{]*)({[\s\S]*?})/gim,
-    hostElementRe = /(.*)((?:\*)|(?:\:scope))(.*)/,
-    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 -shadowcsshost.
-    polyfillHost = '-shadowcsshost',
-    // note: :ancestor pre-processed to -shadowcssancestor.
-    polyfillAncestor = '-shadowcssancestor',
-    parenSuffix = ')(?:\\((' +
-        '(?:\\([^)(]*\\)|[^)(]*)+?' +
-        ')\\))?([^,{]*)';
-    cssColonHostRe = new RegExp('(' + polyfillHost + parenSuffix, 'gim'),
-    cssColonAncestorRe = new RegExp('(' + polyfillAncestor + parenSuffix, 'gim'),
-    selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$',
-    hostRe = /@host/gim,
-    colonHostRe = /\:host/gim,
-    colonAncestorRe = /\:ancestor/gim,
-    /* host name without combinator */
-    polyfillHostNoCombinator = polyfillHost + '-no-combinator',
-    polyfillHostRe = new RegExp(polyfillHost, 'gim');
-    polyfillAncestorRe = new RegExp(polyfillAncestor, 'gim');
-
-function stylesToCssText(styles, preserveComments) {
-  var cssText = '';
-  Array.prototype.forEach.call(styles, function(s) {
-    cssText += s.textContent + '\n\n';
-  });
-  // strip comments for easier processing
-  if (!preserveComments) {
-    cssText = cssText.replace(cssCommentRe, '');
-  }
-  return 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);
-  return rules;
-}
-
-function rulesToCss(cssRules) {
-  for (var i=0, css=[]; i < cssRules.length; i++) {
-    css.push(cssRules[i].cssText);
-  }
-  return css.join('\n\n');
-}
-
-function addCssToDocument(cssText) {
-  if (cssText) {
-    getSheet().appendChild(document.createTextNode(cssText));
-  }
-}
-
-var sheet;
-function getSheet() {
-  if (!sheet) {
-    sheet = document.createElement("style");
-    sheet.setAttribute('ShadowCSSShim', '');
-    sheet.shadowCssShim = true;
-  }
-  return sheet;
-}
-
-// add polyfill stylesheet to document
-if (window.ShadowDOMPolyfill) {
-  addCssToDocument('style { display: none !important; }\n');
-  var doc = wrap(document);
-  var head = doc.querySelector('head');
-  head.insertBefore(getSheet(), head.childNodes[0]);
-
-  document.addEventListener('DOMContentLoaded', function() {
-    if (window.HTMLImports && !HTMLImports.useNative) {
-      HTMLImports.importer.preloadSelectors += 
-          ', link[rel=stylesheet]:not([nopolyfill])';
-      HTMLImports.parser.parseGeneric = function(elt) {
-        if (elt.shadowCssShim) {
-          return;
-        }
-        var style = elt;
-        if (!elt.hasAttribute('nopolyfill')) {
-          if (elt.__resource) {
-            style = elt.ownerDocument.createElement('style');
-            style.textContent = Platform.loader.resolveUrlsInCssText(
-                elt.__resource, elt.href);
-            // remove links from main document
-            if (elt.ownerDocument === doc) {
-              elt.parentNode.removeChild(elt);
-            }
-          } else {
-            Platform.loader.resolveUrlsInStyle(style);  
-          }
-          var styles = [style];
-          style.textContent = ShadowCSS.stylesToShimmedCssText(styles, styles);
-          style.shadowCssShim = true;
-        }
-        // place in document
-        if (style.parentNode !== head) {
-          head.appendChild(style);
-        }
-      }
-    }
-  });
-}
-
-// exports
-scope.ShadowCSS = ShadowCSS;
-
-})(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
deleted file mode 100644
index c4c13c8..0000000
--- a/pkg/shadow_dom/lib/shadow_dom.min.js
+++ /dev/null
@@ -1,3 +0,0 @@
-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){b=a}if("function"!=typeof Object.observe||"function"!=typeof Array.observe)return!1;var b=[],c={};if(Object.observe(c,a),c.id=1,c.id=2,delete c.id,Object.deliverChangeRecords(a),3!==b.length)return!1;if("new"==b[0].type&&"updated"==b[1].type&&"deleted"==b[2].type)L="new",M="updated",N="reconfigured",O="deleted";else if("add"!=b[0].type||"update"!=b[1].type||"delete"!=b[2].type)return console.error("Unexpected change record names for Object.observe. Using dirty-checking instead"),!1;return Object.unobserve(c,a),c=[0],Array.observe(c,a),c[1]=1,c.length=0,Object.deliverChangeRecords(a),2!=b.length?!1:b[0].type!=P||b[1].type!=P?!1:(Array.unobserve(c,a),!0)}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:S(a)&&S(b)?!0:a!==a&&b!==b}function h(a){return"string"!=typeof a?!1:(a=a.trim(),""==a?!0:"."==a[0]?!1:$.test(a))}function i(a,b){if(b!==_)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),void(R&&this.length&&(this.getValueFrom=this.compiledGetValueFromFn())))}function j(a){if(a instanceof i)return a;null==a&&(a=""),"string"!=typeof a&&(a=String(a));var b=ab[a];if(b)return b;if(!h(a))return bb;var b=new i(a,_);return ab[a]=b,b}function k(b){for(var c=0;db>c&&b.check_();)c++;return a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=c),c>0}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(){if(!eb.length)return!1;for(var a=0;a<eb.length;a++)eb[a]();return eb.length=0,!0}function p(){function a(a){b&&b.state_===kb&&!d&&b.check_(a)}var b,c,d=!1,e=!0;return{open:function(c){if(b)throw Error("ObservedObject in use");e||Object.deliverChangeRecords(a),b=c,e=!1},observe:function(b,d){c=b,d?Array.observe(c,a):Object.observe(c,a)},deliver:function(b){d=b,Object.deliverChangeRecords(a),d=!1},close:function(){b=void 0,Object.unobserve(c,a),gb.push(this)}}}function q(a,b,c){var d=gb.pop()||p();return d.open(a),d.observe(b,c),d}function r(){function a(b){if(f(b)){var c=i.indexOf(b);c>=0?(i[c]=void 0,h.push(b)):h.indexOf(b)<0&&(h.push(b),Object.observe(b,d)),a(Object.getPrototypeOf(b))}}function b(){if(k=!1,j){var b=i===hb?[]:i;i=h,h=b;var c;for(var f in e)c=e[f],c&&c.state_==kb&&c.iterateObjects_(a);for(var g=0;g<i.length;g++){var l=i[g];l&&Object.unobserve(l,d)}i.length=0}}function c(){k||(j=!0,k=!0,fb(b))}function d(){var a;for(var b in e)a=e[b],a&&a.state_==kb&&a.check_();c()}var e=[],g=0,h=[],i=hb,j=!1,k=!1,l={object:void 0,objects:h,open:function(b){e[b.id_]=b,g++,b.iterateObjects_(a)},close:function(a){if(e[a.id_]=void 0,g--,g)return void c();j=!1;for(var b=0;b<h.length;b++)Object.unobserve(h[b],d),t.unobservedCount++;e.length=0,h.length=0,ib.push(this)},reset:c};return l}function s(a,b){return cb&&cb.object===b||(cb=ib.pop()||r(),cb.object=b),cb.open(a),cb}function t(){this.state_=jb,this.callback_=void 0,this.target_=void 0,this.directObserver_=void 0,this.value_=void 0,this.id_=nb++}function u(a){t._allObserversCount++,pb&&ob.push(a)}function v(){t._allObserversCount--}function w(a){t.call(this),this.value_=a,this.oldObject_=void 0}function x(a){if(!Array.isArray(a))throw Error("Provided object is not an Array");w.call(this,a)}function y(a,b){t.call(this),this.object_=a,this.path_=b instanceof i?b:j(b),this.directObserver_=void 0}function z(){t.call(this),this.value_=[],this.directObserver_=void 0,this.observed_=[]}function A(a){return a}function B(a,b,c,d){this.callback_=void 0,this.target_=void 0,this.value_=void 0,this.observable_=a,this.getValueFn_=b||A,this.setValueFn_=c||A,this.dontPassThroughSet_=d}function C(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 D(a,b,c){for(var d={},e={},f=0;f<b.length;f++){var g=b[f];tb[g.type]?(g.name in c||(c[g.name]=g.oldValue),g.type!=M&&(g.type!=L?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 E(a,b,c){return{index:a,removed:b,addedCount:c}}function F(){}function G(a,b,c,d,e,f){return yb.calcSplices(a,b,c,d,e,f)}function H(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 I(a,b,c,d){for(var e=E(b,c,d),f=!1,g=0,h=0;h<a.length;h++){var i=a[h];if(i.index+=g,!f){var j=H(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 J(a,b){for(var c=[],f=0;f<b.length;f++){var g=b[f];switch(g.type){case P:I(c,g.index,g.removed.slice(),g.addedCount);break;case L:case M:case O:if(!d(g.name))continue;var h=e(g.name);if(0>h)continue;I(c,h,[g.oldValue],1);break;default:console.error("Unexpected record type: "+JSON.stringify(g))}}return c}function K(a,b){var c=[];return J(a,b).forEach(function(b){return 1==b.addedCount&&1==b.removed.length?void(b.removed[0]!==a[b.index]&&c.push(b)):void(c=c.concat(G(a,b.index,b.index+b.addedCount,b.removed,0,b.removed.length)))}),c}var L="add",M="update",N="reconfigure",O="delete",P="splice",Q=b(),R=c(),S=a.Number.isNaN||function(b){return"number"==typeof b&&a.isNaN(b)},T="__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},U="[$_a-zA-Z]",V="[$_a-zA-Z0-9]",W=U+"+"+V+"*",X="(?:[0-9]|[1-9]+[0-9]+)",Y="(?:"+W+"|"+X+")",Z="(?:"+Y+")(?:\\s*\\.\\s*"+Y+")*",$=new RegExp("^"+Z+"$"),_={},ab={};i.get=j,i.prototype=T({__proto__:[],valid:!0,toString:function(){return this.join(".")},getValueFrom:function(a){for(var b=0;b<this.length;b++){if(null==a)return;a=a[this[b]]}return a},iterateObjects:function(a,b){for(var c=0;c<this.length;c++){if(c&&(a=a[this[c-1]]),!a)return;b(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 bb=new i("",_);bb.valid=!1,bb.getValueFrom=bb.setValueFrom=function(){};var cb,db=1e3,eb=[],fb=Q?function(){var a={pingPong:!0},b=!1;return Object.observe(a,function(){o(),b=!1}),function(c){eb.push(c),b||(b=!0,a.pingPong=!a.pingPong)}}():function(){return function(a){eb.push(a)}}(),gb=[],hb=[],ib=[],jb=0,kb=1,lb=2,mb=3,nb=1;t.prototype={open:function(a,b){if(this.state_!=jb)throw Error("Observer has already been opened.");return u(this),this.callback_=a,this.target_=b,this.state_=kb,this.connect_(),this.value_},close:function(){this.state_==kb&&(v(this),this.state_=lb,this.disconnect_(),this.value_=void 0,this.callback_=void 0,this.target_=void 0)},deliver:function(){this.state_==kb&&k(this)},report_:function(a){try{this.callback_.apply(this.target_,a)}catch(b){t._errorThrownDuringCallback=!0,console.error("Exception caught during observer callback: "+(b.stack||b))}},discardChanges:function(){return this.check_(void 0,!0),this.value_}};var ob,pb=!Q;t._allObserversCount=0,pb&&(ob=[]);var qb=!1,rb="function"==typeof Object.deliverAllChangeRecords;a.Platform=a.Platform||{},a.Platform.performMicrotaskCheckpoint=function(){if(!qb){if(rb)return void Object.deliverAllChangeRecords();if(pb){qb=!0;var b,c,d=0;do{d++,c=ob,ob=[],b=!1;for(var e=0;e<c.length;e++){var f=c[e];f.state_==kb&&(f.check_()&&(b=!0),ob.push(f))}o()&&(b=!0)}while(db>d&&b);a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=d),qb=!1}}},pb&&(a.Platform.clearObservers=function(){ob=[]}),w.prototype=T({__proto__:t.prototype,arrayObserve:!1,connect_:function(){Q?this.directObserver_=q(this,this.value_,this.arrayObserve):this.oldObject_=this.copyObject(this.value_)},copyObject:function(a){var b=Array.isArray(a)?[]:{};for(var c in a)b[c]=a[c];return Array.isArray(a)&&(b.length=a.length),b},check_:function(a){var b,c;if(Q){if(!a)return!1;c={},b=D(this.value_,a,c)}else c=this.oldObject_,b=n(this.value_,this.oldObject_);return m(b)?!1:(Q||(this.oldObject_=this.copyObject(this.value_)),this.report_([b.added||{},b.removed||{},b.changed||{},function(a){return c[a]}]),!0)},disconnect_:function(){Q?(this.directObserver_.close(),this.directObserver_=void 0):this.oldObject_=void 0},deliver:function(){this.state_==kb&&(Q?this.directObserver_.deliver(!1):k(this))},discardChanges:function(){return this.directObserver_?this.directObserver_.deliver(!0):this.oldObject_=this.copyObject(this.value_),this.value_}}),x.prototype=T({__proto__:w.prototype,arrayObserve:!0,copyObject:function(a){return a.slice()},check_:function(a){var b;if(Q){if(!a)return!1;b=K(this.value_,a)}else b=G(this.value_,0,this.value_.length,this.oldObject_,0,this.oldObject_.length);return b&&b.length?(Q||(this.oldObject_=this.copyObject(this.value_)),this.report_([b]),!0):!1}}),x.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)})},y.prototype=T({__proto__:t.prototype,connect_:function(){Q&&(this.directObserver_=s(this,this.object_)),this.check_(void 0,!0)},disconnect_:function(){this.value_=void 0,this.directObserver_&&(this.directObserver_.close(this),this.directObserver_=void 0)},iterateObjects_:function(a){this.path_.iterateObjects(this.object_,a)},check_:function(a,b){var c=this.value_;return this.value_=this.path_.getValueFrom(this.object_),b||g(this.value_,c)?!1:(this.report_([this.value_,c]),!0)},setValue:function(a){this.path_&&this.path_.setValueFrom(this.object_,a)}});var sb={};z.prototype=T({__proto__:t.prototype,connect_:function(){if(this.check_(void 0,!0),Q){for(var a,b=!1,c=0;c<this.observed_.length;c+=2)if(a=this.observed_[c],a!==sb){b=!0;break}return this.directObserver_?b?void this.directObserver_.reset():(this.directObserver_.close(),void(this.directObserver_=void 0)):void(b&&(this.directObserver_=s(this,a)))}},closeObservers_:function(){for(var a=0;a<this.observed_.length;a+=2)this.observed_[a]===sb&&this.observed_[a+1].close();this.observed_.length=0},disconnect_:function(){this.value_=void 0,this.directObserver_&&(this.directObserver_.close(this),this.directObserver_=void 0),this.closeObservers_()},addPath:function(a,b){if(this.state_!=jb&&this.state_!=mb)throw Error("Cannot add paths once started.");this.observed_.push(a,b instanceof i?b:j(b))},addObserver:function(a){if(this.state_!=jb&&this.state_!=mb)throw Error("Cannot add observers once started.");a.open(this.deliver,this),this.observed_.push(sb,a)},startReset:function(){if(this.state_!=kb)throw Error("Can only reset while open");this.state_=mb,this.closeObservers_()},finishReset:function(){if(this.state_!=mb)throw Error("Can only finishReset after startReset");return this.state_=kb,this.connect_(),this.value_},iterateObjects_:function(a){for(var b,c=0;c<this.observed_.length;c+=2)b=this.observed_[c],b!==sb&&this.observed_[c+1].iterateObjects(b,a)},check_:function(a,b){for(var c,d=0;d<this.observed_.length;d+=2){var e=this.observed_[d+1],f=this.observed_[d],h=f===sb?e.discardChanges():e.getValueFrom(f);b?this.value_[d/2]=h:g(h,this.value_[d/2])||(c=c||[],c[d/2]=this.value_[d/2],this.value_[d/2]=h)}return c?(this.report_([this.value_,c,this.observed_]),!0):!1}}),B.prototype={open:function(a,b){return this.callback_=a,this.target_=b,this.value_=this.getValueFn_(this.observable_.open(this.observedCallback_,this)),this.value_},observedCallback_:function(a){if(a=this.getValueFn_(a),!g(a,this.value_)){var b=this.value_;this.value_=a,this.callback_.call(this.target_,this.value_,b)}},discardChanges:function(){return this.value_=this.getValueFn_(this.observable_.discardChanges()),this.value_},deliver:function(){return this.observable_.deliver()},setValue:function(a){return a=this.setValueFn_(a),!this.dontPassThroughSet_&&this.observable_.setValue?this.observable_.setValue(a):void 0},close:function(){this.observable_&&this.observable_.close(),this.callback_=void 0,this.target_=void 0,this.observable_=void 0,this.value_=void 0,this.getValueFn_=void 0,this.setValueFn_=void 0}};var tb={};tb[L]=!0,tb[M]=!0,tb[O]=!0,t.defineComputedProperty=function(a,b,c){var d=C(a,b),e=c.open(function(a,b){e=a,d&&d(M,b)});return Object.defineProperty(a,b,{get:function(){return c.deliver(),e},set:function(a){return c.setValue(a),a},configurable:!0}),{close:function(){c.close(),Object.defineProperty(a,b,{value:e,writable:!0,configurable:!0})}}};var ub=0,vb=1,wb=2,xb=3;F.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(ub):(e.push(vb),d=g),b--,c--):f==h?(e.push(xb),b--,d=h):(e.push(wb),c--,d=i)}else e.push(xb),b--;else e.push(wb),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,c-b==0&&f-e==0)return[];if(b==c){for(var j=E(b,[],0);f>e;)j.removed.push(d[e++]);return[j]}if(e==f)return[E(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 ub:j&&(l.push(j),j=void 0),m++,n++;break;case vb:j||(j=E(m,[],0)),j.addedCount++,m++,j.removed.push(d[n]),n++;break;case wb:j||(j=E(m,[],0)),j.addedCount++,m++;break;case xb:j||(j=E(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 yb=new F;a.Observer=t,a.Observer.runEOM_=fb,a.Observer.hasObjectObserve=Q,a.ArrayObserver=x,a.ArrayObserver.calculateSplices=function(a,b){return yb.calculateSplices(a,b)},a.ArraySplice=F,a.ObjectObserver=w,a.PathObserver=y,a.CompoundObserver=z,a.Path=i,a.ObserverTransform=B,a.Observer.changeRecordTypes={add:L,update:M,reconfigure:N,"delete":O,splice:P}}("undefined"!=typeof global&&global&&"undefined"!=typeof module&&module?global:this||window),"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}(),window.ShadowDOMPolyfill={},function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a,b){return L(b).forEach(function(c){K(a,c,M(b,c))}),a}function d(a,b){return L(b).forEach(function(c){switch(c){case"arguments":case"caller":case"length":case"name":case"prototype":case"toString":return}K(a,c,M(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=E.get(b);if(c)return c;var d=f(b),e=t(d);return q(b,e,a),e}function g(a,b){o(a,b,!0)}function h(a,b){o(b,a,!1)}function i(a){return/^on[a-z]+$/.test(a)}function j(a){return/^\w[a-zA-Z_0-9]*$/.test(a)}function k(a){return H&&j(a)?new Function("return this.impl."+a):function(){return this.impl[a]}}function l(a){return H&&j(a)?new Function("v","this.impl."+a+" = v"):function(b){this.impl[a]=b}}function m(a){return H&&j(a)?new Function("return this.impl."+a+".apply(this.impl, arguments)"):function(){return this.impl[a].apply(this.impl,arguments)}}function n(a,b){try{return Object.getOwnPropertyDescriptor(a,b)}catch(c){return O}}function o(b,c,d){for(var e=L(b),f=0;f<e.length;f++){var g=e[f];if("polymerBlackList_"!==g&&!(g in c||b.polymerBlackList_&&b.polymerBlackList_[g])){N&&b.__lookupGetter__(g);var h,j,o=n(b,g);if(d&&"function"==typeof o.value)c[g]=m(g);else{var p=i(g);h=p?a.getEventHandlerGetter(g):k(g),(o.writable||o.set)&&(j=p?a.getEventHandlerSetter(g):l(g)),K(c,g,{get:h,set:j,configurable:o.configurable,enumerable:o.enumerable})}}}}function p(a,b,c){var e=a.prototype;q(e,b,c),d(b,a)}function q(a,c,d){var e=c.prototype;b(void 0===E.get(a)),E.set(a,c),F.set(e,a),g(a,e),d&&h(e,d),K(e,"constructor",{value:c,configurable:!0,enumerable:!1,writable:!0})}function r(a,b){return E.get(b.prototype)===a}function s(a){var b=Object.getPrototypeOf(a),c=f(b),d=t(c);return q(b,d,a),d}function t(a){function b(b){a.call(this,b)}return b.prototype=Object.create(a.prototype),b.prototype.constructor=b,b}function u(a){return a instanceof G.EventTarget||a instanceof G.Event||a instanceof G.Range||a instanceof G.DOMImplementation||a instanceof G.CanvasRenderingContext2D||G.WebGLRenderingContext&&a instanceof G.WebGLRenderingContext}function v(a){return Q&&a instanceof Q||a instanceof S||a instanceof R||a instanceof T||a instanceof U||a instanceof P||a instanceof V||W&&a instanceof W||X&&a instanceof X}function w(a){return null===a?null:(b(v(a)),a.polymerWrapper_||(a.polymerWrapper_=new(f(a))(a)))}function x(a){return null===a?null:(b(u(a)),a.impl)}function y(a){return a&&u(a)?x(a):a}function z(a){return a&&!u(a)?w(a):a}function A(a,c){null!==c&&(b(v(a)),b(void 0===c||u(c)),a.polymerWrapper_=c)}function B(a,b,c){K(a.prototype,b,{get:c,configurable:!0,enumerable:!0})}function C(a,b){B(a,b,function(){return w(this.impl[b])})}function D(a,b){a.forEach(function(a){b.forEach(function(b){a.prototype[b]=function(){var a=z(this);return a[b].apply(a,arguments)}})})}var E=new WeakMap,F=new WeakMap,G=Object.create(null),H=!("securityPolicy"in document)||document.securityPolicy.allowsEval;if(H)try{var I=new Function("","return true;");H=I()}catch(J){H=!1}var K=Object.defineProperty,L=Object.getOwnPropertyNames,M=Object.getOwnPropertyDescriptor;L(window);var N=/Firefox/.test(navigator.userAgent),O={get:function(){},set:function(){},configurable:!0,enumerable:!0},P=window.DOMImplementation,Q=window.EventTarget,R=window.Event,S=window.Node,T=window.Window,U=window.Range,V=window.CanvasRenderingContext2D,W=window.WebGLRenderingContext,X=window.SVGElementInstance;a.assert=b,a.constructorTable=E,a.defineGetter=B,a.defineWrapGetter=C,a.forwardMethodsToWrapper=D,a.isWrapper=u,a.isWrapperFor=r,a.mixin=c,a.nativePrototypeTable=F,a.oneOf=e,a.registerObject=s,a.registerWrapper=p,a.rewrap=A,a.unwrap=x,a.unwrapIfNeeded=y,a.wrap=w,a.wrapIfNeeded=z,a.wrappers=G}(window.ShadowDOMPolyfill),function(a){"use strict";function b(){g=!1;var a=f.slice(0);f=[];for(var b=0;b<a.length;b++)a[b]()}function c(a){f.push(a),g||(g=!0,d(b,0))}var d,e=window.MutationObserver,f=[],g=!1;if(e){var h=1,i=new e(b),j=document.createTextNode(h);i.observe(j,{characterData:!0}),d=function(){h=(h+1)%2,j.data=h}}else d=window.setImmediate||window.setTimeout;a.setEndOfMicrotask=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(){p||(k(c),p=!0)}function c(){p=!1;do for(var a=o.slice(),b=!1,c=0;c<a.length;c++){var d=a[c],e=d.takeRecords();f(d),e.length&&(d.callback_(e,d),b=!0)}while(b)}function d(a,b){this.type=a,this.target=b,this.addedNodes=new m.NodeList,this.removedNodes=new m.NodeList,this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function e(a,b){for(;a;a=a.parentNode){var c=n.get(a);if(c)for(var d=0;d<c.length;d++){var e=c[d];e.options.subtree&&e.addTransientObserver(b)}}}function f(a){for(var b=0;b<a.nodes_.length;b++){var c=a.nodes_[b],d=n.get(c);if(!d)return;for(var e=0;e<d.length;e++){var f=d[e];f.observer===a&&f.removeTransientObservers()}}}function g(a,c,e){for(var f=Object.create(null),g=Object.create(null),h=a;h;h=h.parentNode){var i=n.get(h);if(i)for(var j=0;j<i.length;j++){var k=i[j],l=k.options;if((h===a||l.subtree)&&!("attributes"===c&&!l.attributes||"attributes"===c&&l.attributeFilter&&(null!==e.namespace||-1===l.attributeFilter.indexOf(e.name))||"characterData"===c&&!l.characterData||"childList"===c&&!l.childList)){var m=k.observer;f[m.uid_]=m,("attributes"===c&&l.attributeOldValue||"characterData"===c&&l.characterDataOldValue)&&(g[m.uid_]=e.oldValue)}}}var o=!1;for(var p in f){var m=f[p],q=new d(c,a);"name"in e&&"namespace"in e&&(q.attributeName=e.name,q.attributeNamespace=e.namespace),e.addedNodes&&(q.addedNodes=e.addedNodes),e.removedNodes&&(q.removedNodes=e.removedNodes),e.previousSibling&&(q.previousSibling=e.previousSibling),e.nextSibling&&(q.nextSibling=e.nextSibling),void 0!==g[p]&&(q.oldValue=g[p]),m.records_.push(q),o=!0}o&&b()}function h(a){if(this.childList=!!a.childList,this.subtree=!!a.subtree,this.attributes="attributes"in a||!("attributeOldValue"in a||"attributeFilter"in a)?!!a.attributes:!0,this.characterData="characterDataOldValue"in a&&!("characterData"in a)?!0:!!a.characterData,!this.attributes&&(a.attributeOldValue||"attributeFilter"in a)||!this.characterData&&a.characterDataOldValue)throw new TypeError;if(this.characterData=!!a.characterData,this.attributeOldValue=!!a.attributeOldValue,this.characterDataOldValue=!!a.characterDataOldValue,"attributeFilter"in a){if(null==a.attributeFilter||"object"!=typeof a.attributeFilter)throw new TypeError;this.attributeFilter=q.call(a.attributeFilter)}else this.attributeFilter=null}function i(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++r,o.push(this)}function j(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var k=a.setEndOfMicrotask,l=a.wrapIfNeeded,m=a.wrappers,n=new WeakMap,o=[],p=!1,q=Array.prototype.slice,r=0;i.prototype={observe:function(a,b){a=l(a);var c,d=new h(b),e=n.get(a);e||n.set(a,e=[]);for(var f=0;f<e.length;f++)e[f].observer===this&&(c=e[f],c.removeTransientObservers(),c.options=d);c||(c=new j(this,a,d),e.push(c),this.nodes_.push(a))},disconnect:function(){this.nodes_.forEach(function(a){for(var b=n.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}},j.prototype={addTransientObserver:function(a){if(a!==this.target){this.transientObservedNodes.push(a);var b=n.get(a);b||n.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[];for(var b=0;b<a.length;b++)for(var c=a[b],d=n.get(c),e=0;e<d.length;e++)if(d[e]===this){d.splice(e,1);break}}},a.enqueueMutation=g,a.registerTransientObservers=e,a.wrappers.MutationObserver=i,a.wrappers.MutationRecord=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a instanceof Q.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)&&P(b)||null}function f(f,g,h){if(h.length)return h.shift();if(b(f))return j(f)||f.host;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(a,d){for(var e=[];a;){for(var g=[],i=d,j=void 0;i;){var l=null;if(g.length){if(c(i)&&(l=h(g),k(j))){var n=g[g.length-1];g.push(n)}}else g.push(i);if(m(i,a))return g[g.length-1];b(i)&&g.pop(),j=i,i=f(i,l,e)}a=b(a)?a.host:a.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(a,b){return a===b?!0:a instanceof Q.ShadowRoot?n(l(a.host),b):!1}function o(a){return S.get(a)?void 0:(S.set(a,!0),p(P(a),P(a.target)))}function p(b,c){if(T.get(b))throw new Error("InvalidStateError");T.set(b,!0),a.renderAllPending();var d=g(c);return"load"===b.type&&2===d.length&&d[0].target instanceof Q.Document&&d.shift(),_.set(b,d),q(b,d)&&r(b,d)&&s(b,d),X.set(b,v.NONE),V.delete(b,null),T.delete(b),b.defaultPrevented}function q(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=v.CAPTURING_PHASE,!t(b[d],a,c)))return!1}return!0}function r(a,b){var c=v.AT_TARGET;return t(b[0],a,c)}function s(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=v.AT_TARGET;else{if(!d||Z.get(a))continue;c=v.BUBBLING_PHASE}if(!t(b[e],a,c))return}}function t(a,b,c){var d=a.target,e=a.currentTarget,f=R.get(e);if(!f)return!0;if("relatedTarget"in b){var g=O(b);if(g.relatedTarget){var h=P(g.relatedTarget),j=i(e,h);if(j===d)return!0;W.set(b,j)}}X.set(b,c);var k=b.type,l=!1;U.set(b,d),V.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===v.CAPTURING_PHASE||n.capture&&c===v.BUBBLING_PHASE))try{if("function"==typeof n.handler?n.handler.call(e,b):n.handler.handleEvent(b),Z.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!Y.get(b)}function u(a,b,c){this.type=a,this.handler=b,this.capture=Boolean(c)}function v(a,b){return a instanceof ab?void(this.impl=a):P(z(ab,"Event",a,b))}function w(a){return a&&a.relatedTarget?Object.create(a,{relatedTarget:{value:O(a.relatedTarget)}}):a}function x(a,b,c){var d=window[a],e=function(b,c){return b instanceof d?void(this.impl=b):P(z(d,a,b,c))};if(e.prototype=Object.create(b.prototype),c&&M(e.prototype,c),d)try{N(d,e,new d("temp"))}catch(f){N(d,e,document.createEvent(a))}return e}function y(a,b){return function(){arguments[b]=O(arguments[b]);var c=O(this);c[a].apply(c,arguments)}}function z(a,b,c,d){if(jb)return new a(c,w(d));var e=O(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=O(b)),g.push(b)}),e["init"+b].apply(e,g),e}function A(){v.call(this)}function B(a){return"function"==typeof a?!0:a&&a.handleEvent}function C(a){switch(a){case"DOMAttrModified":case"DOMAttributeNameChanged":case"DOMCharacterDataModified":case"DOMElementNameChanged":case"DOMNodeInserted":case"DOMNodeInsertedIntoDocument":case"DOMNodeRemoved":case"DOMNodeRemovedFromDocument":case"DOMSubtreeModified":return!0}return!1}function D(a){this.impl=a}function E(a){return a instanceof Q.ShadowRoot&&(a=a.host),O(a)}function F(a,b){var c=R.get(a);if(c)for(var d=0;d<c.length;d++)if(!c[d].removed&&c[d].type===b)return!0;return!1}function G(a,b){for(var c=O(a);c;c=c.parentNode)if(F(P(c),b))return!0;return!1}function H(a){L(a,mb)}function I(b,c,d,e){a.renderAllPending();for(var f=P(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 J(a){return function(){var b=$.get(this);return b&&b[a]&&b[a].value||null}}function K(a){var b=a.slice(2);return function(c){var d=$.get(this);d||(d=Object.create(null),$.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 L=a.forwardMethodsToWrapper,M=a.mixin,N=a.registerWrapper,O=a.unwrap,P=a.wrap,Q=a.wrappers,R=(new WeakMap,new WeakMap),S=new WeakMap,T=new WeakMap,U=new WeakMap,V=new WeakMap,W=new WeakMap,X=new WeakMap,Y=new WeakMap,Z=new WeakMap,$=new WeakMap,_=new WeakMap;u.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 ab=window.Event;ab.prototype.polymerBlackList_={returnValue:!0,keyLocation:!0},v.prototype={get target(){return U.get(this)},get currentTarget(){return V.get(this)},get eventPhase(){return X.get(this)},get path(){var a=new Q.NodeList,b=_.get(this);if(b){for(var c=0,d=b.length-1,e=l(V.get(this)),f=0;d>=f;f++){var g=b[f].currentTarget,h=l(g);n(e,h)&&(f!==d||g instanceof Q.Node)&&(a[c++]=g)}a.length=c}return a},stopPropagation:function(){Y.set(this,!0)},stopImmediatePropagation:function(){Y.set(this,!0),Z.set(this,!0)}},N(ab,v,document.createEvent("Event"));var bb=x("UIEvent",v),cb=x("CustomEvent",v),db={get relatedTarget(){return W.get(this)||P(O(this).relatedTarget)}},eb=M({initMouseEvent:y("initMouseEvent",14)},db),fb=M({initFocusEvent:y("initFocusEvent",5)},db),gb=x("MouseEvent",bb,eb),hb=x("FocusEvent",bb,fb),ib=Object.create(null),jb=function(){try{new window.FocusEvent("focus")}catch(a){return!1}return!0}();if(!jb){var kb=function(a,b,c){if(c){var d=ib[c];b=M(M({},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")}A.prototype=Object.create(v.prototype),M(A.prototype,{get returnValue(){return this.impl.returnValue},set returnValue(a){this.impl.returnValue=a}});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(B(b)&&!C(a)){var d=new u(a,b,c),e=R.get(this);if(e){for(var f=0;f<e.length;f++)if(d.equals(e[f]))return}else e=[],R.set(this,e);e.push(d);var g=E(this);g.addEventListener_(a,o,!0)
-}},removeEventListener:function(a,b,c){c=Boolean(c);var d=R.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,o,!0)}}},dispatchEvent:function(b){var c=O(b),d=c.type;S.set(c,!1),a.renderAllPending();var e;G(this,d)||(e=function(){},this.addEventListener(d,e,!0));try{return O(this).dispatchEvent_(c)}finally{e&&this.removeEventListener(d,e,!0)}}},lb&&N(lb,D);var nb=document.elementFromPoint;a.adjustRelatedTarget=i,a.elementFromPoint=I,a.getEventHandlerGetter=J,a.getEventHandlerSetter=K,a.wrapEventTargetMethods=H,a.wrappers.BeforeUnloadEvent=A,a.wrappers.CustomEvent=cb,a.wrappers.Event=v,a.wrappers.EventTarget=D,a.wrappers.FocusEvent=hb,a.wrappers.MouseEvent=gb,a.wrappers.UIEvent=bb}(window.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}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){x(a instanceof u)}function c(a){var b=new w;return b[0]=a,b.length=1,b}function d(a,b,c){z(b,"childList",{removedNodes:c,previousSibling:a.previousSibling,nextSibling:a.nextSibling})}function e(a,b){z(a,"childList",{removedNodes:b})}function f(a,b,d,e){if(a instanceof DocumentFragment){var f=h(a);H=!0;for(var g=f.length-1;g>=0;g--)a.removeChild(f[g]),f[g].parentNode_=b;H=!1;for(var g=0;g<f.length;g++)f[g].previousSibling_=f[g-1]||d,f[g].nextSibling_=f[g+1]||e;return d&&(d.nextSibling_=f[0]),e&&(e.previousSibling_=f[f.length-1]),f}var f=c(a),i=a.parentNode;return i&&i.removeChild(a),a.parentNode_=b,a.previousSibling_=d,a.nextSibling_=e,d&&(d.nextSibling_=a),e&&(e.previousSibling_=a),f}function g(a){if(a instanceof DocumentFragment)return h(a);var b=c(a),e=a.parentNode;return e&&d(a,e,b),b}function h(a){for(var b=new w,c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b.length=c,e(a,b),b}function i(a){return a}function j(a){a.nodeIsInserted_()}function k(a){for(var b=0;b<a.length;b++)j(a[b])}function l(){}function m(){}function n(a,b){var c=a.nodeType===u.DOCUMENT_NODE?a:a.ownerDocument;c!==b.ownerDocument&&c.adoptNode(b)}function o(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 p(a,b){o(a,b);var c=b.length;if(1===c)return E(b[0]);for(var d=E(a.ownerDocument.createDocumentFragment()),e=0;c>e;e++)d.appendChild(E(b[e]));return d}function q(a){if(void 0!==a.firstChild_)for(var b=a.firstChild_;b;){var c=b;b=b.nextSibling_,c.parentNode_=c.previousSibling_=c.nextSibling_=void 0}a.firstChild_=a.lastChild_=void 0}function r(a){if(a.invalidateShadowRenderer()){for(var b=a.firstChild;b;){x(b.parentNode===a);var c=b.nextSibling,d=E(b),e=d.parentNode;e&&M.call(e,d),b.previousSibling_=b.nextSibling_=b.parentNode_=null,b=c}a.firstChild_=a.lastChild_=null}else for(var c,f=E(a),g=f.firstChild;g;)c=g.nextSibling,M.call(f,g),g=c}function s(a){var b=a.parentNode;return b&&b.invalidateShadowRenderer()}function t(a){for(var b,c=0;c<a.length;c++)b=a[c],b.parentNode.removeChild(b)}function u(a){x(a instanceof I),v.call(this,a),this.parentNode_=void 0,this.firstChild_=void 0,this.lastChild_=void 0,this.nextSibling_=void 0,this.previousSibling_=void 0}var v=a.wrappers.EventTarget,w=a.wrappers.NodeList,x=a.assert,y=a.defineWrapGetter,z=a.enqueueMutation,A=a.isWrapper,B=a.mixin,C=a.registerTransientObservers,D=a.registerWrapper,E=a.unwrap,F=a.wrap,G=a.wrapIfNeeded,H=!1,I=window.Node,J=window.DocumentFragment,K=(I.prototype.appendChild,I.prototype.compareDocumentPosition),L=I.prototype.insertBefore,M=I.prototype.removeChild,N=I.prototype.replaceChild,O=/Trident/.test(navigator.userAgent),P=O?function(a,b){try{M.call(a,b)}catch(c){if(!(a instanceof J))throw c}}:function(a,b){M.call(a,b)};u.prototype=Object.create(v.prototype),B(u.prototype,{appendChild:function(a){return this.insertBefore(a,null)},insertBefore:function(a,c){b(a);var d;c?A(c)?d=E(c):(d=c,c=F(d)):(c=null,d=null),c&&x(c.parentNode===this);var e,h=c?c.previousSibling:this.lastChild,i=!this.invalidateShadowRenderer()&&!s(a);if(e=i?g(a):f(a,this,h,c),i)n(this,a),q(this),L.call(this.impl,E(a),d);else{h||(this.firstChild_=e[0]),c||(this.lastChild_=e[e.length-1]);var j=d?d.parentNode:this.impl;j?L.call(j,p(this,e),d):o(this,e)}return z(this,"childList",{addedNodes:e,nextSibling:c,previousSibling:h}),k(e),a},removeChild:function(a){if(b(a),a.parentNode!==this){for(var d=!1,e=(this.childNodes,this.firstChild);e;e=e.nextSibling)if(e===a){d=!0;break}if(!d)throw new Error("NotFoundError")}var f=E(a),g=a.nextSibling,h=a.previousSibling;if(this.invalidateShadowRenderer()){var i=this.firstChild,j=this.lastChild,k=f.parentNode;k&&P(k,f),i===a&&(this.firstChild_=g),j===a&&(this.lastChild_=h),h&&(h.nextSibling_=g),g&&(g.previousSibling_=h),a.previousSibling_=a.nextSibling_=a.parentNode_=void 0}else q(this),P(this.impl,f);return H||z(this,"childList",{removedNodes:c(a),nextSibling:g,previousSibling:h}),C(this,a),a},replaceChild:function(a,d){b(a);var e;if(A(d)?e=E(d):(e=d,d=F(e)),d.parentNode!==this)throw new Error("NotFoundError");var h,i=d.nextSibling,j=d.previousSibling,m=!this.invalidateShadowRenderer()&&!s(a);return m?h=g(a):(i===a&&(i=a.nextSibling),h=f(a,this,j,i)),m?(n(this,a),q(this),N.call(this.impl,E(a),e)):(this.firstChild===d&&(this.firstChild_=h[0]),this.lastChild===d&&(this.lastChild_=h[h.length-1]),d.previousSibling_=d.nextSibling_=d.parentNode_=void 0,e.parentNode&&N.call(e.parentNode,p(this,h),e)),z(this,"childList",{addedNodes:h,removedNodes:c(d),nextSibling:i,previousSibling:j}),l(d),k(h),d},nodeIsInserted_:function(){for(var a=this.firstChild;a;a=a.nextSibling)a.nodeIsInserted_()},hasChildNodes:function(){return null!==this.firstChild},get parentNode(){return void 0!==this.parentNode_?this.parentNode_:F(this.impl.parentNode)},get firstChild(){return void 0!==this.firstChild_?this.firstChild_:F(this.impl.firstChild)},get lastChild(){return void 0!==this.lastChild_?this.lastChild_:F(this.impl.lastChild)},get nextSibling(){return void 0!==this.nextSibling_?this.nextSibling_:F(this.impl.nextSibling)},get previousSibling(){return void 0!==this.previousSibling_?this.previousSibling_:F(this.impl.previousSibling)},get parentElement(){for(var a=this.parentNode;a&&a.nodeType!==u.ELEMENT_NODE;)a=a.parentNode;return a},get textContent(){for(var a="",b=this.firstChild;b;b=b.nextSibling)b.nodeType!=u.COMMENT_NODE&&(a+=b.textContent);return a},set textContent(a){var b=i(this.childNodes);if(this.invalidateShadowRenderer()){if(r(this),""!==a){var c=this.impl.ownerDocument.createTextNode(a);this.appendChild(c)}}else q(this),this.impl.textContent=a;var d=i(this.childNodes);z(this,"childList",{addedNodes:d,removedNodes:b}),m(b),k(d)},get childNodes(){for(var a=new w,b=0,c=this.firstChild;c;c=c.nextSibling)a[b++]=c;return a.length=b,a},cloneNode:function(a){var b=F(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=G(a),a===this)return!0;var b=a.parentNode;return b?this.contains(b):!1},compareDocumentPosition:function(a){return K.call(this.impl,E(a))},normalize:function(){for(var a,b,c=i(this.childNodes),d=[],e="",f=0;f<c.length;f++)b=c[f],b.nodeType===u.TEXT_NODE?a||b.data.length?a?(e+=b.data,d.push(b)):a=b:this.removeNode(b):(a&&d.length&&(a.data+=e,cleanUpNodes(d)),d=[],e="",a=null,b.childNodes.length&&b.normalize());a&&d.length&&(a.data+=e,t(d))}}),y(u,"ownerDocument"),D(I,u,document.createDocumentFragment()),delete u.prototype.querySelector,delete u.prototype.querySelectorAll,u.prototype=B(Object.create(v.prototype),u.prototype),a.nodeWasAdded=j,a.nodeWasRemoved=l,a.nodesWereAdded=k,a.nodesWereRemoved=m,a.snapshotNodeList=i,a.wrappers.Node=u}(window.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}(window.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}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}var c=a.ChildNodeInterface,d=a.wrappers.Node,e=a.enqueueMutation,f=a.mixin,g=a.registerWrapper,h=window.CharacterData;b.prototype=Object.create(d.prototype),f(b.prototype,{get textContent(){return this.data},set textContent(a){this.data=a},get data(){return this.impl.data},set data(a){var b=this.impl.data;e(this,"characterData",{oldValue:b}),this.impl.data=a}}),f(b.prototype,c),g(h,b,document.createTextNode("")),a.wrappers.CharacterData=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a>>>0}function c(a){d.call(this,a)}var d=a.wrappers.CharacterData,e=(a.enqueueMutation,a.mixin),f=a.registerWrapper,g=window.Text;c.prototype=Object.create(d.prototype),e(c.prototype,{splitText:function(a){a=b(a);var c=this.data;if(a>c.length)throw new Error("IndexSizeError");var d=c.slice(0,a),e=c.slice(a);this.data=d;var f=this.ownerDocument.createTextNode(e);return this.parentNode&&this.parentNode.insertBefore(f,this.nextSibling),f}}),f(g,c,document.createTextNode("")),a.wrappers.Text=c}(window.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,b,c){k(a,"attributes",{name:b,namespace:null,oldValue:c})}function d(a){h.call(this,a)}function e(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 f=a.ChildNodeInterface,g=a.GetElementsByInterface,h=a.wrappers.Node,i=a.ParentNodeInterface,j=a.SelectorsInterface,k=(a.addWrapNodeListMethod,a.enqueueMutation),l=a.mixin,m=(a.oneOf,a.registerWrapper),n=a.wrappers,o=window.Element,p=["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"].filter(function(a){return o.prototype[a]}),q=p[0],r=o.prototype[q];d.prototype=Object.create(h.prototype),l(d.prototype,{createShadowRoot:function(){var b=new n.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,d){var e=this.impl.getAttribute(a);this.impl.setAttribute(a,d),c(this,a,e),b(this,a)},removeAttribute:function(a){var d=this.impl.getAttribute(a);this.impl.removeAttribute(a),c(this,a,d),b(this,a)},matches:function(a){return r.call(this.impl,a)}}),p.forEach(function(a){"matches"!==a&&(d.prototype[a]=function(a){return this.matches(a)})}),o.prototype.webkitCreateShadowRoot&&(d.prototype.webkitCreateShadowRoot=d.prototype.createShadowRoot),e(d.prototype,"id"),e(d.prototype,"className","class"),l(d.prototype,f),l(d.prototype,g),l(d.prototype,i),l(d.prototype,j),m(o,d,document.createElementNS(null,"x")),a.matchesNames=p,a.wrappers.Element=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a){case"&":return"&amp;";case"<":return"&lt;";case">":return"&gt;";case'"':return"&quot;";case" ":return"&nbsp;"}}function c(a){return a.replace(y,b)}function d(a){return a.replace(z,b)}function e(a){for(var b={},c=0;c<a.length;c++)b[a[c]]=!0;return b}function f(a,b){switch(a.nodeType){case Node.ELEMENT_NODE:for(var e,f=a.tagName.toLowerCase(),h="<"+f,i=a.attributes,j=0;e=i[j];j++)h+=" "+e.name+'="'+c(e.value)+'"';return h+=">",A[f]?h:h+g(a)+"</"+f+">";case Node.TEXT_NODE:var k=a.data;return b&&B[b.localName]?k:d(k);case Node.COMMENT_NODE:return"<!--"+a.data+"-->";default:throw console.error(a),new Error("not implemented")}}function g(a){for(var b="",c=a.firstChild;c;c=c.nextSibling)b+=f(c,a);return b}function h(a,b,c){var d=c||"div";a.textContent="";var e=w(a.ownerDocument.createElement(d));e.innerHTML=b;for(var f;f=e.firstChild;)a.appendChild(x(f))}function i(a){o.call(this,a)}function j(a,b){var c=w(a.cloneNode(!1));c.innerHTML=b;for(var d,e=w(document.createDocumentFragment());d=c.firstChild;)e.appendChild(d);return x(e)}function k(b){return function(){return a.renderAllPending(),this.impl[b]}}function l(a){p(i,a,k(a))}function m(b){Object.defineProperty(i.prototype,b,{get:k(b),set:function(c){a.renderAllPending(),this.impl[b]=c},configurable:!0,enumerable:!0})}function n(b){Object.defineProperty(i.prototype,b,{value:function(){return a.renderAllPending(),this.impl[b].apply(this.impl,arguments)},configurable:!0,enumerable:!0})}var o=a.wrappers.Element,p=a.defineGetter,q=a.enqueueMutation,r=a.mixin,s=a.nodesWereAdded,t=a.nodesWereRemoved,u=a.registerWrapper,v=a.snapshotNodeList,w=a.unwrap,x=a.wrap,y=/[& "]/g,z=/[& <>]/g,A=e(["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"]),B=e(["style","script","xmp","iframe","noembed","noframes","plaintext","noscript"]),C=/MSIE/.test(navigator.userAgent),D=window.HTMLElement;i.prototype=Object.create(o.prototype),r(i.prototype,{get innerHTML(){return g(this)},set innerHTML(a){if(C&&B[this.localName])return void(this.textContent=a);var b=v(this.childNodes);this.invalidateShadowRenderer()?h(this,a,this.tagName):this.impl.innerHTML=a;var c=v(this.childNodes);q(this,"childList",{addedNodes:c,removedNodes:b}),t(b),s(c)},get outerHTML(){return f(this,this.parentNode)},set outerHTML(a){var b=this.parentNode;if(b){b.invalidateShadowRenderer();var c=j(b,a);b.replaceChild(c,this)}},insertAdjacentHTML:function(a,b){var c,d;switch(String(a).toLowerCase()){case"beforebegin":c=this.parentNode,d=this;break;case"afterend":c=this.parentNode,d=this.nextSibling;break;case"afterbegin":c=this,d=this.firstChild;break;case"beforeend":c=this,d=null;break;default:return}var e=j(c,b);c.insertBefore(e,d)}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(l),["scrollLeft","scrollTop"].forEach(m),["getBoundingClientRect","getClientRects","scrollIntoView"].forEach(n),u(D,i,document.createElement("b")),a.wrappers.HTMLElement=i,a.getInnerHTML=g,a.setInnerHTML=h}(window.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,document.createElement("canvas")),a.wrappers.HTMLCanvasElement=b}(window.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}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a,b){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var e=f(document.createElement("img"));d.call(this,e),g(e,this),void 0!==a&&(e.width=a),void 0!==b&&(e.height=b)}var d=a.wrappers.HTMLElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLImageElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("img")),c.prototype=b.prototype,a.wrappers.HTMLImageElement=b,a.wrappers.Image=c}(window.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}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){if(!a.defaultView)return a;var b=m.get(a);if(!b){for(b=a.implementation.createHTMLDocument("");b.lastChild;)b.removeChild(b.lastChild);m.set(a,b)}return b}function c(a){for(var c,d=b(a.ownerDocument),e=j(d.createDocumentFragment());c=a.firstChild;)e.appendChild(c);return e}function d(a){if(e.call(this,a),!n){var b=c(a);l.set(this,k(b))}}var e=a.wrappers.HTMLElement,f=a.getInnerHTML,g=a.mixin,h=a.registerWrapper,i=a.setInnerHTML,j=a.unwrap,k=a.wrap,l=new WeakMap,m=new WeakMap,n=window.HTMLTemplateElement;d.prototype=Object.create(e.prototype),g(d.prototype,{get content(){return n?k(this.impl.content):l.get(this)},get innerHTML(){return f(this.content)},set innerHTML(a){i(this.content,a)}}),n&&h(n,d),a.wrappers.HTMLTemplateElement=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.registerWrapper,e=window.HTMLMediaElement;b.prototype=Object.create(c.prototype),d(e,b,document.createElement("audio")),a.wrappers.HTMLMediaElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var b=f(document.createElement("audio"));d.call(this,b),g(b,this),b.setAttribute("preload","auto"),void 0!==a&&b.setAttribute("src",a)}var d=a.wrappers.HTMLMediaElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLAudioElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("audio")),c.prototype=b.prototype,a.wrappers.HTMLAudioElement=b,a.wrappers.Audio=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a.replace(/\s+/g," ").trim()}function c(a){e.call(this,a)}function d(a,b,c,f){if(!(this instanceof d))throw new TypeError("DOM object constructor cannot be called as a function.");var g=i(document.createElement("option"));e.call(this,g),h(g,this),void 0!==a&&(g.text=a),void 0!==b&&g.setAttribute("value",b),c===!0&&g.setAttribute("selected",""),g.selected=f===!0}var e=a.wrappers.HTMLElement,f=a.mixin,g=a.registerWrapper,h=a.rewrap,i=a.unwrap,j=a.wrap,k=window.HTMLOptionElement;c.prototype=Object.create(e.prototype),f(c.prototype,{get text(){return b(this.textContent)},set text(a){this.textContent=b(String(a))},get form(){return j(i(this).form)}}),g(k,c,document.createElement("option")),d.prototype=c.prototype,a.wrappers.HTMLOptionElement=c,a.wrappers.Option=d}(window.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,g=(a.mixin,a.registerWrapper),h=window.HTMLUnknownElement;b.prototype=Object.create(d.prototype),g(h,b),a.wrappers.HTMLUnknownElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";var b=a.registerObject,c="http://www.w3.org/2000/svg",d=document.createElementNS(c,"title"),e=b(d),f=Object.getPrototypeOf(e.prototype).constructor;a.wrappers.SVGElement=f}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){m.call(this,a)}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.wrap,g=window.SVGUseElement,h="http://www.w3.org/2000/svg",i=f(document.createElementNS(h,"g")),j=document.createElementNS(h,"use"),k=i.constructor,l=Object.getPrototypeOf(k.prototype),m=l.constructor;b.prototype=Object.create(l),"instanceRoot"in j&&c(b.prototype,{get instanceRoot(){return f(e(this).instanceRoot)},get animatedInstanceRoot(){return f(e(this).animatedInstanceRoot)}}),d(g,b,j),a.wrappers.SVGUseElement=b}(window.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.wrap,g=window.SVGElementInstance;g&&(b.prototype=Object.create(c.prototype),d(b.prototype,{get correspondingElement(){return f(this.impl.correspondingElement)},get correspondingUseElement(){return f(this.impl.correspondingUseElement)},get parentNode(){return f(this.impl.parentNode)},get childNodes(){throw new Error("Not implemented")},get firstChild(){return f(this.impl.firstChild)},get lastChild(){return f(this.impl.lastChild)},get previousSibling(){return f(this.impl.previousSibling)},get nextSibling(){return f(this.impl.nextSibling)}}),e(g,b),a.wrappers.SVGElementInstance=b)}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.unwrapIfNeeded,g=a.wrap,h=window.CanvasRenderingContext2D;c(b.prototype,{get canvas(){return g(this.impl.canvas)},drawImage:function(){arguments[0]=f(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(h,b,document.createElement("canvas").getContext("2d")),a.wrappers.CanvasRenderingContext2D=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrapIfNeeded,f=a.wrap,g=window.WebGLRenderingContext;if(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)}});var h=/WebKit/.test(navigator.userAgent)?{drawingBufferHeight:null,drawingBufferWidth:null}:{};d(g,b,h),a.wrappers.WebGLRenderingContext=b}}(window.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))},toString:function(){return this.impl.toString()}},g.prototype.createContextualFragment&&(b.prototype.createContextualFragment=function(a){return f(this.impl.createContextualFragment(a))}),c(window.Range,b,document.createRange()),a.wrappers.Range=b}(window.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.createComment(""));a.wrappers.Comment=h,a.wrappers.DocumentFragment=g}(window.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,l=/[ \t\n\r\f]/;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},get host(){return j.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 l.test(a)?null:this.querySelector('[id="'+a+'"]')}}),a.wrappers.ShadowRoot=b}(window.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=F(a),g=F(c),h=e?F(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=G(f.lastChild);i&&(i.nextSibling_=i.nextSibling)}f.insertBefore(g,h)}function d(a){var c=F(a),d=c.parentNode;if(d){var e=G(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=I.get(a);c||I.set(a,c=[]),c.push(b)}function f(a){H.set(a,[])}function g(a){return H.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 z))return!1;if("*"===c||c===a.localName)return!0;if(!L.test(c))return!1;if(":"===c[0]&&!M.test(c))return!1;try{return a.matches(c)}catch(d){return!1}}function k(){for(var a=0;a<O.length;a++)O[a].render();O=[]}function l(){y=null,k()}function m(a){var b=K.get(a);return b||(b=new q(a),K.set(a,b)),b}function n(a){for(;a;a=a.parentNode)if(a instanceof D)return a;return null}function o(a){return m(a.host)}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 A}function s(a){return a instanceof A}function t(a){return a instanceof B}function u(a){return a instanceof B}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){J.set(a,b)}var y,z=a.wrappers.Element,A=a.wrappers.HTMLContentElement,B=a.wrappers.HTMLShadowElement,C=a.wrappers.Node,D=a.wrappers.ShadowRoot,E=(a.assert,a.mixin,a.oneOf),F=a.unwrap,G=a.wrap,H=new WeakMap,I=new WeakMap,J=new WeakMap,K=new WeakMap,L=/^[*.:#[a-zA-Z_|]/,M=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("|")+")"),N=E(window,["requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","setTimeout"]),O=[],P=new ArraySplice;P.equals=function(a,b){return F(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(F(b)),g=a||new WeakMap,i=P.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=G(f[k++]);g.get(q)||d(q)}for(var r=n.addedCount,s=f[k]&&G(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,O.push(this),y)return;y=window[N](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}},C.prototype.invalidateShadowRenderer=function(){var a=this.impl.polymerShadowRenderer_;return a?(a.invalidate(),!0):!1},A.prototype.getDistributedNodes=function(){return k(),g(this)},B.prototype.nodeIsInserted_=A.prototype.nodeIsInserted_=function(){this.invalidateShadowRenderer();var a,b=n(this);b&&(a=o(b)),this.impl.polymerShadowRenderer_=a,a&&a.invalidate()},a.eventParentsTable=I,a.getRendererForHost=m,a.getShadowTrees=w,a.insertionParentTable=J,a.renderAllPending=k,a.visual={insertBefore:c,remove:d}}(window.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","HTMLOutputElement","HTMLSelectElement","HTMLTextAreaElement"];i.forEach(b)}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}{var c=a.registerWrapper,d=a.unwrap,e=a.unwrapIfNeeded,f=a.wrap;window.Selection}b.prototype={get anchorNode(){return f(this.impl.anchorNode)},get focusNode(){return f(this.impl.focusNode)},addRange:function(a){this.impl.addRange(d(a))},collapse:function(a,b){this.impl.collapse(e(a),b)},containsNode:function(a,b){return this.impl.containsNode(e(a),b)},extend:function(a,b){this.impl.extend(e(a),b)},getRangeAt:function(a){return f(this.impl.getRangeAt(a))},removeRange:function(a){this.impl.removeRange(d(a))},selectAllChildren:function(a){this.impl.selectAllChildren(e(a))},toString:function(){return this.impl.toString()}},c(window.Selection,b,window.getSelection()),a.wrappers.Selection=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){k.call(this,a)}function c(a){var c=document[a];b.prototype[a]=function(){return y(c.apply(this.impl,arguments))}}function d(a,b){B.call(b.impl,x(a)),e(a,b)}function e(a,b){a.shadowRoot&&b.adoptNode(a.shadowRoot),a instanceof o&&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 y(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.wrappers.Selection,n=a.SelectorsInterface,o=a.wrappers.ShadowRoot,p=a.defineWrapGetter,q=a.elementFromPoint,r=a.forwardMethodsToWrapper,s=a.matchesNames,t=a.mixin,u=a.registerWrapper,v=a.renderAllPending,w=a.rewrap,x=a.unwrap,y=a.wrap,z=a.wrapEventTargetMethods,A=(a.wrapNodeList,new WeakMap);b.prototype=Object.create(k.prototype),p(b,"documentElement"),p(b,"body"),p(b,"head"),["createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","getElementById"].forEach(c);var B=document.adoptNode,C=document.importNode,D=document.getSelection;if(t(b.prototype,{adoptNode:function(a){return a.parentNode&&a.parentNode.removeChild(a),d(a,this),a},elementFromPoint:function(a,b){return q(this,this,a,b)},importNode:function(a,b){var c=y(C.call(this.impl,x(a),!1));if(b)for(var d=a.firstChild;d;d=d.nextSibling)c.appendChild(this.importNode(d,!0));return c},getSelection:function(){return v(),new m(D.call(x(this)))}}),document.registerElement){var E=document.registerElement;b.prototype.registerElement=function(b,c){function d(a){return a?void(this.impl=a):c.extends?document.createElement(c.extends,b):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);["createdCallback","attachedCallback","detachedCallback","attributeChangedCallback"].forEach(function(a){var b=e[a];b&&(i[a]=function(){y(this)instanceof d||w(this),b.apply(y(this),arguments)})});var k={prototype:i};c.extends&&(k.extends=c.extends),d.prototype=e,d.prototype.constructor=d,a.constructorTable.set(i,d),a.nativePrototypeTable.set(e,i);E.call(x(this),b,k);return d},r([window.HTMLDocument||window.Document],["registerElement"])}r([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild"].concat(s)),r([window.HTMLDocument||window.Document],["adoptNode","importNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","elementFromPoint","getElementById","getSelection"]),t(b.prototype,j),t(b.prototype,l),t(b.prototype,n),t(b.prototype,{get implementation(){var a=A.get(this);return a?a:(a=new g(x(this).implementation),A.set(this,a),a)}}),u(window.Document,b,document.implementation.createHTMLDocument("")),window.HTMLDocument&&u(window.HTMLDocument,b),z([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]),h(g,"createDocumentType"),h(g,"createDocument"),h(g,"createHTMLDocument"),i(g,"hasFeature"),u(window.DOMImplementation,g),r([window.DOMImplementation],["createDocumentType","createDocument","createHTMLDocument","hasFeature"]),a.adoptNodeNoRemove=d,a.wrappers.DOMImplementation=g,a.wrappers.Document=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.EventTarget,d=a.wrappers.Selection,e=a.mixin,f=a.registerWrapper,g=a.renderAllPending,h=a.unwrap,i=a.unwrapIfNeeded,j=a.wrap,k=window.Window,l=window.getComputedStyle,m=window.getSelection;b.prototype=Object.create(c.prototype),k.prototype.getComputedStyle=function(a,b){return j(this||window).getComputedStyle(i(a),b)},k.prototype.getSelection=function(){return j(this||window).getSelection()},delete window.getComputedStyle,delete window.getSelection,["addEventListener","removeEventListener","dispatchEvent"].forEach(function(a){k.prototype[a]=function(){var b=j(this||window);return b[a].apply(b,arguments)},delete window[a]}),e(b.prototype,{getComputedStyle:function(a,b){return g(),l.call(h(this),i(a),b)},getSelection:function(){return g(),new d(m.call(h(this)))}}),f(k,b),a.wrappers.Window=b}(window.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}}var c=(a.isWrapperFor,{a:"HTMLAnchorElement",area:"HTMLAreaElement",br:"HTMLBRElement",base:"HTMLBaseElement",body:"HTMLBodyElement",button:"HTMLButtonElement",dl:"HTMLDListElement",datalist:"HTMLDataListElement",data:"HTMLDataElement",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",marquee:"HTMLMarqueeElement",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",time:"HTMLTimeElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",table:"HTMLTableElement",tr:"HTMLTableRowElement",thead:"HTMLTableSectionElement",tbody:"HTMLTableSectionElement",textarea:"HTMLTextAreaElement",track:"HTMLTrackElement",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}(window.ShadowDOMPolyfill),function(){{var a=window.ShadowDOMPolyfill;a.wrap}Object.defineProperties(HTMLElement.prototype,{webkitShadowRoot:{get:function(){return this.shadowRoot}}}),window.wrap=window.ShadowDOMPolyfill.wrap,window.unwrap=window.ShadowDOMPolyfill.unwrap,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");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 v||(v=document.createElement("style"),v.setAttribute("ShadowCSSShim",""),v.shadowCssShim=!0),v}var h=(a.loader,{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);var h=this.stylesToShimmedCssText(g.rootStyles,g.scopeStyles,b,e);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)},stylesToShimmedCssText:function(a,b,c,d){c=c||"",this.insertPolyfillDirectives(a),this.insertPolyfillRules(a);var e=this.shimAtHost(b,c,d)+this.shimScoping(b,c,d);return e+=this.extractPolyfillUnscopedRules(a)},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(n,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(o,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=p.exec(a);)c+=b[1].slice(0,-1)+"\n\n";return 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(i,function(a,b){return h.scopeHostCss(b,c,f)}),g=e(this.findAtHostRules(d(g),this.makeScopeMatcher(c,f)))},scopeHostCss:function(a,b,c){var d=this;return a.replace(j,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(k)?a=a.replace(k,c?f+"$1$3":b+"$1$3"):a.match(l)&&(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(i,"");f=this.insertPolyfillHostInCssText(f),f=this.convertColonHost(f),f=this.convertColonAncestor(f),f=this.convertPseudos(f),f=this.convertParts(f),f=this.convertCombinators(f);var g=d(f);return c&&(f=this.scopeRules(g,c,e)),f},convertPseudos:function(a){return a.replace(q," [pseudo=$1]")},convertParts:function(a){return a.replace(r," [part=$1]")},convertColonHost:function(a){return this.convertColonRule(a,cssColonHostRe,this.colonHostPartReplacer)},convertColonAncestor:function(a){return this.convertColonRule(a,cssColonAncestorRe,this.colonAncestorPartReplacer)},convertColonRule:function(a,b,c){return a.replace(b,function(a,b,d,e){if(b=polyfillHostNoCombinator,d){for(var f,g=d.split(","),h=[],i=0,j=g.length;j>i&&(f=g[i]);i++)f=f.trim(),h.push(c(b,f,e));return h.join(",")}return b+e})},colonAncestorPartReplacer:function(a,b,c){return b.match(s)?this.colonHostPartReplacer(a,b,c):a+b+c+", "+b+" "+a+c},colonHostPartReplacer:function(a,b,c){return a+b.replace(s,"")+c},convertCombinators:function(a){return a.replace(/\^\^/g," ").replace(/\^/g," ")},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,c),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&&!a.match(polyfillHostNoCombinator)?this.applyStrictSelectorScope(a,b):this.applySimpleSelectorScope(a,b,c)),e.push(a)},this),e.join(", ")},selectorNeedsScoping:function(a,b,c){var d=this.makeScopeMatcher(b,c);return!a.match(d)},makeScopeMatcher:function(a,b){var c=b?"\\[is=['\"]?"+a+"['\"]?\\]":a;return new RegExp("^("+c+")"+selectorReSuffix,"m")},applySimpleSelectorScope:function(a,b,c){var d=c?"[is="+b+"]":b;return a.match(polyfillHostRe)?(a=a.replace(polyfillHostNoCombinator,d),a.replace(polyfillHostRe,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(polyfillHostRe,"");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(hostRe,s).replace(colonHostRe,s).replace(colonAncestorRe,t)},propertiesFromRule:function(a){return a.style.content&&!a.style.content.match(/['"]+/)?a.style.cssText.replace(/content:[^;]*;/g,"content: '"+a.style.content+"';"):a.style.cssText}}),i=/@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim,j=/([^{]*)({[\s\S]*?})/gim,k=/(.*)((?:\*)|(?:\:scope))(.*)/,l=/^[.\[:]/,m=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,n=/\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim,o=/\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,p=/\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,q=/::(x-[^\s{,(]*)/gim,r=/::part\(([^)]*)\)/gim,s="-shadowcsshost",t="-shadowcssancestor",u=")(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)";cssColonHostRe=new RegExp("("+s+u,"gim"),cssColonAncestorRe=new RegExp("("+t+u,"gim"),selectorReSuffix="([>\\s~+[.,{:][\\s\\S]*)?$",hostRe=/@host/gim,colonHostRe=/\:host/gim,colonAncestorRe=/\:ancestor/gim,polyfillHostNoCombinator=s+"-no-combinator",polyfillHostRe=new RegExp(s,"gim"),polyfillAncestorRe=new RegExp(t,"gim");var v;if(window.ShadowDOMPolyfill){f("style { display: none !important; }\n");var w=wrap(document),x=w.querySelector("head");x.insertBefore(g(),x.childNodes[0]),document.addEventListener("DOMContentLoaded",function(){window.HTMLImports&&!HTMLImports.useNative&&(HTMLImports.importer.preloadSelectors+=", link[rel=stylesheet]:not([nopolyfill])",HTMLImports.parser.parseGeneric=function(a){if(!a.shadowCssShim){var b=a;if(!a.hasAttribute("nopolyfill")){a.__resource?(b=a.ownerDocument.createElement("style"),b.textContent=Platform.loader.resolveUrlsInCssText(a.__resource,a.href),a.ownerDocument===w&&a.parentNode.removeChild(a)):Platform.loader.resolveUrlsInStyle(b);var c=[b];b.textContent=h.stylesToShimmedCssText(c,c),b.shadowCssShim=!0}b.parentNode!==x&&x.appendChild(b)}})})}a.ShadowCSS=h}(window.Platform)}
\ No newline at end of file
diff --git a/pkg/shadow_dom/lib/src/platform/patches-shadowdom-polyfill-before.js b/pkg/shadow_dom/lib/src/platform/patches-shadowdom-polyfill-before.js
deleted file mode 100644
index fe15015..0000000
--- a/pkg/shadow_dom/lib/src/platform/patches-shadowdom-polyfill-before.js
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright 2013 The Polymer Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style
- * license that can be found in the LICENSE file.
- */
-(function() {
-  // TODO(jmesserly): fix dart:html to use unprefixed name
-  if (Element.prototype.webkitCreateShadowRoot) {
-    Element.prototype.webkitCreateShadowRoot = function() {
-      return window.ShadowDOMPolyfill.wrapIfNeeded(this).createShadowRoot();
-    };
-  }
-})();
diff --git a/pkg/shadow_dom/lib/src/platform/patches-shadowdom-polyfill.js b/pkg/shadow_dom/lib/src/platform/patches-shadowdom-polyfill.js
deleted file mode 100644
index a5749ab..0000000
--- a/pkg/shadow_dom/lib/src/platform/patches-shadowdom-polyfill.js
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2013 The Polymer Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style
- * license that can be found in the LICENSE file.
- */
-(function() {
-  var ShadowDOMPolyfill = window.ShadowDOMPolyfill;
-  var wrap = ShadowDOMPolyfill.wrap;
-
-  // patch in prefixed name
-  Object.defineProperties(HTMLElement.prototype, {
-    //TODO(sjmiles): review accessor alias with Arv
-    webkitShadowRoot: {
-      get: function() {
-        return this.shadowRoot;
-      }
-    }
-  });
-
-  // ShadowCSS needs this:
-  window.wrap = window.ShadowDOMPolyfill.wrap;
-  window.unwrap = window.ShadowDOMPolyfill.unwrap;
-
-  //TODO(sjmiles): review method alias with Arv
-  HTMLElement.prototype.webkitCreateShadowRoot =
-      HTMLElement.prototype.createShadowRoot;
-
-  // TODO(jmesserly): we need to wrap document somehow (a dart:html hook?)
-  window.dartExperimentalFixupGetTag = function(originalGetTag) {
-    var NodeList = ShadowDOMPolyfill.wrappers.NodeList;
-    var ShadowRoot = ShadowDOMPolyfill.wrappers.ShadowRoot;
-    var unwrapIfNeeded = ShadowDOMPolyfill.unwrapIfNeeded;
-    function getTag(obj) {
-      // TODO(jmesserly): do we still need these?
-      if (obj instanceof NodeList) return 'NodeList';
-      if (obj instanceof ShadowRoot) return 'ShadowRoot';
-      if (window.MutationRecord && (obj instanceof MutationRecord))
-          return 'MutationRecord';
-      if (window.MutationObserver && (obj instanceof MutationObserver))
-          return 'MutationObserver';
-
-      // TODO(jmesserly): this prevents incorrect interaction between ShadowDOM
-      // and dart:html's <template> polyfill. Essentially, ShadowDOM is
-      // polyfilling native template, but our Dart polyfill fails to detect this
-      // because the unwrapped node is an HTMLUnknownElement, leading it to
-      // think the node has no content.
-      if (obj instanceof HTMLTemplateElement) return 'HTMLTemplateElement';
-
-      var unwrapped = unwrapIfNeeded(obj);
-      if (obj !== unwrapped) {
-        // Fix up class names for Firefox.
-        // For some of them (like HTMLFormElement and HTMLInputElement),
-        // the "constructor" property of the unwrapped nodes points at the
-        // same constructor as the wrapper.
-        var ctor = obj.constructor
-        if (ctor === unwrapped.constructor) {
-          var name = ctor._ShadowDOMPolyfill$cacheTag_;
-          if (!name) {
-            name = Object.prototype.toString.call(unwrapped);
-            name = name.substring(8, name.length - 1);
-            ctor._ShadowDOMPolyfill$cacheTag_ = name;
-          }
-          return name;
-        }
-
-        obj = unwrapped;
-      }
-      return originalGetTag(obj);
-    }
-
-    return getTag;
-  };
-})();
diff --git a/pkg/shadow_dom/lib/src/platform/platform-init.js b/pkg/shadow_dom/lib/src/platform/platform-init.js
deleted file mode 100644
index 4e83afc..0000000
--- a/pkg/shadow_dom/lib/src/platform/platform-init.js
+++ /dev/null
@@ -1,5 +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.
-
-var Platform = {};
diff --git a/pkg/shadow_dom/pubspec.yaml b/pkg/shadow_dom/pubspec.yaml
deleted file mode 100644
index fc1a529..0000000
--- a/pkg/shadow_dom/pubspec.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-name: shadow_dom
-version: 0.9.2
-author: Polymer.dart Authors <web-ui-dev@dartlang.org>
-homepage: https://www.dartlang.org/polymer-dart/
-description: >
-  Shadow DOM is designed to provide encapsulation by hiding DOM subtrees under
-  shadow roots. It provides a method of establishing and maintaining functional
-  boundaries between DOM trees and how these trees interact with each other
-  within a document, thus enabling better functional encapsulation within the
-  DOM.
-environment:
-  sdk: ">=1.2.0-dev.3.0 <2.0.0"
diff --git a/pkg/shadow_dom/test/runner.html b/pkg/shadow_dom/test/runner.html
deleted file mode 100644
index 83dd0ee..0000000
--- a/pkg/shadow_dom/test/runner.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright 2012 The Polymer Authors. All rights reserved.
-Use of this source code is governed by a BSD-style
-license that can be found in the LICENSE file.
--->
-<meta charset="utf-8">
-<link rel="stylesheet" href="../tool/node_modules/mocha/mocha.css">
-<script src="../tool/node_modules/chai/chai.js"></script>
-<script src="../tool/node_modules/mocha/mocha.js"></script>
-<script src="../tools/test/mocha-htmltest.js"></script>
-<script src="../tool/shadowdom.js"></script>
-<script src="../../../third_party/polymer/ShadowDOM/test/test.main.js"></script>
-<div id="mocha"></div>
-<script>
-mocha.run();
-</script>
diff --git a/pkg/shadow_dom/test/runner.min.html b/pkg/shadow_dom/test/runner.min.html
deleted file mode 100644
index 6c45525..0000000
--- a/pkg/shadow_dom/test/runner.min.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright 2012 The Polymer Authors. All rights reserved.
-Use of this source code is governed by a BSD-style
-license that can be found in the LICENSE file.
--->
-<meta charset="utf-8">
-<link rel="stylesheet" href="../tool/node_modules/mocha/mocha.css">
-<script src="../tool/node_modules/chai/chai.js"></script>
-<script src="../tool/node_modules/mocha/mocha.js"></script>
-<script src="../tools/test/mocha-htmltest.js"></script>
-<script src="../tool/shadowdom.min.js"></script>
-<script src="../../../third_party/polymer/ShadowDOM/test/test.main.js"></script>
-<div id="mocha"></div>
-<script>
-mocha.run();
-</script>
-
diff --git a/pkg/shadow_dom/tool/README.md b/pkg/shadow_dom/tool/README.md
deleted file mode 100644
index b4ee42c..0000000
--- a/pkg/shadow_dom/tool/README.md
+++ /dev/null
@@ -1,52 +0,0 @@
-This folder contains the logic for building the shadow_dom package's
-concatenated and minified JS files.
-
-## Prerequisites
-
-Install nodejs and npm. On Debian based systems this is typically:
-
-```bash
-     sudo apt-get install nodejs
-     sudo apt-get install npm
-```
-- Install grunt-cli:
-
-```bash
-    npm install -g grunt-cli
-```
-
-See the Grunt [getting started](http://gruntjs.com/getting-started) page
-for more information.
-
-## Building
-
-Run shadow_dom/tool/build.sh (from any directory):
-
-```bash
-    ./build.sh
-```
-
-## (optional) How to integrate Polymer upstream changes
-
-One time setup:
-
-```bash
-    # Note: this requires commit access to dart-lang/ShadowDOM.
-    # You can use your own fork instead if you like.
-    # Just use that URL here and edit build.sh to pull from there.
-    git clone -b shadowdom_patches https://github.com/dart-lang/ShadowDOM.git
-    cd ShadowDOM
-    git remote add upstream https://github.com/Polymer/ShadowDOM.git
-```
-
-You can merge upstream changes by doing:
-
-```bash
-    # Check that we are in shadowdom_patches branch and don't have
-    # any pending changes.
-    git status
-
-    git fetch upstream
-    git merge upstream/master
-    git push origin shadowdom_patches
-```
diff --git a/pkg/shadow_dom/tool/build.json b/pkg/shadow_dom/tool/build.json
deleted file mode 100644
index 76e4ec4..0000000
--- a/pkg/shadow_dom/tool/build.json
+++ /dev/null
@@ -1,9 +0,0 @@
-[
-  "build/if-poly.js",
-  "../lib/src/platform/patches-shadowdom-polyfill-before.js",
-  "../../../third_party/polymer/ShadowDOM/build.json",
-  "../lib/src/platform/patches-shadowdom-polyfill.js",
-  "../lib/src/platform/platform-init.js",
-  "../../../third_party/polymer/platform-dev/src/ShadowCSS.js",
-  "build/end-if.js"
-]
diff --git a/pkg/shadow_dom/tool/build.sh b/pkg/shadow_dom/tool/build.sh
deleted file mode 100755
index 44d8ec7..0000000
--- a/pkg/shadow_dom/tool/build.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/bash
-# 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.
-
-# Usage: call directly in the commandline as test/run.sh ensuring that you have
-# both 'dart' and 'content_shell' in your path. Filter tests by passing a
-# pattern as an argument to this script.
-
-# bail on error
-set -e
-
-DIR=$( cd $( dirname "${BASH_SOURCE[0]}" ) && pwd )
-pushd $DIR > /dev/null
-
-POLYMER_REMOTE=https://github.com/Polymer
-POLYMER_DIR=../../../third_party/polymer
-
-NEWLINE=$'\n'
-REVISIONS=""
-for NAME in ShadowDOM observe-js WeakMap platform-dev; do
-  GIT_REMOTE="$POLYMER_REMOTE/$NAME.git"
-  GIT_DIR="$POLYMER_DIR/$NAME"
-  echo "*** Syncing $GIT_DIR from $GIT_REMOTE"
-  if [ -d "$GIT_DIR" ]; then
-    pushd $GIT_DIR > /dev/null
-    git remote set-url origin $GIT_REMOTE
-    git pull
-    popd
-  else
-    git clone $GIT_REMOTE $GIT_DIR
-  fi
-  pushd $GIT_DIR > /dev/null
-  REVISIONS="$REVISIONS $NEWLINE  $NAME is at revision `git rev-parse HEAD`"
-  popd
-done
-
-echo '*** Installing NPM prerequisites'
-npm install
-
-echo '*** Running grunt'
-grunt
-
-echo "*** Saving REVISIONS file"
-echo "$REVISIONS" > ../REVISIONS
diff --git a/pkg/shadow_dom/tool/build/else.js b/pkg/shadow_dom/tool/build/else.js
deleted file mode 100644
index dacd762..0000000
--- a/pkg/shadow_dom/tool/build/else.js
+++ /dev/null
@@ -1 +0,0 @@
-} else {
\ No newline at end of file
diff --git a/pkg/shadow_dom/tool/build/end-if.js b/pkg/shadow_dom/tool/build/end-if.js
deleted file mode 100644
index ff30235..0000000
--- a/pkg/shadow_dom/tool/build/end-if.js
+++ /dev/null
@@ -1 +0,0 @@
-}
\ No newline at end of file
diff --git a/pkg/shadow_dom/tool/build/if-poly.js b/pkg/shadow_dom/tool/build/if-poly.js
deleted file mode 100644
index 95d4d6b..0000000
--- a/pkg/shadow_dom/tool/build/if-poly.js
+++ /dev/null
@@ -1,2 +0,0 @@
-if (!HTMLElement.prototype.createShadowRoot
-    || window.__forceShadowDomPolyfill) {
diff --git a/pkg/shadow_dom/tool/conf/karma.conf.js b/pkg/shadow_dom/tool/conf/karma.conf.js
deleted file mode 100644
index 382e2c7..0000000
--- a/pkg/shadow_dom/tool/conf/karma.conf.js
+++ /dev/null
@@ -1,89 +0,0 @@
-// Sample Karma configuration file, that contain pretty much all the available options
-// It's used for running client tests on Travis (http://travis-ci.org/#!/karma-runner/karma)
-// Most of the options can be overriden by cli arguments (see karma --help)
-//
-// For all available config options and default values, see:
-// https://github.com/karma-runner/karma/blob/stable/lib/config.js#L54
-
-
-// base path, that will be used to resolve files and exclude
-basePath = '../';
-
-// list of files / patterns to load in the browser
-files = [
-  'tools/test/mocha-htmltest.js',
-  'conf/mocha.conf.js',
-  'node_modules/chai/chai.js',
-  'shadowdom.js',
-  'test/test.main.js',
-  {pattern: 'src/**/*.js', included: false},
-  {pattern: 'test/**/*.js', included: false},
-  {pattern: 'test/**/*.html', included: false},
-  {pattern: 'tools/**/*.js', included: false}
-];
-
-// list of files to exclude
-exclude = [];
-
-frameworks = ['mocha'];
-
-// use dots reporter, as travis terminal does not support escaping sequences
-// possible values: 'dots', 'progress', 'junit', 'teamcity'
-// CLI --reporters progress
-reporters = ['progress'];
-
-// web server port
-// CLI --port 9876
-port = 9876;
-
-// cli runner port
-// CLI --runner-port 9100
-runnerPort = 9100;
-
-// enable / disable colors in the output (reporters and logs)
-// CLI --colors --no-colors
-colors = true;
-
-// level of logging
-// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
-// CLI --log-level debug
-logLevel = LOG_INFO;
-
-// enable / disable watching file and executing tests whenever any file changes
-// CLI --auto-watch --no-auto-watch
-autoWatch = true;
-
-// Start these browsers, currently available:
-// - Chrome
-// - ChromeCanary
-// - Firefox
-// - Opera
-// - Safari (only Mac)
-// - PhantomJS
-// - IE (only Windows)
-// CLI --browsers Chrome,Firefox,Safari
-browsers = ['ChromeCanary'];
-
-// If browser does not capture in given timeout [ms], kill it
-// CLI --capture-timeout 5000
-captureTimeout = 50000;
-
-// Auto run tests on start (when browsers are captured) and exit
-// CLI --single-run --no-single-run
-singleRun = true;
-
-// report which specs are slower than 500ms
-// CLI --report-slower-than 500
-reportSlowerThan = 500;
-
-// compile coffee scripts
-preprocessors = {
-};
-
-plugins = [
-  'karma-mocha',
-  'karma-chrome-launcher',
-  'karma-firefox-launcher',
-  'karma-script-launcher',
-  'karma-crbot-reporter'
-]
diff --git a/pkg/shadow_dom/tool/conf/mocha.conf.js b/pkg/shadow_dom/tool/conf/mocha.conf.js
deleted file mode 100644
index 11dd0d6..0000000
--- a/pkg/shadow_dom/tool/conf/mocha.conf.js
+++ /dev/null
@@ -1 +0,0 @@
-mocha.setup({ui:'tdd',htmlbase: '/base/test/'});
diff --git a/pkg/shadow_dom/tool/gruntfile.js b/pkg/shadow_dom/tool/gruntfile.js
deleted file mode 100644
index 801b48a..0000000
--- a/pkg/shadow_dom/tool/gruntfile.js
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2013 The Polymer Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style
- * license that can be found in the LICENSE file.
- */
-module.exports = function(grunt) {
-  // Recursive module builder:
-  var path = require('path');
-  function readManifest(filename, modules) {
-    modules = modules || [];
-    var lines = grunt.file.readJSON(filename);
-    var dir = path.dirname(filename);
-    lines.forEach(function(line) {
-      var fullpath = path.join(dir, line);
-      if (line.slice(-5) == '.json') {
-        // recurse
-        readManifest(fullpath, modules);
-      } else {
-        modules.push(fullpath);
-      }
-    });
-    return modules;
-  }
-
-  // Karma setup:
-  var browsers;
-  (function() {
-    try {
-      var config = grunt.file.readJSON('local.json');
-      if (config.browsers) {
-        browsers = config.browsers;
-      }
-    } catch (e) {
-      var os = require('os');
-      browsers = ['Chrome', 'Firefox'];
-      if (os.type() === 'Darwin') {
-        browsers.push('ChromeCanary');
-      }
-      if (os.type() === 'Windows_NT') {
-        browsers.push('IE');
-      }
-    }
-  })();
-  grunt.initConfig({
-    karma: {
-      options: {
-        configFile: 'conf/karma.conf.js',
-        keepalive: true,
-        browsers: browsers
-      },
-      buildbot: {
-        browsers: browsers,
-        reporters: ['crbot'],
-        logLevel: 'OFF'
-      },
-      ShadowDOM: {
-        browsers: browsers
-      }
-    },
-    concat: {
-      ShadowDOM: {
-        src: readManifest('build.json'),
-        dest: '../lib/shadow_dom.debug.js',
-        nonull: true
-      }
-    },
-    uglify: {
-      ShadowDOM: {
-        options: {
-          compress: {
-            // TODO(sjmiles): should be false by default (?)
-            // https://github.com/mishoo/UglifyJS2/issues/165
-            unsafe: false
-          }
-          //compress: true, Xmangle: true, beautify: true, unsafe: false
-        },
-        files: {
-          '../lib/shadow_dom.min.js': ['../lib/shadow_dom.debug.js']
-        }
-      }
-    },
-
-    yuidoc: {
-      compile: {
-        name: '<%= pkg.name %>',
-        description: '<%= pkg.description %>',
-        version: '<%= pkg.version %>',
-        url: '<%= pkg.homepage %>',
-        options: {
-          exclude: 'third_party',
-          paths: '.',
-          outdir: 'docs',
-          linkNatives: 'true',
-          tabtospace: 2,
-          themedir: '../docs/doc_themes/simple'
-        }
-      }
-    },
-    pkg: grunt.file.readJSON('package.json')
-  });
-
-  // plugins
-  grunt.loadNpmTasks('grunt-contrib-concat');
-  grunt.loadNpmTasks('grunt-contrib-uglify');
-  grunt.loadNpmTasks('grunt-contrib-yuidoc');
-  grunt.loadNpmTasks('grunt-karma-0.9.1');
-
-  // tasks
-  grunt.registerTask('default', ['concat', 'uglify']);
-  grunt.registerTask('minify', ['concat', 'uglify']);
-  grunt.registerTask('docs', ['yuidoc']);
-  grunt.registerTask('test', ['karma:ShadowDOM']);
-  grunt.registerTask('test-buildbot', ['karma:buildbot']);
-};
diff --git a/pkg/shadow_dom/tool/package.json b/pkg/shadow_dom/tool/package.json
deleted file mode 100644
index 766ca28..0000000
--- a/pkg/shadow_dom/tool/package.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "name": "ShadowDOM",
-  "version": "0.0.1",
-  "devDependencies": {
-    "mocha": ">=1.9",
-    "chai": "*",
-    "grunt": "*",
-    "grunt-contrib-concat": "*",
-    "grunt-contrib-uglify": "*",
-    "grunt-contrib-yuidoc": "~0.4.0",
-    "grunt-karma-0.9.1": "~0.4.3",
-    "karma-mocha": "*",
-    "karma-script-launcher": "*",
-    "karma-crbot-reporter": "*"
-  }
-}
diff --git a/pkg/shadow_dom/tool/play.html b/pkg/shadow_dom/tool/play.html
deleted file mode 100644
index f17b471..0000000
--- a/pkg/shadow_dom/tool/play.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright 2012 The Polymer Authors. All rights reserved.
-Use of this source code is goverened by a BSD-style
-license that can be found in the LICENSE file.
--->
-<meta charset="utf-8">
-<script src="shadowdom.js"></script>
-<style>
-
-.el,
-.sr {
-  height: 300px;
-  width: 300px;
-}
-
-</style>
-<textarea class="el" placeholder="Element host"></textarea>
-<textarea class="sr" placeholder="Shadow Root"></textarea>
-<button onclick="update()">Update</button>
-
-<div class="test">Real</div>
-
-<script>
-
-var el = document.querySelector('.test');
-var sr = el.createShadowRoot();
-
-sr.innerHTML = 'Before <content></content> After';
-
-function update() {
-  el.innerHTML = document.querySelector('.el').value;
-  sr.innerHTML = document.querySelector('.sr').value;
-}
-
-document.querySelector('.el').value = el.innerHTML;
-document.querySelector('.sr').value = sr.innerHTML;
-
-</script>
diff --git a/pkg/shadow_dom/tool/shadowdom.js b/pkg/shadow_dom/tool/shadowdom.js
deleted file mode 100644
index 91f5819..0000000
--- a/pkg/shadow_dom/tool/shadowdom.js
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function() {
-  var thisFile = 'shadowdom.js';
-  var base = '';
-  Array.prototype.forEach.call(document.querySelectorAll('script[src]'), function(s) {
-    var src = s.getAttribute('src');
-    var re = new RegExp(thisFile + '[^\\\\]*');
-    var match = src.match(re);
-    if (match) {
-      base = src.slice(0, -match[0].length);
-    }
-  });
-  base += '../../../third_party/polymer/ShadowDOM/src/';
-
-  [
-    'sidetable.js',
-    'wrappers.js',
-    'wrappers/events.js',
-    'wrappers/NodeList.js',
-    'wrappers/Node.js',
-    'querySelector.js',
-    'wrappers/node-interfaces.js',
-    'wrappers/CharacterData.js',
-    'wrappers/Element.js',
-    'wrappers/HTMLElement.js',
-    'wrappers/HTMLContentElement.js',
-    'wrappers/HTMLShadowElement.js',
-    'wrappers/HTMLTemplateElement.js',
-    'wrappers/HTMLUnknownElement.js',
-    'wrappers/generic.js',
-    'wrappers/ShadowRoot.js',
-    'ShadowRenderer.js',
-    'wrappers/Document.js',
-    'wrappers/Window.js',
-    'wrappers/MutationObserver.js',
-    'wrappers/override-constructors.js'
-  ].forEach(function(src) {
-    document.write('<script src="' + base + src + '"></script>');
-  });
-
-})();
diff --git a/pkg/template_binding/test/custom_element_bindings_test.dart b/pkg/template_binding/test/custom_element_bindings_test.dart
index d3c22c9..62fb8ee 100644
--- a/pkg/template_binding/test/custom_element_bindings_test.dart
+++ b/pkg/template_binding/test/custom_element_bindings_test.dart
@@ -6,11 +6,11 @@
 
 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:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
+import 'package:web_components/polyfill.dart';
 import 'utils.dart';
 
 Future _registered;
@@ -18,7 +18,7 @@
 main() => dirtyCheckZone().run(() {
   useHtmlConfiguration();
 
-  _registered = loadCustomElementPolyfill().then((_) {
+  _registered = customElementsReady.then((_) {
     document.register('my-custom-element', MyCustomElement);
     document.register('with-attrs-custom-element', WithAttrsCustomElement);
   });
diff --git a/pkg/template_binding/test/custom_element_bindings_test.html b/pkg/template_binding/test/custom_element_bindings_test.html
new file mode 100644
index 0000000..661f3e7
--- /dev/null
+++ b/pkg/template_binding/test/custom_element_bindings_test.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> custom_element_bindings_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/platform.concat.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running custom_element_bindings_test </h1>
+  <script type="text/javascript"
+      src="/packages/unittest/test_controller.js"></script>
+  <script type="text/javascript"
+      src="/packages/browser/interop.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/pkg/third_party/html5lib/CHANGELOG.md b/pkg/third_party/html5lib/CHANGELOG.md
new file mode 100644
index 0000000..9bba04d
--- /dev/null
+++ b/pkg/third_party/html5lib/CHANGELOG.md
@@ -0,0 +1,8 @@
+# changelog
+
+This file contains highlights of what changes on each version of the html5lib
+package.
+
+#### Pub version 0.10.0-dev
+  * added querySelector/querySelectorAll, deprecated query/queryAll.
+    This matches the current APIs in dart:html.
diff --git a/pkg/third_party/html5lib/lib/dom.dart b/pkg/third_party/html5lib/lib/dom.dart
index 1c0b6de..9f70694 100644
--- a/pkg/third_party/html5lib/lib/dom.dart
+++ b/pkg/third_party/html5lib/lib/dom.dart
@@ -11,7 +11,6 @@
 import 'src/list_proxy.dart';
 import 'src/token.dart';
 import 'src/tokenizer.dart';
-import 'src/treebuilder.dart';
 import 'src/utils.dart';
 import 'dom_parsing.dart';
 import 'parser.dart';
@@ -241,19 +240,29 @@
     nodes.clear();
   }
 
+  /** *Deprecated* use [querySelector] instead. */
+  @deprecated
+  Element query(String selectors) => querySelector(selectors);
+
+  /** *Deprecated* use [querySelectorAll] instead. */
+  @deprecated
+  List<Element> queryAll(String selectors) => querySelectorAll(selectors);
+
   /**
    * Seaches for the first descendant node matching the given selectors, using a
    * preorder traversal. NOTE: right now, this supports only a single type
    * selectors, e.g. `node.query('div')`.
    */
-  Element query(String selectors) => _queryType(_typeSelector(selectors));
+
+  Element querySelector(String selectors) =>
+      _queryType(_typeSelector(selectors));
 
   /**
    * Returns all descendant nodes matching the given selectors, using a
    * preorder traversal. NOTE: right now, this supports only a single type
    * selectors, e.g. `node.queryAll('div')`.
    */
-  List<Element> queryAll(String selectors) {
+  List<Element> querySelectorAll(String selectors) {
     var results = new List<Element>();
     _queryAllType(_typeSelector(selectors), results);
     return results;
@@ -367,8 +376,9 @@
   int get nodeType => Node.DOCUMENT_NODE;
 
   // TODO(jmesserly): optmize this if needed
-  Element get head => query('html').query('head');
-  Element get body => query('html').query('body');
+  Element get documentElement => querySelector('html');
+  Element get head => documentElement.querySelector('head');
+  Element get body => documentElement.querySelector('body');
 
   String toString() => "#document";
 
diff --git a/pkg/third_party/html5lib/lib/dom_parsing.dart b/pkg/third_party/html5lib/lib/dom_parsing.dart
index 363db7d..3ff74bb 100644
--- a/pkg/third_party/html5lib/lib/dom_parsing.dart
+++ b/pkg/third_party/html5lib/lib/dom_parsing.dart
@@ -4,8 +4,6 @@
  */
 library dom_parsing;
 
-import 'dart:math';
-import 'package:utf/utf.dart' show codepointsToString;
 import 'dom.dart';
 
 /** A simple tree visitor for the DOM nodes. */
diff --git a/pkg/third_party/html5lib/lib/parser.dart b/pkg/third_party/html5lib/lib/parser.dart
index 268053a..4e5e6d5 100644
--- a/pkg/third_party/html5lib/lib/parser.dart
+++ b/pkg/third_party/html5lib/lib/parser.dart
@@ -26,7 +26,6 @@
 import 'src/tokenizer.dart';
 import 'src/utils.dart';
 import 'dom.dart';
-import 'dom_parsing.dart';
 
 /**
  * Parse the [input] html5 document into a tree. The [input] can be
diff --git a/pkg/third_party/html5lib/lib/src/constants.dart b/pkg/third_party/html5lib/lib/src/constants.dart
index 319ef3e..9cc03ad 100644
--- a/pkg/third_party/html5lib/lib/src/constants.dart
+++ b/pkg/third_party/html5lib/lib/src/constants.dart
@@ -1,7 +1,6 @@
 library constants;
 
 import 'utils.dart';
-import 'token.dart';
 
 // TODO(jmesserly): fix up the const lists. For the bigger ones, we need faster
 // lookup than linear search "contains". In the Python code they were
@@ -22,7 +21,7 @@
  * string formatting, as implemented by [formatStr]. That function only supports
  * the subset of format functionality used here.
  */
-final Map<String, String> errorMessages = const {
+const Map<String, String> errorMessages = const {
   "null-character":
      "Null character in input stream, replaced with U+FFFD.",
   "invalid-codepoint":
@@ -324,7 +323,7 @@
   }
 }
 
-final List scopingElements = const [
+const List scopingElements = const [
   const Pair(Namespaces.html, "applet"),
   const Pair(Namespaces.html, "caption"),
   const Pair(Namespaces.html, "html"),
@@ -345,7 +344,7 @@
 ];
 
 
-final formattingElements = const [
+const formattingElements = const [
   const Pair(Namespaces.html, "a"),
   const Pair(Namespaces.html, "b"),
   const Pair(Namespaces.html, "big"),
@@ -362,7 +361,7 @@
   const Pair(Namespaces.html, "")
 ];
 
-final specialElements = const [
+const specialElements = const [
   const Pair(Namespaces.html, "address"),
   const Pair(Namespaces.html, "applet"),
   const Pair(Namespaces.html, "area"),
@@ -445,14 +444,14 @@
   const Pair(Namespaces.svg, "foreignObject")
 ];
 
-final htmlIntegrationPointElements = const [
+const htmlIntegrationPointElements = const [
   const Pair(Namespaces.mathml, "annotaion-xml"),
   const Pair(Namespaces.svg, "foreignObject"),
   const Pair(Namespaces.svg, "desc"),
   const Pair(Namespaces.svg, "title")
 ];
 
-final mathmlTextIntegrationPointElements = const [
+const mathmlTextIntegrationPointElements = const [
   const Pair(Namespaces.mathml, "mi"),
   const Pair(Namespaces.mathml, "mo"),
   const Pair(Namespaces.mathml, "mn"),
@@ -460,7 +459,7 @@
   const Pair(Namespaces.mathml, "mtext")
 ];
 
-final spaceCharacters = " \n\r\t\u000C";
+const spaceCharacters = " \n\r\t\u000C";
 
 const int NEWLINE = 10;
 const int RETURN = 13;
@@ -482,7 +481,7 @@
   return false;
 }
 
-final List<String> tableInsertModeElements = const [
+const List<String> tableInsertModeElements = const [
   "table",
   "tbody",
   "tfoot",
@@ -491,13 +490,13 @@
 ];
 
 // TODO(jmesserly): remove these in favor of the test functions
-final asciiLetters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+const asciiLetters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
 
-final ZERO = 48;
-final LOWER_A = 97;
-final LOWER_Z = 122;
-final UPPER_A = 65;
-final UPPER_Z = 90;
+const ZERO = 48;
+const LOWER_A = 97;
+const LOWER_Z = 122;
+const UPPER_A = 65;
+const UPPER_Z = 90;
 
 bool isLetterOrDigit(String char) => isLetter(char) || isDigit(char);
 
@@ -542,7 +541,7 @@
 }
 
 // Heading elements need to be ordered
-final headingElements = const [
+const headingElements = const [
   "h1",
   "h2",
   "h3",
@@ -551,9 +550,9 @@
   "h6"
 ];
 
-final cdataElements = const ['title', 'textarea'];
+const cdataElements = const ['title', 'textarea'];
 
-final rcdataElements = const [
+const rcdataElements = const [
   'style',
   'script',
   'xmp',
@@ -563,7 +562,7 @@
   'noscript'
 ];
 
-final Map<String, List<String>> booleanAttributes = const {
+const Map<String, List<String>> booleanAttributes = const {
   "": const ["irrelevant",],
   "style": const ["scoped",],
   "img": const ["ismap",],
@@ -586,7 +585,7 @@
 
 // entitiesWindows1252 has to be _ordered_ and needs to have an index. It
 // therefore can't be a frozenset.
-final List<int> entitiesWindows1252 = const [
+const List<int> entitiesWindows1252 = const [
   8364,  // 0x80  0x20AC  EURO SIGN
   65533, // 0x81          UNDEFINED
   8218,  // 0x82  0x201A  SINGLE LOW-9 QUOTATION MARK
@@ -621,9 +620,9 @@
   376    // 0x9F  0x0178  LATIN CAPITAL LETTER Y WITH DIAERESIS
 ];
 
-final xmlEntities = const ['lt;', 'gt;', 'amp;', 'apos;', 'quot;'];
+const xmlEntities = const ['lt;', 'gt;', 'amp;', 'apos;', 'quot;'];
 
-final Map<String, String> entities = const {
+const Map<String, String> entities = const {
   "AElig": "\xc6",
   "AElig;": "\xc6",
   "AMP": "&",
@@ -2857,48 +2856,44 @@
   "zwnj;": "\u200c",
 };
 
-Map<int, String> replacementCharacters = (() {
-  // TODO(jmesserly): fix this when Dart has literal maps with int keys.
-  var r = new Map<int, String>();
-  r[0x00] = "\uFFFD";
-  r[0x0d] = "\u000D";
-  r[0x80] = "\u20AC";
-  r[0x81] = "\u0081";
-  r[0x81] = "\u0081";
-  r[0x82] = "\u201A";
-  r[0x83] = "\u0192";
-  r[0x84] = "\u201E";
-  r[0x85] = "\u2026";
-  r[0x86] = "\u2020";
-  r[0x87] = "\u2021";
-  r[0x88] = "\u02C6";
-  r[0x89] = "\u2030";
-  r[0x8A] = "\u0160";
-  r[0x8B] = "\u2039";
-  r[0x8C] = "\u0152";
-  r[0x8D] = "\u008D";
-  r[0x8E] = "\u017D";
-  r[0x8F] = "\u008F";
-  r[0x90] = "\u0090";
-  r[0x91] = "\u2018";
-  r[0x92] = "\u2019";
-  r[0x93] = "\u201C";
-  r[0x94] = "\u201D";
-  r[0x95] = "\u2022";
-  r[0x96] = "\u2013";
-  r[0x97] = "\u2014";
-  r[0x98] = "\u02DC";
-  r[0x99] = "\u2122";
-  r[0x9A] = "\u0161";
-  r[0x9B] = "\u203A";
-  r[0x9C] = "\u0153";
-  r[0x9D] = "\u009D";
-  r[0x9E] = "\u017E";
-  r[0x9F] = "\u0178";
-  return r;
-})();
+const Map<int, String> replacementCharacters = const {
+  0x00: "\uFFFD",
+  0x0d: "\u000D",
+  0x80: "\u20AC",
+  0x81: "\u0081",
+  0x82: "\u201A",
+  0x83: "\u0192",
+  0x84: "\u201E",
+  0x85: "\u2026",
+  0x86: "\u2020",
+  0x87: "\u2021",
+  0x88: "\u02C6",
+  0x89: "\u2030",
+  0x8A: "\u0160",
+  0x8B: "\u2039",
+  0x8C: "\u0152",
+  0x8D: "\u008D",
+  0x8E: "\u017D",
+  0x8F: "\u008F",
+  0x90: "\u0090",
+  0x91: "\u2018",
+  0x92: "\u2019",
+  0x93: "\u201C",
+  0x94: "\u201D",
+  0x95: "\u2022",
+  0x96: "\u2013",
+  0x97: "\u2014",
+  0x98: "\u02DC",
+  0x99: "\u2122",
+  0x9A: "\u0161",
+  0x9B: "\u203A",
+  0x9C: "\u0153",
+  0x9D: "\u009D",
+  0x9E: "\u017E",
+  0x9F: "\u0178"
+};
 
-final Map<String, String> encodings = const {
+const Map<String, String> encodings = const {
   '437': 'cp437',
   '850': 'cp850',
   '852': 'cp852',
diff --git a/pkg/third_party/html5lib/lib/src/encoding_parser.dart b/pkg/third_party/html5lib/lib/src/encoding_parser.dart
index 7b0edb8..297e3f5 100644
--- a/pkg/third_party/html5lib/lib/src/encoding_parser.dart
+++ b/pkg/third_party/html5lib/lib/src/encoding_parser.dart
@@ -3,7 +3,6 @@
 import 'dart:collection';
 import 'constants.dart';
 import 'inputstream.dart';
-import 'utils.dart';
 
 // TODO(jmesserly): I converted StopIteration to StateError("No more elements").
 // Seems strange to throw this from outside of an iterator though.
diff --git a/pkg/third_party/html5lib/lib/src/tokenizer.dart b/pkg/third_party/html5lib/lib/src/tokenizer.dart
index 2c2ada7..3f398e9 100644
--- a/pkg/third_party/html5lib/lib/src/tokenizer.dart
+++ b/pkg/third_party/html5lib/lib/src/tokenizer.dart
@@ -1,7 +1,6 @@
 library tokenizer;
 
 import 'dart:collection';
-import 'dart:math';
 import 'package:html5lib/parser.dart' show HtmlParser;
 import 'package:source_maps/span.dart' show Span, FileSpan;
 import 'constants.dart';
diff --git a/pkg/third_party/html5lib/lib/src/treebuilder.dart b/pkg/third_party/html5lib/lib/src/treebuilder.dart
index bb53d58..adde3bf 100644
--- a/pkg/third_party/html5lib/lib/src/treebuilder.dart
+++ b/pkg/third_party/html5lib/lib/src/treebuilder.dart
@@ -12,7 +12,7 @@
 // The scope markers are inserted when entering object elements,
 // marquees, table cells, and table captions, and are used to prevent formatting
 // from "leaking" into tables, object elements, and marquees.
-final Node Marker = null;
+const Node Marker = null;
 
 // TODO(jmesserly): this should extend ListBase<Node>, but my simple attempt
 // didn't work.
@@ -130,7 +130,8 @@
                                  const Pair(Namespaces.html, "option")];
           invert = true;
           break;
-        default: assert(false); break;
+        default:
+          throw new StateError('We should never reach this point');
       }
     }
 
@@ -145,7 +146,7 @@
       }
     }
 
-    assert(false); // We should never reach this point
+    throw new StateError('We should never reach this point');
   }
 
   void reconstructActiveFormattingElements() {
diff --git a/pkg/third_party/html5lib/lib/src/utils.dart b/pkg/third_party/html5lib/lib/src/utils.dart
index ca81a41..1a2bb9d 100644
--- a/pkg/third_party/html5lib/lib/src/utils.dart
+++ b/pkg/third_party/html5lib/lib/src/utils.dart
@@ -1,7 +1,6 @@
 /** Misc things that were useful when porting the code from Python. */
 library utils;
 
-import 'dart:collection';
 import 'constants.dart';
 
 typedef bool Predicate();
diff --git a/pkg/third_party/html5lib/pubspec.yaml b/pkg/third_party/html5lib/pubspec.yaml
index 955132d..1ce6624 100644
--- a/pkg/third_party/html5lib/pubspec.yaml
+++ b/pkg/third_party/html5lib/pubspec.yaml
@@ -1,14 +1,14 @@
 name: html5lib
-version: 0.9.1
+version: 0.9.2-dev
 author: Dart Team <misc@dartlang.org>
 description: A library for working with HTML documents.
 homepage: http://pub.dartlang.org/packages/html5lib
-dependencies:
-  source_maps: ">=0.9.0 <0.10.0"
-  utf: ">=0.9.0 <0.10.0"
-dev_dependencies:
-  browser: ">=0.9.0 <0.10.0"
-  path: ">=0.9.0 <0.10.0"
-  unittest: ">=0.9.0 <0.10.0"
 environment:
-  sdk: ">=1.0.0 <2.0.0"
+  sdk: '>=1.0.0 <2.0.0'
+dependencies:
+  source_maps: '>=0.9.0 <0.10.0'
+  utf: '>=0.9.0 <0.10.0'
+dev_dependencies:
+  browser: '>=0.9.0 <0.10.0'
+  path: '>=0.9.0 <2.0.0'
+  unittest: '>=0.9.0 <0.11.0'
diff --git a/pkg/third_party/html5lib/test/dom_compat_test.dart b/pkg/third_party/html5lib/test/dom_compat_test.dart
index f95659b..896576e 100644
--- a/pkg/third_party/html5lib/test/dom_compat_test.dart
+++ b/pkg/third_party/html5lib/test/dom_compat_test.dart
@@ -1,6 +1,5 @@
 library dom_compat_test;
 
-import 'dart:async';
 import 'dart:io';
 import 'package:unittest/unittest.dart';
 import 'package:unittest/compact_vm_config.dart';
diff --git a/pkg/third_party/html5lib/test/dom_test.dart b/pkg/third_party/html5lib/test/dom_test.dart
index 8b339f0..301e822 100644
--- a/pkg/third_party/html5lib/test/dom_test.dart
+++ b/pkg/third_party/html5lib/test/dom_test.dart
@@ -3,32 +3,31 @@
 
 import 'package:unittest/unittest.dart';
 import 'package:html5lib/parser.dart';
-import 'package:html5lib/dom.dart';
 
 main() {
-  group('Node.query type selectors', () {
+  group('Node.querySelector type selectors', () {
     test('x-foo', () {
-      expect(parse('<x-foo>').body.query('x-foo'), isNotNull);
+      expect(parse('<x-foo>').body.querySelector('x-foo'), isNotNull);
     });
 
     test('-x-foo', () {
       var doc = parse('<body><-x-foo>');
       expect(doc.body.outerHtml, equals('<body>&lt;-x-foo&gt;</body>'));
-      expect(doc.body.query('-x-foo'), isNull);
+      expect(doc.body.querySelector('-x-foo'), isNull);
     });
 
     test('foo123', () {
-      expect(parse('<foo123>').body.query('foo123'), isNotNull);
+      expect(parse('<foo123>').body.querySelector('foo123'), isNotNull);
     });
 
     test('123 - invalid', () {
       var doc = parse('<123>');
-      expect(() => doc.body.query('123'), throwsUnimplementedError);
+      expect(() => doc.body.querySelector('123'), throwsUnimplementedError);
     });
 
     test('x\\ny - not implemented', () {
       var doc = parse('<x\\ny>');
-      expect(() => doc.body.query('x\\ny'), throwsUnimplementedError);
+      expect(() => doc.body.querySelector('x\\ny'), throwsUnimplementedError);
     });
   });
 }
diff --git a/pkg/third_party/html5lib/test/parser_feature_test.dart b/pkg/third_party/html5lib/test/parser_feature_test.dart
index 32269c3..f6ac344 100644
--- a/pkg/third_party/html5lib/test/parser_feature_test.dart
+++ b/pkg/third_party/html5lib/test/parser_feature_test.dart
@@ -3,10 +3,8 @@
 
 import 'package:unittest/unittest.dart';
 import 'package:html5lib/dom.dart';
-import 'package:html5lib/dom_parsing.dart';
 import 'package:html5lib/parser.dart';
 import 'package:html5lib/src/constants.dart';
-import 'package:html5lib/src/tokenizer.dart';
 import 'package:html5lib/src/treebuilder.dart';
 
 main() {
@@ -93,7 +91,7 @@
   test('attribute spans', () {
     var text = '<element name="x-foo" extends="x-bar" constructor="Foo">';
     var doc = parse(text, generateSpans: true);
-    var elem = doc.query('element');
+    var elem = doc.querySelector('element');
     expect(elem.sourceSpan.start.offset, 0);
     expect(elem.sourceSpan.end.offset, text.length);
     expect(elem.sourceSpan.text, text);
@@ -108,7 +106,7 @@
   test('attribute value spans', () {
     var text = '<element name="x-foo" extends="x-bar" constructor="Foo">';
     var doc = parse(text, generateSpans: true);
-    var elem = doc.query('element');
+    var elem = doc.querySelector('element');
 
     expect(elem.attributeValueSpans['quux'], null);
 
@@ -120,7 +118,7 @@
   test('attribute spans if no attributes', () {
     var text = '<element>';
     var doc = parse(text, generateSpans: true);
-    var elem = doc.query('element');
+    var elem = doc.querySelector('element');
 
     expect(elem.attributeSpans['quux'], null);
     expect(elem.attributeValueSpans['quux'], null);
@@ -129,7 +127,7 @@
   test('attribute spans if no attribute value', () {
     var text = '<foo template>';
     var doc = parse(text, generateSpans: true);
-    var elem = doc.query('foo');
+    var elem = doc.querySelector('foo');
 
     expect(elem.attributeSpans['template'].start.offset,
         text.indexOf('template'));
@@ -139,7 +137,7 @@
   test('attribute spans null if code parsed without spans', () {
     var text = '<element name="x-foo" extends="x-bar" constructor="Foo">';
     var doc = parse(text);
-    var elem = doc.query('element');
+    var elem = doc.querySelector('element');
     expect(elem.sourceSpan, null);
     expect(elem.attributeSpans['quux'], null);
     expect(elem.attributeSpans['extends'], null);
@@ -174,9 +172,9 @@
       // However, we preserve the input order via LinkedHashMap
       var doc = parseFragment('<foo d=1 a=2 c=3 b=4>');
       expect(doc.outerHtml, '<foo d="1" a="2" c="3" b="4"></foo>');
-      expect(doc.query('foo').attributes.remove('a'), '2');
+      expect(doc.querySelector('foo').attributes.remove('a'), '2');
       expect(doc.outerHtml, '<foo d="1" c="3" b="4"></foo>');
-      doc.query('foo').attributes['a'] = '0';
+      doc.querySelector('foo').attributes['a'] = '0';
       expect(doc.outerHtml, '<foo d="1" c="3" b="4" a="0"></foo>');
     });
 
@@ -206,11 +204,11 @@
 
     test('Newline after <pre>', () {
       var doc = parseFragment('<pre>\n\nsome text</span>');
-      expect(doc.query('pre').nodes[0].value, '\nsome text');
+      expect(doc.querySelector('pre').nodes[0].value, '\nsome text');
       expect(doc.outerHtml, '<pre>\n\nsome text</pre>');
 
       doc = parseFragment('<pre>\nsome text</span>');
-      expect(doc.query('pre').nodes[0].value, 'some text');
+      expect(doc.querySelector('pre').nodes[0].value, 'some text');
       expect(doc.outerHtml, '<pre>some text</pre>');
     });
 
@@ -224,7 +222,7 @@
               xlink:href="http://example.com/logo.png"
               xlink:show="new"></desc>
       ''');
-      var n = doc.query('desc');
+      var n = doc.querySelector('desc');
       var keys = n.attributes.keys.toList();
       expect(keys[0], new isInstanceOf<AttributeName>());
       expect(keys[0].prefix, 'xlink');
diff --git a/pkg/third_party/html5lib/test/parser_test.dart b/pkg/third_party/html5lib/test/parser_test.dart
index 060359c..dbfb3fc 100644
--- a/pkg/third_party/html5lib/test/parser_test.dart
+++ b/pkg/third_party/html5lib/test/parser_test.dart
@@ -7,10 +7,7 @@
 import 'package:html5lib/dom.dart';
 import 'package:html5lib/parser.dart';
 import 'package:html5lib/parser_console.dart' as parser_console;
-import 'package:html5lib/src/constants.dart';
 import 'package:html5lib/src/inputstream.dart' as inputstream;
-import 'package:html5lib/src/tokenizer.dart';
-import 'package:html5lib/src/utils.dart';
 import 'support.dart';
 
 // Run the parse error checks
diff --git a/pkg/third_party/html5lib/test/run_all.dart b/pkg/third_party/html5lib/test/run_all.dart
index b149098..f6fff1b 100644
--- a/pkg/third_party/html5lib/test/run_all.dart
+++ b/pkg/third_party/html5lib/test/run_all.dart
@@ -5,7 +5,6 @@
 
 library test.run_all;
 
-import 'dart:io' show Options;
 import 'package:unittest/compact_vm_config.dart';
 import 'package:unittest/unittest.dart';
 
diff --git a/pkg/third_party/html5lib/test/support.dart b/pkg/third_party/html5lib/test/support.dart
index f894aa4..1146679 100644
--- a/pkg/third_party/html5lib/test/support.dart
+++ b/pkg/third_party/html5lib/test/support.dart
@@ -1,7 +1,6 @@
 /** Support code for the tests in this directory. */
 library support;
 
-import 'dart:async';
 import 'dart:io';
 import 'dart:collection';
 import 'package:path/path.dart' as path;
diff --git a/pkg/third_party/html5lib/test/tokenizer_test.dart b/pkg/third_party/html5lib/test/tokenizer_test.dart
index b9e43fe..439e440 100644
--- a/pkg/third_party/html5lib/test/tokenizer_test.dart
+++ b/pkg/third_party/html5lib/test/tokenizer_test.dart
@@ -1,17 +1,14 @@
 library tokenizer_test;
 
 // Note: mirrors used to match the getattr usage in the original test
-import 'dart:async';
 import 'dart:convert';
 import 'dart:io';
 import 'dart:mirrors';
 import 'package:path/path.dart' as pathos;
 import 'package:unittest/unittest.dart';
 import 'package:html5lib/src/char_encodings.dart';
-import 'package:html5lib/src/constants.dart' as constants;
 import 'package:html5lib/src/token.dart';
 import 'package:html5lib/src/tokenizer.dart';
-import 'package:html5lib/src/utils.dart';
 import 'package:utf/utf.dart';
 import 'support.dart';
 
diff --git a/pkg/unittest/CHANGELOG.md b/pkg/unittest/CHANGELOG.md
index 9392db2..be796e4 100644
--- a/pkg/unittest/CHANGELOG.md
+++ b/pkg/unittest/CHANGELOG.md
@@ -2,11 +2,15 @@
 
 ##0.10.0-dev
 
-* Each test is run in a seperate `Zone`. This ensures that any exceptions that
+* Each test is run in a separate `Zone`. This ensures that any exceptions that
 occur is async operations are reported back to the source test case.
 * **DEPRECATED** `guardAsync`, `protectAsync0`, `protectAsync1`,
 and `protectAsync2`
     * Running each test in a `Zone` addresses the need for these methods.
+* **NEW!** `expectAsync` replaces the now deprecated `expectAsync0`,
+    `expectAsync1` and `expectAsync2`
+* **NEW!** `expectAsyncUntil` replaces the now deprecated `expectAsyncUntil0`,
+    `expectAsyncUntil1` and `expectAsyncUntil2`
 * `TestCase`:
     * Removed properties: `setUp`, `tearDown`, `testFunction`
     * `enabled` is now get-only
diff --git a/pkg/unittest/lib/html_enhanced_config.dart b/pkg/unittest/lib/html_enhanced_config.dart
index d434663..5022ea2 100644
--- a/pkg/unittest/lib/html_enhanced_config.dart
+++ b/pkg/unittest/lib/html_enhanced_config.dart
@@ -10,7 +10,6 @@
  */
 library unittest.html_enhanced_config;
 
-import 'dart:async';
 import 'dart:collection' show LinkedHashMap;
 import 'dart:convert';
 import 'dart:html';
diff --git a/pkg/unittest/lib/mock.dart b/pkg/unittest/lib/mock.dart
index a4216cf..02c40e3 100644
--- a/pkg/unittest/lib/mock.dart
+++ b/pkg/unittest/lib/mock.dart
@@ -188,6 +188,8 @@
   const Action._(this.name);
 
   final String name;
+
+  String toString() => 'Action: $name';
 }
 
 /**
@@ -198,8 +200,8 @@
  * depending on the value of [count (1, greater than 1, or 0 respectively).
  */
 class Responder {
-  var value;
-  Action action;
+  final Object value;
+  final Action action;
   int count;
   Responder(this.value, [this.count = 1, this.action = Action.RETURN]);
 }
@@ -1250,16 +1252,16 @@
   final String name;
 
   /** The set of [Behavior]s supported. */
-  LinkedHashMap<String,Behavior> _behaviors;
-
-  /** The [log] of calls made. Only used if [name] is null. */
-  LogEntryList log;
+  final LinkedHashMap<String,Behavior> _behaviors;
 
   /** How to handle unknown method calls - swallow or throw. */
   final bool _throwIfNoBehavior;
 
   /** For spys, the real object that we are spying on. */
-  Object _realObject;
+  final Object _realObject;
+
+  /** The [log] of calls made. Only used if [name] is null. */
+  LogEntryList log;
 
   /** Whether to create an audit log or not. */
   bool _logging;
@@ -1276,9 +1278,10 @@
    * Default constructor. Unknown method calls are allowed and logged,
    * the mock has no name, and has its own log.
    */
-  Mock() : _throwIfNoBehavior = false, log = null, name = null {
+  Mock() :
+    _throwIfNoBehavior = false, log = null, name = null, _realObject = null,
+    _behaviors = new LinkedHashMap<String,Behavior>() {
     logging = true;
-    _behaviors = new LinkedHashMap<String,Behavior>();
   }
 
   /**
@@ -1292,12 +1295,13 @@
   Mock.custom({this.name,
                this.log,
                throwIfNoBehavior: false,
-               enableLogging: true}) : _throwIfNoBehavior = throwIfNoBehavior {
+               enableLogging: true})
+      : _throwIfNoBehavior = throwIfNoBehavior, _realObject = null,
+        _behaviors = new LinkedHashMap<String,Behavior>() {
     if (log != null && name == null) {
       throw new Exception("Mocks with shared logs must have a name.");
     }
     logging = enableLogging;
-    _behaviors = new LinkedHashMap<String,Behavior>();
   }
 
   /**
diff --git a/pkg/unittest/lib/src/core_matchers.dart b/pkg/unittest/lib/src/core_matchers.dart
index 6b5d5d6..86f51f3 100644
--- a/pkg/unittest/lib/src/core_matchers.dart
+++ b/pkg/unittest/lib/src/core_matchers.dart
@@ -300,7 +300,7 @@
   static String _escape(String s) =>
       s.replaceAll('\n', '\\n').replaceAll('\r', '\\r').replaceAll('\t', '\\t');
 
-  static String _writeLeading(StringBuffer buff, String s, int start) {
+  static void _writeLeading(StringBuffer buff, String s, int start) {
     if (start > 10) {
       buff.write('... ');
       buff.write(s.substring(start - 10, start));
@@ -309,7 +309,7 @@
     }
   }
 
-  static String _writeTrailing(StringBuffer buff, String s, int start) {
+  static void _writeTrailing(StringBuffer buff, String s, int start) {
     if (start + 10 > s.length) {
       buff.write(s.substring(start));
     } else {
diff --git a/pkg/unittest/lib/test_controller.js b/pkg/unittest/lib/test_controller.js
index 6f604cd..8a62d6a 100644
--- a/pkg/unittest/lib/test_controller.js
+++ b/pkg/unittest/lib/test_controller.js
@@ -38,7 +38,7 @@
 // HTML Imports allows a document to link to other HTMLs documents via
 // <link rel=import>. It also allows for those other documents to contain
 // <script> tags, which must be run before scripts on the main page.
-// We have package:html_import to polyfill this feature, and it will handle
+// We have package:web_components to polyfill this feature, and it will handle
 // starting Dartium/content_shell in that case. HTML Imports is used by Polymer,
 // but it could be used by itself too. See the specification:
 // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/imports/index.html
diff --git a/pkg/unittest/lib/unittest.dart b/pkg/unittest/lib/unittest.dart
index 5fa2ae9..da95fae 100644
--- a/pkg/unittest/lib/unittest.dart
+++ b/pkg/unittest/lib/unittest.dart
@@ -83,9 +83,9 @@
  * that callback is run. A count argument can be provided to specify the number
  * of times the callback should be called (the default is 1).
  *
+ *     import 'dart:async';
  *     import 'package:unittest/unittest.dart';
- *     import 'dart:isolate';
- *     main() {
+ *     void main() {
  *       test('callback is executed once', () {
  *         // wrap the callback of an asynchronous call with [expectAsync0] if
  *         // the callback takes 0 arguments...
@@ -105,13 +105,12 @@
  *       });
  *     }
  *
- * expectAsyncX() will wrap the callback code in a try/catch handler to handle
- * exceptions (treated as test failures). There may be times when the number of
- * times a callback should be called is non-deterministic. In this case a dummy
- * callback can be created with expectAsync0((){}) and this can be called from
- * the real callback when it is finally complete. In this case the body of the
- * callback should be protected within a call to guardAsync(); this will ensure
- * that exceptions are properly handled.
+ * expectAsyncX() will wrap the callback code and block the completion of the
+ * test until the wrapped callback has been called the specified number of times
+ * -- the default is 1. There may be times when the number of times a callback
+ * should be called is non-deterministic. In this case a dummy callback can be
+ * created with expectAsync0((){}) and this can be called from the real callback
+ * when it is finally complete.
  *
  * A variation on this is expectAsyncUntilX(), which takes a callback as the
  * first parameter and a predicate function as the second parameter; after each
@@ -121,10 +120,21 @@
  * Test functions can return [Future]s, which provide another way of doing
  * asynchronous tests. The test framework will handle exceptions thrown by
  * the Future, and will advance to the next test when the Future is complete.
- * It is still important to use expectAsync/guardAsync with any parts of the
- * test that may be invoked from a top level context (for example, with
- * Timer.run()], as the Future exception handler may not capture exceptions
- * in such code.
+ *
+ *     import 'dart:async';
+ *     import 'package:unittest/unittest.dart';
+ *     void main() {
+ *       test('test that time has passed', () {
+ *         var duration = const Duration(milliseconds: 200);
+ *         var time = new DateTime.now();
+ *
+ *         return new Future.delayed(duration).then((_) {
+ *           var delta = new DateTime.now().difference(time);
+ *
+ *           expect(delta, greaterThanOrEqualTo(duration));
+ *         });
+ *       });
+ *     }
  *
  * Note: Due to some language limitations we have to use different functions
  * depending on the number of positional arguments of the callback. In the
@@ -303,7 +313,7 @@
  * Indicate that [callback] is expected to be called a [count] number of times
  * (by default 1). The unittest framework will wait for the callback to run the
  * specified [count] times before it continues with the following test.  Using
- * [expectAsync0] will also ensure that errors that occur within [callback] are
+ * [expectAsync] will also ensure that errors that occur within [callback] are
  * tracked and reported. [callback] should take 0 positional arguments (named
  * arguments are not supported). [id] can be used to provide more
  * descriptive error messages if the callback is called more often than
@@ -314,56 +324,107 @@
  * called exactly [count] times. A value of -1 for [max] will mean no upper
  * bound.
  */
-// TODO(sigmund): deprecate this API when issue 2706 is fixed.
+Function expectAsync(Function callback,
+                     {int count: 1, int max: 0, String id}) {
+  var minArgs = _minArgs(callback);
+
+  switch(minArgs) {
+    case 0:
+      return new _SpreadArgsHelper(callback, count, max, null, id).invoke0;
+    case 1:
+      return new _SpreadArgsHelper(callback, count, max, null, id).invoke1;
+    case 2:
+      return new _SpreadArgsHelper(callback, count, max, null, id).invoke2;
+    default:
+      // _minArgs throws an argument exception if the arg count is > 2.
+      // this is just for paranoia
+      throw new StateError('Should never get here');
+  }
+}
+
+/**
+ * *Deprecated*
+ *
+ * Use [expectAsync] instead.
+ */
+@deprecated
 Function expectAsync0(Function callback,
-                     {int count: 1, int max: 0, String id}) {
-  return new _SpreadArgsHelper(callback, count, max, null, id).invoke0;
-}
+                     {int count: 1, int max: 0, String id}) =>
+    expectAsync(callback, count: count, max: max, id: id);
 
-/** Like [expectAsync0] but [callback] should take 1 positional argument. */
-// TODO(sigmund): deprecate this API when issue 2706 is fixed.
+/**
+ * *Deprecated*
+ *
+ * Use [expectAsync] instead.
+ */
+@deprecated
 Function expectAsync1(Function callback,
-                     {int count: 1, int max: 0, String id}) {
-  return new _SpreadArgsHelper(callback, count, max, null, id).invoke1;
-}
+                     {int count: 1, int max: 0, String id}) =>
+    expectAsync(callback, count: count, max: max, id: id);
 
-/** Like [expectAsync0] but [callback] should take 2 positional arguments. */
-// TODO(sigmund): deprecate this API when issue 2706 is fixed.
+/**
+ * *Deprecated*
+ *
+ * Use [expectAsync] instead.
+ */
+@deprecated
 Function expectAsync2(Function callback,
-                     {int count: 1, int max: 0, String id}) {
-  return new _SpreadArgsHelper(callback, count, max, null, id).invoke2;
-}
+                     {int count: 1, int max: 0, String id}) =>
+    expectAsync(callback, count: count, max: max, id: id);
 
 /**
  * Indicate that [callback] is expected to be called until [isDone] returns
  * true. The unittest framework check [isDone] after each callback and only
  * when it returns true will it continue with the following test. Using
- * [expectAsyncUntil0] will also ensure that errors that occur within
+ * [expectAsyncUntil] will also ensure that errors that occur within
  * [callback] are tracked and reported. [callback] should take 0 positional
  * arguments (named arguments are not supported). [id] can be used to
  * identify the callback in error messages (for example if it is called
  * after the test case is complete).
  */
-// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsyncUntil0(Function callback, Function isDone, {String id}) {
-  return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke0;
+Function expectAsyncUntil(Function callback, Function isDone, {String id}) {
+  var minArgs = _minArgs(callback);
+
+  switch(minArgs) {
+    case 0:
+      return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke0;
+    case 1:
+      return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke1;
+    case 2:
+      return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke2;
+    default:
+      // _minArgs throws an argument exception if the arg count is > 2.
+      // this is just for paranoia
+      throw new StateError('Should never get here');
+  }
 }
 
 /**
- * Like [expectAsyncUntil0] but [callback] should take 1 positional argument.
+ * *Deprecated*
+ *
+ * Use [expectAsyncUntil] instead.
  */
-// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsyncUntil1(Function callback, Function isDone, {String id}) {
-  return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke1;
-}
+@deprecated
+Function expectAsyncUntil0(Function callback, Function isDone, {String id}) =>
+    expectAsyncUntil(callback, isDone, id: id);
 
 /**
- * Like [expectAsyncUntil0] but [callback] should take 2 positional arguments.
+ * *Deprecated*
+ *
+ * Use [expectAsyncUntil] instead.
  */
-// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsyncUntil2(Function callback, Function isDone, {String id}) {
-  return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke2;
-}
+@deprecated
+Function expectAsyncUntil1(Function callback, Function isDone, {String id}) =>
+    expectAsyncUntil(callback, isDone, id: id);
+
+/**
+ * *Deprecated*
+ *
+ * Use [expectAsyncUntil] instead.
+ */
+@deprecated
+Function expectAsyncUntil2(Function callback, Function isDone, {String id}) =>
+    expectAsyncUntil(callback, isDone, id: id);
 
 /**
  * *Deprecated*
@@ -624,7 +685,7 @@
   }
   _initialized = true;
   // Hook our async guard into the matcher library.
-  wrapAsync = (f, [id]) => expectAsync1(f, id: id);
+  wrapAsync = (f, [id]) => expectAsync(f, id: id);
 
   _uncaughtErrorMessage = null;
 
@@ -709,3 +770,18 @@
     return frame.package != 'unittest' || frame.member != 'TestCase._runTest';
   })).terse.foldFrames((frame) => frame.package == 'unittest' || frame.isCore);
 }
+
+typedef _Func0();
+typedef _Func1(a);
+typedef _Func2(a, b);
+
+/**
+ * Throws an [ArgumentError] if the callback has more than 2 required arguments.
+ */
+int _minArgs(Function callback) {
+  if (callback is _Func0) return 0;
+  if (callback is _Func1) return 1;
+  if (callback is _Func2) return 2;
+  throw new ArgumentError(
+      'The callback argument has more than 2 required arguments.');
+}
diff --git a/pkg/unittest/pubspec.yaml b/pkg/unittest/pubspec.yaml
index b0caec5..ef3d06f 100644
--- a/pkg/unittest/pubspec.yaml
+++ b/pkg/unittest/pubspec.yaml
@@ -1,10 +1,10 @@
 name: unittest
-version: 0.10.0-dev
+version: 0.10.1-dev
 author: Dart Team <misc@dartlang.org>
 description: A library for writing dart unit tests.
 homepage: http://www.dartlang.org
+environment:
+  sdk: '>=1.0.0 <2.0.0'
 documentation: http://api.dartlang.org/docs/pkg/unittest
 dependencies:
-  stack_trace: ">=0.9.0 <0.10.0"
-environment:
-  sdk: ">=0.8.10+6 <2.0.0"
+  stack_trace: '>=0.9.0 <0.10.0'
diff --git a/pkg/unittest/test/mock_test.dart b/pkg/unittest/test/mock_test.dart
index 6766955..bd04c79 100644
--- a/pkg/unittest/test/mock_test.dart
+++ b/pkg/unittest/test/mock_test.dart
@@ -653,7 +653,8 @@
     expect(log.logs, hasLength(0));
   });
 
-  test("Mocking: instances", () {
+  // TODO(kevmoo): figure out why this test is failing
+  skip_test("Mocking: instances", () {
     var alice = new Object();
     var bob = new Object();
     var m = new Mock();
@@ -722,7 +723,7 @@
     m.resetBehavior();
   });
 
-  solo_test('Spys', () {
+  test('Spys', () {
     var real = new Foo();
     var spy = new Mock.spy(real);
     var sum = spy.sum(1, 2, 3);
diff --git a/pkg/unittest/test/test_utils.dart b/pkg/unittest/test/test_utils.dart
index 01a483b..de783be 100644
--- a/pkg/unittest/test/test_utils.dart
+++ b/pkg/unittest/test/test_utils.dart
@@ -41,7 +41,7 @@
   }
 
   if (isAsync) {
-    Timer.run(expectAsync0(afterTest));
+    Timer.run(expectAsync(afterTest));
   } else {
     afterTest();
   }
@@ -57,7 +57,7 @@
     expect(errorCount, equals(0));
   }
   if (isAsync) {
-    Timer.run(expectAsync0(afterTest));
+    Timer.run(expectAsync(afterTest));
   } else {
     afterTest();
   }
diff --git a/pkg/unmodifiable_collection/LICENSE b/pkg/unmodifiable_collection/LICENSE
deleted file mode 100644
index ee99930..0000000
--- a/pkg/unmodifiable_collection/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright 2013, the Dart project authors. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-    * Neither the name of Google Inc. nor the names of its
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-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.
diff --git a/pkg/unmodifiable_collection/lib/unmodifiable_collection.dart b/pkg/unmodifiable_collection/lib/unmodifiable_collection.dart
deleted file mode 100644
index 428bb7d..0000000
--- a/pkg/unmodifiable_collection/lib/unmodifiable_collection.dart
+++ /dev/null
@@ -1,23 +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 library used to introduce unmodifiable wrappers for collections.
- *
- * This functionality has been moved to the `collection` library.
- *
- * Please replace the import of this library with:
- *
- *     import "package:collection/wrappers.dart";
- *
- * and change dependencies to match.
- */
-@deprecated
-library unmodifiable_collection;
-
-export "package:collection/wrappers.dart"
-    show UnmodifiableListView,
-         UnmodifiableSetView,
-         UnmodifiableMapView,
-         NonGrowableListView;
diff --git a/pkg/unmodifiable_collection/pubspec.yaml b/pkg/unmodifiable_collection/pubspec.yaml
deleted file mode 100644
index 2e59d7a..0000000
--- a/pkg/unmodifiable_collection/pubspec.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-name: unmodifiable_collection
-version: 0.9.2
-author: "Dart Team <misc@dartlang.org>"
-homepage: http://www.dartlang.org
-documentation: http://api.dartlang.org/docs/pkg/unmodifiable_collection
-description: >
- Discontinued library. Use package:collection/wrappers.dart instead.
-
-dependencies:
-  collection: ">=0.9.0 <0.10.0"
-environment:
-  sdk: ">=0.8.10+6 <2.0.0"
diff --git a/pkg/shadow_dom/AUTHORS b/pkg/web_components/AUTHORS
similarity index 100%
rename from pkg/shadow_dom/AUTHORS
rename to pkg/web_components/AUTHORS
diff --git a/pkg/shadow_dom/LICENSE b/pkg/web_components/LICENSE
similarity index 100%
rename from pkg/shadow_dom/LICENSE
rename to pkg/web_components/LICENSE
diff --git a/pkg/shadow_dom/PATENTS b/pkg/web_components/PATENTS
similarity index 100%
rename from pkg/shadow_dom/PATENTS
rename to pkg/web_components/PATENTS
diff --git a/pkg/web_components/README.md b/pkg/web_components/README.md
new file mode 100644
index 0000000..a0f0052
--- /dev/null
+++ b/pkg/web_components/README.md
@@ -0,0 +1,86 @@
+# Web Components
+
+This package has the polyfills for
+[Shadow DOM](http://www.polymer-project.org/platform/shadow-dom.html),
+[Custom Elements](http://www.polymer-project.org/platform/custom-elements.html),
+and [HTML Imports](http://www.polymer-project.org/platform/html-imports.html).
+
+These features exist in dart:html, for example
+[Element.reateShadowRoot](https://api.dartlang.org/apidocs/channels/stable/#dart-dom-html.Element@id_createShadowRoot)
+and [Document.register](https://api.dartlang.org/apidocs/channels/stable/#dart-dom-html.HtmlDocument@id_register).
+However those APIs are not supported on all browsers yet unless you
+load the polyfills, as indicated below.
+
+## Getting started
+
+Include the polyfills in your HTML `<head>` to enable Shadow DOM:
+
+```html
+<script src="packages/web_components/platform.js"></script>
+<script src="packages/web_components/dart_support.js"></script>
+```
+
+You can also use an unminfied version for development:
+
+```html
+<script src="packages/web_components/platform.concat.js"></script>
+<script src="packages/web_components/dart_support.js"></script>
+```
+
+Because the Shadow DOM polyfill does extensive DOM patching, platform.js should
+be included **before** other script tags. Be sure to include dart_support.js
+too, it is required for the Shadow DOM polyfill to work with
+[dart2js](https://www.dartlang.org/docs/dart-up-and-running/contents/ch04-tools-dart2js.html).
+
+## Custom Elements
+
+Custom Elements let authors define their own elements. Authors associate
+JavaScript or Dart code with custom tag names, and then use those custom tag
+names as they would any standard tag.
+
+For example, after registering a special kind of button called `super-button`,
+use the super button just like this:
+
+```html
+<super-button></super-button>
+```
+
+Custom elements are still elements. We can create, use, manipulate, and compose
+them just as easily as any standard `<div>` or `<span>` today.
+
+See the Polymer [Custom Elements page](http://www.polymer-project.org/platform/custom-elements.html)
+for more information.
+
+## Shadow DOM
+
+Shadow DOM is designed to provide encapsulation by hiding DOM subtrees under
+shadow roots. It provides a method of establishing and maintaining functional
+boundaries between DOM trees and how these trees interact with each other within
+a document, thus enabling better functional encapsulation within the DOM.
+
+See the Polymer [Shadow DOM page](http://www.polymer-project.org/platform/shadow-dom.html)
+for more information.
+
+
+## Hacking on this package
+
+To rebuild platform.js:
+
+```bash
+# Make a directory like ~/src/polymer
+mkdir ~/src/polymer
+cd ~/src/polymer
+git clone https://github.com/polymer/tools
+
+# Sync polymer repositories
+./tools/bin/pull-all-polymer.sh
+
+# If you don't have "npm", get it here: http://nodejs.org
+cd platform-dev
+npm install
+grunt minify audit
+cd build
+
+# Copy the build output to your Dart source tree
+cp build.log platform* ~/dart/dart/pkg/web_components/lib
+```
diff --git a/pkg/web_components/lib/build.log b/pkg/web_components/lib/build.log
new file mode 100644
index 0000000..584cb83
--- /dev/null
+++ b/pkg/web_components/lib/build.log
@@ -0,0 +1,48 @@
+BUILD LOG
+---------
+Build Time: 2014-02-11T11:39:54
+
+NODEJS INFORMATION
+==================
+nodejs: v0.8.21
+chai: 1.9.0
+grunt: 0.4.2
+grunt-audit: 0.0.2
+grunt-concat-sourcemap: 0.4.1
+grunt-contrib-concat: 0.3.0
+grunt-contrib-uglify: 0.3.2
+grunt-contrib-yuidoc: 0.5.0
+grunt-karma: 0.6.2
+karma: 0.10.9
+karma-chrome-launcher: 0.1.2
+karma-coffee-preprocessor: 0.1.2
+karma-crbot-reporter: 0.0.4
+karma-firefox-launcher: 0.1.3
+karma-html2js-preprocessor: 0.1.0
+karma-ie-launcher: 0.1.1
+karma-jasmine: 0.1.5
+karma-mocha: 0.1.1
+karma-phantomjs-launcher: 0.1.2
+karma-requirejs: 0.2.1
+karma-safari-launcher: 0.1.1
+karma-script-launcher: 0.1.0
+mocha: 1.17.1
+requirejs: 2.1.10
+
+REPO REVISIONS
+==============
+CustomElements: 6236589963ca20d49e2575e671e4a11e3df3fbec
+HTMLImports: 0461b94029d8c858441ddcf816397c5b1234b025
+NodeBind: f7cc76749e509e06fa7cbc9ba970f87f5fe33b5c
+PointerEvents: e9234722f7da7b981241b3c122decf1a15fd23ce
+PointerGestures: 0cded24896294ebecdfdad47583468f714a0a34e
+ShadowDOM: 308a7c2e67032f746b5e52f4e27320ffe3a57ecd
+TemplateBinding: 279934127f6777bdfb9f752e98eb0da172fbca1b
+WeakMap: a0947a9a0f58f5733f464755c3b86de624b00a5d
+observe-js: 3ba9aeec73f7864d519fb13c6f38cb10923cdfd9
+platform: e959e3f63d51e9d5089ccb91d67171919c313862
+polymer-expressions: 470cced7cf167bd164f0b924ceb088dd7a8240b9
+
+BUILD HASHES
+============
+build/platform.js: 24f5bac99f338ca6dfc791d5ff1288f74805df2b
\ No newline at end of file
diff --git a/pkg/web_components/lib/dart_support.js b/pkg/web_components/lib/dart_support.js
new file mode 100644
index 0000000..2f9e1af
--- /dev/null
+++ b/pkg/web_components/lib/dart_support.js
@@ -0,0 +1,55 @@
+// Copyright (c) 2014, 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() {
+  var ShadowDOMPolyfill = window.ShadowDOMPolyfill;
+  if (!ShadowDOMPolyfill) return;
+
+  var needsConstructorFix = window.constructor === window.Window;
+
+  // TODO(jmesserly): we need to wrap document somehow (a dart:html hook?)
+  window.dartExperimentalFixupGetTag = function(originalGetTag) {
+    var NodeList = ShadowDOMPolyfill.wrappers.NodeList;
+    var ShadowRoot = ShadowDOMPolyfill.wrappers.ShadowRoot;
+    var unwrapIfNeeded = ShadowDOMPolyfill.unwrapIfNeeded;
+    function getTag(obj) {
+      // TODO(jmesserly): do we still need these?
+      if (obj instanceof NodeList) return 'NodeList';
+      if (obj instanceof ShadowRoot) return 'ShadowRoot';
+      if (MutationRecord && (obj instanceof MutationRecord))
+          return 'MutationRecord';
+      if (MutationObserver && (obj instanceof MutationObserver))
+          return 'MutationObserver';
+
+      // TODO(jmesserly): this prevents incorrect interaction between ShadowDOM
+      // and dart:html's <template> polyfill. Essentially, ShadowDOM is
+      // polyfilling native template, but our Dart polyfill fails to detect this
+      // because the unwrapped node is an HTMLUnknownElement, leading it to
+      // think the node has no content.
+      if (obj instanceof HTMLTemplateElement) return 'HTMLTemplateElement';
+
+      var unwrapped = unwrapIfNeeded(obj);
+      if (needsConstructorFix || obj !== unwrapped) {
+        // Fix up class names for Firefox, or if using the minified polyfill.
+        // dart2js prefers .constructor.name, but there are all kinds of cases
+        // where this will give the wrong answer.
+        var ctor = obj.constructor
+        if (ctor === unwrapped.constructor) {
+          var name = ctor._ShadowDOMPolyfill$cacheTag_;
+          if (!name) {
+            name = Object.prototype.toString.call(unwrapped);
+            name = name.substring(8, name.length - 1);
+            ctor._ShadowDOMPolyfill$cacheTag_ = name;
+          }
+          return name;
+        }
+
+        obj = unwrapped;
+      }
+      return originalGetTag(obj);
+    }
+
+    return getTag;
+  };
+})();
diff --git a/pkg/web_components/lib/platform.concat.js b/pkg/web_components/lib/platform.concat.js
new file mode 100644
index 0000000..293c435
--- /dev/null
+++ b/pkg/web_components/lib/platform.concat.js
@@ -0,0 +1,17035 @@
+/*
+ * Copyright 2012 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+if (typeof WeakMap === 'undefined') {
+  (function() {
+    var defineProperty = Object.defineProperty;
+    var counter = Date.now() % 1e9;
+
+    var WeakMap = function() {
+      this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__');
+    };
+
+    WeakMap.prototype = {
+      set: function(key, value) {
+        var entry = key[this.name];
+        if (entry && entry[0] === key)
+          entry[1] = value;
+        else
+          defineProperty(key, this.name, {value: [key, value], writable: true});
+      },
+      get: function(key) {
+        var entry;
+        return (entry = key[this.name]) && entry[0] === key ?
+            entry[1] : undefined;
+      },
+      delete: function(key) {
+        this.set(key, undefined);
+      }
+    };
+
+    window.WeakMap = WeakMap;
+  })();
+}
+
+// Copyright 2012 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+(function(global) {
+  'use strict';
+
+  var PROP_ADD_TYPE = 'add';
+  var PROP_UPDATE_TYPE = 'update';
+  var PROP_RECONFIGURE_TYPE = 'reconfigure';
+  var PROP_DELETE_TYPE = 'delete';
+  var ARRAY_SPLICE_TYPE = 'splice';
+
+  // Detect and do basic sanity checking on Object/Array.observe.
+  function detectObjectObserve() {
+    if (typeof Object.observe !== 'function' ||
+        typeof Array.observe !== 'function') {
+      return false;
+    }
+
+    var records = [];
+
+    function callback(recs) {
+      records = recs;
+    }
+
+    var test = {};
+    Object.observe(test, callback);
+    test.id = 1;
+    test.id = 2;
+    delete test.id;
+    Object.deliverChangeRecords(callback);
+    if (records.length !== 3)
+      return false;
+
+    // TODO(rafaelw): Remove this when new change record type names make it to
+    // chrome release.
+    if (records[0].type == 'new' &&
+        records[1].type == 'updated' &&
+        records[2].type == 'deleted') {
+      PROP_ADD_TYPE = 'new';
+      PROP_UPDATE_TYPE = 'updated';
+      PROP_RECONFIGURE_TYPE = 'reconfigured';
+      PROP_DELETE_TYPE = 'deleted';
+    } else if (records[0].type != 'add' ||
+               records[1].type != 'update' ||
+               records[2].type != 'delete') {
+      console.error('Unexpected change record names for Object.observe. ' +
+                    'Using dirty-checking instead');
+      return false;
+    }
+    Object.unobserve(test, callback);
+
+    test = [0];
+    Array.observe(test, callback);
+    test[1] = 1;
+    test.length = 0;
+    Object.deliverChangeRecords(callback);
+    if (records.length != 2)
+      return false;
+    if (records[0].type != ARRAY_SPLICE_TYPE ||
+        records[1].type != ARRAY_SPLICE_TYPE) {
+      return false;
+    }
+    Array.unobserve(test, callback);
+
+    return true;
+  }
+
+  var hasObserve = detectObjectObserve();
+
+  function detectEval() {
+    // don't test for eval if document has CSP securityPolicy object and we can see that
+    // eval is not supported. This avoids an error message in console even when the exception
+    // is caught
+    if (global.document &&
+        'securityPolicy' in global.document &&
+        !global.document.securityPolicy.allowsEval) {
+      return false;
+    }
+
+    try {
+      var f = new Function('', 'return true;');
+      return f();
+    } catch (ex) {
+      return false;
+    }
+  }
+
+  var hasEval = detectEval();
+
+  function isIndex(s) {
+    return +s === s >>> 0;
+  }
+
+  function toNumber(s) {
+    return +s;
+  }
+
+  function isObject(obj) {
+    return obj === Object(obj);
+  }
+
+  var numberIsNaN = global.Number.isNaN || function isNaN(value) {
+    return typeof value === 'number' && global.isNaN(value);
+  }
+
+  function areSameValue(left, right) {
+    if (left === right)
+      return left !== 0 || 1 / left === 1 / right;
+    if (numberIsNaN(left) && numberIsNaN(right))
+      return true;
+
+    return left !== left && right !== right;
+  }
+
+  var createObject = ('__proto__' in {}) ?
+    function(obj) { return obj; } :
+    function(obj) {
+      var proto = obj.__proto__;
+      if (!proto)
+        return obj;
+      var newObject = Object.create(proto);
+      Object.getOwnPropertyNames(obj).forEach(function(name) {
+        Object.defineProperty(newObject, name,
+                             Object.getOwnPropertyDescriptor(obj, name));
+      });
+      return newObject;
+    };
+
+  var identStart = '[\$_a-zA-Z]';
+  var identPart = '[\$_a-zA-Z0-9]';
+  var ident = identStart + '+' + identPart + '*';
+  var elementIndex = '(?:[0-9]|[1-9]+[0-9]+)';
+  var identOrElementIndex = '(?:' + ident + '|' + elementIndex + ')';
+  var path = '(?:' + identOrElementIndex + ')(?:\\s*\\.\\s*' + identOrElementIndex + ')*';
+  var pathRegExp = new RegExp('^' + path + '$');
+
+  function isPathValid(s) {
+    if (typeof s != 'string')
+      return false;
+    s = s.trim();
+
+    if (s == '')
+      return true;
+
+    if (s[0] == '.')
+      return false;
+
+    return pathRegExp.test(s);
+  }
+
+  var constructorIsPrivate = {};
+
+  function Path(s, privateToken) {
+    if (privateToken !== constructorIsPrivate)
+      throw Error('Use Path.get to retrieve path objects');
+
+    if (s.trim() == '')
+      return this;
+
+    if (isIndex(s)) {
+      this.push(s);
+      return this;
+    }
+
+    s.split(/\s*\.\s*/).filter(function(part) {
+      return part;
+    }).forEach(function(part) {
+      this.push(part);
+    }, this);
+
+    if (hasEval && this.length) {
+      this.getValueFrom = this.compiledGetValueFromFn();
+    }
+  }
+
+  // TODO(rafaelw): Make simple LRU cache
+  var pathCache = {};
+
+  function getPath(pathString) {
+    if (pathString instanceof Path)
+      return pathString;
+
+    if (pathString == null)
+      pathString = '';
+
+    if (typeof pathString !== 'string')
+      pathString = String(pathString);
+
+    var path = pathCache[pathString];
+    if (path)
+      return path;
+    if (!isPathValid(pathString))
+      return invalidPath;
+    var path = new Path(pathString, constructorIsPrivate);
+    pathCache[pathString] = path;
+    return path;
+  }
+
+  Path.get = getPath;
+
+  Path.prototype = createObject({
+    __proto__: [],
+    valid: true,
+
+    toString: function() {
+      return this.join('.');
+    },
+
+    getValueFrom: function(obj, directObserver) {
+      for (var i = 0; i < this.length; i++) {
+        if (obj == null)
+          return;
+        obj = obj[this[i]];
+      }
+      return obj;
+    },
+
+    iterateObjects: function(obj, observe) {
+      for (var i = 0; i < this.length; i++) {
+        if (i)
+          obj = obj[this[i - 1]];
+        if (!obj)
+          return;
+        observe(obj);
+      }
+    },
+
+    compiledGetValueFromFn: function() {
+      var accessors = this.map(function(ident) {
+        return isIndex(ident) ? '["' + ident + '"]' : '.' + ident;
+      });
+
+      var str = '';
+      var pathString = 'obj';
+      str += 'if (obj != null';
+      var i = 0;
+      for (; i < (this.length - 1); i++) {
+        var ident = this[i];
+        pathString += accessors[i];
+        str += ' &&\n     ' + pathString + ' != null';
+      }
+      str += ')\n';
+
+      pathString += accessors[i];
+
+      str += '  return ' + pathString + ';\nelse\n  return undefined;';
+      return new Function('obj', str);
+    },
+
+    setValueFrom: function(obj, value) {
+      if (!this.length)
+        return false;
+
+      for (var i = 0; i < this.length - 1; i++) {
+        if (!isObject(obj))
+          return false;
+        obj = obj[this[i]];
+      }
+
+      if (!isObject(obj))
+        return false;
+
+      obj[this[i]] = value;
+      return true;
+    }
+  });
+
+  var invalidPath = new Path('', constructorIsPrivate);
+  invalidPath.valid = false;
+  invalidPath.getValueFrom = invalidPath.setValueFrom = function() {};
+
+  var MAX_DIRTY_CHECK_CYCLES = 1000;
+
+  function dirtyCheck(observer) {
+    var cycles = 0;
+    while (cycles < MAX_DIRTY_CHECK_CYCLES && observer.check_()) {
+      cycles++;
+    }
+    if (global.testingExposeCycleCount)
+      global.dirtyCheckCycleCount = cycles;
+
+    return cycles > 0;
+  }
+
+  function objectIsEmpty(object) {
+    for (var prop in object)
+      return false;
+    return true;
+  }
+
+  function diffIsEmpty(diff) {
+    return objectIsEmpty(diff.added) &&
+           objectIsEmpty(diff.removed) &&
+           objectIsEmpty(diff.changed);
+  }
+
+  function diffObjectFromOldObject(object, oldObject) {
+    var added = {};
+    var removed = {};
+    var changed = {};
+
+    for (var prop in oldObject) {
+      var newValue = object[prop];
+
+      if (newValue !== undefined && newValue === oldObject[prop])
+        continue;
+
+      if (!(prop in object)) {
+        removed[prop] = undefined;
+        continue;
+      }
+
+      if (newValue !== oldObject[prop])
+        changed[prop] = newValue;
+    }
+
+    for (var prop in object) {
+      if (prop in oldObject)
+        continue;
+
+      added[prop] = object[prop];
+    }
+
+    if (Array.isArray(object) && object.length !== oldObject.length)
+      changed.length = object.length;
+
+    return {
+      added: added,
+      removed: removed,
+      changed: changed
+    };
+  }
+
+  var eomTasks = [];
+  function runEOMTasks() {
+    if (!eomTasks.length)
+      return false;
+
+    for (var i = 0; i < eomTasks.length; i++) {
+      eomTasks[i]();
+    }
+    eomTasks.length = 0;
+    return true;
+  }
+
+  var runEOM = hasObserve ? (function(){
+    var eomObj = { pingPong: true };
+    var eomRunScheduled = false;
+
+    Object.observe(eomObj, function() {
+      runEOMTasks();
+      eomRunScheduled = false;
+    });
+
+    return function(fn) {
+      eomTasks.push(fn);
+      if (!eomRunScheduled) {
+        eomRunScheduled = true;
+        eomObj.pingPong = !eomObj.pingPong;
+      }
+    };
+  })() :
+  (function() {
+    return function(fn) {
+      eomTasks.push(fn);
+    };
+  })();
+
+  var observedObjectCache = [];
+
+  function newObservedObject() {
+    var observer;
+    var object;
+    var discardRecords = false;
+    var first = true;
+
+    function callback(records) {
+      if (observer && observer.state_ === OPENED && !discardRecords)
+        observer.check_(records);
+    }
+
+    return {
+      open: function(obs) {
+        if (observer)
+          throw Error('ObservedObject in use');
+
+        if (!first)
+          Object.deliverChangeRecords(callback);
+
+        observer = obs;
+        first = false;
+      },
+      observe: function(obj, arrayObserve) {
+        object = obj;
+        if (arrayObserve)
+          Array.observe(object, callback);
+        else
+          Object.observe(object, callback);
+      },
+      deliver: function(discard) {
+        discardRecords = discard;
+        Object.deliverChangeRecords(callback);
+        discardRecords = false;
+      },
+      close: function() {
+        observer = undefined;
+        Object.unobserve(object, callback);
+        observedObjectCache.push(this);
+      }
+    };
+  }
+
+  function getObservedObject(observer, object, arrayObserve) {
+    var dir = observedObjectCache.pop() || newObservedObject();
+    dir.open(observer);
+    dir.observe(object, arrayObserve);
+    return dir;
+  }
+
+  var emptyArray = [];
+  var observedSetCache = [];
+
+  function newObservedSet() {
+    var observers = [];
+    var observerCount = 0;
+    var objects = [];
+    var toRemove = emptyArray;
+    var resetNeeded = false;
+    var resetScheduled = false;
+
+    function observe(obj) {
+      if (!isObject(obj))
+        return;
+
+      var index = toRemove.indexOf(obj);
+      if (index >= 0) {
+        toRemove[index] = undefined;
+        objects.push(obj);
+      } else if (objects.indexOf(obj) < 0) {
+        objects.push(obj);
+        Object.observe(obj, callback);
+      }
+
+      observe(Object.getPrototypeOf(obj));
+    }
+
+    function reset() {
+      resetScheduled = false;
+      if (!resetNeeded)
+        return;
+
+      var objs = toRemove === emptyArray ? [] : toRemove;
+      toRemove = objects;
+      objects = objs;
+
+      var observer;
+      for (var id in observers) {
+        observer = observers[id];
+        if (!observer || observer.state_ != OPENED)
+          continue;
+
+        observer.iterateObjects_(observe);
+      }
+
+      for (var i = 0; i < toRemove.length; i++) {
+        var obj = toRemove[i];
+        if (obj)
+          Object.unobserve(obj, callback);
+      }
+
+      toRemove.length = 0;
+    }
+
+    function scheduleReset() {
+      if (resetScheduled)
+        return;
+
+      resetNeeded = true;
+      resetScheduled = true;
+      runEOM(reset);
+    }
+
+    function callback() {
+      var observer;
+
+      for (var id in observers) {
+        observer = observers[id];
+        if (!observer || observer.state_ != OPENED)
+          continue;
+
+        observer.check_();
+      }
+
+      scheduleReset();
+    }
+
+    var record = {
+      object: undefined,
+      objects: objects,
+      open: function(obs) {
+        observers[obs.id_] = obs;
+        observerCount++;
+        obs.iterateObjects_(observe);
+      },
+      close: function(obs) {
+        var anyLeft = false;
+
+        observers[obs.id_] = undefined;
+        observerCount--;
+
+        if (observerCount) {
+          scheduleReset();
+          return;
+        }
+        resetNeeded = false;
+
+        for (var i = 0; i < objects.length; i++) {
+          Object.unobserve(objects[i], callback);
+          Observer.unobservedCount++;
+        }
+
+        observers.length = 0;
+        objects.length = 0;
+        observedSetCache.push(this);
+      },
+      reset: scheduleReset
+    };
+
+    return record;
+  }
+
+  var lastObservedSet;
+
+  function getObservedSet(observer, obj) {
+    if (!lastObservedSet || lastObservedSet.object !== obj) {
+      lastObservedSet = observedSetCache.pop() || newObservedSet();
+      lastObservedSet.object = obj;
+    }
+    lastObservedSet.open(observer);
+    return lastObservedSet;
+  }
+
+  var UNOPENED = 0;
+  var OPENED = 1;
+  var CLOSED = 2;
+  var RESETTING = 3;
+
+  var nextObserverId = 1;
+
+  function Observer() {
+    this.state_ = UNOPENED;
+    this.callback_ = undefined;
+    this.target_ = undefined; // TODO(rafaelw): Should be WeakRef
+    this.directObserver_ = undefined;
+    this.value_ = undefined;
+    this.id_ = nextObserverId++;
+  }
+
+  Observer.prototype = {
+    open: function(callback, target) {
+      if (this.state_ != UNOPENED)
+        throw Error('Observer has already been opened.');
+
+      addToAll(this);
+      this.callback_ = callback;
+      this.target_ = target;
+      this.state_ = OPENED;
+      this.connect_();
+      return this.value_;
+    },
+
+    close: function() {
+      if (this.state_ != OPENED)
+        return;
+
+      removeFromAll(this);
+      this.state_ = CLOSED;
+      this.disconnect_();
+      this.value_ = undefined;
+      this.callback_ = undefined;
+      this.target_ = undefined;
+    },
+
+    deliver: function() {
+      if (this.state_ != OPENED)
+        return;
+
+      dirtyCheck(this);
+    },
+
+    report_: function(changes) {
+      try {
+        this.callback_.apply(this.target_, changes);
+      } catch (ex) {
+        Observer._errorThrownDuringCallback = true;
+        console.error('Exception caught during observer callback: ' +
+                       (ex.stack || ex));
+      }
+    },
+
+    discardChanges: function() {
+      this.check_(undefined, true);
+      return this.value_;
+    }
+  }
+
+  var collectObservers = !hasObserve;
+  var allObservers;
+  Observer._allObserversCount = 0;
+
+  if (collectObservers) {
+    allObservers = [];
+  }
+
+  function addToAll(observer) {
+    Observer._allObserversCount++;
+    if (!collectObservers)
+      return;
+
+    allObservers.push(observer);
+  }
+
+  function removeFromAll(observer) {
+    Observer._allObserversCount--;
+  }
+
+  var runningMicrotaskCheckpoint = false;
+
+  var hasDebugForceFullDelivery = typeof Object.deliverAllChangeRecords == 'function';
+
+  global.Platform = global.Platform || {};
+
+  global.Platform.performMicrotaskCheckpoint = function() {
+    if (runningMicrotaskCheckpoint)
+      return;
+
+    if (hasDebugForceFullDelivery) {
+      Object.deliverAllChangeRecords();
+      return;
+    }
+
+    if (!collectObservers)
+      return;
+
+    runningMicrotaskCheckpoint = true;
+
+    var cycles = 0;
+    var anyChanged, toCheck;
+
+    do {
+      cycles++;
+      toCheck = allObservers;
+      allObservers = [];
+      anyChanged = false;
+
+      for (var i = 0; i < toCheck.length; i++) {
+        var observer = toCheck[i];
+        if (observer.state_ != OPENED)
+          continue;
+
+        if (observer.check_())
+          anyChanged = true;
+
+        allObservers.push(observer);
+      }
+      if (runEOMTasks())
+        anyChanged = true;
+    } while (cycles < MAX_DIRTY_CHECK_CYCLES && anyChanged);
+
+    if (global.testingExposeCycleCount)
+      global.dirtyCheckCycleCount = cycles;
+
+    runningMicrotaskCheckpoint = false;
+  };
+
+  if (collectObservers) {
+    global.Platform.clearObservers = function() {
+      allObservers = [];
+    };
+  }
+
+  function ObjectObserver(object) {
+    Observer.call(this);
+    this.value_ = object;
+    this.oldObject_ = undefined;
+  }
+
+  ObjectObserver.prototype = createObject({
+    __proto__: Observer.prototype,
+
+    arrayObserve: false,
+
+    connect_: function(callback, target) {
+      if (hasObserve) {
+        this.directObserver_ = getObservedObject(this, this.value_,
+                                                 this.arrayObserve);
+      } else {
+        this.oldObject_ = this.copyObject(this.value_);
+      }
+
+    },
+
+    copyObject: function(object) {
+      var copy = Array.isArray(object) ? [] : {};
+      for (var prop in object) {
+        copy[prop] = object[prop];
+      };
+      if (Array.isArray(object))
+        copy.length = object.length;
+      return copy;
+    },
+
+    check_: function(changeRecords, skipChanges) {
+      var diff;
+      var oldValues;
+      if (hasObserve) {
+        if (!changeRecords)
+          return false;
+
+        oldValues = {};
+        diff = diffObjectFromChangeRecords(this.value_, changeRecords,
+                                           oldValues);
+      } else {
+        oldValues = this.oldObject_;
+        diff = diffObjectFromOldObject(this.value_, this.oldObject_);
+      }
+
+      if (diffIsEmpty(diff))
+        return false;
+
+      if (!hasObserve)
+        this.oldObject_ = this.copyObject(this.value_);
+
+      this.report_([
+        diff.added || {},
+        diff.removed || {},
+        diff.changed || {},
+        function(property) {
+          return oldValues[property];
+        }
+      ]);
+
+      return true;
+    },
+
+    disconnect_: function() {
+      if (hasObserve) {
+        this.directObserver_.close();
+        this.directObserver_ = undefined;
+      } else {
+        this.oldObject_ = undefined;
+      }
+    },
+
+    deliver: function() {
+      if (this.state_ != OPENED)
+        return;
+
+      if (hasObserve)
+        this.directObserver_.deliver(false);
+      else
+        dirtyCheck(this);
+    },
+
+    discardChanges: function() {
+      if (this.directObserver_)
+        this.directObserver_.deliver(true);
+      else
+        this.oldObject_ = this.copyObject(this.value_);
+
+      return this.value_;
+    }
+  });
+
+  function ArrayObserver(array) {
+    if (!Array.isArray(array))
+      throw Error('Provided object is not an Array');
+    ObjectObserver.call(this, array);
+  }
+
+  ArrayObserver.prototype = createObject({
+
+    __proto__: ObjectObserver.prototype,
+
+    arrayObserve: true,
+
+    copyObject: function(arr) {
+      return arr.slice();
+    },
+
+    check_: function(changeRecords) {
+      var splices;
+      if (hasObserve) {
+        if (!changeRecords)
+          return false;
+        splices = projectArraySplices(this.value_, changeRecords);
+      } else {
+        splices = calcSplices(this.value_, 0, this.value_.length,
+                              this.oldObject_, 0, this.oldObject_.length);
+      }
+
+      if (!splices || !splices.length)
+        return false;
+
+      if (!hasObserve)
+        this.oldObject_ = this.copyObject(this.value_);
+
+      this.report_([splices]);
+      return true;
+    }
+  });
+
+  ArrayObserver.applySplices = function(previous, current, splices) {
+    splices.forEach(function(splice) {
+      var spliceArgs = [splice.index, splice.removed.length];
+      var addIndex = splice.index;
+      while (addIndex < splice.index + splice.addedCount) {
+        spliceArgs.push(current[addIndex]);
+        addIndex++;
+      }
+
+      Array.prototype.splice.apply(previous, spliceArgs);
+    });
+  };
+
+  function PathObserver(object, path) {
+    Observer.call(this);
+
+    this.object_ = object;
+    this.path_ = path instanceof Path ? path : getPath(path);
+    this.directObserver_ = undefined;
+  }
+
+  PathObserver.prototype = createObject({
+    __proto__: Observer.prototype,
+
+    connect_: function() {
+      if (hasObserve)
+        this.directObserver_ = getObservedSet(this, this.object_);
+
+      this.check_(undefined, true);
+    },
+
+    disconnect_: function() {
+      this.value_ = undefined;
+
+      if (this.directObserver_) {
+        this.directObserver_.close(this);
+        this.directObserver_ = undefined;
+      }
+    },
+
+    iterateObjects_: function(observe) {
+      this.path_.iterateObjects(this.object_, observe);
+    },
+
+    check_: function(changeRecords, skipChanges) {
+      var oldValue = this.value_;
+      this.value_ = this.path_.getValueFrom(this.object_);
+      if (skipChanges || areSameValue(this.value_, oldValue))
+        return false;
+
+      this.report_([this.value_, oldValue]);
+      return true;
+    },
+
+    setValue: function(newValue) {
+      if (this.path_)
+        this.path_.setValueFrom(this.object_, newValue);
+    }
+  });
+
+  function CompoundObserver() {
+    Observer.call(this);
+
+    this.value_ = [];
+    this.directObserver_ = undefined;
+    this.observed_ = [];
+  }
+
+  var observerSentinel = {};
+
+  CompoundObserver.prototype = createObject({
+    __proto__: Observer.prototype,
+
+    connect_: function() {
+      this.check_(undefined, true);
+
+      if (!hasObserve)
+        return;
+
+      var object;
+      var needsDirectObserver = false;
+      for (var i = 0; i < this.observed_.length; i += 2) {
+        object = this.observed_[i]
+        if (object !== observerSentinel) {
+          needsDirectObserver = true;
+          break;
+        }
+      }
+
+      if (this.directObserver_) {
+        if (needsDirectObserver) {
+          this.directObserver_.reset();
+          return;
+        }
+        this.directObserver_.close();
+        this.directObserver_ = undefined;
+        return;
+      }
+
+      if (needsDirectObserver)
+        this.directObserver_ = getObservedSet(this, object);
+    },
+
+    closeObservers_: function() {
+      for (var i = 0; i < this.observed_.length; i += 2) {
+        if (this.observed_[i] === observerSentinel)
+          this.observed_[i + 1].close();
+      }
+      this.observed_.length = 0;
+    },
+
+    disconnect_: function() {
+      this.value_ = undefined;
+
+      if (this.directObserver_) {
+        this.directObserver_.close(this);
+        this.directObserver_ = undefined;
+      }
+
+      this.closeObservers_();
+    },
+
+    addPath: function(object, path) {
+      if (this.state_ != UNOPENED && this.state_ != RESETTING)
+        throw Error('Cannot add paths once started.');
+
+      this.observed_.push(object, path instanceof Path ? path : getPath(path));
+    },
+
+    addObserver: function(observer) {
+      if (this.state_ != UNOPENED && this.state_ != RESETTING)
+        throw Error('Cannot add observers once started.');
+
+      observer.open(this.deliver, this);
+      this.observed_.push(observerSentinel, observer);
+    },
+
+    startReset: function() {
+      if (this.state_ != OPENED)
+        throw Error('Can only reset while open');
+
+      this.state_ = RESETTING;
+      this.closeObservers_();
+    },
+
+    finishReset: function() {
+      if (this.state_ != RESETTING)
+        throw Error('Can only finishReset after startReset');
+      this.state_ = OPENED;
+      this.connect_();
+
+      return this.value_;
+    },
+
+    iterateObjects_: function(observe) {
+      var object;
+      for (var i = 0; i < this.observed_.length; i += 2) {
+        object = this.observed_[i]
+        if (object !== observerSentinel)
+          this.observed_[i + 1].iterateObjects(object, observe)
+      }
+    },
+
+    check_: function(changeRecords, skipChanges) {
+      var oldValues;
+      for (var i = 0; i < this.observed_.length; i += 2) {
+        var pathOrObserver = this.observed_[i+1];
+        var object = this.observed_[i];
+        var value = object === observerSentinel ?
+            pathOrObserver.discardChanges() :
+            pathOrObserver.getValueFrom(object)
+
+        if (skipChanges) {
+          this.value_[i / 2] = value;
+          continue;
+        }
+
+        if (areSameValue(value, this.value_[i / 2]))
+          continue;
+
+        oldValues = oldValues || [];
+        oldValues[i / 2] = this.value_[i / 2];
+        this.value_[i / 2] = value;
+      }
+
+      if (!oldValues)
+        return false;
+
+      // TODO(rafaelw): Having observed_ as the third callback arg here is
+      // pretty lame API. Fix.
+      this.report_([this.value_, oldValues, this.observed_]);
+      return true;
+    }
+  });
+
+  function identFn(value) { return value; }
+
+  function ObserverTransform(observable, getValueFn, setValueFn,
+                             dontPassThroughSet) {
+    this.callback_ = undefined;
+    this.target_ = undefined;
+    this.value_ = undefined;
+    this.observable_ = observable;
+    this.getValueFn_ = getValueFn || identFn;
+    this.setValueFn_ = setValueFn || identFn;
+    // TODO(rafaelw): This is a temporary hack. PolymerExpressions needs this
+    // at the moment because of a bug in it's dependency tracking.
+    this.dontPassThroughSet_ = dontPassThroughSet;
+  }
+
+  ObserverTransform.prototype = {
+    open: function(callback, target) {
+      this.callback_ = callback;
+      this.target_ = target;
+      this.value_ =
+          this.getValueFn_(this.observable_.open(this.observedCallback_, this));
+      return this.value_;
+    },
+
+    observedCallback_: function(value) {
+      value = this.getValueFn_(value);
+      if (areSameValue(value, this.value_))
+        return;
+      var oldValue = this.value_;
+      this.value_ = value;
+      this.callback_.call(this.target_, this.value_, oldValue);
+    },
+
+    discardChanges: function() {
+      this.value_ = this.getValueFn_(this.observable_.discardChanges());
+      return this.value_;
+    },
+
+    deliver: function() {
+      return this.observable_.deliver();
+    },
+
+    setValue: function(value) {
+      value = this.setValueFn_(value);
+      if (!this.dontPassThroughSet_ && this.observable_.setValue)
+        return this.observable_.setValue(value);
+    },
+
+    close: function() {
+      if (this.observable_)
+        this.observable_.close();
+      this.callback_ = undefined;
+      this.target_ = undefined;
+      this.observable_ = undefined;
+      this.value_ = undefined;
+      this.getValueFn_ = undefined;
+      this.setValueFn_ = undefined;
+    }
+  }
+
+  var expectedRecordTypes = {};
+  expectedRecordTypes[PROP_ADD_TYPE] = true;
+  expectedRecordTypes[PROP_UPDATE_TYPE] = true;
+  expectedRecordTypes[PROP_DELETE_TYPE] = true;
+
+  function notifyFunction(object, name) {
+    if (typeof Object.observe !== 'function')
+      return;
+
+    var notifier = Object.getNotifier(object);
+    return function(type, oldValue) {
+      var changeRecord = {
+        object: object,
+        type: type,
+        name: name
+      };
+      if (arguments.length === 2)
+        changeRecord.oldValue = oldValue;
+      notifier.notify(changeRecord);
+    }
+  }
+
+  Observer.defineComputedProperty = function(target, name, observable) {
+    var notify = notifyFunction(target, name);
+    var value = observable.open(function(newValue, oldValue) {
+      value = newValue;
+      if (notify)
+        notify(PROP_UPDATE_TYPE, oldValue);
+    });
+
+    Object.defineProperty(target, name, {
+      get: function() {
+        observable.deliver();
+        return value;
+      },
+      set: function(newValue) {
+        observable.setValue(newValue);
+        return newValue;
+      },
+      configurable: true
+    });
+
+    return {
+      close: function() {
+        observable.close();
+        Object.defineProperty(target, name, {
+          value: value,
+          writable: true,
+          configurable: true
+        });
+      }
+    };
+  }
+
+  function diffObjectFromChangeRecords(object, changeRecords, oldValues) {
+    var added = {};
+    var removed = {};
+
+    for (var i = 0; i < changeRecords.length; i++) {
+      var record = changeRecords[i];
+      if (!expectedRecordTypes[record.type]) {
+        console.error('Unknown changeRecord type: ' + record.type);
+        console.error(record);
+        continue;
+      }
+
+      if (!(record.name in oldValues))
+        oldValues[record.name] = record.oldValue;
+
+      if (record.type == PROP_UPDATE_TYPE)
+        continue;
+
+      if (record.type == PROP_ADD_TYPE) {
+        if (record.name in removed)
+          delete removed[record.name];
+        else
+          added[record.name] = true;
+
+        continue;
+      }
+
+      // type = 'delete'
+      if (record.name in added) {
+        delete added[record.name];
+        delete oldValues[record.name];
+      } else {
+        removed[record.name] = true;
+      }
+    }
+
+    for (var prop in added)
+      added[prop] = object[prop];
+
+    for (var prop in removed)
+      removed[prop] = undefined;
+
+    var changed = {};
+    for (var prop in oldValues) {
+      if (prop in added || prop in removed)
+        continue;
+
+      var newValue = object[prop];
+      if (oldValues[prop] !== newValue)
+        changed[prop] = newValue;
+    }
+
+    return {
+      added: added,
+      removed: removed,
+      changed: changed
+    };
+  }
+
+  function newSplice(index, removed, addedCount) {
+    return {
+      index: index,
+      removed: removed,
+      addedCount: addedCount
+    };
+  }
+
+  var EDIT_LEAVE = 0;
+  var EDIT_UPDATE = 1;
+  var EDIT_ADD = 2;
+  var EDIT_DELETE = 3;
+
+  function ArraySplice() {}
+
+  ArraySplice.prototype = {
+
+    // Note: This function is *based* on the computation of the Levenshtein
+    // "edit" distance. The one change is that "updates" are treated as two
+    // edits - not one. With Array splices, an update is really a delete
+    // followed by an add. By retaining this, we optimize for "keeping" the
+    // maximum array items in the original array. For example:
+    //
+    //   'xxxx123' -> '123yyyy'
+    //
+    // With 1-edit updates, the shortest path would be just to update all seven
+    // characters. With 2-edit updates, we delete 4, leave 3, and add 4. This
+    // leaves the substring '123' intact.
+    calcEditDistances: function(current, currentStart, currentEnd,
+                                old, oldStart, oldEnd) {
+      // "Deletion" columns
+      var rowCount = oldEnd - oldStart + 1;
+      var columnCount = currentEnd - currentStart + 1;
+      var distances = new Array(rowCount);
+
+      // "Addition" rows. Initialize null column.
+      for (var i = 0; i < rowCount; i++) {
+        distances[i] = new Array(columnCount);
+        distances[i][0] = i;
+      }
+
+      // Initialize null row
+      for (var j = 0; j < columnCount; j++)
+        distances[0][j] = j;
+
+      for (var i = 1; i < rowCount; i++) {
+        for (var j = 1; j < columnCount; j++) {
+          if (this.equals(current[currentStart + j - 1], old[oldStart + i - 1]))
+            distances[i][j] = distances[i - 1][j - 1];
+          else {
+            var north = distances[i - 1][j] + 1;
+            var west = distances[i][j - 1] + 1;
+            distances[i][j] = north < west ? north : west;
+          }
+        }
+      }
+
+      return distances;
+    },
+
+    // This starts at the final weight, and walks "backward" by finding
+    // the minimum previous weight recursively until the origin of the weight
+    // matrix.
+    spliceOperationsFromEditDistances: function(distances) {
+      var i = distances.length - 1;
+      var j = distances[0].length - 1;
+      var current = distances[i][j];
+      var edits = [];
+      while (i > 0 || j > 0) {
+        if (i == 0) {
+          edits.push(EDIT_ADD);
+          j--;
+          continue;
+        }
+        if (j == 0) {
+          edits.push(EDIT_DELETE);
+          i--;
+          continue;
+        }
+        var northWest = distances[i - 1][j - 1];
+        var west = distances[i - 1][j];
+        var north = distances[i][j - 1];
+
+        var min;
+        if (west < north)
+          min = west < northWest ? west : northWest;
+        else
+          min = north < northWest ? north : northWest;
+
+        if (min == northWest) {
+          if (northWest == current) {
+            edits.push(EDIT_LEAVE);
+          } else {
+            edits.push(EDIT_UPDATE);
+            current = northWest;
+          }
+          i--;
+          j--;
+        } else if (min == west) {
+          edits.push(EDIT_DELETE);
+          i--;
+          current = west;
+        } else {
+          edits.push(EDIT_ADD);
+          j--;
+          current = north;
+        }
+      }
+
+      edits.reverse();
+      return edits;
+    },
+
+    /**
+     * Splice Projection functions:
+     *
+     * A splice map is a representation of how a previous array of items
+     * was transformed into a new array of items. Conceptually it is a list of
+     * tuples of
+     *
+     *   <index, removed, addedCount>
+     *
+     * which are kept in ascending index order of. The tuple represents that at
+     * the |index|, |removed| sequence of items were removed, and counting forward
+     * from |index|, |addedCount| items were added.
+     */
+
+    /**
+     * Lacking individual splice mutation information, the minimal set of
+     * splices can be synthesized given the previous state and final state of an
+     * array. The basic approach is to calculate the edit distance matrix and
+     * choose the shortest path through it.
+     *
+     * Complexity: O(l * p)
+     *   l: The length of the current array
+     *   p: The length of the old array
+     */
+    calcSplices: function(current, currentStart, currentEnd,
+                          old, oldStart, oldEnd) {
+      var prefixCount = 0;
+      var suffixCount = 0;
+
+      var minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart);
+      if (currentStart == 0 && oldStart == 0)
+        prefixCount = this.sharedPrefix(current, old, minLength);
+
+      if (currentEnd == current.length && oldEnd == old.length)
+        suffixCount = this.sharedSuffix(current, old, minLength - prefixCount);
+
+      currentStart += prefixCount;
+      oldStart += prefixCount;
+      currentEnd -= suffixCount;
+      oldEnd -= suffixCount;
+
+      if (currentEnd - currentStart == 0 && oldEnd - oldStart == 0)
+        return [];
+
+      if (currentStart == currentEnd) {
+        var splice = newSplice(currentStart, [], 0);
+        while (oldStart < oldEnd)
+          splice.removed.push(old[oldStart++]);
+
+        return [ splice ];
+      } else if (oldStart == oldEnd)
+        return [ newSplice(currentStart, [], currentEnd - currentStart) ];
+
+      var ops = this.spliceOperationsFromEditDistances(
+          this.calcEditDistances(current, currentStart, currentEnd,
+                                 old, oldStart, oldEnd));
+
+      var splice = undefined;
+      var splices = [];
+      var index = currentStart;
+      var oldIndex = oldStart;
+      for (var i = 0; i < ops.length; i++) {
+        switch(ops[i]) {
+          case EDIT_LEAVE:
+            if (splice) {
+              splices.push(splice);
+              splice = undefined;
+            }
+
+            index++;
+            oldIndex++;
+            break;
+          case EDIT_UPDATE:
+            if (!splice)
+              splice = newSplice(index, [], 0);
+
+            splice.addedCount++;
+            index++;
+
+            splice.removed.push(old[oldIndex]);
+            oldIndex++;
+            break;
+          case EDIT_ADD:
+            if (!splice)
+              splice = newSplice(index, [], 0);
+
+            splice.addedCount++;
+            index++;
+            break;
+          case EDIT_DELETE:
+            if (!splice)
+              splice = newSplice(index, [], 0);
+
+            splice.removed.push(old[oldIndex]);
+            oldIndex++;
+            break;
+        }
+      }
+
+      if (splice) {
+        splices.push(splice);
+      }
+      return splices;
+    },
+
+    sharedPrefix: function(current, old, searchLength) {
+      for (var i = 0; i < searchLength; i++)
+        if (!this.equals(current[i], old[i]))
+          return i;
+      return searchLength;
+    },
+
+    sharedSuffix: function(current, old, searchLength) {
+      var index1 = current.length;
+      var index2 = old.length;
+      var count = 0;
+      while (count < searchLength && this.equals(current[--index1], old[--index2]))
+        count++;
+
+      return count;
+    },
+
+    calculateSplices: function(current, previous) {
+      return this.calcSplices(current, 0, current.length, previous, 0,
+                              previous.length);
+    },
+
+    equals: function(currentValue, previousValue) {
+      return currentValue === previousValue;
+    }
+  };
+
+  var arraySplice = new ArraySplice();
+
+  function calcSplices(current, currentStart, currentEnd,
+                       old, oldStart, oldEnd) {
+    return arraySplice.calcSplices(current, currentStart, currentEnd,
+                                   old, oldStart, oldEnd);
+  }
+
+  function intersect(start1, end1, start2, end2) {
+    // Disjoint
+    if (end1 < start2 || end2 < start1)
+      return -1;
+
+    // Adjacent
+    if (end1 == start2 || end2 == start1)
+      return 0;
+
+    // Non-zero intersect, span1 first
+    if (start1 < start2) {
+      if (end1 < end2)
+        return end1 - start2; // Overlap
+      else
+        return end2 - start2; // Contained
+    } else {
+      // Non-zero intersect, span2 first
+      if (end2 < end1)
+        return end2 - start1; // Overlap
+      else
+        return end1 - start1; // Contained
+    }
+  }
+
+  function mergeSplice(splices, index, removed, addedCount) {
+
+    var splice = newSplice(index, removed, addedCount);
+
+    var inserted = false;
+    var insertionOffset = 0;
+
+    for (var i = 0; i < splices.length; i++) {
+      var current = splices[i];
+      current.index += insertionOffset;
+
+      if (inserted)
+        continue;
+
+      var intersectCount = intersect(splice.index,
+                                     splice.index + splice.removed.length,
+                                     current.index,
+                                     current.index + current.addedCount);
+
+      if (intersectCount >= 0) {
+        // Merge the two splices
+
+        splices.splice(i, 1);
+        i--;
+
+        insertionOffset -= current.addedCount - current.removed.length;
+
+        splice.addedCount += current.addedCount - intersectCount;
+        var deleteCount = splice.removed.length +
+                          current.removed.length - intersectCount;
+
+        if (!splice.addedCount && !deleteCount) {
+          // merged splice is a noop. discard.
+          inserted = true;
+        } else {
+          var removed = current.removed;
+
+          if (splice.index < current.index) {
+            // some prefix of splice.removed is prepended to current.removed.
+            var prepend = splice.removed.slice(0, current.index - splice.index);
+            Array.prototype.push.apply(prepend, removed);
+            removed = prepend;
+          }
+
+          if (splice.index + splice.removed.length > current.index + current.addedCount) {
+            // some suffix of splice.removed is appended to current.removed.
+            var append = splice.removed.slice(current.index + current.addedCount - splice.index);
+            Array.prototype.push.apply(removed, append);
+          }
+
+          splice.removed = removed;
+          if (current.index < splice.index) {
+            splice.index = current.index;
+          }
+        }
+      } else if (splice.index < current.index) {
+        // Insert splice here.
+
+        inserted = true;
+
+        splices.splice(i, 0, splice);
+        i++;
+
+        var offset = splice.addedCount - splice.removed.length
+        current.index += offset;
+        insertionOffset += offset;
+      }
+    }
+
+    if (!inserted)
+      splices.push(splice);
+  }
+
+  function createInitialSplices(array, changeRecords) {
+    var splices = [];
+
+    for (var i = 0; i < changeRecords.length; i++) {
+      var record = changeRecords[i];
+      switch(record.type) {
+        case ARRAY_SPLICE_TYPE:
+          mergeSplice(splices, record.index, record.removed.slice(), record.addedCount);
+          break;
+        case PROP_ADD_TYPE:
+        case PROP_UPDATE_TYPE:
+        case PROP_DELETE_TYPE:
+          if (!isIndex(record.name))
+            continue;
+          var index = toNumber(record.name);
+          if (index < 0)
+            continue;
+          mergeSplice(splices, index, [record.oldValue], 1);
+          break;
+        default:
+          console.error('Unexpected record type: ' + JSON.stringify(record));
+          break;
+      }
+    }
+
+    return splices;
+  }
+
+  function projectArraySplices(array, changeRecords) {
+    var splices = [];
+
+    createInitialSplices(array, changeRecords).forEach(function(splice) {
+      if (splice.addedCount == 1 && splice.removed.length == 1) {
+        if (splice.removed[0] !== array[splice.index])
+          splices.push(splice);
+
+        return
+      };
+
+      splices = splices.concat(calcSplices(array, splice.index, splice.index + splice.addedCount,
+                                           splice.removed, 0, splice.removed.length));
+    });
+
+    return splices;
+  }
+
+  global.Observer = Observer;
+  global.Observer.runEOM_ = runEOM;
+  global.Observer.hasObjectObserve = hasObserve;
+  global.ArrayObserver = ArrayObserver;
+  global.ArrayObserver.calculateSplices = function(current, previous) {
+    return arraySplice.calculateSplices(current, previous);
+  };
+
+  global.ArraySplice = ArraySplice;
+  global.ObjectObserver = ObjectObserver;
+  global.PathObserver = PathObserver;
+  global.CompoundObserver = CompoundObserver;
+  global.Path = Path;
+  global.ObserverTransform = ObserverTransform;
+
+  // TODO(rafaelw): Only needed for testing until new change record names
+  // make it to release.
+  global.Observer.changeRecordTypes = {
+    add: PROP_ADD_TYPE,
+    update: PROP_UPDATE_TYPE,
+    reconfigure: PROP_RECONFIGURE_TYPE,
+    'delete': PROP_DELETE_TYPE,
+    splice: ARRAY_SPLICE_TYPE
+  };
+})(typeof global !== 'undefined' && global && typeof module !== 'undefined' && module ? global : this || window);
+
+// prepoulate window.Platform.flags for default controls

+window.Platform = window.Platform || {};

+// prepopulate window.logFlags if necessary

+window.logFlags = window.logFlags || {};

+// process flags

+(function(scope){

+  // import

+  var flags = scope.flags || {};

+  // populate flags from location

+  location.search.slice(1).split('&').forEach(function(o) {

+    o = o.split('=');

+    o[0] && (flags[o[0]] = o[1] || true);

+  });

+  var entryPoint = document.currentScript || document.querySelector('script[src*="platform.js"]');

+  if (entryPoint) {

+    var a = entryPoint.attributes;

+    for (var i = 0, n; i < a.length; i++) {

+      n = a[i];

+      if (n.name !== 'src') {

+        flags[n.name] = n.value || true;

+      }

+    }

+  }

+  if (flags.log) {

+    flags.log.split(',').forEach(function(f) {

+      window.logFlags[f] = true;

+    });

+  }

+  // If any of these flags match 'native', then force native ShadowDOM; any

+  // other truthy value, or failure to detect native

+  // ShadowDOM, results in polyfill

+  flags.shadow = (flags.shadow || flags.shadowdom || flags.polyfill);

+  if (flags.shadow === 'native') {

+    flags.shadow = false;

+  } else {

+    flags.shadow = flags.shadow || !HTMLElement.prototype.createShadowRoot;

+  }

+

+  // CustomElements polyfill flag

+  if (flags.register) {

+    window.CustomElements = window.CustomElements || {flags: {}};

+    window.CustomElements.flags.register = flags.register;

+  }

+

+  if (flags.imports) {

+    window.HTMLImports = window.HTMLImports || {flags: {}};

+    window.HTMLImports.flags.imports = flags.imports;

+  }

+

+  // export

+  scope.flags = flags;

+})(Platform);

+

+// select ShadowDOM impl

+if (Platform.flags.shadow) {

+
+// Copyright 2012 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+window.ShadowDOMPolyfill = {};
+
+(function(scope) {
+  'use strict';
+
+  var constructorTable = new WeakMap();
+  var nativePrototypeTable = new WeakMap();
+  var wrappers = Object.create(null);
+
+  // Don't test for eval if document has CSP securityPolicy object and we can
+  // see that eval is not supported. This avoids an error message in console
+  // even when the exception is caught
+  var hasEval = !('securityPolicy' in document) ||
+      document.securityPolicy.allowsEval;
+  if (hasEval) {
+    try {
+      var f = new Function('', 'return true;');
+      hasEval = f();
+    } catch (ex) {
+      hasEval = false;
+    }
+  }
+
+  function assert(b) {
+    if (!b)
+      throw new Error('Assertion failed');
+  };
+
+  var defineProperty = Object.defineProperty;
+  var getOwnPropertyNames = Object.getOwnPropertyNames;
+  var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
+
+  function mixin(to, from) {
+    getOwnPropertyNames(from).forEach(function(name) {
+      defineProperty(to, name, getOwnPropertyDescriptor(from, name));
+    });
+    return to;
+  };
+
+  function mixinStatics(to, from) {
+    getOwnPropertyNames(from).forEach(function(name) {
+      switch (name) {
+        case 'arguments':
+        case 'caller':
+        case 'length':
+        case 'name':
+        case 'prototype':
+        case 'toString':
+          return;
+      }
+      defineProperty(to, name, getOwnPropertyDescriptor(from, name));
+    });
+    return to;
+  };
+
+  function oneOf(object, propertyNames) {
+    for (var i = 0; i < propertyNames.length; i++) {
+      if (propertyNames[i] in object)
+        return propertyNames[i];
+    }
+  }
+
+  // Mozilla's old DOM bindings are bretty busted:
+  // https://bugzilla.mozilla.org/show_bug.cgi?id=855844
+  // Make sure they are create before we start modifying things.
+  getOwnPropertyNames(window);
+
+  function getWrapperConstructor(node) {
+    var nativePrototype = node.__proto__ || Object.getPrototypeOf(node);
+    var wrapperConstructor = constructorTable.get(nativePrototype);
+    if (wrapperConstructor)
+      return wrapperConstructor;
+
+    var parentWrapperConstructor = getWrapperConstructor(nativePrototype);
+
+    var GeneratedWrapper = createWrapperConstructor(parentWrapperConstructor);
+    registerInternal(nativePrototype, GeneratedWrapper, node);
+
+    return GeneratedWrapper;
+  }
+
+  function addForwardingProperties(nativePrototype, wrapperPrototype) {
+    installProperty(nativePrototype, wrapperPrototype, true);
+  }
+
+  function registerInstanceProperties(wrapperPrototype, instanceObject) {
+    installProperty(instanceObject, wrapperPrototype, false);
+  }
+
+  var isFirefox = /Firefox/.test(navigator.userAgent);
+
+  // This is used as a fallback when getting the descriptor fails in
+  // installProperty.
+  var dummyDescriptor = {
+    get: function() {},
+    set: function(v) {},
+    configurable: true,
+    enumerable: true
+  };
+
+  function isEventHandlerName(name) {
+    return /^on[a-z]+$/.test(name);
+  }
+
+  function isIdentifierName(name) {
+    return /^\w[a-zA-Z_0-9]*$/.test(name);
+  }
+
+  function getGetter(name) {
+    return hasEval && isIdentifierName(name) ?
+        new Function('return this.impl.' + name) :
+        function() { return this.impl[name]; };
+  }
+
+  function getSetter(name) {
+    return hasEval && isIdentifierName(name) ?
+        new Function('v', 'this.impl.' + name + ' = v') :
+        function(v) { this.impl[name] = v; };
+  }
+
+  function getMethod(name) {
+    return hasEval && isIdentifierName(name) ?
+        new Function('return this.impl.' + name +
+                     '.apply(this.impl, arguments)') :
+        function() { return this.impl[name].apply(this.impl, arguments); };
+  }
+
+  function getDescriptor(source, name) {
+    try {
+      return Object.getOwnPropertyDescriptor(source, name);
+    } catch (ex) {
+      // JSC and V8 both use data properties instead of accessors which can
+      // cause getting the property desciptor to throw an exception.
+      // https://bugs.webkit.org/show_bug.cgi?id=49739
+      return dummyDescriptor;
+    }
+  }
+
+  function installProperty(source, target, allowMethod, opt_blacklist) {
+    var names = getOwnPropertyNames(source);
+    for (var i = 0; i < names.length; i++) {
+      var name = names[i];
+      if (name === 'polymerBlackList_')
+        continue;
+
+      if (name in target)
+        continue;
+
+      if (source.polymerBlackList_ && source.polymerBlackList_[name])
+        continue;
+
+      if (isFirefox) {
+        // Tickle Firefox's old bindings.
+        source.__lookupGetter__(name);
+      }
+      var descriptor = getDescriptor(source, name);
+      var getter, setter;
+      if (allowMethod && typeof descriptor.value === 'function') {
+        target[name] = getMethod(name);
+        continue;
+      }
+
+      var isEvent = isEventHandlerName(name);
+      if (isEvent)
+        getter = scope.getEventHandlerGetter(name);
+      else
+        getter = getGetter(name);
+
+      if (descriptor.writable || descriptor.set) {
+        if (isEvent)
+          setter = scope.getEventHandlerSetter(name);
+        else
+          setter = getSetter(name);
+      }
+
+      defineProperty(target, name, {
+        get: getter,
+        set: setter,
+        configurable: descriptor.configurable,
+        enumerable: descriptor.enumerable
+      });
+    }
+  }
+
+  /**
+   * @param {Function} nativeConstructor
+   * @param {Function} wrapperConstructor
+   * @param {Object=} opt_instance If present, this is used to extract
+   *     properties from an instance object.
+   */
+  function register(nativeConstructor, wrapperConstructor, opt_instance) {
+    var nativePrototype = nativeConstructor.prototype;
+    registerInternal(nativePrototype, wrapperConstructor, opt_instance);
+    mixinStatics(wrapperConstructor, nativeConstructor);
+  }
+
+  function registerInternal(nativePrototype, wrapperConstructor, opt_instance) {
+    var wrapperPrototype = wrapperConstructor.prototype;
+    assert(constructorTable.get(nativePrototype) === undefined);
+
+    constructorTable.set(nativePrototype, wrapperConstructor);
+    nativePrototypeTable.set(wrapperPrototype, nativePrototype);
+
+    addForwardingProperties(nativePrototype, wrapperPrototype);
+    if (opt_instance)
+      registerInstanceProperties(wrapperPrototype, opt_instance);
+    defineProperty(wrapperPrototype, 'constructor', {
+      value: wrapperConstructor,
+      configurable: true,
+      enumerable: false,
+      writable: true
+    });
+  }
+
+  function isWrapperFor(wrapperConstructor, nativeConstructor) {
+    return constructorTable.get(nativeConstructor.prototype) ===
+        wrapperConstructor;
+  }
+
+  /**
+   * Creates a generic wrapper constructor based on |object| and its
+   * constructor.
+   * @param {Node} object
+   * @return {Function} The generated constructor.
+   */
+  function registerObject(object) {
+    var nativePrototype = Object.getPrototypeOf(object);
+
+    var superWrapperConstructor = getWrapperConstructor(nativePrototype);
+    var GeneratedWrapper = createWrapperConstructor(superWrapperConstructor);
+    registerInternal(nativePrototype, GeneratedWrapper, object);
+
+    return GeneratedWrapper;
+  }
+
+  function createWrapperConstructor(superWrapperConstructor) {
+    function GeneratedWrapper(node) {
+      superWrapperConstructor.call(this, node);
+    }
+    GeneratedWrapper.prototype =
+        Object.create(superWrapperConstructor.prototype);
+    GeneratedWrapper.prototype.constructor = GeneratedWrapper;
+
+    return GeneratedWrapper;
+  }
+
+  var OriginalDOMImplementation = window.DOMImplementation;
+  var OriginalEventTarget = window.EventTarget;
+  var OriginalEvent = window.Event;
+  var OriginalNode = window.Node;
+  var OriginalWindow = window.Window;
+  var OriginalRange = window.Range;
+  var OriginalCanvasRenderingContext2D = window.CanvasRenderingContext2D;
+  var OriginalWebGLRenderingContext = window.WebGLRenderingContext;
+  var OriginalSVGElementInstance = window.SVGElementInstance;
+
+  function isWrapper(object) {
+    return object instanceof wrappers.EventTarget ||
+           object instanceof wrappers.Event ||
+           object instanceof wrappers.Range ||
+           object instanceof wrappers.DOMImplementation ||
+           object instanceof wrappers.CanvasRenderingContext2D ||
+           wrappers.WebGLRenderingContext &&
+               object instanceof wrappers.WebGLRenderingContext;
+  }
+
+  function isNative(object) {
+    return OriginalEventTarget && object instanceof OriginalEventTarget ||
+           object instanceof OriginalNode ||
+           object instanceof OriginalEvent ||
+           object instanceof OriginalWindow ||
+           object instanceof OriginalRange ||
+           object instanceof OriginalDOMImplementation ||
+           object instanceof OriginalCanvasRenderingContext2D ||
+           OriginalWebGLRenderingContext &&
+               object instanceof OriginalWebGLRenderingContext ||
+           OriginalSVGElementInstance &&
+               object instanceof OriginalSVGElementInstance;
+  }
+
+  /**
+   * Wraps a node in a WrapperNode. If there already exists a wrapper for the
+   * |node| that wrapper is returned instead.
+   * @param {Node} node
+   * @return {WrapperNode}
+   */
+  function wrap(impl) {
+    if (impl === null)
+      return null;
+
+    assert(isNative(impl));
+    return impl.polymerWrapper_ ||
+        (impl.polymerWrapper_ = new (getWrapperConstructor(impl))(impl));
+  }
+
+  /**
+   * Unwraps a wrapper and returns the node it is wrapping.
+   * @param {WrapperNode} wrapper
+   * @return {Node}
+   */
+  function unwrap(wrapper) {
+    if (wrapper === null)
+      return null;
+    assert(isWrapper(wrapper));
+    return wrapper.impl;
+  }
+
+  /**
+   * Unwraps object if it is a wrapper.
+   * @param {Object} object
+   * @return {Object} The native implementation object.
+   */
+  function unwrapIfNeeded(object) {
+    return object && isWrapper(object) ? unwrap(object) : object;
+  }
+
+  /**
+   * Wraps object if it is not a wrapper.
+   * @param {Object} object
+   * @return {Object} The wrapper for object.
+   */
+  function wrapIfNeeded(object) {
+    return object && !isWrapper(object) ? wrap(object) : object;
+  }
+
+  /**
+   * Overrides the current wrapper (if any) for node.
+   * @param {Node} node
+   * @param {WrapperNode=} wrapper If left out the wrapper will be created as
+   *     needed next time someone wraps the node.
+   */
+  function rewrap(node, wrapper) {
+    if (wrapper === null)
+      return;
+    assert(isNative(node));
+    assert(wrapper === undefined || isWrapper(wrapper));
+    node.polymerWrapper_ = wrapper;
+  }
+
+  function defineGetter(constructor, name, getter) {
+    defineProperty(constructor.prototype, name, {
+      get: getter,
+      configurable: true,
+      enumerable: true
+    });
+  }
+
+  function defineWrapGetter(constructor, name) {
+    defineGetter(constructor, name, function() {
+      return wrap(this.impl[name]);
+    });
+  }
+
+  /**
+   * Forwards existing methods on the native object to the wrapper methods.
+   * This does not wrap any of the arguments or the return value since the
+   * wrapper implementation already takes care of that.
+   * @param {Array.<Function>} constructors
+   * @parem {Array.<string>} names
+   */
+  function forwardMethodsToWrapper(constructors, names) {
+    constructors.forEach(function(constructor) {
+      names.forEach(function(name) {
+        constructor.prototype[name] = function() {
+          var w = wrapIfNeeded(this);
+          return w[name].apply(w, arguments);
+        };
+      });
+    });
+  }
+
+  scope.assert = assert;
+  scope.constructorTable = constructorTable;
+  scope.defineGetter = defineGetter;
+  scope.defineWrapGetter = defineWrapGetter;
+  scope.forwardMethodsToWrapper = forwardMethodsToWrapper;
+  scope.isWrapper = isWrapper;
+  scope.isWrapperFor = isWrapperFor;
+  scope.mixin = mixin;
+  scope.nativePrototypeTable = nativePrototypeTable;
+  scope.oneOf = oneOf;
+  scope.registerObject = registerObject;
+  scope.registerWrapper = register;
+  scope.rewrap = rewrap;
+  scope.unwrap = unwrap;
+  scope.unwrapIfNeeded = unwrapIfNeeded;
+  scope.wrap = wrap;
+  scope.wrapIfNeeded = wrapIfNeeded;
+  scope.wrappers = wrappers;
+
+})(window.ShadowDOMPolyfill);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is goverened by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+(function(context) {
+  'use strict';
+
+  var OriginalMutationObserver = window.MutationObserver;
+  var callbacks = [];
+  var pending = false;
+  var timerFunc;
+
+  function handle() {
+    pending = false;
+    var copies = callbacks.slice(0);
+    callbacks = [];
+    for (var i = 0; i < copies.length; i++) {
+      (0, copies[i])();
+    }
+  }
+
+  if (OriginalMutationObserver) {
+    var counter = 1;
+    var observer = new OriginalMutationObserver(handle);
+    var textNode = document.createTextNode(counter);
+    observer.observe(textNode, {characterData: true});
+
+    timerFunc = function() {
+      counter = (counter + 1) % 2;
+      textNode.data = counter;
+    };
+
+  } else {
+    timerFunc = window.setImmediate || window.setTimeout;
+  }
+
+  function setEndOfMicrotask(func) {
+    callbacks.push(func);
+    if (pending)
+      return;
+    pending = true;
+    timerFunc(handle, 0);
+  }
+
+  context.setEndOfMicrotask = setEndOfMicrotask;
+
+})(window.ShadowDOMPolyfill);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is goverened by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+(function(scope) {
+  'use strict';
+
+  var setEndOfMicrotask = scope.setEndOfMicrotask
+  var wrapIfNeeded = scope.wrapIfNeeded
+  var wrappers = scope.wrappers;
+
+  var registrationsTable = new WeakMap();
+  var globalMutationObservers = [];
+  var isScheduled = false;
+
+  function scheduleCallback(observer) {
+    if (isScheduled)
+      return;
+    setEndOfMicrotask(notifyObservers);
+    isScheduled = true;
+  }
+
+  // http://dom.spec.whatwg.org/#mutation-observers
+  function notifyObservers() {
+    isScheduled = false;
+
+    do {
+      var notifyList = globalMutationObservers.slice();
+      var anyNonEmpty = false;
+      for (var i = 0; i < notifyList.length; i++) {
+        var mo = notifyList[i];
+        var queue = mo.takeRecords();
+        removeTransientObserversFor(mo);
+        if (queue.length) {
+          mo.callback_(queue, mo);
+          anyNonEmpty = true;
+        }
+      }
+    } while (anyNonEmpty);
+  }
+
+  /**
+   * @param {string} type
+   * @param {Node} target
+   * @constructor
+   */
+  function MutationRecord(type, target) {
+    this.type = type;
+    this.target = target;
+    this.addedNodes = new wrappers.NodeList();
+    this.removedNodes = new wrappers.NodeList();
+    this.previousSibling = null;
+    this.nextSibling = null;
+    this.attributeName = null;
+    this.attributeNamespace = null;
+    this.oldValue = null;
+  }
+
+  /**
+   * Registers transient observers to ancestor and its ancesors for the node
+   * which was removed.
+   * @param {!Node} ancestor
+   * @param {!Node} node
+   */
+  function registerTransientObservers(ancestor, node) {
+    for (; ancestor; ancestor = ancestor.parentNode) {
+      var registrations = registrationsTable.get(ancestor);
+      if (!registrations)
+        continue;
+      for (var i = 0; i < registrations.length; i++) {
+        var registration = registrations[i];
+        if (registration.options.subtree)
+          registration.addTransientObserver(node);
+      }
+    }
+  }
+
+  function removeTransientObserversFor(observer) {
+    for (var i = 0; i < observer.nodes_.length; i++) {
+      var node = observer.nodes_[i];
+      var registrations = registrationsTable.get(node);
+      if (!registrations)
+        return;
+      for (var j = 0; j < registrations.length; j++) {
+        var registration = registrations[j];
+        if (registration.observer === observer)
+          registration.removeTransientObservers();
+      }
+    }
+  }
+
+  // http://dom.spec.whatwg.org/#queue-a-mutation-record
+  function enqueueMutation(target, type, data) {
+    // 1.
+    var interestedObservers = Object.create(null);
+    var associatedStrings = Object.create(null);
+
+    // 2.
+    for (var node = target; node; node = node.parentNode) {
+      // 3.
+      var registrations = registrationsTable.get(node);
+      if (!registrations)
+        continue;
+      for (var j = 0; j < registrations.length; j++) {
+        var registration = registrations[j];
+        var options = registration.options;
+        // 1.
+        if (node !== target && !options.subtree)
+          continue;
+
+        // 2.
+        if (type === 'attributes' && !options.attributes)
+          continue;
+
+        // 3. If type is "attributes", options's attributeFilter is present, and
+        // either options's attributeFilter does not contain name or namespace
+        // is non-null, continue.
+        if (type === 'attributes' && options.attributeFilter &&
+            (data.namespace !== null ||
+             options.attributeFilter.indexOf(data.name) === -1)) {
+          continue;
+        }
+
+        // 4.
+        if (type === 'characterData' && !options.characterData)
+          continue;
+
+        // 5.
+        if (type === 'childList' && !options.childList)
+          continue;
+
+        // 6.
+        var observer = registration.observer;
+        interestedObservers[observer.uid_] = observer;
+
+        // 7. If either type is "attributes" and options's attributeOldValue is
+        // true, or type is "characterData" and options's characterDataOldValue
+        // is true, set the paired string of registered observer's observer in
+        // interested observers to oldValue.
+        if (type === 'attributes' && options.attributeOldValue ||
+            type === 'characterData' && options.characterDataOldValue) {
+          associatedStrings[observer.uid_] = data.oldValue;
+        }
+      }
+    }
+
+    var anyRecordsEnqueued = false;
+
+    // 4.
+    for (var uid in interestedObservers) {
+      var observer = interestedObservers[uid];
+      var record = new MutationRecord(type, target);
+
+      // 2.
+      if ('name' in data && 'namespace' in data) {
+        record.attributeName = data.name;
+        record.attributeNamespace = data.namespace;
+      }
+
+      // 3.
+      if (data.addedNodes)
+        record.addedNodes = data.addedNodes;
+
+      // 4.
+      if (data.removedNodes)
+        record.removedNodes = data.removedNodes;
+
+      // 5.
+      if (data.previousSibling)
+        record.previousSibling = data.previousSibling;
+
+      // 6.
+      if (data.nextSibling)
+        record.nextSibling = data.nextSibling;
+
+      // 7.
+      if (associatedStrings[uid] !== undefined)
+        record.oldValue = associatedStrings[uid];
+
+      // 8.
+      observer.records_.push(record);
+
+      anyRecordsEnqueued = true;
+    }
+
+    if (anyRecordsEnqueued)
+      scheduleCallback();
+  }
+
+  var slice = Array.prototype.slice;
+
+  /**
+   * @param {!Object} options
+   * @constructor
+   */
+  function MutationObserverOptions(options) {
+    this.childList = !!options.childList;
+    this.subtree = !!options.subtree;
+
+    // 1. If either options' attributeOldValue or attributeFilter is present
+    // and options' attributes is omitted, set options' attributes to true.
+    if (!('attributes' in options) &&
+        ('attributeOldValue' in options || 'attributeFilter' in options)) {
+      this.attributes = true;
+    } else {
+      this.attributes = !!options.attributes;
+    }
+
+    // 2. If options' characterDataOldValue is present and options'
+    // characterData is omitted, set options' characterData to true.
+    if ('characterDataOldValue' in options && !('characterData' in options))
+      this.characterData = true;
+    else
+      this.characterData = !!options.characterData;
+
+    // 3. & 4.
+    if (!this.attributes &&
+        (options.attributeOldValue || 'attributeFilter' in options) ||
+        // 5.
+        !this.characterData && options.characterDataOldValue) {
+      throw new TypeError();
+    }
+
+    this.characterData = !!options.characterData;
+    this.attributeOldValue = !!options.attributeOldValue;
+    this.characterDataOldValue = !!options.characterDataOldValue;
+    if ('attributeFilter' in options) {
+      if (options.attributeFilter == null ||
+          typeof options.attributeFilter !== 'object') {
+        throw new TypeError();
+      }
+      this.attributeFilter = slice.call(options.attributeFilter);
+    } else {
+      this.attributeFilter = null;
+    }
+  }
+
+  var uidCounter = 0;
+
+  /**
+   * The class that maps to the DOM MutationObserver interface.
+   * @param {Function} callback.
+   * @constructor
+   */
+  function MutationObserver(callback) {
+    this.callback_ = callback;
+    this.nodes_ = [];
+    this.records_ = [];
+    this.uid_ = ++uidCounter;
+
+    // This will leak. There is no way to implement this without WeakRefs :'(
+    globalMutationObservers.push(this);
+  }
+
+  MutationObserver.prototype = {
+    // http://dom.spec.whatwg.org/#dom-mutationobserver-observe
+    observe: function(target, options) {
+      target = wrapIfNeeded(target);
+
+      var newOptions = new MutationObserverOptions(options);
+
+      // 6.
+      var registration;
+      var registrations = registrationsTable.get(target);
+      if (!registrations)
+        registrationsTable.set(target, registrations = []);
+
+      for (var i = 0; i < registrations.length; i++) {
+        if (registrations[i].observer === this) {
+          registration = registrations[i];
+          // 6.1.
+          registration.removeTransientObservers();
+          // 6.2.
+          registration.options = newOptions;
+        }
+      }
+
+      // 7.
+      if (!registration) {
+        registration = new Registration(this, target, newOptions);
+        registrations.push(registration);
+        this.nodes_.push(target);
+      }
+    },
+
+    // http://dom.spec.whatwg.org/#dom-mutationobserver-disconnect
+    disconnect: function() {
+      this.nodes_.forEach(function(node) {
+        var registrations = registrationsTable.get(node);
+        for (var i = 0; i < registrations.length; i++) {
+          var registration = registrations[i];
+          if (registration.observer === this) {
+            registrations.splice(i, 1);
+            // Each node can only have one registered observer associated with
+            // this observer.
+            break;
+          }
+        }
+      }, this);
+      this.records_ = [];
+    },
+
+    takeRecords: function() {
+      var copyOfRecords = this.records_;
+      this.records_ = [];
+      return copyOfRecords;
+    }
+  };
+
+  /**
+   * Class used to represent a registered observer.
+   * @param {MutationObserver} observer
+   * @param {Node} target
+   * @param {MutationObserverOptions} options
+   * @constructor
+   */
+  function Registration(observer, target, options) {
+    this.observer = observer;
+    this.target = target;
+    this.options = options;
+    this.transientObservedNodes = [];
+  }
+
+  Registration.prototype = {
+    /**
+     * Adds a transient observer on node. The transient observer gets removed
+     * next time we deliver the change records.
+     * @param {Node} node
+     */
+    addTransientObserver: function(node) {
+      // Don't add transient observers on the target itself. We already have all
+      // the required listeners set up on the target.
+      if (node === this.target)
+        return;
+
+      this.transientObservedNodes.push(node);
+      var registrations = registrationsTable.get(node);
+      if (!registrations)
+        registrationsTable.set(node, registrations = []);
+
+      // We know that registrations does not contain this because we already
+      // checked if node === this.target.
+      registrations.push(this);
+    },
+
+    removeTransientObservers: function() {
+      var transientObservedNodes = this.transientObservedNodes;
+      this.transientObservedNodes = [];
+
+      for (var i = 0; i < transientObservedNodes.length; i++) {
+        var node = transientObservedNodes[i];
+        var registrations = registrationsTable.get(node);
+        for (var j = 0; j < registrations.length; j++) {
+          if (registrations[j] === this) {
+            registrations.splice(j, 1);
+            // Each node can only have one registered observer associated with
+            // this observer.
+            break;
+          }
+        }
+      }
+    }
+  };
+
+  scope.enqueueMutation = enqueueMutation;
+  scope.registerTransientObservers = registerTransientObservers;
+  scope.wrappers.MutationObserver = MutationObserver;
+  scope.wrappers.MutationRecord = MutationRecord;
+
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var forwardMethodsToWrapper = scope.forwardMethodsToWrapper;
+  var mixin = scope.mixin;
+  var registerWrapper = scope.registerWrapper;
+  var unwrap = scope.unwrap;
+  var wrap = scope.wrap;
+  var wrappers = scope.wrappers;
+
+  var wrappedFuns = new WeakMap();
+  var listenersTable = new WeakMap();
+  var handledEventsTable = new WeakMap();
+  var currentlyDispatchingEvents = new WeakMap();
+  var targetTable = new WeakMap();
+  var currentTargetTable = new WeakMap();
+  var relatedTargetTable = new WeakMap();
+  var eventPhaseTable = new WeakMap();
+  var stopPropagationTable = new WeakMap();
+  var stopImmediatePropagationTable = new WeakMap();
+  var eventHandlersTable = new WeakMap();
+  var eventPathTable = new WeakMap();
+
+  function isShadowRoot(node) {
+    return node instanceof wrappers.ShadowRoot;
+  }
+
+  function isInsertionPoint(node) {
+    var localName = node.localName;
+    return localName === 'content' || localName === 'shadow';
+  }
+
+  function isShadowHost(node) {
+    return !!node.shadowRoot;
+  }
+
+  function getEventParent(node) {
+    var dv;
+    return node.parentNode || (dv = node.defaultView) && wrap(dv) || null;
+  }
+
+  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-adjusted-parent
+  function calculateParents(node, context, ancestors) {
+    if (ancestors.length)
+      return ancestors.shift();
+
+    // 1.
+    if (isShadowRoot(node))
+      return getInsertionParent(node) || node.host;
+
+    // 2.
+    var eventParents = scope.eventParentsTable.get(node);
+    if (eventParents) {
+      // Copy over the remaining event parents for next iteration.
+      for (var i = 1; i < eventParents.length; i++) {
+        ancestors[i - 1] = eventParents[i];
+      }
+      return eventParents[0];
+    }
+
+    // 3.
+    if (context && isInsertionPoint(node)) {
+      var parentNode = node.parentNode;
+      if (parentNode && isShadowHost(parentNode)) {
+        var trees = scope.getShadowTrees(parentNode);
+        var p = getInsertionParent(context);
+        for (var i = 0; i < trees.length; i++) {
+          if (trees[i].contains(p))
+            return p;
+        }
+      }
+    }
+
+    return getEventParent(node);
+  }
+
+  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#event-retargeting
+  function retarget(node) {
+    var stack = [];  // 1.
+    var ancestor = node;  // 2.
+    var targets = [];
+    var ancestors = [];
+    while (ancestor) {  // 3.
+      var context = null;  // 3.2.
+      // TODO(arv): Change order of these. If the stack is empty we always end
+      // up pushing ancestor, no matter what.
+      if (isInsertionPoint(ancestor)) {  // 3.1.
+        context = topMostNotInsertionPoint(stack);  // 3.1.1.
+        var top = stack[stack.length - 1] || ancestor;  // 3.1.2.
+        stack.push(top);
+      } else if (!stack.length) {
+        stack.push(ancestor);  // 3.3.
+      }
+      var target = stack[stack.length - 1];  // 3.4.
+      targets.push({target: target, currentTarget: ancestor});  // 3.5.
+      if (isShadowRoot(ancestor))  // 3.6.
+        stack.pop();  // 3.6.1.
+
+      ancestor = calculateParents(ancestor, context, ancestors);  // 3.7.
+    }
+    return targets;
+  }
+
+  function topMostNotInsertionPoint(stack) {
+    for (var i = stack.length - 1; i >= 0; i--) {
+      if (!isInsertionPoint(stack[i]))
+        return stack[i];
+    }
+    return null;
+  }
+
+  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-adjusted-related-target
+  function adjustRelatedTarget(target, related) {
+    var ancestors = [];
+    while (target) {  // 3.
+      var stack = [];  // 3.1.
+      var ancestor = related;  // 3.2.
+      var last = undefined;  // 3.3. Needs to be reset every iteration.
+      while (ancestor) {
+        var context = null;
+        if (!stack.length) {
+          stack.push(ancestor);
+        } else {
+          if (isInsertionPoint(ancestor)) {  // 3.4.3.
+            context = topMostNotInsertionPoint(stack);
+            // isDistributed is more general than checking whether last is
+            // assigned into ancestor.
+            if (isDistributed(last)) {  // 3.4.3.2.
+              var head = stack[stack.length - 1];
+              stack.push(head);
+            }
+          }
+        }
+
+        if (inSameTree(ancestor, target))  // 3.4.4.
+          return stack[stack.length - 1];
+
+        if (isShadowRoot(ancestor))  // 3.4.5.
+          stack.pop();
+
+        last = ancestor;  // 3.4.6.
+        ancestor = calculateParents(ancestor, context, ancestors);  // 3.4.7.
+      }
+      if (isShadowRoot(target))  // 3.5.
+        target = target.host;
+      else
+        target = target.parentNode;  // 3.6.
+    }
+  }
+
+  function getInsertionParent(node) {
+    return scope.insertionParentTable.get(node);
+  }
+
+  function isDistributed(node) {
+    return getInsertionParent(node);
+  }
+
+  function rootOfNode(node) {
+    var p;
+    while (p = node.parentNode) {
+      node = p;
+    }
+    return node;
+  }
+
+  function inSameTree(a, b) {
+    return rootOfNode(a) === rootOfNode(b);
+  }
+
+  function enclosedBy(a, b) {
+    if (a === b)
+      return true;
+    if (a instanceof wrappers.ShadowRoot)
+      return enclosedBy(rootOfNode(a.host), b);
+    return false;
+  }
+
+
+  function dispatchOriginalEvent(originalEvent) {
+    // Make sure this event is only dispatched once.
+    if (handledEventsTable.get(originalEvent))
+      return;
+    handledEventsTable.set(originalEvent, true);
+
+    return dispatchEvent(wrap(originalEvent), wrap(originalEvent.target));
+  }
+
+  function dispatchEvent(event, originalWrapperTarget) {
+    if (currentlyDispatchingEvents.get(event))
+      throw new Error('InvalidStateError')
+    currentlyDispatchingEvents.set(event, true);
+
+    // Render to ensure that the event path is correct.
+    scope.renderAllPending();
+    var eventPath = retarget(originalWrapperTarget);
+
+    // For window load events the load event is dispatched at the window but
+    // the target is set to the document.
+    //
+    // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#the-end
+    //
+    // TODO(arv): Find a less hacky way to do this.
+    if (event.type === 'load' &&
+        eventPath.length === 2 &&
+        eventPath[0].target instanceof wrappers.Document) {
+      eventPath.shift();
+    }
+
+    eventPathTable.set(event, eventPath);
+
+    if (dispatchCapturing(event, eventPath)) {
+      if (dispatchAtTarget(event, eventPath)) {
+        dispatchBubbling(event, eventPath);
+      }
+    }
+
+    eventPhaseTable.set(event, Event.NONE);
+    currentTargetTable.delete(event, null);
+    currentlyDispatchingEvents.delete(event);
+
+    return event.defaultPrevented;
+  }
+
+  function dispatchCapturing(event, eventPath) {
+    var phase;
+
+    for (var i = eventPath.length - 1; i > 0; i--) {
+      var target = eventPath[i].target;
+      var currentTarget = eventPath[i].currentTarget;
+      if (target === currentTarget)
+        continue;
+
+      phase = Event.CAPTURING_PHASE;
+      if (!invoke(eventPath[i], event, phase))
+        return false;
+    }
+
+    return true;
+  }
+
+  function dispatchAtTarget(event, eventPath) {
+    var phase = Event.AT_TARGET;
+    return invoke(eventPath[0], event, phase);
+  }
+
+  function dispatchBubbling(event, eventPath) {
+    var bubbles = event.bubbles;
+    var phase;
+
+    for (var i = 1; i < eventPath.length; i++) {
+      var target = eventPath[i].target;
+      var currentTarget = eventPath[i].currentTarget;
+      if (target === currentTarget)
+        phase = Event.AT_TARGET;
+      else if (bubbles && !stopImmediatePropagationTable.get(event))
+        phase = Event.BUBBLING_PHASE;
+      else
+        continue;
+
+      if (!invoke(eventPath[i], event, phase))
+        return;
+    }
+  }
+
+  function invoke(tuple, event, phase) {
+    var target = tuple.target;
+    var currentTarget = tuple.currentTarget;
+
+    var listeners = listenersTable.get(currentTarget);
+    if (!listeners)
+      return true;
+
+    if ('relatedTarget' in event) {
+      var originalEvent = unwrap(event);
+      // X-Tag sets relatedTarget on a CustomEvent. If they do that there is no
+      // way to have relatedTarget return the adjusted target but worse is that
+      // the originalEvent might not have a relatedTarget so we hit an assert
+      // when we try to wrap it.
+      if (originalEvent.relatedTarget) {
+        var relatedTarget = wrap(originalEvent.relatedTarget);
+
+        var adjusted = adjustRelatedTarget(currentTarget, relatedTarget);
+        if (adjusted === target)
+          return true;
+
+        relatedTargetTable.set(event, adjusted);
+      }
+    }
+
+    eventPhaseTable.set(event, phase);
+    var type = event.type;
+
+    var anyRemoved = false;
+    targetTable.set(event, target);
+    currentTargetTable.set(event, currentTarget);
+
+    for (var i = 0; i < listeners.length; i++) {
+      var listener = listeners[i];
+      if (listener.removed) {
+        anyRemoved = true;
+        continue;
+      }
+
+      if (listener.type !== type ||
+          !listener.capture && phase === Event.CAPTURING_PHASE ||
+          listener.capture && phase === Event.BUBBLING_PHASE) {
+        continue;
+      }
+
+      try {
+        if (typeof listener.handler === 'function')
+          listener.handler.call(currentTarget, event);
+        else
+          listener.handler.handleEvent(event);
+
+        if (stopImmediatePropagationTable.get(event))
+          return false;
+
+      } catch (ex) {
+        if (window.onerror)
+          window.onerror(ex.message);
+        else
+          console.error(ex, ex.stack);
+      }
+    }
+
+    if (anyRemoved) {
+      var copy = listeners.slice();
+      listeners.length = 0;
+      for (var i = 0; i < copy.length; i++) {
+        if (!copy[i].removed)
+          listeners.push(copy[i]);
+      }
+    }
+
+    return !stopPropagationTable.get(event);
+  }
+
+  function Listener(type, handler, capture) {
+    this.type = type;
+    this.handler = handler;
+    this.capture = Boolean(capture);
+  }
+  Listener.prototype = {
+    equals: function(that) {
+      return this.handler === that.handler && this.type === that.type &&
+          this.capture === that.capture;
+    },
+    get removed() {
+      return this.handler === null;
+    },
+    remove: function() {
+      this.handler = null;
+    }
+  };
+
+  var OriginalEvent = window.Event;
+  OriginalEvent.prototype.polymerBlackList_ = {
+    returnValue: true,
+    // TODO(arv): keyLocation is part of KeyboardEvent but Firefox does not
+    // support constructable KeyboardEvent so we keep it here for now.
+    keyLocation: true
+  };
+
+  /**
+   * Creates a new Event wrapper or wraps an existin native Event object.
+   * @param {string|Event} type
+   * @param {Object=} options
+   * @constructor
+   */
+  function Event(type, options) {
+    if (type instanceof OriginalEvent)
+      this.impl = type;
+    else
+      return wrap(constructEvent(OriginalEvent, 'Event', type, options));
+  }
+  Event.prototype = {
+    get target() {
+      return targetTable.get(this);
+    },
+    get currentTarget() {
+      return currentTargetTable.get(this);
+    },
+    get eventPhase() {
+      return eventPhaseTable.get(this);
+    },
+    get path() {
+      var nodeList = new wrappers.NodeList();
+      var eventPath = eventPathTable.get(this);
+      if (eventPath) {
+        var index = 0;
+        var lastIndex = eventPath.length - 1;
+        var baseRoot = rootOfNode(currentTargetTable.get(this));
+
+        for (var i = 0; i <= lastIndex; i++) {
+          var currentTarget = eventPath[i].currentTarget;
+          var currentRoot = rootOfNode(currentTarget);
+          if (enclosedBy(baseRoot, currentRoot) &&
+              // Make sure we do not add Window to the path.
+              (i !== lastIndex || currentTarget instanceof wrappers.Node)) {
+            nodeList[index++] = currentTarget;
+          }
+        }
+        nodeList.length = index;
+      }
+      return nodeList;
+    },
+    stopPropagation: function() {
+      stopPropagationTable.set(this, true);
+    },
+    stopImmediatePropagation: function() {
+      stopPropagationTable.set(this, true);
+      stopImmediatePropagationTable.set(this, true);
+    }
+  };
+  registerWrapper(OriginalEvent, Event, document.createEvent('Event'));
+
+  function unwrapOptions(options) {
+    if (!options || !options.relatedTarget)
+      return options;
+    return Object.create(options, {
+      relatedTarget: {value: unwrap(options.relatedTarget)}
+    });
+  }
+
+  function registerGenericEvent(name, SuperEvent, prototype) {
+    var OriginalEvent = window[name];
+    var GenericEvent = function(type, options) {
+      if (type instanceof OriginalEvent)
+        this.impl = type;
+      else
+        return wrap(constructEvent(OriginalEvent, name, type, options));
+    };
+    GenericEvent.prototype = Object.create(SuperEvent.prototype);
+    if (prototype)
+      mixin(GenericEvent.prototype, prototype);
+    if (OriginalEvent) {
+      // - Old versions of Safari fails on new FocusEvent (and others?).
+      // - IE does not support event constructors.
+      // - createEvent('FocusEvent') throws in Firefox.
+      // => Try the best practice solution first and fallback to the old way
+      // if needed.
+      try {
+        registerWrapper(OriginalEvent, GenericEvent, new OriginalEvent('temp'));
+      } catch (ex) {
+        registerWrapper(OriginalEvent, GenericEvent,
+                        document.createEvent(name));
+      }
+    }
+    return GenericEvent;
+  }
+
+  var UIEvent = registerGenericEvent('UIEvent', Event);
+  var CustomEvent = registerGenericEvent('CustomEvent', Event);
+
+  var relatedTargetProto = {
+    get relatedTarget() {
+      return relatedTargetTable.get(this) || wrap(unwrap(this).relatedTarget);
+    }
+  };
+
+  function getInitFunction(name, relatedTargetIndex) {
+    return function() {
+      arguments[relatedTargetIndex] = unwrap(arguments[relatedTargetIndex]);
+      var impl = unwrap(this);
+      impl[name].apply(impl, arguments);
+    };
+  }
+
+  var mouseEventProto = mixin({
+    initMouseEvent: getInitFunction('initMouseEvent', 14)
+  }, relatedTargetProto);
+
+  var focusEventProto = mixin({
+    initFocusEvent: getInitFunction('initFocusEvent', 5)
+  }, relatedTargetProto);
+
+  var MouseEvent = registerGenericEvent('MouseEvent', UIEvent, mouseEventProto);
+  var FocusEvent = registerGenericEvent('FocusEvent', UIEvent, focusEventProto);
+
+  // In case the browser does not support event constructors we polyfill that
+  // by calling `createEvent('Foo')` and `initFooEvent` where the arguments to
+  // `initFooEvent` are derived from the registered default event init dict.
+  var defaultInitDicts = Object.create(null);
+
+  var supportsEventConstructors = (function() {
+    try {
+      new window.FocusEvent('focus');
+    } catch (ex) {
+      return false;
+    }
+    return true;
+  })();
+
+  /**
+   * Constructs a new native event.
+   */
+  function constructEvent(OriginalEvent, name, type, options) {
+    if (supportsEventConstructors)
+      return new OriginalEvent(type, unwrapOptions(options));
+
+    // Create the arguments from the default dictionary.
+    var event = unwrap(document.createEvent(name));
+    var defaultDict = defaultInitDicts[name];
+    var args = [type];
+    Object.keys(defaultDict).forEach(function(key) {
+      var v = options != null && key in options ?
+          options[key] : defaultDict[key];
+      if (key === 'relatedTarget')
+        v = unwrap(v);
+      args.push(v);
+    });
+    event['init' + name].apply(event, args);
+    return event;
+  }
+
+  if (!supportsEventConstructors) {
+    var configureEventConstructor = function(name, initDict, superName) {
+      if (superName) {
+        var superDict = defaultInitDicts[superName];
+        initDict = mixin(mixin({}, superDict), initDict);
+      }
+
+      defaultInitDicts[name] = initDict;
+    };
+
+    // The order of the default event init dictionary keys is important, the
+    // arguments to initFooEvent is derived from that.
+    configureEventConstructor('Event', {bubbles: false, cancelable: false});
+    configureEventConstructor('CustomEvent', {detail: null}, 'Event');
+    configureEventConstructor('UIEvent', {view: null, detail: 0}, 'Event');
+    configureEventConstructor('MouseEvent', {
+      screenX: 0,
+      screenY: 0,
+      clientX: 0,
+      clientY: 0,
+      ctrlKey: false,
+      altKey: false,
+      shiftKey: false,
+      metaKey: false,
+      button: 0,
+      relatedTarget: null
+    }, 'UIEvent');
+    configureEventConstructor('FocusEvent', {relatedTarget: null}, 'UIEvent');
+  }
+
+  function BeforeUnloadEvent(impl) {
+    Event.call(this);
+  }
+  BeforeUnloadEvent.prototype = Object.create(Event.prototype);
+  mixin(BeforeUnloadEvent.prototype, {
+    get returnValue() {
+      return this.impl.returnValue;
+    },
+    set returnValue(v) {
+      this.impl.returnValue = v;
+    }
+  });
+
+  function isValidListener(fun) {
+    if (typeof fun === 'function')
+      return true;
+    return fun && fun.handleEvent;
+  }
+
+  function isMutationEvent(type) {
+    switch (type) {
+      case 'DOMAttrModified':
+      case 'DOMAttributeNameChanged':
+      case 'DOMCharacterDataModified':
+      case 'DOMElementNameChanged':
+      case 'DOMNodeInserted':
+      case 'DOMNodeInsertedIntoDocument':
+      case 'DOMNodeRemoved':
+      case 'DOMNodeRemovedFromDocument':
+      case 'DOMSubtreeModified':
+        return true;
+    }
+    return false;
+  }
+
+  var OriginalEventTarget = window.EventTarget;
+
+  /**
+   * This represents a wrapper for an EventTarget.
+   * @param {!EventTarget} impl The original event target.
+   * @constructor
+   */
+  function EventTarget(impl) {
+    this.impl = impl;
+  }
+
+  // Node and Window have different internal type checks in WebKit so we cannot
+  // use the same method as the original function.
+  var methodNames = [
+    'addEventListener',
+    'removeEventListener',
+    'dispatchEvent'
+  ];
+
+  [Node, Window].forEach(function(constructor) {
+    var p = constructor.prototype;
+    methodNames.forEach(function(name) {
+      Object.defineProperty(p, name + '_', {value: p[name]});
+    });
+  });
+
+  function getTargetToListenAt(wrapper) {
+    if (wrapper instanceof wrappers.ShadowRoot)
+      wrapper = wrapper.host;
+    return unwrap(wrapper);
+  }
+
+  EventTarget.prototype = {
+    addEventListener: function(type, fun, capture) {
+      if (!isValidListener(fun) || isMutationEvent(type))
+        return;
+
+      var listener = new Listener(type, fun, capture);
+      var listeners = listenersTable.get(this);
+      if (!listeners) {
+        listeners = [];
+        listenersTable.set(this, listeners);
+      } else {
+        // Might have a duplicate.
+        for (var i = 0; i < listeners.length; i++) {
+          if (listener.equals(listeners[i]))
+            return;
+        }
+      }
+
+      listeners.push(listener);
+
+      var target = getTargetToListenAt(this);
+      target.addEventListener_(type, dispatchOriginalEvent, true);
+    },
+    removeEventListener: function(type, fun, capture) {
+      capture = Boolean(capture);
+      var listeners = listenersTable.get(this);
+      if (!listeners)
+        return;
+      var count = 0, found = false;
+      for (var i = 0; i < listeners.length; i++) {
+        if (listeners[i].type === type && listeners[i].capture === capture) {
+          count++;
+          if (listeners[i].handler === fun) {
+            found = true;
+            listeners[i].remove();
+          }
+        }
+      }
+
+      if (found && count === 1) {
+        var target = getTargetToListenAt(this);
+        target.removeEventListener_(type, dispatchOriginalEvent, true);
+      }
+    },
+    dispatchEvent: function(event) {
+      // We want to use the native dispatchEvent because it triggers the default
+      // actions (like checking a checkbox). However, if there are no listeners
+      // in the composed tree then there are no events that will trigger and
+      // listeners in the non composed tree that are part of the event path are
+      // not notified.
+      //
+      // If we find out that there are no listeners in the composed tree we add
+      // a temporary listener to the target which makes us get called back even
+      // in that case.
+
+      var nativeEvent = unwrap(event);
+      var eventType = nativeEvent.type;
+
+      // Allow dispatching the same event again. This is safe because if user
+      // code calls this during an existing dispatch of the same event the
+      // native dispatchEvent throws (that is required by the spec).
+      handledEventsTable.set(nativeEvent, false);
+
+      // Force rendering since we prefer native dispatch and that works on the
+      // composed tree.
+      scope.renderAllPending();
+
+      var tempListener;
+      if (!hasListenerInAncestors(this, eventType)) {
+        tempListener = function() {};
+        this.addEventListener(eventType, tempListener, true);
+      }
+
+      try {
+        return unwrap(this).dispatchEvent_(nativeEvent);
+      } finally {
+        if (tempListener)
+          this.removeEventListener(eventType, tempListener, true);
+      }
+    }
+  };
+
+  function hasListener(node, type) {
+    var listeners = listenersTable.get(node);
+    if (listeners) {
+      for (var i = 0; i < listeners.length; i++) {
+        if (!listeners[i].removed && listeners[i].type === type)
+          return true;
+      }
+    }
+    return false;
+  }
+
+  function hasListenerInAncestors(target, type) {
+    for (var node = unwrap(target); node; node = node.parentNode) {
+      if (hasListener(wrap(node), type))
+        return true;
+    }
+    return false;
+  }
+
+  if (OriginalEventTarget)
+    registerWrapper(OriginalEventTarget, EventTarget);
+
+  function wrapEventTargetMethods(constructors) {
+    forwardMethodsToWrapper(constructors, methodNames);
+  }
+
+  var originalElementFromPoint = document.elementFromPoint;
+
+  function elementFromPoint(self, document, x, y) {
+    scope.renderAllPending();
+
+    var element = wrap(originalElementFromPoint.call(document.impl, x, y));
+    var targets = retarget(element, this)
+    for (var i = 0; i < targets.length; i++) {
+      var target = targets[i];
+      if (target.currentTarget === self)
+        return target.target;
+    }
+    return null;
+  }
+
+  /**
+   * Returns a function that is to be used as a getter for `onfoo` properties.
+   * @param {string} name
+   * @return {Function}
+   */
+  function getEventHandlerGetter(name) {
+    return function() {
+      var inlineEventHandlers = eventHandlersTable.get(this);
+      return inlineEventHandlers && inlineEventHandlers[name] &&
+          inlineEventHandlers[name].value || null;
+     };
+  }
+
+  /**
+   * Returns a function that is to be used as a setter for `onfoo` properties.
+   * @param {string} name
+   * @return {Function}
+   */
+  function getEventHandlerSetter(name) {
+    var eventType = name.slice(2);
+    return function(value) {
+      var inlineEventHandlers = eventHandlersTable.get(this);
+      if (!inlineEventHandlers) {
+        inlineEventHandlers = Object.create(null);
+        eventHandlersTable.set(this, inlineEventHandlers);
+      }
+
+      var old = inlineEventHandlers[name];
+      if (old)
+        this.removeEventListener(eventType, old.wrapped, false);
+
+      if (typeof value === 'function') {
+        var wrapped = function(e) {
+          var rv = value.call(this, e);
+          if (rv === false)
+            e.preventDefault();
+          else if (name === 'onbeforeunload' && typeof rv === 'string')
+            e.returnValue = rv;
+          // mouseover uses true for preventDefault but preventDefault for
+          // mouseover is ignored by browsers these day.
+        };
+
+        this.addEventListener(eventType, wrapped, false);
+        inlineEventHandlers[name] = {
+          value: value,
+          wrapped: wrapped
+        };
+      }
+    };
+  }
+
+  scope.adjustRelatedTarget = adjustRelatedTarget;
+  scope.elementFromPoint = elementFromPoint;
+  scope.getEventHandlerGetter = getEventHandlerGetter;
+  scope.getEventHandlerSetter = getEventHandlerSetter;
+  scope.wrapEventTargetMethods = wrapEventTargetMethods;
+  scope.wrappers.BeforeUnloadEvent = BeforeUnloadEvent;
+  scope.wrappers.CustomEvent = CustomEvent;
+  scope.wrappers.Event = Event;
+  scope.wrappers.EventTarget = EventTarget;
+  scope.wrappers.FocusEvent = FocusEvent;
+  scope.wrappers.MouseEvent = MouseEvent;
+  scope.wrappers.UIEvent = UIEvent;
+
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2012 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var wrap = scope.wrap;
+
+  function nonEnum(obj, prop) {
+    Object.defineProperty(obj, prop, {enumerable: false});
+  }
+
+  function NodeList() {
+    this.length = 0;
+    nonEnum(this, 'length');
+  }
+  NodeList.prototype = {
+    item: function(index) {
+      return this[index];
+    }
+  };
+  nonEnum(NodeList.prototype, 'item');
+
+  function wrapNodeList(list) {
+    if (list == null)
+      return list;
+    var wrapperList = new NodeList();
+    for (var i = 0, length = list.length; i < length; i++) {
+      wrapperList[i] = wrap(list[i]);
+    }
+    wrapperList.length = length;
+    return wrapperList;
+  }
+
+  function addWrapNodeListMethod(wrapperConstructor, name) {
+    wrapperConstructor.prototype[name] = function() {
+      return wrapNodeList(this.impl[name].apply(this.impl, arguments));
+    };
+  }
+
+  scope.wrappers.NodeList = NodeList;
+  scope.addWrapNodeListMethod = addWrapNodeListMethod;
+  scope.wrapNodeList = wrapNodeList;
+
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2012 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var EventTarget = scope.wrappers.EventTarget;
+  var NodeList = scope.wrappers.NodeList;
+  var assert = scope.assert;
+  var defineWrapGetter = scope.defineWrapGetter;
+  var enqueueMutation = scope.enqueueMutation;
+  var isWrapper = scope.isWrapper;
+  var mixin = scope.mixin;
+  var registerTransientObservers = scope.registerTransientObservers;
+  var registerWrapper = scope.registerWrapper;
+  var unwrap = scope.unwrap;
+  var wrap = scope.wrap;
+  var wrapIfNeeded = scope.wrapIfNeeded;
+  var wrappers = scope.wrappers;
+
+  function assertIsNodeWrapper(node) {
+    assert(node instanceof Node);
+  }
+
+  function createOneElementNodeList(node) {
+    var nodes = new NodeList();
+    nodes[0] = node;
+    nodes.length = 1;
+    return nodes;
+  }
+
+  var surpressMutations = false;
+
+  /**
+   * Called before node is inserted into a node to enqueue its removal from its
+   * old parent.
+   * @param {!Node} node The node that is about to be removed.
+   * @param {!Node} parent The parent node that the node is being removed from.
+   * @param {!NodeList} nodes The collected nodes.
+   */
+  function enqueueRemovalForInsertedNodes(node, parent, nodes) {
+    enqueueMutation(parent, 'childList', {
+      removedNodes: nodes,
+      previousSibling: node.previousSibling,
+      nextSibling: node.nextSibling
+    });
+  }
+
+  function enqueueRemovalForInsertedDocumentFragment(df, nodes) {
+    enqueueMutation(df, 'childList', {
+      removedNodes: nodes
+    });
+  }
+
+  /**
+   * Collects nodes from a DocumentFragment or a Node for removal followed
+   * by an insertion.
+   *
+   * This updates the internal pointers for node, previousNode and nextNode.
+   */
+  function collectNodes(node, parentNode, previousNode, nextNode) {
+    if (node instanceof DocumentFragment) {
+      var nodes = collectNodesForDocumentFragment(node);
+
+      // The extra loop is to work around bugs with DocumentFragments in IE.
+      surpressMutations = true;
+      for (var i = nodes.length - 1; i >= 0; i--) {
+        node.removeChild(nodes[i]);
+        nodes[i].parentNode_ = parentNode;
+      }
+      surpressMutations = false;
+
+      for (var i = 0; i < nodes.length; i++) {
+        nodes[i].previousSibling_ = nodes[i - 1] || previousNode;
+        nodes[i].nextSibling_ = nodes[i + 1] || nextNode;
+      }
+
+      if (previousNode)
+        previousNode.nextSibling_ = nodes[0];
+      if (nextNode)
+        nextNode.previousSibling_ = nodes[nodes.length - 1];
+
+      return nodes;
+    }
+
+    var nodes = createOneElementNodeList(node);
+    var oldParent = node.parentNode;
+    if (oldParent) {
+      // This will enqueue the mutation record for the removal as needed.
+      oldParent.removeChild(node);
+    }
+
+    node.parentNode_ = parentNode;
+    node.previousSibling_ = previousNode;
+    node.nextSibling_ = nextNode;
+    if (previousNode)
+      previousNode.nextSibling_ = node;
+    if (nextNode)
+      nextNode.previousSibling_ = node;
+
+    return nodes;
+  }
+
+  function collectNodesNative(node) {
+    if (node instanceof DocumentFragment)
+      return collectNodesForDocumentFragment(node);
+
+    var nodes = createOneElementNodeList(node);
+    var oldParent = node.parentNode;
+    if (oldParent)
+      enqueueRemovalForInsertedNodes(node, oldParent, nodes);
+    return nodes;
+  }
+
+  function collectNodesForDocumentFragment(node) {
+    var nodes = new NodeList();
+    var i = 0;
+    for (var child = node.firstChild; child; child = child.nextSibling) {
+      nodes[i++] = child;
+    }
+    nodes.length = i;
+    enqueueRemovalForInsertedDocumentFragment(node, nodes);
+    return nodes;
+  }
+
+  function snapshotNodeList(nodeList) {
+    // NodeLists are not live at the moment so just return the same object.
+    return nodeList;
+  }
+
+  // http://dom.spec.whatwg.org/#node-is-inserted
+  function nodeWasAdded(node) {
+    node.nodeIsInserted_();
+  }
+
+  function nodesWereAdded(nodes) {
+    for (var i = 0; i < nodes.length; i++) {
+      nodeWasAdded(nodes[i]);
+    }
+  }
+
+  // http://dom.spec.whatwg.org/#node-is-removed
+  function nodeWasRemoved(node) {
+    // Nothing at this point in time.
+  }
+
+  function nodesWereRemoved(nodes) {
+    // Nothing at this point in time.
+  }
+
+  function ensureSameOwnerDocument(parent, child) {
+    var ownerDoc = parent.nodeType === Node.DOCUMENT_NODE ?
+        parent : parent.ownerDocument;
+    if (ownerDoc !== child.ownerDocument)
+      ownerDoc.adoptNode(child);
+  }
+
+  function adoptNodesIfNeeded(owner, nodes) {
+    if (!nodes.length)
+      return;
+
+    var ownerDoc = owner.ownerDocument;
+
+    // All nodes have the same ownerDocument when we get here.
+    if (ownerDoc === nodes[0].ownerDocument)
+      return;
+
+    for (var i = 0; i < nodes.length; i++) {
+      scope.adoptNodeNoRemove(nodes[i], ownerDoc);
+    }
+  }
+
+  function unwrapNodesForInsertion(owner, nodes) {
+    adoptNodesIfNeeded(owner, nodes);
+    var length = nodes.length;
+
+    if (length === 1)
+      return unwrap(nodes[0]);
+
+    var df = unwrap(owner.ownerDocument.createDocumentFragment());
+    for (var i = 0; i < length; i++) {
+      df.appendChild(unwrap(nodes[i]));
+    }
+    return df;
+  }
+
+  function clearChildNodes(wrapper) {
+    if (wrapper.firstChild_ !== undefined) {
+      var child = wrapper.firstChild_;
+      while (child) {
+        var tmp = child;
+        child = child.nextSibling_;
+        tmp.parentNode_ = tmp.previousSibling_ = tmp.nextSibling_ = undefined;
+      }
+    }
+    wrapper.firstChild_ = wrapper.lastChild_ = undefined;
+  }
+
+  function removeAllChildNodes(wrapper) {
+    if (wrapper.invalidateShadowRenderer()) {
+      var childWrapper = wrapper.firstChild;
+      while (childWrapper) {
+        assert(childWrapper.parentNode === wrapper);
+        var nextSibling = childWrapper.nextSibling;
+        var childNode = unwrap(childWrapper);
+        var parentNode = childNode.parentNode;
+        if (parentNode)
+          originalRemoveChild.call(parentNode, childNode);
+        childWrapper.previousSibling_ = childWrapper.nextSibling_ =
+            childWrapper.parentNode_ = null;
+        childWrapper = nextSibling;
+      }
+      wrapper.firstChild_ = wrapper.lastChild_ = null;
+    } else {
+      var node = unwrap(wrapper);
+      var child = node.firstChild;
+      var nextSibling;
+      while (child) {
+        nextSibling = child.nextSibling;
+        originalRemoveChild.call(node, child);
+        child = nextSibling;
+      }
+    }
+  }
+
+  function invalidateParent(node) {
+    var p = node.parentNode;
+    return p && p.invalidateShadowRenderer();
+  }
+
+  function cleanupNodes(nodes) {
+    for (var i = 0, n; i < nodes.length; i++) {
+      n = nodes[i];
+      n.parentNode.removeChild(n);
+    }
+  }
+
+  var originalImportNode = document.importNode;
+  var originalCloneNode = window.Node.prototype.cloneNode;
+
+  function cloneNode(node, deep, opt_doc) {
+    var clone;
+    if (opt_doc)
+      clone = wrap(originalImportNode.call(opt_doc, node.impl, false));
+    else
+      clone = wrap(originalCloneNode.call(node.impl, false));
+
+    if (deep) {
+      for (var child = node.firstChild; child; child = child.nextSibling) {
+        clone.appendChild(cloneNode(child, true, opt_doc));
+      }
+
+      if (node instanceof wrappers.HTMLTemplateElement) {
+        var cloneContent = clone.content;
+        for (var child = node.content.firstChild;
+             child;
+             child = child.nextSibling) {
+         cloneContent.appendChild(cloneNode(child, true, opt_doc));
+        }
+      }
+    }
+    // TODO(arv): Some HTML elements also clone other data like value.
+    return clone;
+  }
+
+  var OriginalNode = window.Node;
+
+  /**
+   * This represents a wrapper of a native DOM node.
+   * @param {!Node} original The original DOM node, aka, the visual DOM node.
+   * @constructor
+   * @extends {EventTarget}
+   */
+  function Node(original) {
+    assert(original instanceof OriginalNode);
+
+    EventTarget.call(this, original);
+
+    // These properties are used to override the visual references with the
+    // logical ones. If the value is undefined it means that the logical is the
+    // same as the visual.
+
+    /**
+     * @type {Node|undefined}
+     * @private
+     */
+    this.parentNode_ = undefined;
+
+    /**
+     * @type {Node|undefined}
+     * @private
+     */
+    this.firstChild_ = undefined;
+
+    /**
+     * @type {Node|undefined}
+     * @private
+     */
+    this.lastChild_ = undefined;
+
+    /**
+     * @type {Node|undefined}
+     * @private
+     */
+    this.nextSibling_ = undefined;
+
+    /**
+     * @type {Node|undefined}
+     * @private
+     */
+    this.previousSibling_ = undefined;
+  }
+
+  var OriginalDocumentFragment = window.DocumentFragment;
+  var originalAppendChild = OriginalNode.prototype.appendChild;
+  var originalCompareDocumentPosition =
+      OriginalNode.prototype.compareDocumentPosition;
+  var originalInsertBefore = OriginalNode.prototype.insertBefore;
+  var originalRemoveChild = OriginalNode.prototype.removeChild;
+  var originalReplaceChild = OriginalNode.prototype.replaceChild;
+
+  var isIe = /Trident/.test(navigator.userAgent);
+
+  var removeChildOriginalHelper = isIe ?
+      function(parent, child) {
+        try {
+          originalRemoveChild.call(parent, child);
+        } catch (ex) {
+          if (!(parent instanceof OriginalDocumentFragment))
+            throw ex;
+        }
+      } :
+      function(parent, child) {
+        originalRemoveChild.call(parent, child);
+      };
+
+  Node.prototype = Object.create(EventTarget.prototype);
+  mixin(Node.prototype, {
+    appendChild: function(childWrapper) {
+      return this.insertBefore(childWrapper, null);
+    },
+
+    insertBefore: function(childWrapper, refWrapper) {
+      assertIsNodeWrapper(childWrapper);
+
+      var refNode;
+      if (refWrapper) {
+        if (isWrapper(refWrapper)) {
+          refNode = unwrap(refWrapper);
+        } else {
+          refNode = refWrapper;
+          refWrapper = wrap(refNode);
+        }
+      } else {
+        refWrapper = null;
+        refNode = null;
+      }
+
+      refWrapper && assert(refWrapper.parentNode === this);
+
+      var nodes;
+      var previousNode =
+          refWrapper ? refWrapper.previousSibling : this.lastChild;
+
+      var useNative = !this.invalidateShadowRenderer() &&
+                      !invalidateParent(childWrapper);
+
+      if (useNative)
+        nodes = collectNodesNative(childWrapper);
+      else
+        nodes = collectNodes(childWrapper, this, previousNode, refWrapper);
+
+      if (useNative) {
+        ensureSameOwnerDocument(this, childWrapper);
+        clearChildNodes(this);
+        originalInsertBefore.call(this.impl, unwrap(childWrapper), refNode);
+      } else {
+        if (!previousNode)
+          this.firstChild_ = nodes[0];
+        if (!refWrapper)
+          this.lastChild_ = nodes[nodes.length - 1];
+
+        var parentNode = refNode ? refNode.parentNode : this.impl;
+
+        // insertBefore refWrapper no matter what the parent is?
+        if (parentNode) {
+          originalInsertBefore.call(parentNode,
+              unwrapNodesForInsertion(this, nodes), refNode);
+        } else {
+          adoptNodesIfNeeded(this, nodes);
+        }
+      }
+
+      enqueueMutation(this, 'childList', {
+        addedNodes: nodes,
+        nextSibling: refWrapper,
+        previousSibling: previousNode
+      });
+
+      nodesWereAdded(nodes);
+
+      return childWrapper;
+    },
+
+    removeChild: function(childWrapper) {
+      assertIsNodeWrapper(childWrapper);
+      if (childWrapper.parentNode !== this) {
+        // IE has invalid DOM trees at times.
+        var found = false;
+        var childNodes = this.childNodes;
+        for (var ieChild = this.firstChild; ieChild;
+             ieChild = ieChild.nextSibling) {
+          if (ieChild === childWrapper) {
+            found = true;
+            break;
+          }
+        }
+        if (!found) {
+          // TODO(arv): DOMException
+          throw new Error('NotFoundError');
+        }
+      }
+
+      var childNode = unwrap(childWrapper);
+      var childWrapperNextSibling = childWrapper.nextSibling;
+      var childWrapperPreviousSibling = childWrapper.previousSibling;
+
+      if (this.invalidateShadowRenderer()) {
+        // We need to remove the real node from the DOM before updating the
+        // pointers. This is so that that mutation event is dispatched before
+        // the pointers have changed.
+        var thisFirstChild = this.firstChild;
+        var thisLastChild = this.lastChild;
+
+        var parentNode = childNode.parentNode;
+        if (parentNode)
+          removeChildOriginalHelper(parentNode, childNode);
+
+        if (thisFirstChild === childWrapper)
+          this.firstChild_ = childWrapperNextSibling;
+        if (thisLastChild === childWrapper)
+          this.lastChild_ = childWrapperPreviousSibling;
+        if (childWrapperPreviousSibling)
+          childWrapperPreviousSibling.nextSibling_ = childWrapperNextSibling;
+        if (childWrapperNextSibling) {
+          childWrapperNextSibling.previousSibling_ =
+              childWrapperPreviousSibling;
+        }
+
+        childWrapper.previousSibling_ = childWrapper.nextSibling_ =
+            childWrapper.parentNode_ = undefined;
+      } else {
+        clearChildNodes(this);
+        removeChildOriginalHelper(this.impl, childNode);
+      }
+
+      if (!surpressMutations) {
+        enqueueMutation(this, 'childList', {
+          removedNodes: createOneElementNodeList(childWrapper),
+          nextSibling: childWrapperNextSibling,
+          previousSibling: childWrapperPreviousSibling
+        });
+      }
+
+      registerTransientObservers(this, childWrapper);
+
+      return childWrapper;
+    },
+
+    replaceChild: function(newChildWrapper, oldChildWrapper) {
+      assertIsNodeWrapper(newChildWrapper);
+
+      var oldChildNode;
+      if (isWrapper(oldChildWrapper)) {
+        oldChildNode = unwrap(oldChildWrapper);
+      } else {
+        oldChildNode = oldChildWrapper;
+        oldChildWrapper = wrap(oldChildNode);
+      }
+
+      if (oldChildWrapper.parentNode !== this) {
+        // TODO(arv): DOMException
+        throw new Error('NotFoundError');
+      }
+
+      var nextNode = oldChildWrapper.nextSibling;
+      var previousNode = oldChildWrapper.previousSibling;
+      var nodes;
+
+      var useNative = !this.invalidateShadowRenderer() &&
+                      !invalidateParent(newChildWrapper);
+
+      if (useNative) {
+        nodes = collectNodesNative(newChildWrapper);
+      } else {
+        if (nextNode === newChildWrapper)
+          nextNode = newChildWrapper.nextSibling;
+        nodes = collectNodes(newChildWrapper, this, previousNode, nextNode);
+      }
+
+      if (!useNative) {
+        if (this.firstChild === oldChildWrapper)
+          this.firstChild_ = nodes[0];
+        if (this.lastChild === oldChildWrapper)
+          this.lastChild_ = nodes[nodes.length - 1];
+
+        oldChildWrapper.previousSibling_ = oldChildWrapper.nextSibling_ =
+            oldChildWrapper.parentNode_ = undefined;
+
+        // replaceChild no matter what the parent is?
+        if (oldChildNode.parentNode) {
+          originalReplaceChild.call(
+              oldChildNode.parentNode,
+              unwrapNodesForInsertion(this, nodes),
+              oldChildNode);
+        }
+      } else {
+        ensureSameOwnerDocument(this, newChildWrapper);
+        clearChildNodes(this);
+        originalReplaceChild.call(this.impl, unwrap(newChildWrapper),
+                                  oldChildNode);
+      }
+
+      enqueueMutation(this, 'childList', {
+        addedNodes: nodes,
+        removedNodes: createOneElementNodeList(oldChildWrapper),
+        nextSibling: nextNode,
+        previousSibling: previousNode
+      });
+
+      nodeWasRemoved(oldChildWrapper);
+      nodesWereAdded(nodes);
+
+      return oldChildWrapper;
+    },
+
+    /**
+     * Called after a node was inserted. Subclasses override this to invalidate
+     * the renderer as needed.
+     * @private
+     */
+    nodeIsInserted_: function() {
+      for (var child = this.firstChild; child; child = child.nextSibling) {
+        child.nodeIsInserted_();
+      }
+    },
+
+    hasChildNodes: function() {
+      return this.firstChild !== null;
+    },
+
+    /** @type {Node} */
+    get parentNode() {
+      // If the parentNode has not been overridden, use the original parentNode.
+      return this.parentNode_ !== undefined ?
+          this.parentNode_ : wrap(this.impl.parentNode);
+    },
+
+    /** @type {Node} */
+    get firstChild() {
+      return this.firstChild_ !== undefined ?
+          this.firstChild_ : wrap(this.impl.firstChild);
+    },
+
+    /** @type {Node} */
+    get lastChild() {
+      return this.lastChild_ !== undefined ?
+          this.lastChild_ : wrap(this.impl.lastChild);
+    },
+
+    /** @type {Node} */
+    get nextSibling() {
+      return this.nextSibling_ !== undefined ?
+          this.nextSibling_ : wrap(this.impl.nextSibling);
+    },
+
+    /** @type {Node} */
+    get previousSibling() {
+      return this.previousSibling_ !== undefined ?
+          this.previousSibling_ : wrap(this.impl.previousSibling);
+    },
+
+    get parentElement() {
+      var p = this.parentNode;
+      while (p && p.nodeType !== Node.ELEMENT_NODE) {
+        p = p.parentNode;
+      }
+      return p;
+    },
+
+    get textContent() {
+      // TODO(arv): This should fallback to this.impl.textContent if there
+      // are no shadow trees below or above the context node.
+      var s = '';
+      for (var child = this.firstChild; child; child = child.nextSibling) {
+        if (child.nodeType != Node.COMMENT_NODE) {
+          s += child.textContent;
+        }
+      }
+      return s;
+    },
+    set textContent(textContent) {
+      var removedNodes = snapshotNodeList(this.childNodes);
+
+      if (this.invalidateShadowRenderer()) {
+        removeAllChildNodes(this);
+        if (textContent !== '') {
+          var textNode = this.impl.ownerDocument.createTextNode(textContent);
+          this.appendChild(textNode);
+        }
+      } else {
+        clearChildNodes(this);
+        this.impl.textContent = textContent;
+      }
+
+      var addedNodes = snapshotNodeList(this.childNodes);
+
+      enqueueMutation(this, 'childList', {
+        addedNodes: addedNodes,
+        removedNodes: removedNodes
+      });
+
+      nodesWereRemoved(removedNodes);
+      nodesWereAdded(addedNodes);
+    },
+
+    get childNodes() {
+      var wrapperList = new NodeList();
+      var i = 0;
+      for (var child = this.firstChild; child; child = child.nextSibling) {
+        wrapperList[i++] = child;
+      }
+      wrapperList.length = i;
+      return wrapperList;
+    },
+
+    cloneNode: function(deep) {
+      return cloneNode(this, deep);
+    },
+
+    contains: function(child) {
+      if (!child)
+        return false;
+
+      child = wrapIfNeeded(child);
+
+      // TODO(arv): Optimize using ownerDocument etc.
+      if (child === this)
+        return true;
+      var parentNode = child.parentNode;
+      if (!parentNode)
+        return false;
+      return this.contains(parentNode);
+    },
+
+    compareDocumentPosition: function(otherNode) {
+      // This only wraps, it therefore only operates on the composed DOM and not
+      // the logical DOM.
+      return originalCompareDocumentPosition.call(this.impl, unwrap(otherNode));
+    },
+
+    normalize: function() {
+      var nodes = snapshotNodeList(this.childNodes);
+      var remNodes = [];
+      var s = '';
+      var modNode;
+
+      for (var i = 0, n; i < nodes.length; i++) {
+        n = nodes[i];
+        if (n.nodeType === Node.TEXT_NODE) {
+          if (!modNode && !n.data.length)
+            this.removeNode(n);
+          else if (!modNode)
+            modNode = n;
+          else {
+            s += n.data;
+            remNodes.push(n);
+          }
+        } else {
+          if (modNode && remNodes.length) {
+            modNode.data += s;
+            cleanUpNodes(remNodes);
+          }
+          remNodes = [];
+          s = '';
+          modNode = null;
+          if (n.childNodes.length)
+            n.normalize();
+        }
+      }
+
+      // handle case where >1 text nodes are the last children
+      if (modNode && remNodes.length) {
+        modNode.data += s;
+        cleanupNodes(remNodes);
+      }
+    }
+  });
+
+  defineWrapGetter(Node, 'ownerDocument');
+
+  // We use a DocumentFragment as a base and then delete the properties of
+  // DocumentFragment.prototype from the wrapper Node. Since delete makes
+  // objects slow in some JS engines we recreate the prototype object.
+  registerWrapper(OriginalNode, Node, document.createDocumentFragment());
+  delete Node.prototype.querySelector;
+  delete Node.prototype.querySelectorAll;
+  Node.prototype = mixin(Object.create(EventTarget.prototype), Node.prototype);
+
+  scope.nodeWasAdded = nodeWasAdded;
+  scope.nodeWasRemoved = nodeWasRemoved;
+  scope.nodesWereAdded = nodesWereAdded;
+  scope.nodesWereRemoved = nodesWereRemoved;
+  scope.snapshotNodeList = snapshotNodeList;
+  scope.wrappers.Node = Node;
+  scope.cloneNode = cloneNode;
+
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. 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) {
+  'use strict';
+
+  function findOne(node, selector) {
+    var m, el = node.firstElementChild;
+    while (el) {
+      if (el.matches(selector))
+        return el;
+      m = findOne(el, selector);
+      if (m)
+        return m;
+      el = el.nextElementSibling;
+    }
+    return null;
+  }
+
+  function findAll(node, selector, results) {
+    var el = node.firstElementChild;
+    while (el) {
+      if (el.matches(selector))
+        results[results.length++] = el;
+      findAll(el, selector, results);
+      el = el.nextElementSibling;
+    }
+    return results;
+  }
+
+  // find and findAll will only match Simple Selectors,
+  // Structural Pseudo Classes are not guarenteed to be correct
+  // http://www.w3.org/TR/css3-selectors/#simple-selectors
+
+  var SelectorsInterface = {
+    querySelector: function(selector) {
+      return findOne(this, selector);
+    },
+    querySelectorAll: function(selector) {
+      return findAll(this, selector, new NodeList())
+    }
+  };
+
+  var GetElementsByInterface = {
+    getElementsByTagName: function(tagName) {
+      // TODO(arv): Check tagName?
+      return this.querySelectorAll(tagName);
+    },
+    getElementsByClassName: function(className) {
+      // TODO(arv): Check className?
+      return this.querySelectorAll('.' + className);
+    },
+    getElementsByTagNameNS: function(ns, tagName) {
+      if (ns === '*')
+        return this.getElementsByTagName(tagName);
+
+      // TODO(arv): Check tagName?
+      var result = new NodeList;
+      var els = this.getElementsByTagName(tagName);
+      for (var i = 0, j = 0; i < els.length; i++) {
+        if (els[i].namespaceURI === ns)
+          result[j++] = els[i];
+      }
+      result.length = j;
+      return result;
+    }
+  };
+
+  scope.GetElementsByInterface = GetElementsByInterface;
+  scope.SelectorsInterface = SelectorsInterface;
+
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var NodeList = scope.wrappers.NodeList;
+
+  function forwardElement(node) {
+    while (node && node.nodeType !== Node.ELEMENT_NODE) {
+      node = node.nextSibling;
+    }
+    return node;
+  }
+
+  function backwardsElement(node) {
+    while (node && node.nodeType !== Node.ELEMENT_NODE) {
+      node = node.previousSibling;
+    }
+    return node;
+  }
+
+  var ParentNodeInterface = {
+    get firstElementChild() {
+      return forwardElement(this.firstChild);
+    },
+
+    get lastElementChild() {
+      return backwardsElement(this.lastChild);
+    },
+
+    get childElementCount() {
+      var count = 0;
+      for (var child = this.firstElementChild;
+           child;
+           child = child.nextElementSibling) {
+        count++;
+      }
+      return count;
+    },
+
+    get children() {
+      var wrapperList = new NodeList();
+      var i = 0;
+      for (var child = this.firstElementChild;
+           child;
+           child = child.nextElementSibling) {
+        wrapperList[i++] = child;
+      }
+      wrapperList.length = i;
+      return wrapperList;
+    }
+  };
+
+  var ChildNodeInterface = {
+    get nextElementSibling() {
+      return forwardElement(this.nextSibling);
+    },
+
+    get previousElementSibling() {
+      return backwardsElement(this.previousSibling);
+    }
+  };
+
+  scope.ChildNodeInterface = ChildNodeInterface;
+  scope.ParentNodeInterface = ParentNodeInterface;
+
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var ChildNodeInterface = scope.ChildNodeInterface;
+  var Node = scope.wrappers.Node;
+  var enqueueMutation = scope.enqueueMutation;
+  var mixin = scope.mixin;
+  var registerWrapper = scope.registerWrapper;
+
+  var OriginalCharacterData = window.CharacterData;
+
+  function CharacterData(node) {
+    Node.call(this, node);
+  }
+  CharacterData.prototype = Object.create(Node.prototype);
+  mixin(CharacterData.prototype, {
+    get textContent() {
+      return this.data;
+    },
+    set textContent(value) {
+      this.data = value;
+    },
+    get data() {
+      return this.impl.data;
+    },
+    set data(value) {
+      var oldValue = this.impl.data;
+      enqueueMutation(this, 'characterData', {
+        oldValue: oldValue
+      });
+      this.impl.data = value;
+    }
+  });
+
+  mixin(CharacterData.prototype, ChildNodeInterface);
+
+  registerWrapper(OriginalCharacterData, CharacterData,
+                  document.createTextNode(''));
+
+  scope.wrappers.CharacterData = CharacterData;
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2014 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var CharacterData = scope.wrappers.CharacterData;
+  var enqueueMutation = scope.enqueueMutation;
+  var mixin = scope.mixin;
+  var registerWrapper = scope.registerWrapper;
+
+  function toUInt32(x) {
+    return x >>> 0;
+  }
+
+  var OriginalText = window.Text;
+
+  function Text(node) {
+    CharacterData.call(this, node);
+  }
+  Text.prototype = Object.create(CharacterData.prototype);
+  mixin(Text.prototype, {
+    splitText: function(offset) {
+      offset = toUInt32(offset);
+      var s = this.data;
+      if (offset > s.length)
+        throw new Error('IndexSizeError');
+      var head = s.slice(0, offset);
+      var tail = s.slice(offset);
+      this.data = head;
+      var newTextNode = this.ownerDocument.createTextNode(tail);
+      if (this.parentNode)
+        this.parentNode.insertBefore(newTextNode, this.nextSibling);
+      return newTextNode;
+    }
+  });
+
+  registerWrapper(OriginalText, Text, document.createTextNode(''));
+
+  scope.wrappers.Text = Text;
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var ChildNodeInterface = scope.ChildNodeInterface;
+  var GetElementsByInterface = scope.GetElementsByInterface;
+  var Node = scope.wrappers.Node;
+  var ParentNodeInterface = scope.ParentNodeInterface;
+  var SelectorsInterface = scope.SelectorsInterface;
+  var addWrapNodeListMethod = scope.addWrapNodeListMethod;
+  var enqueueMutation = scope.enqueueMutation;
+  var mixin = scope.mixin;
+  var oneOf = scope.oneOf;
+  var registerWrapper = scope.registerWrapper;
+  var wrappers = scope.wrappers;
+
+  var OriginalElement = window.Element;
+
+  var matchesNames = [
+    'matches',  // needs to come first.
+    'mozMatchesSelector',
+    'msMatchesSelector',
+    'webkitMatchesSelector',
+  ].filter(function(name) {
+    return OriginalElement.prototype[name];
+  });
+
+  var matchesName = matchesNames[0];
+
+  var originalMatches = OriginalElement.prototype[matchesName];
+
+  function invalidateRendererBasedOnAttribute(element, name) {
+    // Only invalidate if parent node is a shadow host.
+    var p = element.parentNode;
+    if (!p || !p.shadowRoot)
+      return;
+
+    var renderer = scope.getRendererForHost(p);
+    if (renderer.dependsOnAttribute(name))
+      renderer.invalidate();
+  }
+
+  function enqueAttributeChange(element, name, oldValue) {
+    // This is not fully spec compliant. We should use localName (which might
+    // have a different case than name) and the namespace (which requires us
+    // to get the Attr object).
+    enqueueMutation(element, 'attributes', {
+      name: name,
+      namespace: null,
+      oldValue: oldValue
+    });
+  }
+
+  function Element(node) {
+    Node.call(this, node);
+  }
+  Element.prototype = Object.create(Node.prototype);
+  mixin(Element.prototype, {
+    createShadowRoot: function() {
+      var newShadowRoot = new wrappers.ShadowRoot(this);
+      this.impl.polymerShadowRoot_ = newShadowRoot;
+
+      var renderer = scope.getRendererForHost(this);
+      renderer.invalidate();
+
+      return newShadowRoot;
+    },
+
+    get shadowRoot() {
+      return this.impl.polymerShadowRoot_ || null;
+    },
+
+    setAttribute: function(name, value) {
+      var oldValue = this.impl.getAttribute(name);
+      this.impl.setAttribute(name, value);
+      enqueAttributeChange(this, name, oldValue);
+      invalidateRendererBasedOnAttribute(this, name);
+    },
+
+    removeAttribute: function(name) {
+      var oldValue = this.impl.getAttribute(name);
+      this.impl.removeAttribute(name);
+      enqueAttributeChange(this, name, oldValue);
+      invalidateRendererBasedOnAttribute(this, name);
+    },
+
+    matches: function(selector) {
+      return originalMatches.call(this.impl, selector);
+    }
+  });
+
+  matchesNames.forEach(function(name) {
+    if (name !== 'matches') {
+      Element.prototype[name] = function(selector) {
+        return this.matches(selector);
+      };
+    }
+  });
+
+  if (OriginalElement.prototype.webkitCreateShadowRoot) {
+    Element.prototype.webkitCreateShadowRoot =
+        Element.prototype.createShadowRoot;
+  }
+
+  /**
+   * Useful for generating the accessor pair for a property that reflects an
+   * attribute.
+   */
+  function setterDirtiesAttribute(prototype, propertyName, opt_attrName) {
+    var attrName = opt_attrName || propertyName;
+    Object.defineProperty(prototype, propertyName, {
+      get: function() {
+        return this.impl[propertyName];
+      },
+      set: function(v) {
+        this.impl[propertyName] = v;
+        invalidateRendererBasedOnAttribute(this, attrName);
+      },
+      configurable: true,
+      enumerable: true
+    });
+  }
+
+  setterDirtiesAttribute(Element.prototype, 'id');
+  setterDirtiesAttribute(Element.prototype, 'className', 'class');
+
+  mixin(Element.prototype, ChildNodeInterface);
+  mixin(Element.prototype, GetElementsByInterface);
+  mixin(Element.prototype, ParentNodeInterface);
+  mixin(Element.prototype, SelectorsInterface);
+
+  registerWrapper(OriginalElement, Element,
+                  document.createElementNS(null, 'x'));
+
+  // TODO(arv): Export setterDirtiesAttribute and apply it to more bindings
+  // that reflect attributes.
+  scope.matchesNames = matchesNames;
+  scope.wrappers.Element = Element;
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var Element = scope.wrappers.Element;
+  var defineGetter = scope.defineGetter;
+  var enqueueMutation = scope.enqueueMutation;
+  var mixin = scope.mixin;
+  var nodesWereAdded = scope.nodesWereAdded;
+  var nodesWereRemoved = scope.nodesWereRemoved;
+  var registerWrapper = scope.registerWrapper;
+  var snapshotNodeList = scope.snapshotNodeList;
+  var unwrap = scope.unwrap;
+  var wrap = scope.wrap;
+  var wrappers = scope.wrappers;
+
+  /////////////////////////////////////////////////////////////////////////////
+  // innerHTML and outerHTML
+
+  // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#escapingString
+  var escapeAttrRegExp = /[&\u00A0"]/g;
+  var escapeDataRegExp = /[&\u00A0<>]/g;
+
+  function escapeReplace(c) {
+    switch (c) {
+      case '&':
+        return '&amp;';
+      case '<':
+        return '&lt;';
+      case '>':
+        return '&gt;';
+      case '"':
+        return '&quot;'
+      case '\u00A0':
+        return '&nbsp;';
+    }
+  }
+
+  function escapeAttr(s) {
+    return s.replace(escapeAttrRegExp, escapeReplace);
+  }
+
+  function escapeData(s) {
+    return s.replace(escapeDataRegExp, escapeReplace);
+  }
+
+  function makeSet(arr) {
+    var set = {};
+    for (var i = 0; i < arr.length; i++) {
+      set[arr[i]] = true;
+    }
+    return set;
+  }
+
+  // http://www.whatwg.org/specs/web-apps/current-work/#void-elements
+  var voidElements = makeSet([
+    'area',
+    'base',
+    'br',
+    'col',
+    'command',
+    'embed',
+    'hr',
+    'img',
+    'input',
+    'keygen',
+    'link',
+    'meta',
+    'param',
+    'source',
+    'track',
+    'wbr'
+  ]);
+
+  var plaintextParents = makeSet([
+    'style',
+    'script',
+    'xmp',
+    'iframe',
+    'noembed',
+    'noframes',
+    'plaintext',
+    'noscript'
+  ]);
+
+  function getOuterHTML(node, parentNode) {
+    switch (node.nodeType) {
+      case Node.ELEMENT_NODE:
+        var tagName = node.tagName.toLowerCase();
+        var s = '<' + tagName;
+        var attrs = node.attributes;
+        for (var i = 0, attr; attr = attrs[i]; i++) {
+          s += ' ' + attr.name + '="' + escapeAttr(attr.value) + '"';
+        }
+        s += '>';
+        if (voidElements[tagName])
+          return s;
+
+        return s + getInnerHTML(node) + '</' + tagName + '>';
+
+      case Node.TEXT_NODE:
+        var data = node.data;
+        if (parentNode && plaintextParents[parentNode.localName])
+          return data;
+        return escapeData(data);
+
+      case Node.COMMENT_NODE:
+        return '<!--' + node.data + '-->';
+
+      default:
+        console.error(node);
+        throw new Error('not implemented');
+    }
+  }
+
+  function getInnerHTML(node) {
+    if (node instanceof wrappers.HTMLTemplateElement)
+      node = node.content;
+
+    var s = '';
+    for (var child = node.firstChild; child; child = child.nextSibling) {
+      s += getOuterHTML(child, node);
+    }
+    return s;
+  }
+
+  function setInnerHTML(node, value, opt_tagName) {
+    var tagName = opt_tagName || 'div';
+    node.textContent = '';
+    var tempElement = unwrap(node.ownerDocument.createElement(tagName));
+    tempElement.innerHTML = value;
+    var firstChild;
+    while (firstChild = tempElement.firstChild) {
+      node.appendChild(wrap(firstChild));
+    }
+  }
+
+  // IE11 does not have MSIE in the user agent string.
+  var oldIe = /MSIE/.test(navigator.userAgent);
+
+  var OriginalHTMLElement = window.HTMLElement;
+  var OriginalHTMLTemplateElement = window.HTMLTemplateElement;
+
+  function HTMLElement(node) {
+    Element.call(this, node);
+  }
+  HTMLElement.prototype = Object.create(Element.prototype);
+  mixin(HTMLElement.prototype, {
+    get innerHTML() {
+      return getInnerHTML(this);
+    },
+    set innerHTML(value) {
+      // IE9 does not handle set innerHTML correctly on plaintextParents. It
+      // creates element children. For example
+      //
+      //   scriptElement.innerHTML = '<a>test</a>'
+      //
+      // Creates a single HTMLAnchorElement child.
+      if (oldIe && plaintextParents[this.localName]) {
+        this.textContent = value;
+        return;
+      }
+
+      var removedNodes = snapshotNodeList(this.childNodes);
+
+      if (this.invalidateShadowRenderer()) {
+        if (this instanceof wrappers.HTMLTemplateElement)
+          setInnerHTML(this.content, value);
+        else
+          setInnerHTML(this, value, this.tagName);
+
+      // If we have a non native template element we need to handle this
+      // manually since setting impl.innerHTML would add the html as direct
+      // children and not be moved over to the content fragment.
+      } else if (!OriginalHTMLTemplateElement &&
+                 this instanceof wrappers.HTMLTemplateElement) {
+        setInnerHTML(this.content, value);
+      } else {
+        this.impl.innerHTML = value;
+      }
+
+      var addedNodes = snapshotNodeList(this.childNodes);
+
+      enqueueMutation(this, 'childList', {
+        addedNodes: addedNodes,
+        removedNodes: removedNodes
+      });
+
+      nodesWereRemoved(removedNodes);
+      nodesWereAdded(addedNodes);
+    },
+
+    get outerHTML() {
+      return getOuterHTML(this, this.parentNode);
+    },
+    set outerHTML(value) {
+      var p = this.parentNode;
+      if (p) {
+        p.invalidateShadowRenderer();
+        var df = frag(p, value);
+        p.replaceChild(df, this);
+      }
+    },
+
+    insertAdjacentHTML: function(position, text) {
+      var contextElement, refNode;
+      switch (String(position).toLowerCase()) {
+        case 'beforebegin':
+          contextElement = this.parentNode;
+          refNode = this;
+          break;
+        case 'afterend':
+          contextElement = this.parentNode;
+          refNode = this.nextSibling;
+          break;
+        case 'afterbegin':
+          contextElement = this;
+          refNode = this.firstChild;
+          break;
+        case 'beforeend':
+          contextElement = this;
+          refNode = null;
+          break;
+        default:
+          return;
+      }
+
+      var df = frag(contextElement, text);
+      contextElement.insertBefore(df, refNode);
+    }
+  });
+
+  function frag(contextElement, html) {
+    // TODO(arv): This does not work with SVG and other non HTML elements.
+    var p = unwrap(contextElement.cloneNode(false));
+    p.innerHTML = html;
+    var df = unwrap(document.createDocumentFragment());
+    var c;
+    while (c = p.firstChild) {
+      df.appendChild(c);
+    }
+    return wrap(df);
+  }
+
+  function getter(name) {
+    return function() {
+      scope.renderAllPending();
+      return this.impl[name];
+    };
+  }
+
+  function getterRequiresRendering(name) {
+    defineGetter(HTMLElement, name, getter(name));
+  }
+
+  [
+    'clientHeight',
+    'clientLeft',
+    'clientTop',
+    'clientWidth',
+    'offsetHeight',
+    'offsetLeft',
+    'offsetTop',
+    'offsetWidth',
+    'scrollHeight',
+    'scrollWidth',
+  ].forEach(getterRequiresRendering);
+
+  function getterAndSetterRequiresRendering(name) {
+    Object.defineProperty(HTMLElement.prototype, name, {
+      get: getter(name),
+      set: function(v) {
+        scope.renderAllPending();
+        this.impl[name] = v;
+      },
+      configurable: true,
+      enumerable: true
+    });
+  }
+
+  [
+    'scrollLeft',
+    'scrollTop',
+  ].forEach(getterAndSetterRequiresRendering);
+
+  function methodRequiresRendering(name) {
+    Object.defineProperty(HTMLElement.prototype, name, {
+      value: function() {
+        scope.renderAllPending();
+        return this.impl[name].apply(this.impl, arguments);
+      },
+      configurable: true,
+      enumerable: true
+    });
+  }
+
+  [
+    'getBoundingClientRect',
+    'getClientRects',
+    'scrollIntoView'
+  ].forEach(methodRequiresRendering);
+
+  // HTMLElement is abstract so we use a subclass that has no members.
+  registerWrapper(OriginalHTMLElement, HTMLElement,
+                  document.createElement('b'));
+
+  scope.wrappers.HTMLElement = HTMLElement;
+
+  // TODO: Find a better way to share these two with WrapperShadowRoot.
+  scope.getInnerHTML = getInnerHTML;
+  scope.setInnerHTML = setInnerHTML
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var HTMLElement = scope.wrappers.HTMLElement;
+  var mixin = scope.mixin;
+  var registerWrapper = scope.registerWrapper;
+  var wrap = scope.wrap;
+
+  var OriginalHTMLCanvasElement = window.HTMLCanvasElement;
+
+  function HTMLCanvasElement(node) {
+    HTMLElement.call(this, node);
+  }
+  HTMLCanvasElement.prototype = Object.create(HTMLElement.prototype);
+
+  mixin(HTMLCanvasElement.prototype, {
+    getContext: function() {
+      var context = this.impl.getContext.apply(this.impl, arguments);
+      return context && wrap(context);
+    }
+  });
+
+  registerWrapper(OriginalHTMLCanvasElement, HTMLCanvasElement,
+                  document.createElement('canvas'));
+
+  scope.wrappers.HTMLCanvasElement = HTMLCanvasElement;
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var HTMLElement = scope.wrappers.HTMLElement;
+  var mixin = scope.mixin;
+  var registerWrapper = scope.registerWrapper;
+
+  var OriginalHTMLContentElement = window.HTMLContentElement;
+
+  function HTMLContentElement(node) {
+    HTMLElement.call(this, node);
+  }
+  HTMLContentElement.prototype = Object.create(HTMLElement.prototype);
+  mixin(HTMLContentElement.prototype, {
+    get select() {
+      return this.getAttribute('select');
+    },
+    set select(value) {
+      this.setAttribute('select', value);
+    },
+
+    setAttribute: function(n, v) {
+      HTMLElement.prototype.setAttribute.call(this, n, v);
+      if (String(n).toLowerCase() === 'select')
+        this.invalidateShadowRenderer(true);
+    }
+
+    // getDistributedNodes is added in ShadowRenderer
+
+    // TODO: attribute boolean resetStyleInheritance;
+  });
+
+  if (OriginalHTMLContentElement)
+    registerWrapper(OriginalHTMLContentElement, HTMLContentElement);
+
+  scope.wrappers.HTMLContentElement = HTMLContentElement;
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var HTMLElement = scope.wrappers.HTMLElement;
+  var registerWrapper = scope.registerWrapper;
+  var unwrap = scope.unwrap;
+  var rewrap = scope.rewrap;
+
+  var OriginalHTMLImageElement = window.HTMLImageElement;
+
+  function HTMLImageElement(node) {
+    HTMLElement.call(this, node);
+  }
+  HTMLImageElement.prototype = Object.create(HTMLElement.prototype);
+
+  registerWrapper(OriginalHTMLImageElement, HTMLImageElement,
+                  document.createElement('img'));
+
+  function Image(width, height) {
+    if (!(this instanceof Image)) {
+      throw new TypeError(
+          'DOM object constructor cannot be called as a function.');
+    }
+
+    var node = unwrap(document.createElement('img'));
+    HTMLElement.call(this, node);
+    rewrap(node, this);
+
+    if (width !== undefined)
+      node.width = width;
+    if (height !== undefined)
+      node.height = height;
+  }
+
+  Image.prototype = HTMLImageElement.prototype;
+
+  scope.wrappers.HTMLImageElement = HTMLImageElement;
+  scope.wrappers.Image = Image;
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var HTMLElement = scope.wrappers.HTMLElement;
+  var mixin = scope.mixin;
+  var registerWrapper = scope.registerWrapper;
+
+  var OriginalHTMLShadowElement = window.HTMLShadowElement;
+
+  function HTMLShadowElement(node) {
+    HTMLElement.call(this, node);
+  }
+  HTMLShadowElement.prototype = Object.create(HTMLElement.prototype);
+  mixin(HTMLShadowElement.prototype, {
+    // TODO: attribute boolean resetStyleInheritance;
+  });
+
+  if (OriginalHTMLShadowElement)
+    registerWrapper(OriginalHTMLShadowElement, HTMLShadowElement);
+
+  scope.wrappers.HTMLShadowElement = HTMLShadowElement;
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var HTMLElement = scope.wrappers.HTMLElement;
+  var mixin = scope.mixin;
+  var registerWrapper = scope.registerWrapper;
+  var unwrap = scope.unwrap;
+  var wrap = scope.wrap;
+
+  var contentTable = new WeakMap();
+  var templateContentsOwnerTable = new WeakMap();
+
+  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
+  function getTemplateContentsOwner(doc) {
+    if (!doc.defaultView)
+      return doc;
+    var d = templateContentsOwnerTable.get(doc);
+    if (!d) {
+      // TODO(arv): This should either be a Document or HTMLDocument depending
+      // on doc.
+      d = doc.implementation.createHTMLDocument('');
+      while (d.lastChild) {
+        d.removeChild(d.lastChild);
+      }
+      templateContentsOwnerTable.set(doc, d);
+    }
+    return d;
+  }
+
+  function extractContent(templateElement) {
+    // templateElement is not a wrapper here.
+    var doc = getTemplateContentsOwner(templateElement.ownerDocument);
+    var df = unwrap(doc.createDocumentFragment());
+    var child;
+    while (child = templateElement.firstChild) {
+      df.appendChild(child);
+    }
+    return df;
+  }
+
+  var OriginalHTMLTemplateElement = window.HTMLTemplateElement;
+
+  function HTMLTemplateElement(node) {
+    HTMLElement.call(this, node);
+    if (!OriginalHTMLTemplateElement) {
+      var content = extractContent(node);
+      contentTable.set(this, wrap(content));
+    }
+  }
+  HTMLTemplateElement.prototype = Object.create(HTMLElement.prototype);
+
+  mixin(HTMLTemplateElement.prototype, {
+    get content() {
+      if (OriginalHTMLTemplateElement)
+        return wrap(this.impl.content);
+      return contentTable.get(this);
+    },
+
+    // TODO(arv): cloneNode needs to clone content.
+
+  });
+
+  if (OriginalHTMLTemplateElement)
+    registerWrapper(OriginalHTMLTemplateElement, HTMLTemplateElement);
+
+  scope.wrappers.HTMLTemplateElement = HTMLTemplateElement;
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var HTMLElement = scope.wrappers.HTMLElement;
+  var registerWrapper = scope.registerWrapper;
+
+  var OriginalHTMLMediaElement = window.HTMLMediaElement;
+
+  function HTMLMediaElement(node) {
+    HTMLElement.call(this, node);
+  }
+  HTMLMediaElement.prototype = Object.create(HTMLElement.prototype);
+
+  registerWrapper(OriginalHTMLMediaElement, HTMLMediaElement,
+                  document.createElement('audio'));
+
+  scope.wrappers.HTMLMediaElement = HTMLMediaElement;
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var HTMLMediaElement = scope.wrappers.HTMLMediaElement;
+  var registerWrapper = scope.registerWrapper;
+  var unwrap = scope.unwrap;
+  var rewrap = scope.rewrap;
+
+  var OriginalHTMLAudioElement = window.HTMLAudioElement;
+
+  function HTMLAudioElement(node) {
+    HTMLMediaElement.call(this, node);
+  }
+  HTMLAudioElement.prototype = Object.create(HTMLMediaElement.prototype);
+
+  registerWrapper(OriginalHTMLAudioElement, HTMLAudioElement,
+                  document.createElement('audio'));
+
+  function Audio(src) {
+    if (!(this instanceof Audio)) {
+      throw new TypeError(
+          'DOM object constructor cannot be called as a function.');
+    }
+
+    var node = unwrap(document.createElement('audio'));
+    HTMLMediaElement.call(this, node);
+    rewrap(node, this);
+
+    node.setAttribute('preload', 'auto');
+    if (src !== undefined)
+      node.setAttribute('src', src);
+  }
+
+  Audio.prototype = HTMLAudioElement.prototype;
+
+  scope.wrappers.HTMLAudioElement = HTMLAudioElement;
+  scope.wrappers.Audio = Audio;
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var HTMLElement = scope.wrappers.HTMLElement;
+  var mixin = scope.mixin;
+  var registerWrapper = scope.registerWrapper;
+  var rewrap = scope.rewrap;
+  var unwrap = scope.unwrap;
+  var wrap = scope.wrap;
+
+  var OriginalHTMLOptionElement = window.HTMLOptionElement;
+
+  function trimText(s) {
+    return s.replace(/\s+/g, ' ').trim();
+  }
+
+  function HTMLOptionElement(node) {
+    HTMLElement.call(this, node);
+  }
+  HTMLOptionElement.prototype = Object.create(HTMLElement.prototype);
+  mixin(HTMLOptionElement.prototype, {
+    get text() {
+      return trimText(this.textContent);
+    },
+    set text(value) {
+      this.textContent = trimText(String(value));
+    },
+    get form() {
+      return wrap(unwrap(this).form);
+    }
+  });
+
+  registerWrapper(OriginalHTMLOptionElement, HTMLOptionElement,
+                  document.createElement('option'));
+
+  function Option(text, value, defaultSelected, selected) {
+    if (!(this instanceof Option)) {
+      throw new TypeError(
+          'DOM object constructor cannot be called as a function.');
+    }
+
+    var node = unwrap(document.createElement('option'));
+    HTMLElement.call(this, node);
+    rewrap(node, this);
+
+    if (text !== undefined)
+      node.text = text;
+    if (value !== undefined)
+      node.setAttribute('value', value);
+    if (defaultSelected === true)
+      node.setAttribute('selected', '');
+    node.selected = selected === true;
+  }
+
+  Option.prototype = HTMLOptionElement.prototype;
+
+  scope.wrappers.HTMLOptionElement = HTMLOptionElement;
+  scope.wrappers.Option = Option;
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var HTMLContentElement = scope.wrappers.HTMLContentElement;
+  var HTMLElement = scope.wrappers.HTMLElement;
+  var HTMLShadowElement = scope.wrappers.HTMLShadowElement;
+  var HTMLTemplateElement = scope.wrappers.HTMLTemplateElement;
+  var mixin = scope.mixin;
+  var registerWrapper = scope.registerWrapper;
+
+  var OriginalHTMLUnknownElement = window.HTMLUnknownElement;
+
+  function HTMLUnknownElement(node) {
+    switch (node.localName) {
+      case 'content':
+        return new HTMLContentElement(node);
+      case 'shadow':
+        return new HTMLShadowElement(node);
+      case 'template':
+        return new HTMLTemplateElement(node);
+    }
+    HTMLElement.call(this, node);
+  }
+  HTMLUnknownElement.prototype = Object.create(HTMLElement.prototype);
+  registerWrapper(OriginalHTMLUnknownElement, HTMLUnknownElement);
+  scope.wrappers.HTMLUnknownElement = HTMLUnknownElement;
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2014 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var registerObject = scope.registerObject;
+
+  var SVG_NS = 'http://www.w3.org/2000/svg';
+  var svgTitleElement = document.createElementNS(SVG_NS, 'title');
+  var SVGTitleElement = registerObject(svgTitleElement);
+  var SVGElement = Object.getPrototypeOf(SVGTitleElement.prototype).constructor;
+
+  scope.wrappers.SVGElement = SVGElement;
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2014 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var mixin = scope.mixin;
+  var registerWrapper = scope.registerWrapper;
+  var unwrap = scope.unwrap;
+  var wrap = scope.wrap;
+
+  var OriginalSVGUseElement = window.SVGUseElement;
+
+  // IE uses SVGElement as parent interface, SVG2 (Blink & Gecko) uses
+  // SVGGraphicsElement. Use the <g> element to get the right prototype.
+
+  var SVG_NS = 'http://www.w3.org/2000/svg';
+  var gWrapper = wrap(document.createElementNS(SVG_NS, 'g'));
+  var useElement = document.createElementNS(SVG_NS, 'use');
+  var SVGGElement = gWrapper.constructor;
+  var parentInterfacePrototype = Object.getPrototypeOf(SVGGElement.prototype);
+  var parentInterface = parentInterfacePrototype.constructor;
+
+  function SVGUseElement(impl) {
+    parentInterface.call(this, impl);
+  }
+
+  SVGUseElement.prototype = Object.create(parentInterfacePrototype);
+
+  // Firefox does not expose instanceRoot.
+  if ('instanceRoot' in useElement) {
+    mixin(SVGUseElement.prototype, {
+      get instanceRoot() {
+        return wrap(unwrap(this).instanceRoot);
+      },
+      get animatedInstanceRoot() {
+        return wrap(unwrap(this).animatedInstanceRoot);
+      },
+    });
+  }
+
+  registerWrapper(OriginalSVGUseElement, SVGUseElement, useElement);
+
+  scope.wrappers.SVGUseElement = SVGUseElement;
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2014 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var EventTarget = scope.wrappers.EventTarget;
+  var mixin = scope.mixin;
+  var registerWrapper = scope.registerWrapper;
+  var wrap = scope.wrap;
+
+  var OriginalSVGElementInstance = window.SVGElementInstance;
+  if (!OriginalSVGElementInstance)
+    return;
+
+  function SVGElementInstance(impl) {
+    EventTarget.call(this, impl);
+  }
+
+  SVGElementInstance.prototype = Object.create(EventTarget.prototype);
+  mixin(SVGElementInstance.prototype, {
+    /** @type {SVGElement} */
+    get correspondingElement() {
+      return wrap(this.impl.correspondingElement);
+    },
+
+    /** @type {SVGUseElement} */
+    get correspondingUseElement() {
+      return wrap(this.impl.correspondingUseElement);
+    },
+
+    /** @type {SVGElementInstance} */
+    get parentNode() {
+      return wrap(this.impl.parentNode);
+    },
+
+    /** @type {SVGElementInstanceList} */
+    get childNodes() {
+      throw new Error('Not implemented');
+    },
+
+    /** @type {SVGElementInstance} */
+    get firstChild() {
+      return wrap(this.impl.firstChild);
+    },
+
+    /** @type {SVGElementInstance} */
+    get lastChild() {
+      return wrap(this.impl.lastChild);
+    },
+
+    /** @type {SVGElementInstance} */
+    get previousSibling() {
+      return wrap(this.impl.previousSibling);
+    },
+
+    /** @type {SVGElementInstance} */
+    get nextSibling() {
+      return wrap(this.impl.nextSibling);
+    }
+  });
+
+  registerWrapper(OriginalSVGElementInstance, SVGElementInstance);
+
+  scope.wrappers.SVGElementInstance = SVGElementInstance;
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var mixin = scope.mixin;
+  var registerWrapper = scope.registerWrapper;
+  var unwrap = scope.unwrap;
+  var unwrapIfNeeded = scope.unwrapIfNeeded;
+  var wrap = scope.wrap;
+
+  var OriginalCanvasRenderingContext2D = window.CanvasRenderingContext2D;
+
+  function CanvasRenderingContext2D(impl) {
+    this.impl = impl;
+  }
+
+  mixin(CanvasRenderingContext2D.prototype, {
+    get canvas() {
+      return wrap(this.impl.canvas);
+    },
+
+    drawImage: function() {
+      arguments[0] = unwrapIfNeeded(arguments[0]);
+      this.impl.drawImage.apply(this.impl, arguments);
+    },
+
+    createPattern: function() {
+      arguments[0] = unwrap(arguments[0]);
+      return this.impl.createPattern.apply(this.impl, arguments);
+    }
+  });
+
+  registerWrapper(OriginalCanvasRenderingContext2D, CanvasRenderingContext2D,
+                  document.createElement('canvas').getContext('2d'));
+
+  scope.wrappers.CanvasRenderingContext2D = CanvasRenderingContext2D;
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var mixin = scope.mixin;
+  var registerWrapper = scope.registerWrapper;
+  var unwrapIfNeeded = scope.unwrapIfNeeded;
+  var wrap = scope.wrap;
+
+  var OriginalWebGLRenderingContext = window.WebGLRenderingContext;
+
+  // IE10 does not have WebGL.
+  if (!OriginalWebGLRenderingContext)
+    return;
+
+  function WebGLRenderingContext(impl) {
+    this.impl = impl;
+  }
+
+  mixin(WebGLRenderingContext.prototype, {
+    get canvas() {
+      return wrap(this.impl.canvas);
+    },
+
+    texImage2D: function() {
+      arguments[5] = unwrapIfNeeded(arguments[5]);
+      this.impl.texImage2D.apply(this.impl, arguments);
+    },
+
+    texSubImage2D: function() {
+      arguments[6] = unwrapIfNeeded(arguments[6]);
+      this.impl.texSubImage2D.apply(this.impl, arguments);
+    }
+  });
+
+  // Blink/WebKit has broken DOM bindings. Usually we would create an instance
+  // of the object and pass it into registerWrapper as a "blueprint" but
+  // creating WebGL contexts is expensive and might fail so we use a dummy
+  // object with dummy instance properties for these broken browsers.
+  var instanceProperties = /WebKit/.test(navigator.userAgent) ?
+      {drawingBufferHeight: null, drawingBufferWidth: null} : {};
+
+  registerWrapper(OriginalWebGLRenderingContext, WebGLRenderingContext,
+      instanceProperties);
+
+  scope.wrappers.WebGLRenderingContext = WebGLRenderingContext;
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var registerWrapper = scope.registerWrapper;
+  var unwrap = scope.unwrap;
+  var unwrapIfNeeded = scope.unwrapIfNeeded;
+  var wrap = scope.wrap;
+
+  var OriginalRange = window.Range;
+
+  function Range(impl) {
+    this.impl = impl;
+  }
+  Range.prototype = {
+    get startContainer() {
+      return wrap(this.impl.startContainer);
+    },
+    get endContainer() {
+      return wrap(this.impl.endContainer);
+    },
+    get commonAncestorContainer() {
+      return wrap(this.impl.commonAncestorContainer);
+    },
+    setStart: function(refNode,offset) {
+      this.impl.setStart(unwrapIfNeeded(refNode), offset);
+    },
+    setEnd: function(refNode,offset) {
+      this.impl.setEnd(unwrapIfNeeded(refNode), offset);
+    },
+    setStartBefore: function(refNode) {
+      this.impl.setStartBefore(unwrapIfNeeded(refNode));
+    },
+    setStartAfter: function(refNode) {
+      this.impl.setStartAfter(unwrapIfNeeded(refNode));
+    },
+    setEndBefore: function(refNode) {
+      this.impl.setEndBefore(unwrapIfNeeded(refNode));
+    },
+    setEndAfter: function(refNode) {
+      this.impl.setEndAfter(unwrapIfNeeded(refNode));
+    },
+    selectNode: function(refNode) {
+      this.impl.selectNode(unwrapIfNeeded(refNode));
+    },
+    selectNodeContents: function(refNode) {
+      this.impl.selectNodeContents(unwrapIfNeeded(refNode));
+    },
+    compareBoundaryPoints: function(how, sourceRange) {
+      return this.impl.compareBoundaryPoints(how, unwrap(sourceRange));
+    },
+    extractContents: function() {
+      return wrap(this.impl.extractContents());
+    },
+    cloneContents: function() {
+      return wrap(this.impl.cloneContents());
+    },
+    insertNode: function(node) {
+      this.impl.insertNode(unwrapIfNeeded(node));
+    },
+    surroundContents: function(newParent) {
+      this.impl.surroundContents(unwrapIfNeeded(newParent));
+    },
+    cloneRange: function() {
+      return wrap(this.impl.cloneRange());
+    },
+    isPointInRange: function(node, offset) {
+      return this.impl.isPointInRange(unwrapIfNeeded(node), offset);
+    },
+    comparePoint: function(node, offset) {
+      return this.impl.comparePoint(unwrapIfNeeded(node), offset);
+    },
+    intersectsNode: function(node) {
+      return this.impl.intersectsNode(unwrapIfNeeded(node));
+    },
+    toString: function() {
+      return this.impl.toString();
+    }
+  };
+
+  // IE9 does not have createContextualFragment.
+  if (OriginalRange.prototype.createContextualFragment) {
+    Range.prototype.createContextualFragment = function(html) {
+      return wrap(this.impl.createContextualFragment(html));
+    };
+  }
+
+  registerWrapper(window.Range, Range, document.createRange());
+
+  scope.wrappers.Range = Range;
+
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var GetElementsByInterface = scope.GetElementsByInterface;
+  var ParentNodeInterface = scope.ParentNodeInterface;
+  var SelectorsInterface = scope.SelectorsInterface;
+  var mixin = scope.mixin;
+  var registerObject = scope.registerObject;
+
+  var DocumentFragment = registerObject(document.createDocumentFragment());
+  mixin(DocumentFragment.prototype, ParentNodeInterface);
+  mixin(DocumentFragment.prototype, SelectorsInterface);
+  mixin(DocumentFragment.prototype, GetElementsByInterface);
+
+  var Comment = registerObject(document.createComment(''));
+
+  scope.wrappers.Comment = Comment;
+  scope.wrappers.DocumentFragment = DocumentFragment;
+
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var DocumentFragment = scope.wrappers.DocumentFragment;
+  var elementFromPoint = scope.elementFromPoint;
+  var getInnerHTML = scope.getInnerHTML;
+  var mixin = scope.mixin;
+  var rewrap = scope.rewrap;
+  var setInnerHTML = scope.setInnerHTML;
+  var unwrap = scope.unwrap;
+
+  var shadowHostTable = new WeakMap();
+  var nextOlderShadowTreeTable = new WeakMap();
+
+  var spaceCharRe = /[ \t\n\r\f]/;
+
+  function ShadowRoot(hostWrapper) {
+    var node = unwrap(hostWrapper.impl.ownerDocument.createDocumentFragment());
+    DocumentFragment.call(this, node);
+
+    // createDocumentFragment associates the node with a wrapper
+    // DocumentFragment instance. Override that.
+    rewrap(node, this);
+
+    var oldShadowRoot = hostWrapper.shadowRoot;
+    nextOlderShadowTreeTable.set(this, oldShadowRoot);
+
+    shadowHostTable.set(this, hostWrapper);
+  }
+  ShadowRoot.prototype = Object.create(DocumentFragment.prototype);
+  mixin(ShadowRoot.prototype, {
+    get innerHTML() {
+      return getInnerHTML(this);
+    },
+    set innerHTML(value) {
+      setInnerHTML(this, value);
+      this.invalidateShadowRenderer();
+    },
+
+    get olderShadowRoot() {
+      return nextOlderShadowTreeTable.get(this) || null;
+    },
+
+    get host() {
+      return shadowHostTable.get(this) || null;
+    },
+
+    invalidateShadowRenderer: function() {
+      return shadowHostTable.get(this).invalidateShadowRenderer();
+    },
+
+    elementFromPoint: function(x, y) {
+      return elementFromPoint(this, this.ownerDocument, x, y);
+    },
+
+    getElementById: function(id) {
+      if (spaceCharRe.test(id))
+        return null;
+      return this.querySelector('[id="' + id + '"]');
+    }
+  });
+
+  scope.wrappers.ShadowRoot = ShadowRoot;
+
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. 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) {
+  'use strict';
+
+  var Element = scope.wrappers.Element;
+  var HTMLContentElement = scope.wrappers.HTMLContentElement;
+  var HTMLShadowElement = scope.wrappers.HTMLShadowElement;
+  var Node = scope.wrappers.Node;
+  var ShadowRoot = scope.wrappers.ShadowRoot;
+  var assert = scope.assert;
+  var mixin = scope.mixin;
+  var oneOf = scope.oneOf;
+  var unwrap = scope.unwrap;
+  var wrap = scope.wrap;
+
+  /**
+   * Updates the fields of a wrapper to a snapshot of the logical DOM as needed.
+   * Up means parentNode
+   * Sideways means previous and next sibling.
+   * @param {!Node} wrapper
+   */
+  function updateWrapperUpAndSideways(wrapper) {
+    wrapper.previousSibling_ = wrapper.previousSibling;
+    wrapper.nextSibling_ = wrapper.nextSibling;
+    wrapper.parentNode_ = wrapper.parentNode;
+  }
+
+  /**
+   * Updates the fields of a wrapper to a snapshot of the logical DOM as needed.
+   * Down means first and last child
+   * @param {!Node} wrapper
+   */
+  function updateWrapperDown(wrapper) {
+    wrapper.firstChild_ = wrapper.firstChild;
+    wrapper.lastChild_ = wrapper.lastChild;
+  }
+
+  function updateAllChildNodes(parentNodeWrapper) {
+    assert(parentNodeWrapper instanceof Node);
+    for (var childWrapper = parentNodeWrapper.firstChild;
+         childWrapper;
+         childWrapper = childWrapper.nextSibling) {
+      updateWrapperUpAndSideways(childWrapper);
+    }
+    updateWrapperDown(parentNodeWrapper);
+  }
+
+  function insertBefore(parentNodeWrapper, newChildWrapper, refChildWrapper) {
+    var parentNode = unwrap(parentNodeWrapper);
+    var newChild = unwrap(newChildWrapper);
+    var refChild = refChildWrapper ? unwrap(refChildWrapper) : null;
+
+    remove(newChildWrapper);
+    updateWrapperUpAndSideways(newChildWrapper);
+
+    if (!refChildWrapper) {
+      parentNodeWrapper.lastChild_ = parentNodeWrapper.lastChild;
+      if (parentNodeWrapper.lastChild === parentNodeWrapper.firstChild)
+        parentNodeWrapper.firstChild_ = parentNodeWrapper.firstChild;
+
+      var lastChildWrapper = wrap(parentNode.lastChild);
+      if (lastChildWrapper)
+        lastChildWrapper.nextSibling_ = lastChildWrapper.nextSibling;
+    } else {
+      if (parentNodeWrapper.firstChild === refChildWrapper)
+        parentNodeWrapper.firstChild_ = refChildWrapper;
+
+      refChildWrapper.previousSibling_ = refChildWrapper.previousSibling;
+    }
+
+    parentNode.insertBefore(newChild, refChild);
+  }
+
+  function remove(nodeWrapper) {
+    var node = unwrap(nodeWrapper)
+    var parentNode = node.parentNode;
+    if (!parentNode)
+      return;
+
+    var parentNodeWrapper = wrap(parentNode);
+    updateWrapperUpAndSideways(nodeWrapper);
+
+    if (nodeWrapper.previousSibling)
+      nodeWrapper.previousSibling.nextSibling_ = nodeWrapper;
+    if (nodeWrapper.nextSibling)
+      nodeWrapper.nextSibling.previousSibling_ = nodeWrapper;
+
+    if (parentNodeWrapper.lastChild === nodeWrapper)
+      parentNodeWrapper.lastChild_ = nodeWrapper;
+    if (parentNodeWrapper.firstChild === nodeWrapper)
+      parentNodeWrapper.firstChild_ = nodeWrapper;
+
+    parentNode.removeChild(node);
+  }
+
+  var distributedChildNodesTable = new WeakMap();
+  var eventParentsTable = new WeakMap();
+  var insertionParentTable = new WeakMap();
+  var rendererForHostTable = new WeakMap();
+
+  function distributeChildToInsertionPoint(child, insertionPoint) {
+    getDistributedChildNodes(insertionPoint).push(child);
+    assignToInsertionPoint(child, insertionPoint);
+
+    var eventParents = eventParentsTable.get(child);
+    if (!eventParents)
+      eventParentsTable.set(child, eventParents = []);
+    eventParents.push(insertionPoint);
+  }
+
+  function resetDistributedChildNodes(insertionPoint) {
+    distributedChildNodesTable.set(insertionPoint, []);
+  }
+
+  function getDistributedChildNodes(insertionPoint) {
+    return distributedChildNodesTable.get(insertionPoint);
+  }
+
+  function getChildNodesSnapshot(node) {
+    var result = [], i = 0;
+    for (var child = node.firstChild; child; child = child.nextSibling) {
+      result[i++] = child;
+    }
+    return result;
+  }
+
+  /**
+   * Visits all nodes in the tree that fulfils the |predicate|. If the |visitor|
+   * function returns |false| the traversal is aborted.
+   * @param {!Node} tree
+   * @param {function(!Node) : boolean} predicate
+   * @param {function(!Node) : *} visitor
+   */
+  function visit(tree, predicate, visitor) {
+    // This operates on logical DOM.
+    for (var node = tree.firstChild; node; node = node.nextSibling) {
+      if (predicate(node)) {
+        if (visitor(node) === false)
+          return;
+      } else {
+        visit(node, predicate, visitor);
+      }
+    }
+  }
+
+  // Matching Insertion Points
+  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#matching-insertion-points
+
+  // TODO(arv): Verify this... I don't remember why I picked this regexp.
+  var selectorMatchRegExp = /^[*.:#[a-zA-Z_|]/;
+
+  var allowedPseudoRegExp = 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('|') + ')');
+
+
+  /**
+   * @param {Element} node
+   * @oaram {Element} point The insertion point element.
+   * @return {boolean} Whether the node matches the insertion point.
+   */
+  function matchesCriteria(node, point) {
+    var select = point.getAttribute('select');
+    if (!select)
+      return true;
+
+    // Here we know the select attribute is a non empty string.
+    select = select.trim();
+    if (!select)
+      return true;
+
+    if (!(node instanceof Element))
+      return false;
+
+    // The native matches function in IE9 does not correctly work with elements
+    // that are not in the document.
+    // TODO(arv): Implement matching in JS.
+    // https://github.com/Polymer/ShadowDOM/issues/361
+    if (select === '*' || select === node.localName)
+      return true;
+
+    // TODO(arv): This does not seem right. Need to check for a simple selector.
+    if (!selectorMatchRegExp.test(select))
+      return false;
+
+    // TODO(arv): This no longer matches the spec.
+    if (select[0] === ':' && !allowedPseudoRegExp.test(select))
+      return false;
+
+    try {
+      return node.matches(select);
+    } catch (ex) {
+      // Invalid selector.
+      return false;
+    }
+  }
+
+  var request = oneOf(window, [
+    'requestAnimationFrame',
+    'mozRequestAnimationFrame',
+    'webkitRequestAnimationFrame',
+    'setTimeout'
+  ]);
+
+  var pendingDirtyRenderers = [];
+  var renderTimer;
+
+  function renderAllPending() {
+    for (var i = 0; i < pendingDirtyRenderers.length; i++) {
+      pendingDirtyRenderers[i].render();
+    }
+    pendingDirtyRenderers = [];
+  }
+
+  function handleRequestAnimationFrame() {
+    renderTimer = null;
+    renderAllPending();
+  }
+
+  /**
+   * Returns existing shadow renderer for a host or creates it if it is needed.
+   * @params {!Element} host
+   * @return {!ShadowRenderer}
+   */
+  function getRendererForHost(host) {
+    var renderer = rendererForHostTable.get(host);
+    if (!renderer) {
+      renderer = new ShadowRenderer(host);
+      rendererForHostTable.set(host, renderer);
+    }
+    return renderer;
+  }
+
+  function getShadowRootAncestor(node) {
+    for (; node; node = node.parentNode) {
+      if (node instanceof ShadowRoot)
+        return node;
+    }
+    return null;
+  }
+
+  function getRendererForShadowRoot(shadowRoot) {
+    return getRendererForHost(shadowRoot.host);
+  }
+
+  var spliceDiff = new ArraySplice();
+  spliceDiff.equals = function(renderNode, rawNode) {
+    return unwrap(renderNode.node) === rawNode;
+  };
+
+  /**
+   * RenderNode is used as an in memory "render tree". When we render the
+   * composed tree we create a tree of RenderNodes, then we diff this against
+   * the real DOM tree and make minimal changes as needed.
+   */
+  function RenderNode(node) {
+    this.skip = false;
+    this.node = node;
+    this.childNodes = [];
+  }
+
+  RenderNode.prototype = {
+    append: function(node) {
+      var rv = new RenderNode(node);
+      this.childNodes.push(rv);
+      return rv;
+    },
+
+    sync: function(opt_added) {
+      if (this.skip)
+        return;
+
+      var nodeWrapper = this.node;
+      // plain array of RenderNodes
+      var newChildren = this.childNodes;
+      // plain array of real nodes.
+      var oldChildren = getChildNodesSnapshot(unwrap(nodeWrapper));
+      var added = opt_added || new WeakMap();
+
+      var splices = spliceDiff.calculateSplices(newChildren, oldChildren);
+
+      var newIndex = 0, oldIndex = 0;
+      var lastIndex = 0;
+      for (var i = 0; i < splices.length; i++) {
+        var splice = splices[i];
+        for (; lastIndex < splice.index; lastIndex++) {
+          oldIndex++;
+          newChildren[newIndex++].sync(added);
+        }
+
+        var removedCount = splice.removed.length;
+        for (var j = 0; j < removedCount; j++) {
+          var wrapper = wrap(oldChildren[oldIndex++]);
+          if (!added.get(wrapper))
+            remove(wrapper);
+        }
+
+        var addedCount = splice.addedCount;
+        var refNode = oldChildren[oldIndex] && wrap(oldChildren[oldIndex]);
+        for (var j = 0; j < addedCount; j++) {
+          var newChildRenderNode = newChildren[newIndex++];
+          var newChildWrapper = newChildRenderNode.node;
+          insertBefore(nodeWrapper, newChildWrapper, refNode);
+
+          // Keep track of added so that we do not remove the node after it
+          // has been added.
+          added.set(newChildWrapper, true);
+
+          newChildRenderNode.sync(added);
+        }
+
+        lastIndex += addedCount;
+      }
+
+      for (var i = lastIndex; i < newChildren.length; i++) {
+        newChildren[i].sync(added);
+      }
+    }
+  };
+
+  function ShadowRenderer(host) {
+    this.host = host;
+    this.dirty = false;
+    this.invalidateAttributes();
+    this.associateNode(host);
+  }
+
+  ShadowRenderer.prototype = {
+
+    // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#rendering-shadow-trees
+    render: function(opt_renderNode) {
+      if (!this.dirty)
+        return;
+
+      this.invalidateAttributes();
+      this.treeComposition();
+
+      var host = this.host;
+      var shadowRoot = host.shadowRoot;
+
+      this.associateNode(host);
+      var topMostRenderer = !renderNode;
+      var renderNode = opt_renderNode || new RenderNode(host);
+
+      for (var node = shadowRoot.firstChild; node; node = node.nextSibling) {
+        this.renderNode(shadowRoot, renderNode, node, false);
+      }
+
+      if (topMostRenderer)
+        renderNode.sync();
+
+      this.dirty = false;
+    },
+
+    invalidate: function() {
+      if (!this.dirty) {
+        this.dirty = true;
+        pendingDirtyRenderers.push(this);
+        if (renderTimer)
+          return;
+        renderTimer = window[request](handleRequestAnimationFrame, 0);
+      }
+    },
+
+    renderNode: function(shadowRoot, renderNode, node, isNested) {
+      if (isShadowHost(node)) {
+        renderNode = renderNode.append(node);
+        var renderer = getRendererForHost(node);
+        renderer.dirty = true;  // Need to rerender due to reprojection.
+        renderer.render(renderNode);
+      } else if (isInsertionPoint(node)) {
+        this.renderInsertionPoint(shadowRoot, renderNode, node, isNested);
+      } else if (isShadowInsertionPoint(node)) {
+        this.renderShadowInsertionPoint(shadowRoot, renderNode, node);
+      } else {
+        this.renderAsAnyDomTree(shadowRoot, renderNode, node, isNested);
+      }
+    },
+
+    renderAsAnyDomTree: function(shadowRoot, renderNode, node, isNested) {
+      renderNode = renderNode.append(node);
+
+      if (isShadowHost(node)) {
+        var renderer = getRendererForHost(node);
+        renderNode.skip = !renderer.dirty;
+        renderer.render(renderNode);
+      } else {
+        for (var child = node.firstChild; child; child = child.nextSibling) {
+          this.renderNode(shadowRoot, renderNode, child, isNested);
+        }
+      }
+    },
+
+    renderInsertionPoint: function(shadowRoot, renderNode, insertionPoint,
+                                   isNested) {
+      var distributedChildNodes = getDistributedChildNodes(insertionPoint);
+      if (distributedChildNodes.length) {
+        this.associateNode(insertionPoint);
+
+        for (var i = 0; i < distributedChildNodes.length; i++) {
+          var child = distributedChildNodes[i];
+          if (isInsertionPoint(child) && isNested)
+            this.renderInsertionPoint(shadowRoot, renderNode, child, isNested);
+          else
+            this.renderAsAnyDomTree(shadowRoot, renderNode, child, isNested);
+        }
+      } else {
+        this.renderFallbackContent(shadowRoot, renderNode, insertionPoint);
+      }
+      this.associateNode(insertionPoint.parentNode);
+    },
+
+    renderShadowInsertionPoint: function(shadowRoot, renderNode,
+                                         shadowInsertionPoint) {
+      var nextOlderTree = shadowRoot.olderShadowRoot;
+      if (nextOlderTree) {
+        assignToInsertionPoint(nextOlderTree, shadowInsertionPoint);
+        this.associateNode(shadowInsertionPoint.parentNode);
+        for (var node = nextOlderTree.firstChild;
+             node;
+             node = node.nextSibling) {
+          this.renderNode(nextOlderTree, renderNode, node, true);
+        }
+      } else {
+        this.renderFallbackContent(shadowRoot, renderNode,
+                                   shadowInsertionPoint);
+      }
+    },
+
+    renderFallbackContent: function(shadowRoot, renderNode, fallbackHost) {
+      this.associateNode(fallbackHost);
+      this.associateNode(fallbackHost.parentNode);
+      for (var node = fallbackHost.firstChild; node; node = node.nextSibling) {
+        this.renderAsAnyDomTree(shadowRoot, renderNode, node, false);
+      }
+    },
+
+    /**
+     * Invalidates the attributes used to keep track of which attributes may
+     * cause the renderer to be invalidated.
+     */
+    invalidateAttributes: function() {
+      this.attributes = Object.create(null);
+    },
+
+    /**
+     * Parses the selector and makes this renderer dependent on the attribute
+     * being used in the selector.
+     * @param {string} selector
+     */
+    updateDependentAttributes: function(selector) {
+      if (!selector)
+        return;
+
+      var attributes = this.attributes;
+
+      // .class
+      if (/\.\w+/.test(selector))
+        attributes['class'] = true;
+
+      // #id
+      if (/#\w+/.test(selector))
+        attributes['id'] = true;
+
+      selector.replace(/\[\s*([^\s=\|~\]]+)/g, function(_, name) {
+        attributes[name] = true;
+      });
+
+      // Pseudo selectors have been removed from the spec.
+    },
+
+    dependsOnAttribute: function(name) {
+      return this.attributes[name];
+    },
+
+    // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-distribution-algorithm
+    distribute: function(tree, pool) {
+      var self = this;
+
+      visit(tree, isActiveInsertionPoint,
+          function(insertionPoint) {
+            resetDistributedChildNodes(insertionPoint);
+            self.updateDependentAttributes(
+                insertionPoint.getAttribute('select'));
+
+            for (var i = 0; i < pool.length; i++) {  // 1.2
+              var node = pool[i];  // 1.2.1
+              if (node === undefined)  // removed
+                continue;
+              if (matchesCriteria(node, insertionPoint)) {  // 1.2.2
+                distributeChildToInsertionPoint(node, insertionPoint);  // 1.2.2.1
+                pool[i] = undefined;  // 1.2.2.2
+              }
+            }
+          });
+    },
+
+    // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-tree-composition
+    treeComposition: function () {
+      var shadowHost = this.host;
+      var tree = shadowHost.shadowRoot;  // 1.
+      var pool = [];  // 2.
+
+      for (var child = shadowHost.firstChild;
+           child;
+           child = child.nextSibling) {  // 3.
+        if (isInsertionPoint(child)) {  // 3.2.
+          var reprojected = getDistributedChildNodes(child);  // 3.2.1.
+          // if reprojected is undef... reset it?
+          if (!reprojected || !reprojected.length)  // 3.2.2.
+            reprojected = getChildNodesSnapshot(child);
+          pool.push.apply(pool, reprojected);  // 3.2.3.
+        } else {
+          pool.push(child); // 3.3.
+        }
+      }
+
+      var shadowInsertionPoint, point;
+      while (tree) {  // 4.
+        // 4.1.
+        shadowInsertionPoint = undefined;  // Reset every iteration.
+        visit(tree, isActiveShadowInsertionPoint, function(point) {
+          shadowInsertionPoint = point;
+          return false;
+        });
+        point = shadowInsertionPoint;
+
+        this.distribute(tree, pool);  // 4.2.
+        if (point) {  // 4.3.
+          var nextOlderTree = tree.olderShadowRoot;  // 4.3.1.
+          if (!nextOlderTree) {
+            break;  // 4.3.1.1.
+          } else {
+            tree = nextOlderTree;  // 4.3.2.2.
+            assignToInsertionPoint(tree, point);  // 4.3.2.2.
+            continue;  // 4.3.2.3.
+          }
+        } else {
+          break;  // 4.4.
+        }
+      }
+    },
+
+    associateNode: function(node) {
+      node.impl.polymerShadowRenderer_ = this;
+    }
+  };
+
+  function isInsertionPoint(node) {
+    // Should this include <shadow>?
+    return node instanceof HTMLContentElement;
+  }
+
+  function isActiveInsertionPoint(node) {
+    // <content> inside another <content> or <shadow> is considered inactive.
+    return node instanceof HTMLContentElement;
+  }
+
+  function isShadowInsertionPoint(node) {
+    return node instanceof HTMLShadowElement;
+  }
+
+  function isActiveShadowInsertionPoint(node) {
+    // <shadow> inside another <content> or <shadow> is considered inactive.
+    return node instanceof HTMLShadowElement;
+  }
+
+  function isShadowHost(shadowHost) {
+    return shadowHost.shadowRoot;
+  }
+
+  function getShadowTrees(host) {
+    var trees = [];
+
+    for (var tree = host.shadowRoot; tree; tree = tree.olderShadowRoot) {
+      trees.push(tree);
+    }
+    return trees;
+  }
+
+  function assignToInsertionPoint(tree, point) {
+    insertionParentTable.set(tree, point);
+  }
+
+  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#rendering-shadow-trees
+  function render(host) {
+    new ShadowRenderer(host).render();
+  };
+
+  // Need to rerender shadow host when:
+  //
+  // - a direct child to the ShadowRoot is added or removed
+  // - a direct child to the host is added or removed
+  // - a new shadow root is created
+  // - a direct child to a content/shadow element is added or removed
+  // - a sibling to a content/shadow element is added or removed
+  // - content[select] is changed
+  // - an attribute in a direct child to a host is modified
+
+  /**
+   * This gets called when a node was added or removed to it.
+   */
+  Node.prototype.invalidateShadowRenderer = function(force) {
+    var renderer = this.impl.polymerShadowRenderer_;
+    if (renderer) {
+      renderer.invalidate();
+      return true;
+    }
+
+    return false;
+  };
+
+  HTMLContentElement.prototype.getDistributedNodes = function() {
+    // TODO(arv): We should only rerender the dirty ancestor renderers (from
+    // the root and down).
+    renderAllPending();
+    return getDistributedChildNodes(this);
+  };
+
+  HTMLShadowElement.prototype.nodeIsInserted_ =
+  HTMLContentElement.prototype.nodeIsInserted_ = function() {
+    // Invalidate old renderer if any.
+    this.invalidateShadowRenderer();
+
+    var shadowRoot = getShadowRootAncestor(this);
+    var renderer;
+    if (shadowRoot)
+      renderer = getRendererForShadowRoot(shadowRoot);
+    this.impl.polymerShadowRenderer_ = renderer;
+    if (renderer)
+      renderer.invalidate();
+  };
+
+  scope.eventParentsTable = eventParentsTable;
+  scope.getRendererForHost = getRendererForHost;
+  scope.getShadowTrees = getShadowTrees;
+  scope.insertionParentTable = insertionParentTable;
+  scope.renderAllPending = renderAllPending;
+
+  // Exposed for testing
+  scope.visual = {
+    insertBefore: insertBefore,
+    remove: remove,
+  };
+
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var HTMLElement = scope.wrappers.HTMLElement;
+  var assert = scope.assert;
+  var mixin = scope.mixin;
+  var registerWrapper = scope.registerWrapper;
+  var unwrap = scope.unwrap;
+  var wrap = scope.wrap;
+
+  var elementsWithFormProperty = [
+    'HTMLButtonElement',
+    'HTMLFieldSetElement',
+    'HTMLInputElement',
+    'HTMLKeygenElement',
+    'HTMLLabelElement',
+    'HTMLLegendElement',
+    'HTMLObjectElement',
+    // HTMLOptionElement is handled in HTMLOptionElement.js
+    'HTMLOutputElement',
+    'HTMLSelectElement',
+    'HTMLTextAreaElement',
+  ];
+
+  function createWrapperConstructor(name) {
+    if (!window[name])
+      return;
+
+    // Ensure we are not overriding an already existing constructor.
+    assert(!scope.wrappers[name]);
+
+    var GeneratedWrapper = function(node) {
+      // At this point all of them extend HTMLElement.
+      HTMLElement.call(this, node);
+    }
+    GeneratedWrapper.prototype = Object.create(HTMLElement.prototype);
+    mixin(GeneratedWrapper.prototype, {
+      get form() {
+        return wrap(unwrap(this).form);
+      },
+    });
+
+    registerWrapper(window[name], GeneratedWrapper,
+        document.createElement(name.slice(4, -7)));
+    scope.wrappers[name] = GeneratedWrapper;
+  }
+
+  elementsWithFormProperty.forEach(createWrapperConstructor);
+
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2014 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var registerWrapper = scope.registerWrapper;
+  var unwrap = scope.unwrap;
+  var unwrapIfNeeded = scope.unwrapIfNeeded;
+  var wrap = scope.wrap;
+
+  var OriginalSelection = window.Selection;
+
+  function Selection(impl) {
+    this.impl = impl;
+  }
+  Selection.prototype = {
+    get anchorNode() {
+      return wrap(this.impl.anchorNode);
+    },
+    get focusNode() {
+      return wrap(this.impl.focusNode);
+    },
+    addRange: function(range) {
+      this.impl.addRange(unwrap(range));
+    },
+    collapse: function(node, index) {
+      this.impl.collapse(unwrapIfNeeded(node), index);
+    },
+    containsNode: function(node, allowPartial) {
+      return this.impl.containsNode(unwrapIfNeeded(node), allowPartial);
+    },
+    extend: function(node, offset) {
+      this.impl.extend(unwrapIfNeeded(node), offset);
+    },
+    getRangeAt: function(index) {
+      return wrap(this.impl.getRangeAt(index));
+    },
+    removeRange: function(range) {
+      this.impl.removeRange(unwrap(range));
+    },
+    selectAllChildren: function(node) {
+      this.impl.selectAllChildren(unwrapIfNeeded(node));
+    },
+    toString: function() {
+      return this.impl.toString();
+    }
+  };
+
+  // WebKit extensions. Not implemented.
+  // readonly attribute Node baseNode;
+  // readonly attribute long baseOffset;
+  // readonly attribute Node extentNode;
+  // readonly attribute long extentOffset;
+  // [RaisesException] void setBaseAndExtent([Default=Undefined] optional Node baseNode,
+  //                       [Default=Undefined] optional long baseOffset,
+  //                       [Default=Undefined] optional Node extentNode,
+  //                       [Default=Undefined] optional long extentOffset);
+  // [RaisesException, ImplementedAs=collapse] void setPosition([Default=Undefined] optional Node node,
+  //                  [Default=Undefined] optional long offset);
+
+  registerWrapper(window.Selection, Selection, window.getSelection());
+
+  scope.wrappers.Selection = Selection;
+
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var GetElementsByInterface = scope.GetElementsByInterface;
+  var Node = scope.wrappers.Node;
+  var ParentNodeInterface = scope.ParentNodeInterface;
+  var Selection = scope.wrappers.Selection;
+  var SelectorsInterface = scope.SelectorsInterface;
+  var ShadowRoot = scope.wrappers.ShadowRoot;
+  var cloneNode = scope.cloneNode;
+  var defineWrapGetter = scope.defineWrapGetter;
+  var elementFromPoint = scope.elementFromPoint;
+  var forwardMethodsToWrapper = scope.forwardMethodsToWrapper;
+  var matchesNames = scope.matchesNames;
+  var mixin = scope.mixin;
+  var registerWrapper = scope.registerWrapper;
+  var renderAllPending = scope.renderAllPending;
+  var rewrap = scope.rewrap;
+  var unwrap = scope.unwrap;
+  var wrap = scope.wrap;
+  var wrapEventTargetMethods = scope.wrapEventTargetMethods;
+  var wrapNodeList = scope.wrapNodeList;
+
+  var implementationTable = new WeakMap();
+
+  function Document(node) {
+    Node.call(this, node);
+  }
+  Document.prototype = Object.create(Node.prototype);
+
+  defineWrapGetter(Document, 'documentElement');
+
+  // Conceptually both body and head can be in a shadow but suporting that seems
+  // overkill at this point.
+  defineWrapGetter(Document, 'body');
+  defineWrapGetter(Document, 'head');
+
+  // document cannot be overridden so we override a bunch of its methods
+  // directly on the instance.
+
+  function wrapMethod(name) {
+    var original = document[name];
+    Document.prototype[name] = function() {
+      return wrap(original.apply(this.impl, arguments));
+    };
+  }
+
+  [
+    'createComment',
+    'createDocumentFragment',
+    'createElement',
+    'createElementNS',
+    'createEvent',
+    'createEventNS',
+    'createRange',
+    'createTextNode',
+    'getElementById'
+  ].forEach(wrapMethod);
+
+  var originalAdoptNode = document.adoptNode;
+
+  function adoptNodeNoRemove(node, doc) {
+    originalAdoptNode.call(doc.impl, unwrap(node));
+    adoptSubtree(node, doc);
+  }
+
+  function adoptSubtree(node, doc) {
+    if (node.shadowRoot)
+      doc.adoptNode(node.shadowRoot);
+    if (node instanceof ShadowRoot)
+      adoptOlderShadowRoots(node, doc);
+    for (var child = node.firstChild; child; child = child.nextSibling) {
+      adoptSubtree(child, doc);
+    }
+  }
+
+  function adoptOlderShadowRoots(shadowRoot, doc) {
+    var oldShadowRoot = shadowRoot.olderShadowRoot;
+    if (oldShadowRoot)
+      doc.adoptNode(oldShadowRoot);
+  }
+
+  var originalGetSelection = document.getSelection;
+
+  mixin(Document.prototype, {
+    adoptNode: function(node) {
+      if (node.parentNode)
+        node.parentNode.removeChild(node);
+      adoptNodeNoRemove(node, this);
+      return node;
+    },
+    elementFromPoint: function(x, y) {
+      return elementFromPoint(this, this, x, y);
+    },
+    importNode: function(node, deep) {
+      return cloneNode(node, deep, this.impl);
+    },
+    getSelection: function() {
+      renderAllPending();
+      return new Selection(originalGetSelection.call(unwrap(this)));
+    }
+  });
+
+  if (document.registerElement) {
+    var originalRegisterElement = document.registerElement;
+    Document.prototype.registerElement = function(tagName, object) {
+      var prototype = object.prototype;
+
+      // If we already used the object as a prototype for another custom
+      // element.
+      if (scope.nativePrototypeTable.get(prototype)) {
+        // TODO(arv): DOMException
+        throw new Error('NotSupportedError');
+      }
+
+      // Find first object on the prototype chain that already have a native
+      // prototype. Keep track of all the objects before that so we can create
+      // a similar structure for the native case.
+      var proto = Object.getPrototypeOf(prototype);
+      var nativePrototype;
+      var prototypes = [];
+      while (proto) {
+        nativePrototype = scope.nativePrototypeTable.get(proto);
+        if (nativePrototype)
+          break;
+        prototypes.push(proto);
+        proto = Object.getPrototypeOf(proto);
+      }
+
+      if (!nativePrototype) {
+        // TODO(arv): DOMException
+        throw new Error('NotSupportedError');
+      }
+
+      // This works by creating a new prototype object that is empty, but has
+      // the native prototype as its proto. The original prototype object
+      // passed into register is used as the wrapper prototype.
+
+      var newPrototype = Object.create(nativePrototype);
+      for (var i = prototypes.length - 1; i >= 0; i--) {
+        newPrototype = Object.create(newPrototype);
+      }
+
+      // Add callbacks if present.
+      // Names are taken from:
+      //   https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.cpp&sq=package:chromium&type=cs&l=156
+      // and not from the spec since the spec is out of date.
+      [
+        'createdCallback',
+        'attachedCallback',
+        'detachedCallback',
+        'attributeChangedCallback',
+      ].forEach(function(name) {
+        var f = prototype[name];
+        if (!f)
+          return;
+        newPrototype[name] = function() {
+          // if this element has been wrapped prior to registration,
+          // the wrapper is stale; in this case rewrap
+          if (!(wrap(this) instanceof CustomElementConstructor)) {
+            rewrap(this);
+          }
+          f.apply(wrap(this), arguments);
+        };
+      });
+
+      var p = {prototype: newPrototype};
+      if (object.extends)
+        p.extends = object.extends;
+
+      function CustomElementConstructor(node) {
+        if (!node) {
+          if (object.extends) {
+            return document.createElement(object.extends, tagName);
+          } else {
+            return document.createElement(tagName);
+          }
+        }
+        this.impl = node;
+      }
+      CustomElementConstructor.prototype = prototype;
+      CustomElementConstructor.prototype.constructor = CustomElementConstructor;
+
+      scope.constructorTable.set(newPrototype, CustomElementConstructor);
+      scope.nativePrototypeTable.set(prototype, newPrototype);
+
+      // registration is synchronous so do it last
+      var nativeConstructor = originalRegisterElement.call(unwrap(this),
+          tagName, p);
+      return CustomElementConstructor;
+    };
+
+    forwardMethodsToWrapper([
+      window.HTMLDocument || window.Document,  // Gecko adds these to HTMLDocument
+    ], [
+      'registerElement',
+    ]);
+  }
+
+  // We also override some of the methods on document.body and document.head
+  // for convenience.
+  forwardMethodsToWrapper([
+    window.HTMLBodyElement,
+    window.HTMLDocument || window.Document,  // Gecko adds these to HTMLDocument
+    window.HTMLHeadElement,
+    window.HTMLHtmlElement,
+  ], [
+    'appendChild',
+    'compareDocumentPosition',
+    'contains',
+    'getElementsByClassName',
+    'getElementsByTagName',
+    'getElementsByTagNameNS',
+    'insertBefore',
+    'querySelector',
+    'querySelectorAll',
+    'removeChild',
+    'replaceChild',
+  ].concat(matchesNames));
+
+  forwardMethodsToWrapper([
+    window.HTMLDocument || window.Document,  // Gecko adds these to HTMLDocument
+  ], [
+    'adoptNode',
+    'importNode',
+    'contains',
+    'createComment',
+    'createDocumentFragment',
+    'createElement',
+    'createElementNS',
+    'createEvent',
+    'createEventNS',
+    'createRange',
+    'createTextNode',
+    'elementFromPoint',
+    'getElementById',
+    'getSelection',
+  ]);
+
+  mixin(Document.prototype, GetElementsByInterface);
+  mixin(Document.prototype, ParentNodeInterface);
+  mixin(Document.prototype, SelectorsInterface);
+
+  mixin(Document.prototype, {
+    get implementation() {
+      var implementation = implementationTable.get(this);
+      if (implementation)
+        return implementation;
+      implementation =
+          new DOMImplementation(unwrap(this).implementation);
+      implementationTable.set(this, implementation);
+      return implementation;
+    }
+  });
+
+  registerWrapper(window.Document, Document,
+      document.implementation.createHTMLDocument(''));
+
+  // Both WebKit and Gecko uses HTMLDocument for document. HTML5/DOM only has
+  // one Document interface and IE implements the standard correctly.
+  if (window.HTMLDocument)
+    registerWrapper(window.HTMLDocument, Document);
+
+  wrapEventTargetMethods([
+    window.HTMLBodyElement,
+    window.HTMLDocument || window.Document,  // Gecko adds these to HTMLDocument
+    window.HTMLHeadElement,
+  ]);
+
+  function DOMImplementation(impl) {
+    this.impl = impl;
+  }
+
+  function wrapImplMethod(constructor, name) {
+    var original = document.implementation[name];
+    constructor.prototype[name] = function() {
+      return wrap(original.apply(this.impl, arguments));
+    };
+  }
+
+  function forwardImplMethod(constructor, name) {
+    var original = document.implementation[name];
+    constructor.prototype[name] = function() {
+      return original.apply(this.impl, arguments);
+    };
+  }
+
+  wrapImplMethod(DOMImplementation, 'createDocumentType');
+  wrapImplMethod(DOMImplementation, 'createDocument');
+  wrapImplMethod(DOMImplementation, 'createHTMLDocument');
+  forwardImplMethod(DOMImplementation, 'hasFeature');
+
+  registerWrapper(window.DOMImplementation, DOMImplementation);
+
+  forwardMethodsToWrapper([
+    window.DOMImplementation,
+  ], [
+    'createDocumentType',
+    'createDocument',
+    'createHTMLDocument',
+    'hasFeature',
+  ]);
+
+  scope.adoptNodeNoRemove = adoptNodeNoRemove;
+  scope.wrappers.DOMImplementation = DOMImplementation;
+  scope.wrappers.Document = Document;
+
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var EventTarget = scope.wrappers.EventTarget;
+  var Selection = scope.wrappers.Selection;
+  var mixin = scope.mixin;
+  var registerWrapper = scope.registerWrapper;
+  var renderAllPending = scope.renderAllPending;
+  var unwrap = scope.unwrap;
+  var unwrapIfNeeded = scope.unwrapIfNeeded;
+  var wrap = scope.wrap;
+
+  var OriginalWindow = window.Window;
+  var originalGetComputedStyle = window.getComputedStyle;
+  var originalGetSelection = window.getSelection;
+
+  function Window(impl) {
+    EventTarget.call(this, impl);
+  }
+  Window.prototype = Object.create(EventTarget.prototype);
+
+  OriginalWindow.prototype.getComputedStyle = function(el, pseudo) {
+    return wrap(this || window).getComputedStyle(unwrapIfNeeded(el), pseudo);
+  };
+
+  OriginalWindow.prototype.getSelection = function() {
+    return wrap(this || window).getSelection();
+  };
+
+  // Work around for https://bugzilla.mozilla.org/show_bug.cgi?id=943065
+  delete window.getComputedStyle;
+  delete window.getSelection;
+
+  ['addEventListener', 'removeEventListener', 'dispatchEvent'].forEach(
+      function(name) {
+        OriginalWindow.prototype[name] = function() {
+          var w = wrap(this || window);
+          return w[name].apply(w, arguments);
+        };
+
+        // Work around for https://bugzilla.mozilla.org/show_bug.cgi?id=943065
+        delete window[name];
+      });
+
+  mixin(Window.prototype, {
+    getComputedStyle: function(el, pseudo) {
+      renderAllPending();
+      return originalGetComputedStyle.call(unwrap(this), unwrapIfNeeded(el),
+                                           pseudo);
+    },
+    getSelection: function() {
+      renderAllPending();
+      return new Selection(originalGetSelection.call(unwrap(this)));
+    },
+  });
+
+  registerWrapper(OriginalWindow, Window);
+
+  scope.wrappers.Window = Window;
+
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+  'use strict';
+
+  var isWrapperFor = scope.isWrapperFor;
+
+  // This is a list of the elements we currently override the global constructor
+  // for.
+  var elements = {
+    'a': 'HTMLAnchorElement',
+
+    // Do not create an applet element by default since it shows a warning in
+    // IE.
+    // https://github.com/Polymer/polymer/issues/217
+    // 'applet': 'HTMLAppletElement',
+
+    'area': 'HTMLAreaElement',
+    'br': 'HTMLBRElement',
+    'base': 'HTMLBaseElement',
+    'body': 'HTMLBodyElement',
+    'button': 'HTMLButtonElement',
+    // 'command': 'HTMLCommandElement',  // Not fully implemented in Gecko.
+    'dl': 'HTMLDListElement',
+    'datalist': 'HTMLDataListElement',
+    'data': 'HTMLDataElement',
+    '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',
+    'marquee': 'HTMLMarqueeElement',
+    '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',
+    'time': 'HTMLTimeElement',
+    'caption': 'HTMLTableCaptionElement',
+    // WebKit and Moz are wrong:
+    // https://bugs.webkit.org/show_bug.cgi?id=111469
+    // https://bugzilla.mozilla.org/show_bug.cgi?id=848096
+    // 'td': 'HTMLTableCellElement',
+    'col': 'HTMLTableColElement',
+    'table': 'HTMLTableElement',
+    'tr': 'HTMLTableRowElement',
+    'thead': 'HTMLTableSectionElement',
+    'tbody': 'HTMLTableSectionElement',
+    'textarea': 'HTMLTextAreaElement',
+    'track': 'HTMLTrackElement',
+    'title': 'HTMLTitleElement',
+    'ul': 'HTMLUListElement',
+    'video': 'HTMLVideoElement',
+  };
+
+  function overrideConstructor(tagName) {
+    var nativeConstructorName = elements[tagName];
+    var nativeConstructor = window[nativeConstructorName];
+    if (!nativeConstructor)
+      return;
+    var element = document.createElement(tagName);
+    var wrapperConstructor = element.constructor;
+    window[nativeConstructorName] = wrapperConstructor;
+  }
+
+  Object.keys(elements).forEach(overrideConstructor);
+
+  Object.getOwnPropertyNames(scope.wrappers).forEach(function(name) {
+    window[name] = scope.wrappers[name]
+  });
+
+  // Export for testing.
+  scope.knownElements = elements;
+
+})(window.ShadowDOMPolyfill);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+(function() {
+
+  // convenient global
+  window.wrap = ShadowDOMPolyfill.wrapIfNeeded;
+  window.unwrap = ShadowDOMPolyfill.unwrapIfNeeded;
+
+  // users may want to customize other types
+  // TODO(sjmiles): 'button' is now supported by ShadowDOMPolyfill, but
+  // I've left this code here in case we need to temporarily patch another
+  // type
+  /*
+  (function() {
+    var elts = {HTMLButtonElement: 'button'};
+    for (var c in elts) {
+      window[c] = function() { throw 'Patched Constructor'; };
+      window[c].prototype = Object.getPrototypeOf(
+          document.createElement(elts[c]));
+    }
+  })();
+  */
+
+  // patch in prefixed name
+  Object.defineProperty(Element.prototype, 'webkitShadowRoot',
+      Object.getOwnPropertyDescriptor(Element.prototype, 'shadowRoot'));
+
+  var originalCreateShadowRoot = Element.prototype.createShadowRoot;
+  Element.prototype.createShadowRoot = function() {
+    var root = originalCreateShadowRoot.call(this);
+    CustomElements.watchShadow(this);
+    return root;
+  };
+
+  Element.prototype.webkitCreateShadowRoot = Element.prototype.createShadowRoot;
+})();
+
+/*
+ * Copyright 2012 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+/*
+  This is a limited shim for ShadowDOM css styling.
+  https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#styles
+  
+  The intention here is to support only the styling features which can be 
+  relatively simply implemented. The goal is to allow users to avoid the 
+  most obvious pitfalls and do so without compromising performance significantly. 
+  For ShadowDOM styling that's not covered here, a set of best practices
+  can be provided that should allow users to accomplish more complex styling.
+
+  The following is a list of specific ShadowDOM styling features and a brief
+  discussion of the approach used to shim.
+
+  Shimmed features:
+
+  * :host, :ancestor: ShadowDOM allows styling of the shadowRoot's host
+  element using the :host rule. To shim this feature, the :host styles are 
+  reformatted and prefixed with a given scope name and promoted to a 
+  document level stylesheet.
+  For example, given a scope name of .foo, a rule like this:
+  
+    :host {
+        background: red;
+      }
+    }
+  
+  becomes:
+  
+    .foo {
+      background: red;
+    }
+  
+  * encapsultion: Styles defined within ShadowDOM, apply only to 
+  dom inside the ShadowDOM. Polymer uses one of two techniques to imlement
+  this feature.
+  
+  By default, rules are prefixed with the host element tag name 
+  as a descendant selector. This ensures styling does not leak out of the 'top'
+  of the element's ShadowDOM. For example,
+
+  div {
+      font-weight: bold;
+    }
+  
+  becomes:
+
+  x-foo div {
+      font-weight: bold;
+    }
+  
+  becomes:
+
+
+  Alternatively, if Platform.ShadowCSS.strictStyling is set to true then 
+  selectors are scoped by adding an attribute selector suffix to each
+  simple selector that contains the host element tag name. Each element 
+  in the element's ShadowDOM template is also given the scope attribute. 
+  Thus, these rules match only elements that have the scope attribute.
+  For example, given a scope name of x-foo, a rule like this:
+  
+    div {
+      font-weight: bold;
+    }
+  
+  becomes:
+  
+    div[x-foo] {
+      font-weight: bold;
+    }
+
+  Note that elements that are dynamically added to a scope must have the scope
+  selector added to them manually.
+
+  * upper/lower bound encapsulation: Styles which are defined outside a
+  shadowRoot should not cross the ShadowDOM boundary and should not apply
+  inside a shadowRoot.
+
+  This styling behavior is not emulated. Some possible ways to do this that 
+  were rejected due to complexity and/or performance concerns include: (1) reset
+  every possible property for every possible selector for a given scope name;
+  (2) re-implement css in javascript.
+  
+  As an alternative, users should make sure to use selectors
+  specific to the scope in which they are working.
+  
+  * ::distributed: This behavior is not emulated. It's often not necessary
+  to style the contents of a specific insertion point and instead, descendants
+  of the host element can be styled selectively. Users can also create an 
+  extra node around an insertion point and style that node's contents
+  via descendent selectors. For example, with a shadowRoot like this:
+  
+    <style>
+      ::content(div) {
+        background: red;
+      }
+    </style>
+    <content></content>
+  
+  could become:
+  
+    <style>
+      / *@polyfill .content-container div * / 
+      ::content(div) {
+        background: red;
+      }
+    </style>
+    <div class="content-container">
+      <content></content>
+    </div>
+  
+  Note the use of @polyfill in the comment above a ShadowDOM specific style
+  declaration. This is a directive to the styling shim to use the selector 
+  in comments in lieu of the next selector when running under polyfill.
+*/
+(function(scope) {
+
+var ShadowCSS = {
+  strictStyling: false,
+  registry: {},
+  // 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 */ and /* @polyfill-rule */
+  // 4. shim :host and scoping
+  shimStyling: function(root, name, extendsName) {
+    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);
+    }
+    var cssText = this.stylesToShimmedCssText(def.rootStyles, def.scopeStyles,
+        name, typeExtension);
+    // 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);
+  },
+  // apply @polyfill rules + :host and scope shimming
+  stylesToShimmedCssText: function(rootStyles, scopeStyles, name,
+      typeExtension) {
+    name = name || '';
+    // insert @polyfill and @polyfill-rule rules into style elements
+    // scoping process takes care of shimming these
+    this.insertPolyfillDirectives(rootStyles);
+    this.insertPolyfillRules(rootStyles);
+    var cssText = this.shimScoping(scopeStyles, name, typeExtension);
+    // note: we only need to do rootStyles since these are unscoped.
+    cssText += this.extractPolyfillUnscopedRules(rootStyles);
+    return cssText.trim();
+  },
+  registerDefinition: function(root, name, extendsName) {
+    var def = this.registry[name] = {
+      root: root,
+      name: name,
+      extendsName: extendsName
+    }
+    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 && (!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.
+      Array.prototype.forEach.call(root.querySelectorAll('*'),
+          function(node) {
+            node.setAttribute(name, '');
+          });
+      // and template contents too
+      Array.prototype.forEach.call(root.querySelectorAll('template'),
+          function(template) {
+            this.applyScopeToContent(template.content, name);
+          },
+          this);
+    }
+  },
+  /*
+   * Process styles to convert native ShadowDOM rules that will trip
+   * up the css parser; we rely on decorating the stylesheet with comments.
+   * 
+   * For example, we convert this rule:
+   * 
+   * (comment start) @polyfill :host menu-item (comment end)
+   * shadow::-webkit-distributed(menu-item) {
+   * 
+   * to this:
+   * 
+   * scopeName menu-item {
+   *
+  **/
+  insertPolyfillDirectives: function(styles) {
+    if (styles) {
+      Array.prototype.forEach.call(styles, function(s) {
+        s.textContent = this.insertPolyfillDirectivesInCssText(s.textContent);
+      }, this);
+    }
+  },
+  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);
+    }
+  },
+  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;
+  },
+  /* Ensure styles are scoped. Pseudo-scoping takes a rule like:
+   * 
+   *  .foo {... } 
+   *  
+   *  and converts this to
+   *  
+   *  scopeName .foo { ... }
+  */
+  shimScoping: function(styles, name, typeExtension) {
+    if (styles) {
+      return this.convertScopedStyles(styles, name, typeExtension);
+    }
+  },
+  convertScopedStyles: function(styles, name, typeExtension) {
+    var cssText = stylesToCssText(styles);
+    cssText = this.insertPolyfillHostInCssText(cssText);
+    cssText = this.convertColonHost(cssText);
+    cssText = this.convertColonAncestor(cssText);
+    cssText = this.convertCombinators(cssText);
+    if (name) {
+      var rules = cssToRules(cssText);
+      cssText = this.scopeRules(rules, name, typeExtension);
+    }
+    return cssText;
+  },
+  /*
+   * convert a rule like :host(.foo) > .bar { }
+   *
+   * to
+   *
+   * scopeName.foo > .bar
+  */
+  convertColonHost: function(cssText) {
+    return this.convertColonRule(cssText, cssColonHostRe,
+        this.colonHostPartReplacer);
+  },
+  /*
+   * convert a rule like :ancestor(.foo) > .bar { }
+   *
+   * to
+   *
+   * scopeName.foo > .bar, .foo scopeName > .bar { }
+   * 
+   * and
+   *
+   * :ancestor(.foo:host) .bar { ... }
+   * 
+   * to
+   * 
+   * scopeName.foo .bar { ... }
+  */
+  convertColonAncestor: function(cssText) {
+    return this.convertColonRule(cssText, cssColonAncestorRe,
+        this.colonAncestorPartReplacer);
+  },
+  convertColonRule: function(cssText, regExp, partReplacer) {
+    // p1 = :host, p2 = contents of (), p3 rest of rule
+    return cssText.replace(regExp, function(m, p1, p2, p3) {
+      p1 = polyfillHostNoCombinator;
+      if (p2) {
+        var parts = p2.split(','), r = [];
+        for (var i=0, l=parts.length, p; (i<l) && (p=parts[i]); i++) {
+          p = p.trim();
+          r.push(partReplacer(p1, p, p3));
+        }
+        return r.join(',');
+      } else {
+        return p1 + p3;
+      }
+    });
+  },
+  colonAncestorPartReplacer: function(host, part, suffix) {
+    if (part.match(polyfillHost)) {
+      return this.colonHostPartReplacer(host, part, suffix);
+    } else {
+      return host + part + suffix + ', ' + part + ' ' + host + suffix;
+    }
+  },
+  colonHostPartReplacer: function(host, part, suffix) {
+    return host + part.replace(polyfillHost, '') + suffix;
+  },
+  /*
+   * Convert ^ and ^^ combinators by replacing with space.
+  */
+  convertCombinators: function(cssText) {
+    return cssText.replace(/\^\^/g, ' ').replace(/\^/g, ' ');
+  },
+  // change a selector like 'div' to 'name div'
+  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, typeExtension, 
+          this.strictStyling) + ' {\n\t';
+        cssText += this.propertiesFromRule(rule) + '\n}\n\n';
+      } else if (rule.media) {
+        cssText += '@media ' + rule.media.mediaText + ' {\n';
+        cssText += this.scopeRules(rule.cssRules, name, typeExtension);
+        cssText += '\n}\n\n';
+      } else if (rule.cssText) {
+        cssText += rule.cssText + '\n\n';
+      }
+    }, this);
+    return cssText;
+  },
+  scopeSelector: function(selector, name, typeExtension, strict) {
+    var r = [], parts = selector.split(',');
+    parts.forEach(function(p) {
+      p = p.trim();
+      if (this.selectorNeedsScoping(p, name, typeExtension)) {
+        p = (strict && !p.match(polyfillHostNoCombinator)) ? 
+            this.applyStrictSelectorScope(p, name) :
+            this.applySimpleSelectorScope(p, name, typeExtension);
+      }
+      r.push(p);
+    }, this);
+    return r.join(', ');
+  },
+  selectorNeedsScoping: function(selector, name, typeExtension) {
+    var re = this.makeScopeMatcher(name, typeExtension);
+    return !selector.match(re);
+  },
+  makeScopeMatcher: function(name, typeExtension) {
+    var matchScope = typeExtension ? '\\[is=[\'"]?' + name + '[\'"]?\\]' : name;
+    return new RegExp('^(' + matchScope + ')' + selectorReSuffix, 'm');
+  },
+  // scope via name and [is=name]
+  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]
+  applyStrictSelectorScope: function(selector, name) {
+    var splits = [' ', '>', '+', '~'],
+      scoped = selector,
+      attrName = '[' + name + ']';
+    splits.forEach(function(sep) {
+      var parts = scoped.split(sep);
+      scoped = parts.map(function(p) {
+        // 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')
+        }
+        return p;
+      }).join(sep);
+    });
+    return scoped;
+  },
+  insertPolyfillHostInCssText: function(selector) {
+    return selector.replace(hostRe, polyfillHost).replace(colonHostRe,
+        polyfillHost).replace(colonAncestorRe, polyfillAncestor);
+  },
+  propertiesFromRule: function(rule) {
+    // TODO(sorvell): Safari cssom incorrectly removes quotes from the content
+    // property. (https://bugs.webkit.org/show_bug.cgi?id=118045)
+    if (rule.style.content && !rule.style.content.match(/['"]+/)) {
+      return rule.style.cssText.replace(/content:[^;]*;/g, 'content: \'' + 
+          rule.style.content + '\';');
+    }
+    return rule.style.cssText;
+  }
+};
+
+var selectorRe = /([^{]*)({[\s\S]*?})/gim,
+    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 -shadowcsshost.
+    polyfillHost = '-shadowcsshost',
+    // note: :ancestor pre-processed to -shadowcssancestor.
+    polyfillAncestor = '-shadowcssancestor',
+    parenSuffix = ')(?:\\((' +
+        '(?:\\([^)(]*\\)|[^)(]*)+?' +
+        ')\\))?([^,{]*)';
+    cssColonHostRe = new RegExp('(' + polyfillHost + parenSuffix, 'gim'),
+    cssColonAncestorRe = new RegExp('(' + polyfillAncestor + parenSuffix, 'gim'),
+    selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$',
+    hostRe = /@host/gim,
+    colonHostRe = /\:host/gim,
+    colonAncestorRe = /\:ancestor/gim,
+    /* host name without combinator */
+    polyfillHostNoCombinator = polyfillHost + '-no-combinator',
+    polyfillHostRe = new RegExp(polyfillHost, 'gim');
+    polyfillAncestorRe = new RegExp(polyfillAncestor, 'gim');
+
+function stylesToCssText(styles, preserveComments) {
+  var cssText = '';
+  Array.prototype.forEach.call(styles, function(s) {
+    cssText += s.textContent + '\n\n';
+  });
+  // strip comments for easier processing
+  if (!preserveComments) {
+    cssText = cssText.replace(cssCommentRe, '');
+  }
+  return 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);
+  return rules;
+}
+
+function rulesToCss(cssRules) {
+  for (var i=0, css=[]; i < cssRules.length; i++) {
+    css.push(cssRules[i].cssText);
+  }
+  return css.join('\n\n');
+}
+
+function addCssToDocument(cssText) {
+  if (cssText) {
+    getSheet().appendChild(document.createTextNode(cssText));
+  }
+}
+
+var SHIM_ATTRIBUTE = 'shim-shadowdom';
+var SHIMMED_ATTRIBUTE = 'shim-shadowdom-css';
+
+var sheet;
+function getSheet() {
+  if (!sheet) {
+    sheet = document.createElement("style");
+    sheet.setAttribute(SHIMMED_ATTRIBUTE, '');
+    sheet[SHIMMED_ATTRIBUTE] = true;
+  }
+  return sheet;
+}
+
+// add polyfill stylesheet to document
+if (window.ShadowDOMPolyfill) {
+  addCssToDocument('style { display: none !important; }\n');
+  var doc = wrap(document);
+  var head = doc.querySelector('head');
+  head.insertBefore(getSheet(), head.childNodes[0]);
+
+  // TODO(sorvell): monkey-patching HTMLImports is abusive;
+  // consider a better solution.
+  document.addEventListener('DOMContentLoaded', function() {
+    var urlResolver = scope.urlResolver;
+    
+    if (window.HTMLImports && !HTMLImports.useNative) {
+      var SHIM_SHEET_SELECTOR = 'link[rel=stylesheet]' +
+          '[' + SHIM_ATTRIBUTE + ']';
+      var SHIM_STYLE_SELECTOR = 'style[' + SHIM_ATTRIBUTE + ']';
+      HTMLImports.importer.documentPreloadSelectors += ',' + SHIM_SHEET_SELECTOR;
+      HTMLImports.importer.importsPreloadSelectors += ',' + SHIM_SHEET_SELECTOR;
+
+      HTMLImports.parser.documentSelectors = [
+        HTMLImports.parser.documentSelectors,
+        SHIM_SHEET_SELECTOR,
+        SHIM_STYLE_SELECTOR
+      ].join(',');
+  
+      var originalParseGeneric = HTMLImports.parser.parseGeneric;
+
+      HTMLImports.parser.parseGeneric = function(elt) {
+        if (elt[SHIMMED_ATTRIBUTE]) {
+          return;
+        }
+        var style = elt.__importElement || elt;
+        if (!style.hasAttribute(SHIM_ATTRIBUTE)) {
+          originalParseGeneric.call(this, elt);
+          return;
+        }
+        if (elt.__resource) {
+          style = elt.ownerDocument.createElement('style');
+          style.textContent = urlResolver.resolveCssText(
+              elt.__resource, elt.href);
+        } else {
+          urlResolver.resolveStyle(style);  
+        }
+        var styles = [style];
+        style.textContent = ShadowCSS.stylesToShimmedCssText(styles, styles);
+        style.removeAttribute(SHIM_ATTRIBUTE, '');
+        style.setAttribute(SHIMMED_ATTRIBUTE, '');
+        style[SHIMMED_ATTRIBUTE] = true;
+        // place in document
+        if (style.parentNode !== head) {
+          // replace links in head
+          if (elt.parentNode === head) {
+            head.replaceChild(style, elt);
+          } else {
+            head.appendChild(style);
+          }
+        }
+        style.__importParsed = true;
+        this.markParsingComplete(elt);
+      }
+
+      var hasResource = HTMLImports.parser.hasResource;
+      HTMLImports.parser.hasResource = function(node) {
+        if (node.localName === 'link' && node.rel === 'stylesheet' &&
+            node.hasAttribute(SHIM_ATTRIBUTE)) {
+          return (node.__resource);
+        } else {
+          return hasResource.call(this, node);
+        }
+      }
+
+    }
+  });
+}
+
+// exports
+scope.ShadowCSS = ShadowCSS;
+
+})(window.Platform);
+} else {
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+(function() {
+
+  // poor man's adapter for template.content on various platform scenarios
+  window.templateContent = window.templateContent || function(inTemplate) {
+    return inTemplate.content;
+  };
+
+  // so we can call wrap/unwrap without testing for ShadowDOMPolyfill
+
+  window.wrap = window.unwrap = function(n){
+    return n;
+  }
+
+  var originalCreateShadowRoot = Element.prototype.webkitCreateShadowRoot;
+  Element.prototype.webkitCreateShadowRoot = function() {
+    var elderRoot = this.webkitShadowRoot;
+    var root = originalCreateShadowRoot.call(this);
+    root.olderShadowRoot = elderRoot;
+    root.host = this;
+    CustomElements.watchShadow(this);
+    return root;
+  }
+
+  Object.defineProperties(Element.prototype, {
+    shadowRoot: {
+      get: function() {
+        return this.webkitShadowRoot;
+      }
+    },
+    createShadowRoot: {
+      value: function() {
+        return this.webkitCreateShadowRoot();
+      }
+    }
+  });
+
+  window.templateContent = function(inTemplate) {
+    // if MDV exists, it may need to boostrap this template to reveal content
+    if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) {
+      HTMLTemplateElement.bootstrap(inTemplate);
+    }
+    // fallback when there is no Shadow DOM polyfill, no MDV polyfill, and no
+    // native template support
+    if (!inTemplate.content && !inTemplate._content) {
+      var frag = document.createDocumentFragment();
+      while (inTemplate.firstChild) {
+        frag.appendChild(inTemplate.firstChild);
+      }
+      inTemplate._content = frag;
+    }
+    return inTemplate.content || inTemplate._content;
+  };
+
+})();
+}
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+(function(scope) {
+  'use strict';
+
+  // feature detect for URL constructor
+  var hasWorkingUrl = false;
+  if (!scope.forceJURL) {
+    try {
+      var u = new URL('b', 'http://a');
+      hasWorkingUrl = u.href === 'http://a/b';
+    } catch(e) {}
+  }
+
+  if (hasWorkingUrl)
+    return;
+
+  var relative = Object.create(null);
+  relative['ftp'] = 21;
+  relative['file'] = 0;
+  relative['gopher'] = 70;
+  relative['http'] = 80;
+  relative['https'] = 443;
+  relative['ws'] = 80;
+  relative['wss'] = 443;
+
+  var relativePathDotMapping = Object.create(null);
+  relativePathDotMapping['%2e'] = '.';
+  relativePathDotMapping['.%2e'] = '..';
+  relativePathDotMapping['%2e.'] = '..';
+  relativePathDotMapping['%2e%2e'] = '..';
+
+  function isRelativeScheme(scheme) {
+    return relative[scheme] !== undefined;
+  }
+
+  function invalid() {
+    clear.call(this);
+    this._isInvalid = true;
+  }
+
+  function IDNAToASCII(h) {
+    if ('' == h) {
+      invalid.call(this)
+    }
+    // XXX
+    return h.toLowerCase()
+  }
+
+  function percentEscape(c) {
+    var unicode = c.charCodeAt(0);
+    if (unicode > 0x20 &&
+       unicode < 0x7F &&
+       // " # < > ? `
+       [0x22, 0x23, 0x3C, 0x3E, 0x3F, 0x60].indexOf(unicode) == -1
+      ) {
+      return c;
+    }
+    return encodeURIComponent(c);
+  }
+
+  function percentEscapeQuery(c) {
+    // XXX This actually needs to encode c using encoding and then
+    // convert the bytes one-by-one.
+
+    var unicode = c.charCodeAt(0);
+    if (unicode > 0x20 &&
+       unicode < 0x7F &&
+       // " # < > ` (do not escape '?')
+       [0x22, 0x23, 0x3C, 0x3E, 0x60].indexOf(unicode) == -1
+      ) {
+      return c;
+    }
+    return encodeURIComponent(c);
+  }
+
+  var EOF = undefined,
+      ALPHA = /[a-zA-Z]/,
+      ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
+
+  function parse(input, stateOverride, base) {
+    function err(message) {
+      errors.push(message)
+    }
+
+    var state = stateOverride || 'scheme start',
+        cursor = 0,
+        buffer = '',
+        seenAt = false,
+        seenBracket = false,
+        errors = [];
+
+    loop: while ((input[cursor - 1] != EOF || cursor == 0) && !this._isInvalid) {
+      var c = input[cursor];
+      switch (state) {
+        case 'scheme start':
+          if (c && ALPHA.test(c)) {
+            buffer += c.toLowerCase(); // ASCII-safe
+            state = 'scheme';
+          } else if (!stateOverride) {
+            buffer = '';
+            state = 'no scheme';
+            continue;
+          } else {
+            err('Invalid scheme.');
+            break loop;
+          }
+          break;
+
+        case 'scheme':
+          if (c && ALPHANUMERIC.test(c)) {
+            buffer += c.toLowerCase(); // ASCII-safe
+          } else if (':' == c) {
+            this._scheme = buffer;
+            buffer = '';
+            if (stateOverride) {
+              break loop;
+            }
+            if (isRelativeScheme(this._scheme)) {
+              this._isRelative = true;
+            }
+            if ('file' == this._scheme) {
+              state = 'relative';
+            } else if (this._isRelative && base && base._scheme == this._scheme) {
+              state = 'relative or authority';
+            } else if (this._isRelative) {
+              state = 'authority first slash';
+            } else {
+              state = 'scheme data';
+            }
+          } else if (!stateOverride) {
+            buffer = '';
+            cursor = 0;
+            state = 'no scheme';
+            continue;
+          } else if (EOF == c) {
+            break loop;
+          } else {
+            err('Code point not allowed in scheme: ' + c)
+            break loop;
+          }
+          break;
+
+        case 'scheme data':
+          if ('?' == c) {
+            query = '?';
+            state = 'query';
+          } else if ('#' == c) {
+            this._fragment = '#';
+            state = 'fragment';
+          } else {
+            // XXX error handling
+            if (EOF != c && '\t' != c && '\n' != c && '\r' != c) {
+              this._schemeData += percentEscape(c);
+            }
+          }
+          break;
+
+        case 'no scheme':
+          if (!base || !(isRelativeScheme(base._scheme))) {
+            err('Missing scheme.');
+            invalid.call(this);
+          } else {
+            state = 'relative';
+            continue;
+          }
+          break;
+
+        case 'relative or authority':
+          if ('/' == c && '/' == input[cursor+1]) {
+            state = 'authority ignore slashes';
+          } else {
+            err('Expected /, got: ' + c);
+            state = 'relative';
+            continue
+          }
+          break;
+
+        case 'relative':
+          this._isRelative = true;
+          if ('file' != this._scheme)
+            this._scheme = base._scheme;
+          if (EOF == c) {
+            this._host = base._host;
+            this._port = base._port;
+            this._path = base._path.slice();
+            this._query = base._query;
+            break loop;
+          } else if ('/' == c || '\\' == c) {
+            if ('\\' == c)
+              err('\\ is an invalid code point.');
+            state = 'relative slash';
+          } else if ('?' == c) {
+            this._host = base._host;
+            this._port = base._port;
+            this._path = base._path.slice();
+            this._query = '?';
+            state = 'query';
+          } else if ('#' == c) {
+            this._host = base._host;
+            this._port = base._port;
+            this._path = base._path.slice();
+            this._query = base._query;
+            this._fragment = '#';
+            state = 'fragment';
+          } else {
+            var nextC = input[cursor+1]
+            var nextNextC = input[cursor+2]
+            if (
+              'file' != this._scheme || !ALPHA.test(c) ||
+              (nextC != ':' && nextC != '|') ||
+              (EOF != nextNextC && '/' != nextNextC && '\\' != nextNextC && '?' != nextNextC && '#' != nextNextC)) {
+              this._host = base._host;
+              this._port = base._port;
+              this._path = base._path.slice();
+              this._path.pop();
+            }
+            state = 'relative path';
+            continue;
+          }
+          break;
+
+        case 'relative slash':
+          if ('/' == c || '\\' == c) {
+            if ('\\' == c) {
+              err('\\ is an invalid code point.');
+            }
+            if ('file' == this._scheme) {
+              state = 'file host';
+            } else {
+              state = 'authority ignore slashes';
+            }
+          } else {
+            if ('file' != this._scheme) {
+              this._host = base._host;
+              this._port = base._port;
+            }
+            state = 'relative path';
+            continue;
+          }
+          break;
+
+        case 'authority first slash':
+          if ('/' == c) {
+            state = 'authority second slash';
+          } else {
+            err("Expected '/', got: " + c);
+            state = 'authority ignore slashes';
+            continue;
+          }
+          break;
+
+        case 'authority second slash':
+          state = 'authority ignore slashes';
+          if ('/' != c) {
+            err("Expected '/', got: " + c);
+            continue;
+          }
+          break;
+
+        case 'authority ignore slashes':
+          if ('/' != c && '\\' != c) {
+            state = 'authority';
+            continue;
+          } else {
+            err('Expected authority, got: ' + c);
+          }
+          break;
+
+        case 'authority':
+          if ('@' == c) {
+            if (seenAt) {
+              err('@ already seen.');
+              buffer += '%40';
+            }
+            seenAt = true;
+            for (var i = 0; i < buffer.length; i++) {
+              var cp = buffer[i];
+              if ('\t' == cp || '\n' == cp || '\r' == cp) {
+                err('Invalid whitespace in authority.');
+                continue;
+              }
+              // XXX check URL code points
+              if (':' == cp && null === this._password) {
+                this._password = '';
+                continue;
+              }
+              var tempC = percentEscape(cp);
+              (null !== this._password) ? this._password += tempC : this._username += tempC;
+            }
+            buffer = '';
+          } else if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c) {
+            cursor -= buffer.length;
+            buffer = '';
+            state = 'host';
+            continue;
+          } else {
+            buffer += c;
+          }
+          break;
+
+        case 'file host':
+          if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c) {
+            if (buffer.length == 2 && ALPHA.test(buffer[0]) && (buffer[1] == ':' || buffer[1] == '|')) {
+              state = 'relative path';
+            } else if (buffer.length == 0) {
+              state = 'relative path start';
+            } else {
+              this._host = IDNAToASCII.call(this, buffer);
+              buffer = '';
+              state = 'relative path start';
+            }
+            continue;
+          } else if ('\t' == c || '\n' == c || '\r' == c) {
+            err('Invalid whitespace in file host.');
+          } else {
+            buffer += c;
+          }
+          break;
+
+        case 'host':
+        case 'hostname':
+          if (':' == c && !seenBracket) {
+            // XXX host parsing
+            this._host = IDNAToASCII.call(this, buffer);
+            buffer = '';
+            state = 'port';
+            if ('hostname' == stateOverride) {
+              break loop;
+            }
+          } else if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c) {
+            this._host = IDNAToASCII.call(this, buffer);
+            buffer = '';
+            state = 'relative path start';
+            if (stateOverride) {
+              break loop;
+            }
+            continue;
+          } else if ('\t' != c && '\n' != c && '\r' != c) {
+            if ('[' == c) {
+              seenBracket = true;
+            } else if (']' == c) {
+              seenBracket = false;
+            }
+            buffer += c;
+          } else {
+            err('Invalid code point in host/hostname: ' + c);
+          }
+          break;
+
+        case 'port':
+          if (/[0-9]/.test(c)) {
+            buffer += c;
+          } else if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c || stateOverride) {
+            if ('' != buffer) {
+              var temp = parseInt(buffer, 10);
+              if (temp != relative[this._scheme]) {
+                this._port = temp + '';
+              }
+              buffer = '';
+            }
+            if (stateOverride) {
+              break loop;
+            }
+            state = 'relative path start';
+            continue;
+          } else if ('\t' == c || '\n' == c || '\r' == c) {
+            err('Invalid code point in port: ' + c);
+          } else {
+            invalid.call(this);
+          }
+          break;
+
+        case 'relative path start':
+          if ('\\' == c)
+            err("'\\' not allowed in path.");
+          state = 'relative path';
+          if ('/' != c && '\\' != c) {
+            continue;
+          }
+          break;
+
+        case 'relative path':
+          if (EOF == c || '/' == c || '\\' == c || (!stateOverride && ('?' == c || '#' == c))) {
+            if ('\\' == c) {
+              err('\\ not allowed in relative path.');
+            }
+            var tmp;
+            if (tmp = relativePathDotMapping[buffer.toLowerCase()]) {
+              buffer = tmp;
+            }
+            if ('..' == buffer) {
+              this._path.pop();
+              if ('/' != c && '\\' != c) {
+                this._path.push('');
+              }
+            } else if ('.' == buffer && '/' != c && '\\' != c) {
+              this._path.push('');
+            } else if ('.' != buffer) {
+              if ('file' == this._scheme && this._path.length == 0 && buffer.length == 2 && ALPHA.test(buffer[0]) && buffer[1] == '|') {
+                buffer = buffer[0] + ':';
+              }
+              this._path.push(buffer);
+            }
+            buffer = '';
+            if ('?' == c) {
+              this._query = '?';
+              state = 'query';
+            } else if ('#' == c) {
+              this._fragment = '#';
+              state = 'fragment';
+            }
+          } else if ('\t' != c && '\n' != c && '\r' != c) {
+            buffer += percentEscape(c);
+          }
+          break;
+
+        case 'query':
+          if (!stateOverride && '#' == c) {
+            this._fragment = '#';
+            state = 'fragment';
+          } else if (EOF != c && '\t' != c && '\n' != c && '\r' != c) {
+            this._query += percentEscapeQuery(c);
+          }
+          break;
+
+        case 'fragment':
+          if (EOF != c && '\t' != c && '\n' != c && '\r' != c) {
+            this._fragment += c;
+          }
+          break;
+      }
+
+      cursor++;
+    }
+  }
+
+  function clear() {
+    this._scheme = '';
+    this._schemeData = '';
+    this._username = '';
+    this._password = null;
+    this._host = '';
+    this._port = '';
+    this._path = [];
+    this._query = '';
+    this._fragment = '';
+    this._isInvalid = false;
+    this._isRelative = false;
+  }
+
+  // Does not process domain names or IP addresses.
+  // Does not handle encoding for the query parameter.
+  function jURL(url, base /* , encoding */) {
+    if (base !== undefined && !(base instanceof jURL))
+      base = new jURL(String(base));
+
+    this._url = url;
+    clear.call(this);
+
+    var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, '');
+    // encoding = encoding || 'utf-8'
+
+    parse.call(this, input, null, base);
+  }
+
+  jURL.prototype = {
+    get href() {
+      if (this._isInvalid)
+        return this._url;
+
+      var authority = '';
+      if ('' != this._username || null != this._password) {
+        authority = this._username +
+            (null != this._password ? ':' + this._password : '') + '@';
+      }
+
+      return this.protocol +
+          (this._isRelative ? '//' + authority + this.host : '') +
+          this.pathname + this._query + this._fragment;
+    },
+    set href(href) {
+      clear.call(this);
+      parse.call(this, href);
+    },
+
+    get protocol() {
+      return this._scheme + ':';
+    },
+    set protocol(protocol) {
+      if (this._isInvalid)
+        return;
+      parse.call(this, protocol + ':', 'scheme start');
+    },
+
+    get host() {
+      return this._isInvalid ? '' : this._port ?
+          this._host + ':' + this._port : this._host;
+    },
+    set host(host) {
+      if (this._isInvalid || !this._isRelative)
+        return;
+      parse.call(this, host, 'host');
+    },
+
+    get hostname() {
+      return this._host;
+    },
+    set hostname(hostname) {
+      if (this._isInvalid || !this._isRelative)
+        return;
+      parse.call(this, hostname, 'hostname');
+    },
+
+    get port() {
+      return this._port;
+    },
+    set port(port) {
+      if (this._isInvalid || !this._isRelative)
+        return;
+      parse.call(this, port, 'port');
+    },
+
+    get pathname() {
+      return this._isInvalid ? '' : this._isRelative ?
+          '/' + this._path.join('/') : this._schemeData;
+    },
+    set pathname(pathname) {
+      if (this._isInvalid || !this._isRelative)
+        return;
+      this._path = [];
+      parse.call(this, pathname, 'relative path start');
+    },
+
+    get search() {
+      return this._isInvalid || !this._query || '?' == this._query ?
+          '' : this._query;
+    },
+    set search(search) {
+      if (this._isInvalid || !this._isRelative)
+        return;
+      this._query = '?';
+      if ('?' == search[0])
+        search = search.slice(1);
+      parse.call(this, search, 'query');
+    },
+
+    get hash() {
+      return this._isInvalid || !this._fragment || '#' == this._fragment ?
+          '' : this._fragment;
+    },
+    set hash(hash) {
+      if (this._isInvalid)
+        return;
+      this._fragment = '#';
+      if ('#' == hash[0])
+        hash = hash.slice(1);
+      parse.call(this, hash, 'fragment');
+    }
+  };
+
+  scope.URL = jURL;
+
+})(window);
+
+/*
+ * Copyright 2013 The Polymer Authors. 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) {
+
+// Old versions of iOS do not have bind.
+
+if (!Function.prototype.bind) {
+  Function.prototype.bind = function(scope) {
+    var self = this;
+    var args = Array.prototype.slice.call(arguments, 1);
+    return function() {
+      var args2 = args.slice();
+      args2.push.apply(args2, arguments);
+      return self.apply(scope, args2);
+    };
+  };
+}
+
+// mixin
+
+// copy all properties from inProps (et al) to inObj
+function mixin(inObj/*, inProps, inMoreProps, ...*/) {
+  var obj = inObj || {};
+  for (var i = 1; i < arguments.length; i++) {
+    var p = arguments[i];
+    try {
+      for (var n in p) {
+        copyProperty(n, p, obj);
+      }
+    } catch(x) {
+    }
+  }
+  return obj;
+}
+
+// copy property inName from inSource object to inTarget object
+function copyProperty(inName, inSource, inTarget) {
+  var pd = getPropertyDescriptor(inSource, inName);
+  Object.defineProperty(inTarget, inName, pd);
+}
+
+// get property descriptor for inName on inObject, even if
+// inName exists on some link in inObject's prototype chain
+function getPropertyDescriptor(inObject, inName) {
+  if (inObject) {
+    var pd = Object.getOwnPropertyDescriptor(inObject, inName);
+    return pd || getPropertyDescriptor(Object.getPrototypeOf(inObject), inName);
+  }
+}
+
+// export
+
+scope.mixin = mixin;
+
+})(window.Platform);
+// Copyright 2011 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+(function(scope) {
+
+  'use strict';
+
+  // polyfill DOMTokenList
+  // * add/remove: allow these methods to take multiple classNames
+  // * toggle: add a 2nd argument which forces the given state rather
+  //  than toggling.
+
+  var add = DOMTokenList.prototype.add;
+  var remove = DOMTokenList.prototype.remove;
+  DOMTokenList.prototype.add = function() {
+    for (var i = 0; i < arguments.length; i++) {
+      add.call(this, arguments[i]);
+    }
+  };
+  DOMTokenList.prototype.remove = function() {
+    for (var i = 0; i < arguments.length; i++) {
+      remove.call(this, arguments[i]);
+    }
+  };
+  DOMTokenList.prototype.toggle = function(name, bool) {
+    if (arguments.length == 1) {
+      bool = !this.contains(name);
+    }
+    bool ? this.add(name) : this.remove(name);
+  };
+  DOMTokenList.prototype.switch = function(oldName, newName) {
+    oldName && this.remove(oldName);
+    newName && this.add(newName);
+  };
+
+  // add array() to NodeList, NamedNodeMap, HTMLCollection
+
+  var ArraySlice = function() {
+    return Array.prototype.slice.call(this);
+  };
+
+  var namedNodeMap = (window.NamedNodeMap || window.MozNamedAttrMap || {});
+
+  NodeList.prototype.array = ArraySlice;
+  namedNodeMap.prototype.array = ArraySlice;
+  HTMLCollection.prototype.array = ArraySlice;
+
+  // polyfill performance.now
+
+  if (!window.performance) {
+    var start = Date.now();
+    // only at millisecond precision
+    window.performance = {now: function(){ return Date.now() - start }};
+  }
+
+  // polyfill for requestAnimationFrame
+
+  if (!window.requestAnimationFrame) {
+    window.requestAnimationFrame = (function() {
+      var nativeRaf = window.webkitRequestAnimationFrame ||
+        window.mozRequestAnimationFrame;
+
+      return nativeRaf ?
+        function(callback) {
+          return nativeRaf(function() {
+            callback(performance.now());
+          });
+        } :
+        function( callback ){
+          return window.setTimeout(callback, 1000 / 60);
+        };
+    })();
+  }
+
+  if (!window.cancelAnimationFrame) {
+    window.cancelAnimationFrame = (function() {
+      return  window.webkitCancelAnimationFrame ||
+        window.mozCancelAnimationFrame ||
+        function(id) {
+          clearTimeout(id);
+        };
+    })();
+  }
+
+  // TODO(sorvell): workaround for bug:
+  // https://code.google.com/p/chromium/issues/detail?id=229142
+  // remove when this bug is addressed
+  // give main document templates a base that allows them to fetch eagerly
+  // resolved paths relative to the main document
+  var template = document.createElement('template');
+  var base = document.createElement('base');
+  base.href = document.baseURI;
+  template.content.ownerDocument.appendChild(base);
+  
+
+  // utility
+
+  function createDOM(inTagOrNode, inHTML, inAttrs) {
+    var dom = typeof inTagOrNode == 'string' ?
+        document.createElement(inTagOrNode) : inTagOrNode.cloneNode(true);
+    dom.innerHTML = inHTML;
+    if (inAttrs) {
+      for (var n in inAttrs) {
+        dom.setAttribute(n, inAttrs[n]);
+      }
+    }
+    return dom;
+  }
+  // Make a stub for Polymer() for polyfill purposes; under the HTMLImports
+  // polyfill, scripts in the main document run before imports. That means
+  // if (1) polymer is imported and (2) Polymer() is called in the main document
+  // in a script after the import, 2 occurs before 1. We correct this here
+  // by specfiically patching Polymer(); this is not necessary under native
+  // HTMLImports.
+  var elementDeclarations = [];
+
+  var polymerStub = function(name, dictionary) {
+    elementDeclarations.push(arguments);
+  }
+  window.Polymer = polymerStub;
+
+  // deliver queued delcarations
+  scope.deliverDeclarations = function() {
+    scope.deliverDeclarations = null;
+    return elementDeclarations;
+  }
+
+  // Once DOMContent has loaded, any main document scripts that depend on
+  // Polymer() should have run. Calling Polymer() now is an error until
+  // polymer is imported.
+  window.addEventListener('DOMContentLoaded', function() {
+    if (window.Polymer === polymerStub) {
+      window.Polymer = function() {
+        console.error('You tried to use polymer without loading it first. To ' +
+          'load polymer, <link rel="import" href="' + 
+          'components/polymer/polymer.html">');
+      };
+    }
+  });
+
+  // exports
+  scope.createDOM = createDOM;
+
+})(window.Platform);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+// poor man's adapter for template.content on various platform scenarios
+window.templateContent = window.templateContent || function(inTemplate) {
+  return inTemplate.content;
+};
+(function(scope) {
+  
+  scope = scope || (window.Inspector = {});
+  
+  var inspector;
+
+  window.sinspect = function(inNode, inProxy) {
+    if (!inspector) {
+      inspector = window.open('', 'ShadowDOM Inspector', null, true);
+      inspector.document.write(inspectorHTML);
+      //inspector.document.close();
+      inspector.api = {
+        shadowize: shadowize
+      };
+    }
+    inspect(inNode || wrap(document.body), inProxy);
+  };
+
+  var inspectorHTML = [
+    '<!DOCTYPE html>',
+    '<html>',
+    '  <head>',
+    '    <title>ShadowDOM Inspector</title>',
+    '    <style>',
+    '      body {',
+    '      }',
+    '      pre {',
+    '        font: 9pt "Courier New", monospace;',
+    '        line-height: 1.5em;',
+    '      }',
+    '      tag {',
+    '        color: purple;',
+    '      }',
+    '      ul {',
+    '         margin: 0;',
+    '         padding: 0;',
+    '         list-style: none;',
+    '      }',
+    '      li {',
+    '         display: inline-block;',
+    '         background-color: #f1f1f1;',
+    '         padding: 4px 6px;',
+    '         border-radius: 4px;',
+    '         margin-right: 4px;',
+    '      }',
+    '    </style>',
+    '  </head>',
+    '  <body>',
+    '    <ul id="crumbs">',
+    '    </ul>',
+    '    <div id="tree"></div>',
+    '  </body>',
+    '</html>'
+  ].join('\n');
+  
+  var crumbs = [];
+
+  var displayCrumbs = function() {
+    // alias our document
+    var d = inspector.document;
+    // get crumbbar
+    var cb = d.querySelector('#crumbs');
+    // clear crumbs
+    cb.textContent = '';
+    // build new crumbs
+    for (var i=0, c; c=crumbs[i]; i++) {
+      var a = d.createElement('a');
+      a.href = '#';
+      a.textContent = c.localName;
+      a.idx = i;
+      a.onclick = function(event) {
+        var c;
+        while (crumbs.length > this.idx) {
+          c = crumbs.pop();
+        }
+        inspect(c.shadow || c, c);
+        event.preventDefault();
+      };
+      cb.appendChild(d.createElement('li')).appendChild(a);
+    }
+  };
+
+  var inspect = function(inNode, inProxy) {
+    // alias our document
+    var d = inspector.document;
+    // reset list of drillable nodes
+    drillable = [];
+    // memoize our crumb proxy
+    var proxy = inProxy || inNode;
+    crumbs.push(proxy);
+    // update crumbs
+    displayCrumbs();
+    // reflect local tree
+    d.body.querySelector('#tree').innerHTML =
+        '<pre>' + output(inNode, inNode.childNodes) + '</pre>';
+  };
+
+  var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
+
+  var blacklisted = {STYLE:1, SCRIPT:1, "#comment": 1, TEMPLATE: 1};
+  var blacklist = function(inNode) {
+    return blacklisted[inNode.nodeName];
+  };
+
+  var output = function(inNode, inChildNodes, inIndent) {
+    if (blacklist(inNode)) {
+      return '';
+    }
+    var indent = inIndent || '';
+    if (inNode.localName || inNode.nodeType == 11) {
+      var name = inNode.localName || 'shadow-root';
+      //inChildNodes = ShadowDOM.localNodes(inNode);
+      var info = indent + describe(inNode);
+      // if only textNodes
+      // TODO(sjmiles): make correct for ShadowDOM
+      /*if (!inNode.children.length && inNode.localName !== 'content' && inNode.localName !== 'shadow') {
+        info += catTextContent(inChildNodes);
+      } else*/ {
+        // TODO(sjmiles): native <shadow> has no reference to its projection
+        if (name == 'content' /*|| name == 'shadow'*/) {
+          inChildNodes = inNode.getDistributedNodes();
+        }
+        info += '<br/>';
+        var ind = indent + '&nbsp;&nbsp;';
+        forEach(inChildNodes, function(n) {
+          info += output(n, n.childNodes, ind);
+        });
+        info += indent;
+      }
+      if (!({br:1}[name])) {
+        info += '<tag>&lt;/' + name + '&gt;</tag>';
+        info += '<br/>';
+      }
+    } else {
+      var text = inNode.textContent.trim();
+      info = text ? indent + '"' + text + '"' + '<br/>' : '';
+    }
+    return info;
+  };
+
+  var catTextContent = function(inChildNodes) {
+    var info = '';
+    forEach(inChildNodes, function(n) {
+      info += n.textContent.trim();
+    });
+    return info;
+  };
+
+  var drillable = [];
+
+  var describe = function(inNode) {
+    var tag = '<tag>' + '&lt;';
+    var name = inNode.localName || 'shadow-root';
+    if (inNode.webkitShadowRoot || inNode.shadowRoot) {
+      tag += ' <button idx="' + drillable.length +
+        '" onclick="api.shadowize.call(this)">' + name + '</button>';
+      drillable.push(inNode);
+    } else {
+      tag += name || 'shadow-root';
+    }
+    if (inNode.attributes) {
+      forEach(inNode.attributes, function(a) {
+        tag += ' ' + a.name + (a.value ? '="' + a.value + '"' : '');
+      });
+    }
+    tag += '&gt;'+ '</tag>';
+    return tag;
+  };
+
+  // remote api
+
+  shadowize = function() {
+    var idx = Number(this.attributes.idx.value);
+    //alert(idx);
+    var node = drillable[idx];
+    if (node) {
+      inspect(node.webkitShadowRoot || node.shadowRoot, node)
+    } else {
+      console.log("bad shadowize node");
+      console.dir(this);
+    }
+  };
+  
+  // export
+  
+  scope.output = output;
+  
+})(window.Inspector);
+
+
+
+/*
+ * Copyright 2013 The Polymer Authors. 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(sorvell): It's desireable to provide a default stylesheet 
+  // that's convenient for styling unresolved elements, but
+  // it's cumbersome to have to include this manually in every page.
+  // It would make sense to put inside some HTMLImport but 
+  // the HTMLImports polyfill does not allow loading of stylesheets 
+  // that block rendering. Therefore this injection is tolerated here.
+
+  var style = document.createElement('style');
+  style.textContent = ''
+      + 'body {'
+      + 'transition: opacity ease-in 0.2s;' 
+      + ' } \n'
+      + 'body[unresolved] {'
+      + 'opacity: 0; display: block; overflow: hidden;' 
+      + ' } \n'
+      ;
+  var head = document.querySelector('head');
+  head.insertBefore(style, head.firstChild);
+
+})(Platform);
+
+(function(scope) {
+
+  function withDependencies(task, depends) {
+    depends = depends || [];
+    if (!depends.map) {
+      depends = [depends];
+    }
+    return task.apply(this, depends.map(marshal));
+  }
+
+  function module(name, dependsOrFactory, moduleFactory) {
+    var module;
+    switch (arguments.length) {
+      case 0:
+        return;
+      case 1:
+        module = null;
+        break;
+      case 2:
+        module = dependsOrFactory.apply(this);
+        break;
+      default:
+        module = withDependencies(moduleFactory, dependsOrFactory);
+        break;
+    }
+    modules[name] = module;
+  };
+
+  function marshal(name) {
+    return modules[name];
+  }
+
+  var modules = {};
+
+  function using(depends, task) {
+    HTMLImports.whenImportsReady(function() {
+      withDependencies(task, depends);
+    });
+  };
+
+  // exports
+
+  scope.marshal = marshal;
+  scope.module = module;
+  scope.using = using;
+
+})(window);
+/*
+ * Copyright 2013 The Polymer Authors. 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) {
+
+var iterations = 0;
+var callbacks = [];
+var twiddle = document.createTextNode('');
+
+function endOfMicrotask(callback) {
+  twiddle.textContent = iterations++;
+  callbacks.push(callback);
+}
+
+function atEndOfMicrotask() {
+  while (callbacks.length) {
+    callbacks.shift()();
+  }
+}
+
+new (window.MutationObserver || JsMutationObserver)(atEndOfMicrotask)
+  .observe(twiddle, {characterData: true})
+  ;
+
+// exports
+
+scope.endOfMicrotask = endOfMicrotask;
+
+})(Platform);
+
+
+/*
+ * Copyright 2013 The Polymer Authors. 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) {
+
+var urlResolver = {
+  resolveDom: function(root, url) {
+    url = url || root.ownerDocument.baseURI;
+    this.resolveAttributes(root, url);
+    this.resolveStyles(root, url);
+    // handle template.content
+    var templates = root.querySelectorAll('template');
+    if (templates) {
+      for (var i = 0, l = templates.length, t; (i < l) && (t = templates[i]); i++) {
+        if (t.content) {
+          this.resolveDom(t.content, url);
+        }
+      }
+    }
+  },
+  resolveStyles: function(root, url) {
+    var styles = root.querySelectorAll('style');
+    if (styles) {
+      for (var i = 0, l = styles.length, s; (i < l) && (s = styles[i]); i++) {
+        this.resolveStyle(s, url);
+      }
+    }
+  },
+  resolveStyle: function(style, url) {
+    url = url || style.ownerDocument.baseURI;
+    style.textContent = this.resolveCssText(style.textContent, url);
+  },
+  resolveCssText: function(cssText, baseUrl) {
+    cssText = replaceUrlsInCssText(cssText, baseUrl, CSS_URL_REGEXP);
+    return replaceUrlsInCssText(cssText, baseUrl, CSS_IMPORT_REGEXP);
+  },
+  resolveAttributes: function(root, url) {
+    if (root.hasAttributes && root.hasAttributes()) {
+      this.resolveElementAttributes(root, url);
+    }
+    // search for attributes that host urls
+    var nodes = root && root.querySelectorAll(URL_ATTRS_SELECTOR);
+    if (nodes) {
+      for (var i = 0, l = nodes.length, n; (i < l) && (n = nodes[i]); i++) {
+        this.resolveElementAttributes(n, url);
+      }
+    }
+  },
+  resolveElementAttributes: function(node, url) {
+    url = url || node.ownerDocument.baseURI;
+    URL_ATTRS.forEach(function(v) {
+      var attr = node.attributes[v];
+      if (attr && attr.value &&
+         (attr.value.search(URL_TEMPLATE_SEARCH) < 0)) {
+        var urlPath = resolveRelativeUrl(url, attr.value);
+        attr.value = urlPath;
+      }
+    });
+  }
+};
+
+var CSS_URL_REGEXP = /(url\()([^)]*)(\))/g;
+var CSS_IMPORT_REGEXP = /(@import[\s]+(?!url\())([^;]*)(;)/g;
+var URL_ATTRS = ['href', 'src', 'action'];
+var URL_ATTRS_SELECTOR = '[' + URL_ATTRS.join('],[') + ']';
+var URL_TEMPLATE_SEARCH = '{{.*}}';
+
+function replaceUrlsInCssText(cssText, baseUrl, regexp) {
+  return cssText.replace(regexp, function(m, pre, url, post) {
+    var urlPath = url.replace(/["']/g, '');
+    urlPath = resolveRelativeUrl(baseUrl, urlPath);
+    return pre + '\'' + urlPath + '\'' + post;
+  });
+}
+
+function resolveRelativeUrl(baseUrl, url) {
+  var u = new URL(url, baseUrl);
+  return makeDocumentRelPath(u.href);
+}
+
+function makeDocumentRelPath(url) {
+  var root = document.baseURI;
+  var u = new URL(url, root);
+  if (u.host === root.host && u.port === root.port &&
+      u.protocol === root.protocol) {
+    return makeRelPath(root.pathname, u.pathname);
+  } else {
+    return url;
+  }
+}
+
+// make a relative path from source to target
+function makeRelPath(source, target) {
+  var s = source.split('/');
+  var t = target.split('/');
+  while (s.length && s[0] === t[0]){
+    s.shift();
+    t.shift();
+  }
+  for (var i = 0, l = s.length - 1; i < l; i++) {
+    t.unshift('..');
+  }
+  return t.join('/');
+}
+
+// exports
+scope.urlResolver = urlResolver;
+
+})(Platform);
+
+/*
+ * Copyright 2012 The Polymer Authors. All rights reserved.
+ * Use of this source code is goverened by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+(function(global) {
+
+  var registrationsTable = new WeakMap();
+
+  // We use setImmediate or postMessage for our future callback.
+  var setImmediate = window.msSetImmediate;
+
+  // Use post message to emulate setImmediate.
+  if (!setImmediate) {
+    var setImmediateQueue = [];
+    var sentinel = String(Math.random());
+    window.addEventListener('message', function(e) {
+      if (e.data === sentinel) {
+        var queue = setImmediateQueue;
+        setImmediateQueue = [];
+        queue.forEach(function(func) {
+          func();
+        });
+      }
+    });
+    setImmediate = function(func) {
+      setImmediateQueue.push(func);
+      window.postMessage(sentinel, '*');
+    };
+  }
+
+  // This is used to ensure that we never schedule 2 callas to setImmediate
+  var isScheduled = false;
+
+  // Keep track of observers that needs to be notified next time.
+  var scheduledObservers = [];
+
+  /**
+   * Schedules |dispatchCallback| to be called in the future.
+   * @param {MutationObserver} observer
+   */
+  function scheduleCallback(observer) {
+    scheduledObservers.push(observer);
+    if (!isScheduled) {
+      isScheduled = true;
+      setImmediate(dispatchCallbacks);
+    }
+  }
+
+  function wrapIfNeeded(node) {
+    return window.ShadowDOMPolyfill &&
+        window.ShadowDOMPolyfill.wrapIfNeeded(node) ||
+        node;
+  }
+
+  function dispatchCallbacks() {
+    // http://dom.spec.whatwg.org/#mutation-observers
+
+    isScheduled = false; // Used to allow a new setImmediate call above.
+
+    var observers = scheduledObservers;
+    scheduledObservers = [];
+    // Sort observers based on their creation UID (incremental).
+    observers.sort(function(o1, o2) {
+      return o1.uid_ - o2.uid_;
+    });
+
+    var anyNonEmpty = false;
+    observers.forEach(function(observer) {
+
+      // 2.1, 2.2
+      var queue = observer.takeRecords();
+      // 2.3. Remove all transient registered observers whose observer is mo.
+      removeTransientObserversFor(observer);
+
+      // 2.4
+      if (queue.length) {
+        observer.callback_(queue, observer);
+        anyNonEmpty = true;
+      }
+    });
+
+    // 3.
+    if (anyNonEmpty)
+      dispatchCallbacks();
+  }
+
+  function removeTransientObserversFor(observer) {
+    observer.nodes_.forEach(function(node) {
+      var registrations = registrationsTable.get(node);
+      if (!registrations)
+        return;
+      registrations.forEach(function(registration) {
+        if (registration.observer === observer)
+          registration.removeTransientObservers();
+      });
+    });
+  }
+
+  /**
+   * This function is used for the "For each registered observer observer (with
+   * observer's options as options) in target's list of registered observers,
+   * run these substeps:" and the "For each ancestor ancestor of target, and for
+   * each registered observer observer (with options options) in ancestor's list
+   * of registered observers, run these substeps:" part of the algorithms. The
+   * |options.subtree| is checked to ensure that the callback is called
+   * correctly.
+   *
+   * @param {Node} target
+   * @param {function(MutationObserverInit):MutationRecord} callback
+   */
+  function forEachAncestorAndObserverEnqueueRecord(target, callback) {
+    for (var node = target; node; node = node.parentNode) {
+      var registrations = registrationsTable.get(node);
+
+      if (registrations) {
+        for (var j = 0; j < registrations.length; j++) {
+          var registration = registrations[j];
+          var options = registration.options;
+
+          // Only target ignores subtree.
+          if (node !== target && !options.subtree)
+            continue;
+
+          var record = callback(options);
+          if (record)
+            registration.enqueue(record);
+        }
+      }
+    }
+  }
+
+  var uidCounter = 0;
+
+  /**
+   * The class that maps to the DOM MutationObserver interface.
+   * @param {Function} callback.
+   * @constructor
+   */
+  function JsMutationObserver(callback) {
+    this.callback_ = callback;
+    this.nodes_ = [];
+    this.records_ = [];
+    this.uid_ = ++uidCounter;
+  }
+
+  JsMutationObserver.prototype = {
+    observe: function(target, options) {
+      target = wrapIfNeeded(target);
+
+      // 1.1
+      if (!options.childList && !options.attributes && !options.characterData ||
+
+          // 1.2
+          options.attributeOldValue && !options.attributes ||
+
+          // 1.3
+          options.attributeFilter && options.attributeFilter.length &&
+              !options.attributes ||
+
+          // 1.4
+          options.characterDataOldValue && !options.characterData) {
+
+        throw new SyntaxError();
+      }
+
+      var registrations = registrationsTable.get(target);
+      if (!registrations)
+        registrationsTable.set(target, registrations = []);
+
+      // 2
+      // If target's list of registered observers already includes a registered
+      // observer associated with the context object, replace that registered
+      // observer's options with options.
+      var registration;
+      for (var i = 0; i < registrations.length; i++) {
+        if (registrations[i].observer === this) {
+          registration = registrations[i];
+          registration.removeListeners();
+          registration.options = options;
+          break;
+        }
+      }
+
+      // 3.
+      // Otherwise, add a new registered observer to target's list of registered
+      // observers with the context object as the observer and options as the
+      // options, and add target to context object's list of nodes on which it
+      // is registered.
+      if (!registration) {
+        registration = new Registration(this, target, options);
+        registrations.push(registration);
+        this.nodes_.push(target);
+      }
+
+      registration.addListeners();
+    },
+
+    disconnect: function() {
+      this.nodes_.forEach(function(node) {
+        var registrations = registrationsTable.get(node);
+        for (var i = 0; i < registrations.length; i++) {
+          var registration = registrations[i];
+          if (registration.observer === this) {
+            registration.removeListeners();
+            registrations.splice(i, 1);
+            // Each node can only have one registered observer associated with
+            // this observer.
+            break;
+          }
+        }
+      }, this);
+      this.records_ = [];
+    },
+
+    takeRecords: function() {
+      var copyOfRecords = this.records_;
+      this.records_ = [];
+      return copyOfRecords;
+    }
+  };
+
+  /**
+   * @param {string} type
+   * @param {Node} target
+   * @constructor
+   */
+  function MutationRecord(type, target) {
+    this.type = type;
+    this.target = target;
+    this.addedNodes = [];
+    this.removedNodes = [];
+    this.previousSibling = null;
+    this.nextSibling = null;
+    this.attributeName = null;
+    this.attributeNamespace = null;
+    this.oldValue = null;
+  }
+
+  function copyMutationRecord(original) {
+    var record = new MutationRecord(original.type, original.target);
+    record.addedNodes = original.addedNodes.slice();
+    record.removedNodes = original.removedNodes.slice();
+    record.previousSibling = original.previousSibling;
+    record.nextSibling = original.nextSibling;
+    record.attributeName = original.attributeName;
+    record.attributeNamespace = original.attributeNamespace;
+    record.oldValue = original.oldValue;
+    return record;
+  };
+
+  // We keep track of the two (possibly one) records used in a single mutation.
+  var currentRecord, recordWithOldValue;
+
+  /**
+   * Creates a record without |oldValue| and caches it as |currentRecord| for
+   * later use.
+   * @param {string} oldValue
+   * @return {MutationRecord}
+   */
+  function getRecord(type, target) {
+    return currentRecord = new MutationRecord(type, target);
+  }
+
+  /**
+   * Gets or creates a record with |oldValue| based in the |currentRecord|
+   * @param {string} oldValue
+   * @return {MutationRecord}
+   */
+  function getRecordWithOldValue(oldValue) {
+    if (recordWithOldValue)
+      return recordWithOldValue;
+    recordWithOldValue = copyMutationRecord(currentRecord);
+    recordWithOldValue.oldValue = oldValue;
+    return recordWithOldValue;
+  }
+
+  function clearRecords() {
+    currentRecord = recordWithOldValue = undefined;
+  }
+
+  /**
+   * @param {MutationRecord} record
+   * @return {boolean} Whether the record represents a record from the current
+   * mutation event.
+   */
+  function recordRepresentsCurrentMutation(record) {
+    return record === recordWithOldValue || record === currentRecord;
+  }
+
+  /**
+   * Selects which record, if any, to replace the last record in the queue.
+   * This returns |null| if no record should be replaced.
+   *
+   * @param {MutationRecord} lastRecord
+   * @param {MutationRecord} newRecord
+   * @param {MutationRecord}
+   */
+  function selectRecord(lastRecord, newRecord) {
+    if (lastRecord === newRecord)
+      return lastRecord;
+
+    // Check if the the record we are adding represents the same record. If
+    // so, we keep the one with the oldValue in it.
+    if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord))
+      return recordWithOldValue;
+
+    return null;
+  }
+
+  /**
+   * Class used to represent a registered observer.
+   * @param {MutationObserver} observer
+   * @param {Node} target
+   * @param {MutationObserverInit} options
+   * @constructor
+   */
+  function Registration(observer, target, options) {
+    this.observer = observer;
+    this.target = target;
+    this.options = options;
+    this.transientObservedNodes = [];
+  }
+
+  Registration.prototype = {
+    enqueue: function(record) {
+      var records = this.observer.records_;
+      var length = records.length;
+
+      // There are cases where we replace the last record with the new record.
+      // For example if the record represents the same mutation we need to use
+      // the one with the oldValue. If we get same record (this can happen as we
+      // walk up the tree) we ignore the new record.
+      if (records.length > 0) {
+        var lastRecord = records[length - 1];
+        var recordToReplaceLast = selectRecord(lastRecord, record);
+        if (recordToReplaceLast) {
+          records[length - 1] = recordToReplaceLast;
+          return;
+        }
+      } else {
+        scheduleCallback(this.observer);
+      }
+
+      records[length] = record;
+    },
+
+    addListeners: function() {
+      this.addListeners_(this.target);
+    },
+
+    addListeners_: function(node) {
+      var options = this.options;
+      if (options.attributes)
+        node.addEventListener('DOMAttrModified', this, true);
+
+      if (options.characterData)
+        node.addEventListener('DOMCharacterDataModified', this, true);
+
+      if (options.childList)
+        node.addEventListener('DOMNodeInserted', this, true);
+
+      if (options.childList || options.subtree)
+        node.addEventListener('DOMNodeRemoved', this, true);
+    },
+
+    removeListeners: function() {
+      this.removeListeners_(this.target);
+    },
+
+    removeListeners_: function(node) {
+      var options = this.options;
+      if (options.attributes)
+        node.removeEventListener('DOMAttrModified', this, true);
+
+      if (options.characterData)
+        node.removeEventListener('DOMCharacterDataModified', this, true);
+
+      if (options.childList)
+        node.removeEventListener('DOMNodeInserted', this, true);
+
+      if (options.childList || options.subtree)
+        node.removeEventListener('DOMNodeRemoved', this, true);
+    },
+
+    /**
+     * Adds a transient observer on node. The transient observer gets removed
+     * next time we deliver the change records.
+     * @param {Node} node
+     */
+    addTransientObserver: function(node) {
+      // Don't add transient observers on the target itself. We already have all
+      // the required listeners set up on the target.
+      if (node === this.target)
+        return;
+
+      this.addListeners_(node);
+      this.transientObservedNodes.push(node);
+      var registrations = registrationsTable.get(node);
+      if (!registrations)
+        registrationsTable.set(node, registrations = []);
+
+      // We know that registrations does not contain this because we already
+      // checked if node === this.target.
+      registrations.push(this);
+    },
+
+    removeTransientObservers: function() {
+      var transientObservedNodes = this.transientObservedNodes;
+      this.transientObservedNodes = [];
+
+      transientObservedNodes.forEach(function(node) {
+        // Transient observers are never added to the target.
+        this.removeListeners_(node);
+
+        var registrations = registrationsTable.get(node);
+        for (var i = 0; i < registrations.length; i++) {
+          if (registrations[i] === this) {
+            registrations.splice(i, 1);
+            // Each node can only have one registered observer associated with
+            // this observer.
+            break;
+          }
+        }
+      }, this);
+    },
+
+    handleEvent: function(e) {
+      // Stop propagation since we are managing the propagation manually.
+      // This means that other mutation events on the page will not work
+      // correctly but that is by design.
+      e.stopImmediatePropagation();
+
+      switch (e.type) {
+        case 'DOMAttrModified':
+          // http://dom.spec.whatwg.org/#concept-mo-queue-attributes
+
+          var name = e.attrName;
+          var namespace = e.relatedNode.namespaceURI;
+          var target = e.target;
+
+          // 1.
+          var record = new getRecord('attributes', target);
+          record.attributeName = name;
+          record.attributeNamespace = namespace;
+
+          // 2.
+          var oldValue =
+              e.attrChange === MutationEvent.ADDITION ? null : e.prevValue;
+
+          forEachAncestorAndObserverEnqueueRecord(target, function(options) {
+            // 3.1, 4.2
+            if (!options.attributes)
+              return;
+
+            // 3.2, 4.3
+            if (options.attributeFilter && options.attributeFilter.length &&
+                options.attributeFilter.indexOf(name) === -1 &&
+                options.attributeFilter.indexOf(namespace) === -1) {
+              return;
+            }
+            // 3.3, 4.4
+            if (options.attributeOldValue)
+              return getRecordWithOldValue(oldValue);
+
+            // 3.4, 4.5
+            return record;
+          });
+
+          break;
+
+        case 'DOMCharacterDataModified':
+          // http://dom.spec.whatwg.org/#concept-mo-queue-characterdata
+          var target = e.target;
+
+          // 1.
+          var record = getRecord('characterData', target);
+
+          // 2.
+          var oldValue = e.prevValue;
+
+
+          forEachAncestorAndObserverEnqueueRecord(target, function(options) {
+            // 3.1, 4.2
+            if (!options.characterData)
+              return;
+
+            // 3.2, 4.3
+            if (options.characterDataOldValue)
+              return getRecordWithOldValue(oldValue);
+
+            // 3.3, 4.4
+            return record;
+          });
+
+          break;
+
+        case 'DOMNodeRemoved':
+          this.addTransientObserver(e.target);
+          // Fall through.
+        case 'DOMNodeInserted':
+          // http://dom.spec.whatwg.org/#concept-mo-queue-childlist
+          var target = e.relatedNode;
+          var changedNode = e.target;
+          var addedNodes, removedNodes;
+          if (e.type === 'DOMNodeInserted') {
+            addedNodes = [changedNode];
+            removedNodes = [];
+          } else {
+
+            addedNodes = [];
+            removedNodes = [changedNode];
+          }
+          var previousSibling = changedNode.previousSibling;
+          var nextSibling = changedNode.nextSibling;
+
+          // 1.
+          var record = getRecord('childList', target);
+          record.addedNodes = addedNodes;
+          record.removedNodes = removedNodes;
+          record.previousSibling = previousSibling;
+          record.nextSibling = nextSibling;
+
+          forEachAncestorAndObserverEnqueueRecord(target, function(options) {
+            // 2.1, 3.2
+            if (!options.childList)
+              return;
+
+            // 2.2, 3.3
+            return record;
+          });
+
+      }
+
+      clearRecords();
+    }
+  };
+
+  global.JsMutationObserver = JsMutationObserver;
+
+  if (!global.MutationObserver)
+    global.MutationObserver = JsMutationObserver;
+
+
+})(this);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+window.HTMLImports = window.HTMLImports || {flags:{}};
+/*
+ * Copyright 2013 The Polymer Authors. 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) {
+
+  // imports
+  var path = scope.path;
+  var xhr = scope.xhr;
+  var flags = scope.flags;
+
+  // TODO(sorvell): this loader supports a dynamic list of urls
+  // and an oncomplete callback that is called when the loader is done.
+  // The polyfill currently does *not* need this dynamism or the onComplete
+  // concept. Because of this, the loader could be simplified quite a bit.
+  var Loader = function(onLoad, onComplete) {
+    this.cache = {};
+    this.onload = onLoad;
+    this.oncomplete = onComplete;
+    this.inflight = 0;
+    this.pending = {};
+  };
+
+  Loader.prototype = {
+    addNodes: function(nodes) {
+      // number of transactions to complete
+      this.inflight += nodes.length;
+      // commence transactions
+      for (var i=0, l=nodes.length, n; (i<l) && (n=nodes[i]); i++) {
+        this.require(n);
+      }
+      // anything to do?
+      this.checkDone();
+    },
+    addNode: function(node) {
+      // number of transactions to complete
+      this.inflight++;
+      // commence transactions
+      this.require(node);
+      // anything to do?
+      this.checkDone();
+    },
+    require: function(elt) {
+      var url = elt.src || elt.href;
+      // ensure we have a standard url that can be used
+      // reliably for deduping.
+      // TODO(sjmiles): ad-hoc
+      elt.__nodeUrl = url;
+      // deduplication
+      if (!this.dedupe(url, elt)) {
+        // fetch this resource
+        this.fetch(url, elt);
+      }
+    },
+    dedupe: function(url, elt) {
+      if (this.pending[url]) {
+        // add to list of nodes waiting for inUrl
+        this.pending[url].push(elt);
+        // don't need fetch
+        return true;
+      }
+      var resource;
+      if (this.cache[url]) {
+        this.onload(url, elt, this.cache[url]);
+        // finished this transaction
+        this.tail();
+        // don't need fetch
+        return true;
+      }
+      // first node waiting for inUrl
+      this.pending[url] = [elt];
+      // need fetch (not a dupe)
+      return false;
+    },
+    fetch: function(url, elt) {
+      flags.load && console.log('fetch', url, elt);
+      var receiveXhr = function(err, resource) {
+        this.receive(url, elt, err, resource);
+      }.bind(this);
+      xhr.load(url, receiveXhr);
+      // TODO(sorvell): blocked on
+      // https://code.google.com/p/chromium/issues/detail?id=257221
+      // xhr'ing for a document makes scripts in imports runnable; otherwise
+      // they are not; however, it requires that we have doctype=html in
+      // the import which is unacceptable. This is only needed on Chrome
+      // to avoid the bug above.
+      /*
+      if (isDocumentLink(elt)) {
+        xhr.loadDocument(url, receiveXhr);
+      } else {
+        xhr.load(url, receiveXhr);
+      }
+      */
+    },
+    receive: function(url, elt, err, resource) {
+      this.cache[url] = resource;
+      var $p = this.pending[url];
+      for (var i=0, l=$p.length, p; (i<l) && (p=$p[i]); i++) {
+        //if (!err) {
+          this.onload(url, p, resource);
+        //}
+        this.tail();
+      }
+      this.pending[url] = null;
+    },
+    tail: function() {
+      --this.inflight;
+      this.checkDone();
+    },
+    checkDone: function() {
+      if (!this.inflight) {
+        this.oncomplete();
+      }
+    }
+  };
+
+  xhr = xhr || {
+    async: true,
+    ok: function(request) {
+      return (request.status >= 200 && request.status < 300)
+          || (request.status === 304)
+          || (request.status === 0);
+    },
+    load: function(url, next, nextContext) {
+      var request = new XMLHttpRequest();
+      if (scope.flags.debug || scope.flags.bust) {
+        url += '?' + Math.random();
+      }
+      request.open('GET', url, xhr.async);
+      request.addEventListener('readystatechange', function(e) {
+        if (request.readyState === 4) {
+          next.call(nextContext, !xhr.ok(request) && request,
+              request.response || request.responseText, url);
+        }
+      });
+      request.send();
+      return request;
+    },
+    loadDocument: function(url, next, nextContext) {
+      this.load(url, next, nextContext).responseType = 'document';
+    }
+  };
+
+  // exports
+  scope.xhr = xhr;
+  scope.Loader = Loader;
+
+})(window.HTMLImports);
+
+/*
+ * Copyright 2013 The Polymer Authors. 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) {
+
+var IMPORT_LINK_TYPE = 'import';
+var flags = scope.flags;
+var isIe = /Trident/.test(navigator.userAgent);
+// TODO(sorvell): SD polyfill intrusion
+var mainDoc = window.ShadowDOMPolyfill ? 
+    window.ShadowDOMPolyfill.wrapIfNeeded(document) : document;
+
+// importParser
+// highlander object to manage parsing of imports
+// parses import related elements
+// and ensures proper parse order
+// parse order is enforced by crawling the tree and monitoring which elements
+// have been parsed; async parsing is also supported.
+
+// highlander object for parsing a document tree
+var importParser = {
+  // parse selectors for main document elements
+  documentSelectors: 'link[rel=' + IMPORT_LINK_TYPE + ']',
+  // parse selectors for import document elements
+  importsSelectors: [
+    'link[rel=' + IMPORT_LINK_TYPE + ']',
+    'link[rel=stylesheet]',
+    'style',
+    'script:not([type])',
+    'script[type="text/javascript"]'
+  ].join(','),
+  map: {
+    link: 'parseLink',
+    script: 'parseScript',
+    style: 'parseStyle'
+  },
+  // try to parse the next import in the tree
+  parseNext: function() {
+    var next = this.nextToParse();
+    if (next) {
+      this.parse(next);
+    }
+  },
+  parse: function(elt) {
+    if (this.isParsed(elt)) {
+      flags.parse && console.log('[%s] is already parsed', elt.localName);
+      return;
+    }
+    var fn = this[this.map[elt.localName]];
+    if (fn) {
+      this.markParsing(elt);
+      fn.call(this, elt);
+    }
+  },
+  // only 1 element may be parsed at a time; parsing is async so, each
+  // parsing implementation must inform the system that parsing is complete
+  // via markParsingComplete.
+  markParsing: function(elt) {
+    flags.parse && console.log('parsing', elt);
+    this.parsingElement = elt;
+  },
+  markParsingComplete: function(elt) {
+    elt.__importParsed = true;
+    if (elt.__importElement) {
+      elt.__importElement.__importParsed = true;
+    }
+    this.parsingElement = null;
+    flags.parse && console.log('completed', elt);
+    this.parseNext();
+  },
+  parseImport: function(elt) {
+    elt.import.__importParsed = true;
+    // TODO(sorvell): consider if there's a better way to do this;
+    // expose an imports parsing hook; this is needed, for example, by the
+    // CustomElements polyfill.
+    if (HTMLImports.__importsParsingHook) {
+      HTMLImports.__importsParsingHook(elt);
+    }
+    // fire load event
+    if (elt.__resource) {
+      elt.dispatchEvent(new CustomEvent('load', {bubbles: false}));    
+    } else {
+      elt.dispatchEvent(new CustomEvent('error', {bubbles: false}));
+    }
+    // TODO(sorvell): workaround for Safari addEventListener not working
+    // for elements not in the main document.
+    if (elt.__pending) {
+      var fn;
+      while (elt.__pending.length) {
+        fn = elt.__pending.shift();
+        if (fn) {
+          fn({target: elt});
+        }
+      }
+    }
+    this.markParsingComplete(elt);
+  },
+  parseLink: function(linkElt) {
+    if (nodeIsImport(linkElt)) {
+      this.parseImport(linkElt);
+    } else {
+      // make href absolute
+      linkElt.href = linkElt.href;
+      this.parseGeneric(linkElt);
+    }
+  },
+  parseStyle: function(elt) {
+    // TODO(sorvell): style element load event can just not fire so clone styles
+    var src = elt;
+    elt = cloneStyle(elt);
+    elt.__importElement = src;
+    this.parseGeneric(elt);
+  },
+  parseGeneric: function(elt) {
+    this.trackElement(elt);
+    document.head.appendChild(elt);
+  },
+  // tracks when a loadable element has loaded
+  trackElement: function(elt) {
+    var self = this;
+    var done = function() {
+      self.markParsingComplete(elt);
+    };
+    elt.addEventListener('load', done);
+    elt.addEventListener('error', done);
+
+    // NOTE: IE does not fire "load" event for styles that have already loaded
+    // This is in violation of the spec, so we try our hardest to work around it
+    if (isIe && elt.localName === 'style') {
+      var fakeLoad = false;
+      // If there's not @import in the textContent, assume it has loaded
+      if (elt.textContent.indexOf('@import') == -1) {
+        fakeLoad = true;
+      // if we have a sheet, we have been parsed
+      } else if (elt.sheet) {
+        fakeLoad = true;
+        var csr = elt.sheet.cssRules;
+        var len = csr ? csr.length : 0;
+        // search the rules for @import's
+        for (var i = 0, r; (i < len) && (r = csr[i]); i++) {
+          if (r.type === CSSRule.IMPORT_RULE) {
+            // if every @import has resolved, fake the load
+            fakeLoad = fakeLoad && Boolean(r.styleSheet);
+          }
+        }
+      }
+      // dispatch a fake load event and continue parsing
+      if (fakeLoad) {
+        elt.dispatchEvent(new CustomEvent('load', {bubbles: false}));
+      }
+    }
+  },
+  parseScript: function(scriptElt) {
+    // acquire code to execute
+    var code = (scriptElt.__resource || scriptElt.textContent).trim();
+    if (code) {
+      // calculate source map hint
+      var moniker = scriptElt.__nodeUrl;
+      if (!moniker) {
+        moniker = scriptElt.ownerDocument.baseURI;
+        // there could be more than one script this url
+        var tag = '[' + Math.floor((Math.random()+1)*1000) + ']';
+        // TODO(sjmiles): Polymer hack, should be pluggable if we need to allow 
+        // this sort of thing
+        var matches = code.match(/Polymer\(['"]([^'"]*)/);
+        tag = matches && matches[1] || tag;
+        // tag the moniker
+        moniker += '/' + tag + '.js';
+      }
+      // source map hint
+      code += "\n//# sourceURL=" + moniker + "\n";
+      // evaluate the code
+      scope.currentScript = scriptElt;
+      eval.call(window, code);
+      scope.currentScript = null;
+    }
+    this.markParsingComplete(scriptElt);
+  },
+  // determine the next element in the tree which should be parsed
+  nextToParse: function() {
+    return !this.parsingElement && this.nextToParseInDoc(mainDoc);
+  },
+  nextToParseInDoc: function(doc, link) {
+    var nodes = doc.querySelectorAll(this.parseSelectorsForNode(doc));
+    for (var i=0, l=nodes.length, p=0, n; (i<l) && (n=nodes[i]); i++) {
+      if (!this.isParsed(n)) {
+        if (this.hasResource(n)) {
+          return nodeIsImport(n) ? this.nextToParseInDoc(n.import, n) : n;
+        } else {
+          return;
+        }
+      }
+    }
+    // all nodes have been parsed, ready to parse import, if any
+    return link;
+  },
+  // return the set of parse selectors relevant for this node.
+  parseSelectorsForNode: function(node) {
+    var doc = node.ownerDocument || node;
+    return doc === mainDoc ? this.documentSelectors : this.importsSelectors;
+  },
+  isParsed: function(node) {
+    return node.__importParsed;
+  },
+  hasResource: function(node) {
+    if (nodeIsImport(node) && !node.import) {
+      return false;
+    }
+    if (node.localName === 'script' && node.src && !node.__resource) {
+      return false;
+    }
+    return true;
+  }
+};
+
+function nodeIsImport(elt) {
+  return (elt.localName === 'link') && (elt.rel === IMPORT_LINK_TYPE);
+}
+
+// style/stylesheet handling
+
+// clone style with proper path resolution for main document
+// NOTE: styles are the only elements that require direct path fixup.
+function cloneStyle(style) {
+  var clone = style.ownerDocument.createElement('style');
+  clone.textContent = style.textContent;
+  path.resolveUrlsInStyle(clone);
+  return clone;
+}
+
+// path fixup: style elements in imports must be made relative to the main 
+// document. We fixup url's in url() and @import.
+var CSS_URL_REGEXP = /(url\()([^)]*)(\))/g;
+var CSS_IMPORT_REGEXP = /(@import[\s]+(?!url\())([^;]*)(;)/g;
+
+var path = {
+  resolveUrlsInStyle: function(style) {
+    var doc = style.ownerDocument;
+    var resolver = doc.createElement('a');
+    style.textContent = this.resolveUrlsInCssText(style.textContent, resolver);
+    return style;  
+  },
+  resolveUrlsInCssText: function(cssText, urlObj) {
+    var r = this.replaceUrls(cssText, urlObj, CSS_URL_REGEXP);
+    r = this.replaceUrls(r, urlObj, CSS_IMPORT_REGEXP);
+    return r;
+  },
+  replaceUrls: function(text, urlObj, regexp) {
+    return text.replace(regexp, function(m, pre, url, post) {
+      var urlPath = url.replace(/["']/g, '');
+      urlObj.href = urlPath;
+      urlPath = urlObj.href;
+      return pre + '\'' + urlPath + '\'' + post;
+    });    
+  }
+}
+
+// exports
+scope.parser = importParser;
+scope.path = path;
+scope.isIE = isIe;
+
+})(HTMLImports);
+
+/*
+ * Copyright 2013 The Polymer Authors. 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) {
+
+var hasNative = ('import' in document.createElement('link'));
+var useNative = hasNative;
+var flags = scope.flags;
+var IMPORT_LINK_TYPE = 'import';
+
+// TODO(sorvell): SD polyfill intrusion
+var mainDoc = window.ShadowDOMPolyfill ? 
+    ShadowDOMPolyfill.wrapIfNeeded(document) : document;
+
+if (!useNative) {
+
+  // imports
+  var xhr = scope.xhr;
+  var Loader = scope.Loader;
+  var parser = scope.parser;
+
+  // importer
+  // highlander object to manage loading of imports
+
+  // for any document, importer:
+  // - loads any linked import documents (with deduping)
+  // for any import document, importer also:
+  // - loads text of external script tags
+
+  var importer = {
+    documents: {},
+    // nodes to load in the mian document
+    documentPreloadSelectors: 'link[rel=' + IMPORT_LINK_TYPE + ']',
+    // nodes to load in imports
+    importsPreloadSelectors: [
+        'link[rel=' + IMPORT_LINK_TYPE + ']',
+        'script[src]:not([type])',
+        'script[src][type="text/javascript"]'
+    ].join(','),
+    loadNode: function(node) {
+      importLoader.addNode(node);
+    },
+    // load all loadable elements within the parent element
+    loadSubtree: function(parent) {
+      var nodes = this.marshalNodes(parent);
+      // add these nodes to loader's queue
+      importLoader.addNodes(nodes);
+    },
+    marshalNodes: function(parent) {
+      // all preloadable nodes in inDocument
+      return parent.querySelectorAll(this.loadSelectorsForNode(parent));
+    },
+    // find the proper set of load selectors for a given node
+    loadSelectorsForNode: function(node) {
+      var doc = node.ownerDocument || node;
+      return doc === mainDoc ? this.documentPreloadSelectors :
+          this.importsPreloadSelectors;
+    },
+    loaded: function(url, elt, resource) {
+      flags.load && console.log('loaded', url, elt);
+      // store generic resource
+      // TODO(sorvell): fails for nodes inside <template>.content
+      // see https://code.google.com/p/chromium/issues/detail?id=249381.
+      elt.__resource = resource;
+      if (isDocumentLink(elt)) {
+        var doc = this.documents[url];
+        // if we've never seen a document at this url
+        if (!doc) {
+          // generate an HTMLDocument from data
+          doc = makeDocument(resource, url);
+          doc.__importLink = elt;
+          // TODO(sorvell): we cannot use MO to detect parsed nodes because
+          // SD polyfill does not report these as mutations.
+          this.bootDocument(doc);
+          // cache document
+          this.documents[url] = doc;
+        }
+        // don't store import record until we're actually loaded
+        // store document resource
+        elt.import = doc;
+      }
+      parser.parseNext();
+    },
+    bootDocument: function(doc) {
+      this.loadSubtree(doc);
+      this.observe(doc);
+      parser.parseNext();
+    },
+    loadedAll: function() {
+      parser.parseNext();
+    }
+  };
+
+  // loader singleton
+  var importLoader = new Loader(importer.loaded.bind(importer), 
+      importer.loadedAll.bind(importer));
+
+  function isDocumentLink(elt) {
+    return isLinkRel(elt, IMPORT_LINK_TYPE);
+  }
+
+  function isLinkRel(elt, rel) {
+    return elt.localName === 'link' && elt.getAttribute('rel') === rel;
+  }
+
+  function isScript(elt) {
+    return elt.localName === 'script';
+  }
+
+  function makeDocument(resource, url) {
+    // create a new HTML document
+    var doc = resource;
+    if (!(doc instanceof Document)) {
+      doc = document.implementation.createHTMLDocument(IMPORT_LINK_TYPE);
+    }
+    // cache the new document's source url
+    doc._URL = url;
+    // establish a relative path via <base>
+    var base = doc.createElement('base');
+    base.setAttribute('href', url);
+    // add baseURI support to browsers (IE) that lack it.
+    if (!doc.baseURI) {
+      doc.baseURI = url;
+    }
+    doc.head.appendChild(base);
+    // install HTML last as it may trigger CustomElement upgrades
+    // TODO(sjmiles): problem wrt to template boostrapping below,
+    // template bootstrapping must (?) come before element upgrade
+    // but we cannot bootstrap templates until they are in a document
+    // which is too late
+    if (!(resource instanceof Document)) {
+      // install html
+      doc.body.innerHTML = resource;
+    }
+    // TODO(sorvell): ideally this code is not aware of Template polyfill,
+    // but for now the polyfill needs help to bootstrap these templates
+    if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) {
+      HTMLTemplateElement.bootstrap(doc);
+    }
+    return doc;
+  }
+} else {
+  // do nothing if using native imports
+  var importer = {};
+}
+
+// NOTE: We cannot polyfill document.currentScript because it's not possible
+// both to override and maintain the ability to capture the native value;
+// therefore we choose to expose _currentScript both when native imports
+// and the polyfill are in use.
+var currentScriptDescriptor = {
+  get: function() {
+    return HTMLImports.currentScript || document.currentScript;
+  },
+  configurable: true
+};
+
+Object.defineProperty(document, '_currentScript', currentScriptDescriptor);
+Object.defineProperty(mainDoc, '_currentScript', currentScriptDescriptor);
+
+// Polyfill document.baseURI for browsers without it.
+if (!document.baseURI) {
+  var baseURIDescriptor = {
+    get: function() {
+      return window.location.href;
+    },
+    configurable: true
+  };
+
+  Object.defineProperty(document, 'baseURI', baseURIDescriptor);
+  Object.defineProperty(mainDoc, 'baseURI', baseURIDescriptor);
+}
+
+// call a callback when all HTMLImports in the document at call (or at least
+//  document ready) time have loaded.
+// 1. ensure the document is in a ready state (has dom), then 
+// 2. watch for loading of imports and call callback when done
+function whenImportsReady(callback, doc) {
+  doc = doc || mainDoc;
+  // if document is loading, wait and try again
+  whenDocumentReady(function() {
+    watchImportsLoad(callback, doc);
+  }, doc);
+}
+
+// call the callback when the document is in a ready state (has dom)
+var requiredReadyState = HTMLImports.isIE ? 'complete' : 'interactive';
+var READY_EVENT = 'readystatechange';
+function isDocumentReady(doc) {
+  return (doc.readyState === 'complete' ||
+      doc.readyState === requiredReadyState);
+}
+
+// call <callback> when we ensure the document is in a ready state
+function whenDocumentReady(callback, doc) {
+  if (!isDocumentReady(doc)) {
+    var checkReady = function() {
+      if (doc.readyState === 'complete' || 
+          doc.readyState === requiredReadyState) {
+        doc.removeEventListener(READY_EVENT, checkReady);
+        whenDocumentReady(callback, doc);
+      }
+    }
+    doc.addEventListener(READY_EVENT, checkReady);
+  } else if (callback) {
+    callback();
+  }
+}
+
+// call <callback> when we ensure all imports have loaded
+function watchImportsLoad(callback, doc) {
+  var imports = doc.querySelectorAll('link[rel=import]');
+  var loaded = 0, l = imports.length;
+  function checkDone(d) { 
+    if (loaded == l) {
+      // go async to ensure parser isn't stuck on a script tag
+      requestAnimationFrame(callback);
+    }
+  }
+  function loadedImport(e) {
+    loaded++;
+    checkDone();
+  }
+  if (l) {
+    for (var i=0, imp; (i<l) && (imp=imports[i]); i++) {
+      if (isImportLoaded(imp)) {
+        loadedImport.call(imp);
+      } else {
+        imp.addEventListener('load', loadedImport);
+        imp.addEventListener('error', loadedImport);
+      }
+    }
+  } else {
+    checkDone();
+  }
+}
+
+function isImportLoaded(link) {
+  return useNative ? (link.import && (link.import.readyState !== 'loading')) :
+      link.__importParsed;
+}
+
+// exports
+scope.hasNative = hasNative;
+scope.useNative = useNative;
+scope.importer = importer;
+scope.whenImportsReady = whenImportsReady;
+scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;
+scope.isImportLoaded = isImportLoaded;
+scope.importLoader = importLoader;
+
+})(window.HTMLImports);
+
+ /*
+Copyright 2013 The Polymer Authors. 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){
+
+var IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;
+var importSelector = 'link[rel=' + IMPORT_LINK_TYPE + ']';
+var importer = scope.importer;
+
+// we track mutations for addedNodes, looking for imports
+function handler(mutations) {
+  for (var i=0, l=mutations.length, m; (i<l) && (m=mutations[i]); i++) {
+    if (m.type === 'childList' && m.addedNodes.length) {
+      addedNodes(m.addedNodes);
+    }
+  }
+}
+
+// find loadable elements and add them to the importer
+function addedNodes(nodes) {
+  for (var i=0, l=nodes.length, n; (i<l) && (n=nodes[i]); i++) {
+    if (shouldLoadNode(n)) {
+      importer.loadNode(n);
+    }
+    if (n.children && n.children.length) {
+      addedNodes(n.children);
+    }
+  }
+}
+
+function shouldLoadNode(node) {
+  return (node.nodeType === 1) && matches.call(node,
+      importer.loadSelectorsForNode(node));
+}
+
+// x-plat matches
+var matches = HTMLElement.prototype.matches || 
+    HTMLElement.prototype.matchesSelector || 
+    HTMLElement.prototype.webkitMatchesSelector ||
+    HTMLElement.prototype.mozMatchesSelector ||
+    HTMLElement.prototype.msMatchesSelector;
+
+var observer = new MutationObserver(handler);
+
+// observe the given root for loadable elements
+function observe(root) {
+  observer.observe(root, {childList: true, subtree: true});
+}
+
+// exports
+// TODO(sorvell): factor so can put on scope
+scope.observe = observe;
+importer.observe = observe;
+
+})(HTMLImports);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+(function(){
+
+// bootstrap
+
+// IE shim for CustomEvent
+if (typeof window.CustomEvent !== 'function') {
+  window.CustomEvent = function(inType, dictionary) {
+     var e = document.createEvent('HTMLEvents');
+     e.initEvent(inType,
+        dictionary.bubbles === false ? false : true,
+        dictionary.cancelable === false ? false : true,
+        dictionary.detail);
+     return e;
+  };
+}
+
+// TODO(sorvell): SD polyfill intrusion
+var doc = window.ShadowDOMPolyfill ? 
+    window.ShadowDOMPolyfill.wrapIfNeeded(document) : document;
+
+// Fire the 'HTMLImportsLoaded' event when imports in document at load time 
+// have loaded. This event is required to simulate the script blocking 
+// behavior of native imports. A main document script that needs to be sure
+// imports have loaded should wait for this event.
+HTMLImports.whenImportsReady(function() {
+  HTMLImports.ready = true;
+  HTMLImports.readyTime = new Date().getTime();
+  doc.dispatchEvent(
+    new CustomEvent('HTMLImportsLoaded', {bubbles: true})
+  );
+});
+
+
+// no need to bootstrap the polyfill when native imports is available.
+if (!HTMLImports.useNative) {
+  function bootstrap() {
+    HTMLImports.importer.bootDocument(doc);
+  }
+    
+  // TODO(sorvell): SD polyfill does *not* generate mutations for nodes added
+  // by the parser. For this reason, we must wait until the dom exists to 
+  // bootstrap.
+  if (document.readyState === 'complete' ||
+      (document.readyState === 'interactive' && !window.attachEvent)) {
+    bootstrap();
+  } else {
+    document.addEventListener('DOMContentLoaded', bootstrap);
+  }
+}
+
+})();
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+window.CustomElements = window.CustomElements || {flags:{}};
+ /*

+Copyright 2013 The Polymer Authors. 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){

+

+var logFlags = window.logFlags || {};

+var IMPORT_LINK_TYPE = window.HTMLImports ? HTMLImports.IMPORT_LINK_TYPE : 'none';

+

+// walk the subtree rooted at node, applying 'find(element, data)' function

+// to each element

+// if 'find' returns true for 'element', do not search element's subtree

+function findAll(node, find, data) {

+  var e = node.firstElementChild;

+  if (!e) {

+    e = node.firstChild;

+    while (e && e.nodeType !== Node.ELEMENT_NODE) {

+      e = e.nextSibling;

+    }

+  }

+  while (e) {

+    if (find(e, data) !== true) {

+      findAll(e, find, data);

+    }

+    e = e.nextElementSibling;

+  }

+  return null;

+}

+

+// walk all shadowRoots on a given node.

+function forRoots(node, cb) {

+  var root = node.shadowRoot;

+  while(root) {

+    forSubtree(root, cb);

+    root = root.olderShadowRoot;

+  }

+}

+

+// walk the subtree rooted at node, including descent into shadow-roots,

+// applying 'cb' to each element

+function forSubtree(node, cb) {

+  //logFlags.dom && node.childNodes && node.childNodes.length && console.group('subTree: ', node);

+  findAll(node, function(e) {

+    if (cb(e)) {

+      return true;

+    }

+    forRoots(e, cb);

+  });

+  forRoots(node, cb);

+  //logFlags.dom && node.childNodes && node.childNodes.length && console.groupEnd();

+}

+

+// manage lifecycle on added node

+function added(node) {

+  if (upgrade(node)) {

+    insertedNode(node);

+    return true;

+  }

+  inserted(node);

+}

+

+// manage lifecycle on added node's subtree only

+function addedSubtree(node) {

+  forSubtree(node, function(e) {

+    if (added(e)) {

+      return true;

+    }

+  });

+}

+

+// manage lifecycle on added node and it's subtree

+function addedNode(node) {

+  return added(node) || addedSubtree(node);

+}

+

+// upgrade custom elements at node, if applicable

+function upgrade(node) {

+  if (!node.__upgraded__ && node.nodeType === Node.ELEMENT_NODE) {

+    var type = node.getAttribute('is') || node.localName;

+    var definition = scope.registry[type];

+    if (definition) {

+      logFlags.dom && console.group('upgrade:', node.localName);

+      scope.upgrade(node);

+      logFlags.dom && console.groupEnd();

+      return true;

+    }

+  }

+}

+

+function insertedNode(node) {

+  inserted(node);

+  if (inDocument(node)) {

+    forSubtree(node, function(e) {

+      inserted(e);

+    });

+  }

+}

+

+// TODO(sorvell): on platforms without MutationObserver, mutations may not be

+// reliable and therefore attached/detached are not reliable.

+// To make these callbacks less likely to fail, we defer all inserts and removes

+// to give a chance for elements to be inserted into dom.

+// This ensures attachedCallback fires for elements that are created and

+// immediately added to dom.

+var hasPolyfillMutations = (!window.MutationObserver ||

+    (window.MutationObserver === window.JsMutationObserver));

+scope.hasPolyfillMutations = hasPolyfillMutations;

+

+var isPendingMutations = false;

+var pendingMutations = [];

+function deferMutation(fn) {

+  pendingMutations.push(fn);

+  if (!isPendingMutations) {

+    isPendingMutations = true;

+    var async = (window.Platform && window.Platform.endOfMicrotask) ||

+        setTimeout;

+    async(takeMutations);

+  }

+}

+

+function takeMutations() {

+  isPendingMutations = false;

+  var $p = pendingMutations;

+  for (var i=0, l=$p.length, p; (i<l) && (p=$p[i]); i++) {

+    p();

+  }

+  pendingMutations = [];

+}

+

+function inserted(element) {

+  if (hasPolyfillMutations) {

+    deferMutation(function() {

+      _inserted(element);

+    });

+  } else {

+    _inserted(element);

+  }

+}

+

+// TODO(sjmiles): if there are descents into trees that can never have inDocument(*) true, fix this

+function _inserted(element) {

+  // TODO(sjmiles): it's possible we were inserted and removed in the space

+  // of one microtask, in which case we won't be 'inDocument' here

+  // But there are other cases where we are testing for inserted without

+  // specific knowledge of mutations, and must test 'inDocument' to determine

+  // whether to call inserted

+  // If we can factor these cases into separate code paths we can have

+  // better diagnostics.

+  // TODO(sjmiles): when logging, do work on all custom elements so we can

+  // track behavior even when callbacks not defined

+  //console.log('inserted: ', element.localName);

+  if (element.attachedCallback || element.detachedCallback || (element.__upgraded__ && logFlags.dom)) {

+    logFlags.dom && console.group('inserted:', element.localName);

+    if (inDocument(element)) {

+      element.__inserted = (element.__inserted || 0) + 1;

+      // if we are in a 'removed' state, bluntly adjust to an 'inserted' state

+      if (element.__inserted < 1) {

+        element.__inserted = 1;

+      }

+      // if we are 'over inserted', squelch the callback

+      if (element.__inserted > 1) {

+        logFlags.dom && console.warn('inserted:', element.localName,

+          'insert/remove count:', element.__inserted)

+      } else if (element.attachedCallback) {

+        logFlags.dom && console.log('inserted:', element.localName);

+        element.attachedCallback();

+      }

+    }

+    logFlags.dom && console.groupEnd();

+  }

+}

+

+function removedNode(node) {

+  removed(node);

+  forSubtree(node, function(e) {

+    removed(e);

+  });

+}

+

+function removed(element) {

+  if (hasPolyfillMutations) {

+    deferMutation(function() {

+      _removed(element);

+    });

+  } else {

+    _removed(element);

+  }

+}

+

+function _removed(element) {

+  // TODO(sjmiles): temporary: do work on all custom elements so we can track

+  // behavior even when callbacks not defined

+  if (element.attachedCallback || element.detachedCallback || (element.__upgraded__ && logFlags.dom)) {

+    logFlags.dom && console.group('removed:', element.localName);

+    if (!inDocument(element)) {

+      element.__inserted = (element.__inserted || 0) - 1;

+      // if we are in a 'inserted' state, bluntly adjust to an 'removed' state

+      if (element.__inserted > 0) {

+        element.__inserted = 0;

+      }

+      // if we are 'over removed', squelch the callback

+      if (element.__inserted < 0) {

+        logFlags.dom && console.warn('removed:', element.localName,

+            'insert/remove count:', element.__inserted)

+      } else if (element.detachedCallback) {

+        element.detachedCallback();

+      }

+    }

+    logFlags.dom && console.groupEnd();

+  }

+}

+

+// SD polyfill intrustion due mainly to the fact that 'document'

+// is not entirely wrapped

+function wrapIfNeeded(node) {

+  return window.ShadowDOMPolyfill ? ShadowDOMPolyfill.wrapIfNeeded(node)

+      : node;

+}

+

+function inDocument(element) {

+  var p = element;

+  var doc = wrapIfNeeded(document);

+  while (p) {

+    if (p == doc) {

+      return true;

+    }

+    p = p.parentNode || p.host;

+  }

+}

+

+function watchShadow(node) {

+  if (node.shadowRoot && !node.shadowRoot.__watched) {

+    logFlags.dom && console.log('watching shadow-root for: ', node.localName);

+    // watch all unwatched roots...

+    var root = node.shadowRoot;

+    while (root) {

+      watchRoot(root);

+      root = root.olderShadowRoot;

+    }

+  }

+}

+

+function watchRoot(root) {

+  if (!root.__watched) {

+    observe(root);

+    root.__watched = true;

+  }

+}

+

+function handler(mutations) {

+  //

+  if (logFlags.dom) {

+    var mx = mutations[0];

+    if (mx && mx.type === 'childList' && mx.addedNodes) {

+        if (mx.addedNodes) {

+          var d = mx.addedNodes[0];

+          while (d && d !== document && !d.host) {

+            d = d.parentNode;

+          }

+          var u = d && (d.URL || d._URL || (d.host && d.host.localName)) || '';

+          u = u.split('/?').shift().split('/').pop();

+        }

+    }

+    console.group('mutations (%d) [%s]', mutations.length, u || '');

+  }

+  //

+  mutations.forEach(function(mx) {

+    //logFlags.dom && console.group('mutation');

+    if (mx.type === 'childList') {

+      forEach(mx.addedNodes, function(n) {

+        //logFlags.dom && console.log(n.localName);

+        if (!n.localName) {

+          return;

+        }

+        // nodes added may need lifecycle management

+        addedNode(n);

+      });

+      // removed nodes may need lifecycle management

+      forEach(mx.removedNodes, function(n) {

+        //logFlags.dom && console.log(n.localName);

+        if (!n.localName) {

+          return;

+        }

+        removedNode(n);

+      });

+    }

+    //logFlags.dom && console.groupEnd();

+  });

+  logFlags.dom && console.groupEnd();

+};

+

+var observer = new MutationObserver(handler);

+

+function takeRecords() {

+  // TODO(sjmiles): ask Raf why we have to call handler ourselves

+  handler(observer.takeRecords());

+  takeMutations();

+}

+

+var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);

+

+function observe(inRoot) {

+  observer.observe(inRoot, {childList: true, subtree: true});

+}

+

+function observeDocument(doc) {

+  observe(doc);

+}

+

+function upgradeDocument(doc) {

+  logFlags.dom && console.group('upgradeDocument: ', (doc.baseURI).split('/').pop());

+  addedNode(doc);

+  logFlags.dom && console.groupEnd();

+}

+

+function upgradeDocumentTree(doc) {

+  doc = wrapIfNeeded(doc);

+  upgradeDocument(doc);

+  //console.log('upgradeDocumentTree: ', (doc.baseURI).split('/').pop());

+  // upgrade contained imported documents

+  var imports = doc.querySelectorAll('link[rel=' + IMPORT_LINK_TYPE + ']');

+  for (var i=0, l=imports.length, n; (i<l) && (n=imports[i]); i++) {

+    if (n.import && n.import.__parsed) {

+      upgradeDocumentTree(n.import);

+    }

+  }

+}

+

+// exports

+scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;

+scope.watchShadow = watchShadow;

+scope.upgradeDocumentTree = upgradeDocumentTree;

+scope.upgradeAll = addedNode;

+scope.upgradeSubtree = addedSubtree;

+scope.insertedNode = insertedNode;

+

+scope.observeDocument = observeDocument;

+scope.upgradeDocument = upgradeDocument;

+

+scope.takeRecords = takeRecords;

+

+})(window.CustomElements);

+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+/**
+ * Implements `document.register`
+ * @module CustomElements
+*/
+
+/**
+ * Polyfilled extensions to the `document` object.
+ * @class Document
+*/
+
+(function(scope) {
+
+// imports
+
+if (!scope) {
+  scope = window.CustomElements = {flags:{}};
+}
+var flags = scope.flags;
+
+// native document.registerElement?
+
+var hasNative = Boolean(document.registerElement);
+// TODO(sorvell): See https://github.com/Polymer/polymer/issues/399
+// we'll address this by defaulting to CE polyfill in the presence of the SD
+// polyfill. This will avoid spamming excess attached/detached callbacks.
+// If there is a compelling need to run CE native with SD polyfill,
+// we'll need to fix this issue.
+var useNative = !flags.register && hasNative && !window.ShadowDOMPolyfill;
+
+if (useNative) {
+
+  // stub
+  var nop = function() {};
+
+  // exports
+  scope.registry = {};
+  scope.upgradeElement = nop;
+
+  scope.watchShadow = nop;
+  scope.upgrade = nop;
+  scope.upgradeAll = nop;
+  scope.upgradeSubtree = nop;
+  scope.observeDocument = nop;
+  scope.upgradeDocument = nop;
+  scope.upgradeDocumentTree = nop;
+  scope.takeRecords = nop;
+
+} else {
+
+  /**
+   * Registers a custom tag name with the document.
+   *
+   * When a registered element is created, a `readyCallback` method is called
+   * in the scope of the element. The `readyCallback` method can be specified on
+   * either `options.prototype` or `options.lifecycle` with the latter taking
+   * precedence.
+   *
+   * @method register
+   * @param {String} name The tag name to register. Must include a dash ('-'),
+   *    for example 'x-component'.
+   * @param {Object} options
+   *    @param {String} [options.extends]
+   *      (_off spec_) Tag name of an element to extend (or blank for a new
+   *      element). This parameter is not part of the specification, but instead
+   *      is a hint for the polyfill because the extendee is difficult to infer.
+   *      Remember that the input prototype must chain to the extended element's
+   *      prototype (or HTMLElement.prototype) regardless of the value of
+   *      `extends`.
+   *    @param {Object} options.prototype The prototype to use for the new
+   *      element. The prototype must inherit from HTMLElement.
+   *    @param {Object} [options.lifecycle]
+   *      Callbacks that fire at important phases in the life of the custom
+   *      element.
+   *
+   * @example
+   *      FancyButton = document.registerElement("fancy-button", {
+   *        extends: 'button',
+   *        prototype: Object.create(HTMLButtonElement.prototype, {
+   *          readyCallback: {
+   *            value: function() {
+   *              console.log("a fancy-button was created",
+   *            }
+   *          }
+   *        })
+   *      });
+   * @return {Function} Constructor for the newly registered type.
+   */
+  function register(name, options) {
+    //console.warn('document.registerElement("' + name + '", ', options, ')');
+    // construct a defintion out of options
+    // TODO(sjmiles): probably should clone options instead of mutating it
+    var definition = options || {};
+    if (!name) {
+      // TODO(sjmiles): replace with more appropriate error (EricB can probably
+      // offer guidance)
+      throw new Error('document.registerElement: first argument `name` must not be empty');
+    }
+    if (name.indexOf('-') < 0) {
+      // TODO(sjmiles): replace with more appropriate error (EricB can probably
+      // offer guidance)
+      throw new Error('document.registerElement: first argument (\'name\') must contain a dash (\'-\'). Argument provided was \'' + String(name) + '\'.');
+    }
+    // elements may only be registered once
+    if (getRegisteredDefinition(name)) {
+      throw new Error('DuplicateDefinitionError: a type with name \'' + String(name) + '\' is already registered');
+    }
+    // must have a prototype, default to an extension of HTMLElement
+    // TODO(sjmiles): probably should throw if no prototype, check spec
+    if (!definition.prototype) {
+      // TODO(sjmiles): replace with more appropriate error (EricB can probably
+      // offer guidance)
+      throw new Error('Options missing required prototype property');
+    }
+    // record name
+    definition.__name = name.toLowerCase();
+    // ensure a lifecycle object so we don't have to null test it
+    definition.lifecycle = definition.lifecycle || {};
+    // build a list of ancestral custom elements (for native base detection)
+    // TODO(sjmiles): we used to need to store this, but current code only
+    // uses it in 'resolveTagName': it should probably be inlined
+    definition.ancestry = ancestry(definition.extends);
+    // extensions of native specializations of HTMLElement require localName
+    // to remain native, and use secondary 'is' specifier for extension type
+    resolveTagName(definition);
+    // some platforms require modifications to the user-supplied prototype
+    // chain
+    resolvePrototypeChain(definition);
+    // overrides to implement attributeChanged callback
+    overrideAttributeApi(definition.prototype);
+    // 7.1.5: Register the DEFINITION with DOCUMENT
+    registerDefinition(definition.__name, definition);
+    // 7.1.7. Run custom element constructor generation algorithm with PROTOTYPE
+    // 7.1.8. Return the output of the previous step.
+    definition.ctor = generateConstructor(definition);
+    definition.ctor.prototype = definition.prototype;
+    // force our .constructor to be our actual constructor
+    definition.prototype.constructor = definition.ctor;
+    // if initial parsing is complete
+    if (scope.ready) {
+      // upgrade any pre-existing nodes of this type
+      scope.upgradeDocumentTree(document);
+    }
+    return definition.ctor;
+  }
+
+  function ancestry(extnds) {
+    var extendee = getRegisteredDefinition(extnds);
+    if (extendee) {
+      return ancestry(extendee.extends).concat([extendee]);
+    }
+    return [];
+  }
+
+  function resolveTagName(definition) {
+    // if we are explicitly extending something, that thing is our
+    // baseTag, unless it represents a custom component
+    var baseTag = definition.extends;
+    // if our ancestry includes custom components, we only have a
+    // baseTag if one of them does
+    for (var i=0, a; (a=definition.ancestry[i]); i++) {
+      baseTag = a.is && a.tag;
+    }
+    // our tag is our baseTag, if it exists, and otherwise just our name
+    definition.tag = baseTag || definition.__name;
+    if (baseTag) {
+      // if there is a base tag, use secondary 'is' specifier
+      definition.is = definition.__name;
+    }
+  }
+
+  function resolvePrototypeChain(definition) {
+    // if we don't support __proto__ we need to locate the native level
+    // prototype for precise mixing in
+    if (!Object.__proto__) {
+      // default prototype
+      var nativePrototype = HTMLElement.prototype;
+      // work out prototype when using type-extension
+      if (definition.is) {
+        var inst = document.createElement(definition.tag);
+        nativePrototype = Object.getPrototypeOf(inst);
+      }
+      // ensure __proto__ reference is installed at each point on the prototype
+      // chain.
+      // NOTE: On platforms without __proto__, a mixin strategy is used instead
+      // of prototype swizzling. In this case, this generated __proto__ provides
+      // limited support for prototype traversal.
+      var proto = definition.prototype, ancestor;
+      while (proto && (proto !== nativePrototype)) {
+        var ancestor = Object.getPrototypeOf(proto);
+        proto.__proto__ = ancestor;
+        proto = ancestor;
+      }
+    }
+    // cache this in case of mixin
+    definition.native = nativePrototype;
+  }
+
+  // SECTION 4
+
+  function instantiate(definition) {
+    // 4.a.1. Create a new object that implements PROTOTYPE
+    // 4.a.2. Let ELEMENT by this new object
+    //
+    // the custom element instantiation algorithm must also ensure that the
+    // output is a valid DOM element with the proper wrapper in place.
+    //
+    return upgrade(domCreateElement(definition.tag), definition);
+  }
+
+  function upgrade(element, definition) {
+    // some definitions specify an 'is' attribute
+    if (definition.is) {
+      element.setAttribute('is', definition.is);
+    }
+    // remove 'unresolved' attr, which is a standin for :unresolved.
+    element.removeAttribute('unresolved');
+    // make 'element' implement definition.prototype
+    implement(element, definition);
+    // flag as upgraded
+    element.__upgraded__ = true;
+    // lifecycle management
+    created(element);
+    // attachedCallback fires in tree order, call before recursing
+    scope.insertedNode(element);
+    // there should never be a shadow root on element at this point
+    scope.upgradeSubtree(element);
+    // OUTPUT
+    return element;
+  }
+
+  function implement(element, definition) {
+    // prototype swizzling is best
+    if (Object.__proto__) {
+      element.__proto__ = definition.prototype;
+    } else {
+      // where above we can re-acquire inPrototype via
+      // getPrototypeOf(Element), we cannot do so when
+      // we use mixin, so we install a magic reference
+      customMixin(element, definition.prototype, definition.native);
+      element.__proto__ = definition.prototype;
+    }
+  }
+
+  function customMixin(inTarget, inSrc, inNative) {
+    // TODO(sjmiles): 'used' allows us to only copy the 'youngest' version of
+    // any property. This set should be precalculated. We also need to
+    // consider this for supporting 'super'.
+    var used = {};
+    // start with inSrc
+    var p = inSrc;
+    // sometimes the default is HTMLUnknownElement.prototype instead of
+    // HTMLElement.prototype, so we add a test
+    // the idea is to avoid mixing in native prototypes, so adding
+    // the second test is WLOG
+    while (p !== inNative && p !== HTMLUnknownElement.prototype) {
+      var keys = Object.getOwnPropertyNames(p);
+      for (var i=0, k; k=keys[i]; i++) {
+        if (!used[k]) {
+          Object.defineProperty(inTarget, k,
+              Object.getOwnPropertyDescriptor(p, k));
+          used[k] = 1;
+        }
+      }
+      p = Object.getPrototypeOf(p);
+    }
+  }
+
+  function created(element) {
+    // invoke createdCallback
+    if (element.createdCallback) {
+      element.createdCallback();
+    }
+  }
+
+  // attribute watching
+
+  function overrideAttributeApi(prototype) {
+    // overrides to implement callbacks
+    // TODO(sjmiles): should support access via .attributes NamedNodeMap
+    // TODO(sjmiles): preserves user defined overrides, if any
+    if (prototype.setAttribute._polyfilled) {
+      return;
+    }
+    var setAttribute = prototype.setAttribute;
+    prototype.setAttribute = function(name, value) {
+      changeAttribute.call(this, name, value, setAttribute);
+    }
+    var removeAttribute = prototype.removeAttribute;
+    prototype.removeAttribute = function(name) {
+      changeAttribute.call(this, name, null, removeAttribute);
+    }
+    prototype.setAttribute._polyfilled = true;
+  }
+
+  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/
+  // index.html#dfn-attribute-changed-callback
+  function changeAttribute(name, value, operation) {
+    var oldValue = this.getAttribute(name);
+    operation.apply(this, arguments);
+    var newValue = this.getAttribute(name);
+    if (this.attributeChangedCallback
+        && (newValue !== oldValue)) {
+      this.attributeChangedCallback(name, oldValue, newValue);
+    }
+  }
+
+  // element registry (maps tag names to definitions)
+
+  var registry = {};
+
+  function getRegisteredDefinition(name) {
+    if (name) {
+      return registry[name.toLowerCase()];
+    }
+  }
+
+  function registerDefinition(name, definition) {
+    registry[name] = definition;
+  }
+
+  function generateConstructor(definition) {
+    return function() {
+      return instantiate(definition);
+    };
+  }
+
+  function createElement(tag, typeExtension) {
+    // TODO(sjmiles): ignore 'tag' when using 'typeExtension', we could
+    // error check it, or perhaps there should only ever be one argument
+    var definition = getRegisteredDefinition(typeExtension || tag);
+    if (definition) {
+      if (tag == definition.tag && typeExtension == definition.is) {
+        return new definition.ctor();
+      }
+      // Handle empty string for type extension.
+      if (!typeExtension && !definition.is) {
+        return new definition.ctor();
+      }
+    }
+
+    if (typeExtension) {
+      var element = createElement(tag);
+      element.setAttribute('is', typeExtension);
+      return element;
+    }
+    var element = domCreateElement(tag);
+    // Custom tags should be HTMLElements even if not upgraded.
+    if (tag.indexOf('-') >= 0) {
+      implement(element, HTMLElement);
+    }
+    return element;
+  }
+
+  function upgradeElement(element) {
+    if (!element.__upgraded__ && (element.nodeType === Node.ELEMENT_NODE)) {
+      var is = element.getAttribute('is');
+      var definition = getRegisteredDefinition(is || element.localName);
+      if (definition) {
+        if (is && definition.tag == element.localName) {
+          return upgrade(element, definition);
+        } else if (!is && !definition.extends) {
+          return upgrade(element, definition);
+        }
+      }
+    }
+  }
+
+  function cloneNode(deep) {
+    // call original clone
+    var n = domCloneNode.call(this, deep);
+    // upgrade the element and subtree
+    scope.upgradeAll(n);
+    // return the clone
+    return n;
+  }
+  // capture native createElement before we override it
+
+  var domCreateElement = document.createElement.bind(document);
+
+  // capture native cloneNode before we override it
+
+  var domCloneNode = Node.prototype.cloneNode;
+
+  // exports
+
+  document.registerElement = register;
+  document.createElement = createElement; // override
+  Node.prototype.cloneNode = cloneNode; // override
+
+  scope.registry = registry;
+
+  /**
+   * Upgrade an element to a custom element. Upgrading an element
+   * causes the custom prototype to be applied, an `is` attribute
+   * to be attached (as needed), and invocation of the `readyCallback`.
+   * `upgrade` does nothing if the element is already upgraded, or
+   * if it matches no registered custom tag name.
+   *
+   * @method ugprade
+   * @param {Element} element The element to upgrade.
+   * @return {Element} The upgraded element.
+   */
+  scope.upgrade = upgradeElement;
+}
+
+// bc
+document.register = document.registerElement;
+
+scope.hasNative = hasNative;
+scope.useNative = useNative;
+
+})(window.CustomElements);
+
+/*
+ * Copyright 2013 The Polymer Authors. 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) {
+
+// import
+
+var IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;
+
+// highlander object for parsing a document tree
+
+var parser = {
+  selectors: [
+    'link[rel=' + IMPORT_LINK_TYPE + ']'
+  ],
+  map: {
+    link: 'parseLink'
+  },
+  parse: function(inDocument) {
+    if (!inDocument.__parsed) {
+      // only parse once
+      inDocument.__parsed = true;
+      // all parsable elements in inDocument (depth-first pre-order traversal)
+      var elts = inDocument.querySelectorAll(parser.selectors);
+      // for each parsable node type, call the mapped parsing method
+      forEach(elts, function(e) {
+        parser[parser.map[e.localName]](e);
+      });
+      // upgrade all upgradeable static elements, anything dynamically
+      // created should be caught by observer
+      CustomElements.upgradeDocument(inDocument);
+      // observe document for dom changes
+      CustomElements.observeDocument(inDocument);
+    }
+  },
+  parseLink: function(linkElt) {
+    // imports
+    if (isDocumentLink(linkElt)) {
+      this.parseImport(linkElt);
+    }
+  },
+  parseImport: function(linkElt) {
+    if (linkElt.import) {
+      parser.parse(linkElt.import);
+    }
+  }
+};
+
+function isDocumentLink(inElt) {
+  return (inElt.localName === 'link'
+      && inElt.getAttribute('rel') === IMPORT_LINK_TYPE);
+}
+
+var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
+
+// exports
+
+scope.parser = parser;
+scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;
+
+})(window.CustomElements);
+/*
+ * Copyright 2013 The Polymer Authors. 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){
+
+// bootstrap parsing
+function bootstrap() {
+  // parse document
+  CustomElements.parser.parse(document);
+  // one more pass before register is 'live'
+  CustomElements.upgradeDocument(document);
+  // choose async
+  var async = window.Platform && Platform.endOfMicrotask ? 
+    Platform.endOfMicrotask :
+    setTimeout;
+  async(function() {
+    // set internal 'ready' flag, now document.registerElement will trigger 
+    // synchronous upgrades
+    CustomElements.ready = true;
+    // capture blunt profiling data
+    CustomElements.readyTime = Date.now();
+    if (window.HTMLImports) {
+      CustomElements.elapsed = CustomElements.readyTime - HTMLImports.readyTime;
+    }
+    // notify the system that we are bootstrapped
+    document.dispatchEvent(
+      new CustomEvent('WebComponentsReady', {bubbles: true})
+    );
+
+    // install upgrade hook if HTMLImports are available
+    if (window.HTMLImports) {
+      HTMLImports.__importsParsingHook = function(elt) {
+        CustomElements.parser.parse(elt.import);
+      }
+    }
+  });
+}
+
+// CustomEvent shim for IE
+if (typeof window.CustomEvent !== 'function') {
+  window.CustomEvent = function(inType) {
+    var e = document.createEvent('HTMLEvents');
+    e.initEvent(inType, true, true);
+    return e;
+  };
+}
+
+// When loading at readyState complete time (or via flag), boot custom elements
+// immediately.
+// If relevant, HTMLImports must already be loaded.
+if (document.readyState === 'complete' || scope.flags.eager) {
+  bootstrap();
+// When loading at readyState interactive time, bootstrap only if HTMLImports
+// are not pending. Also avoid IE as the semantics of this state are unreliable.
+} else if (document.readyState === 'interactive' && !window.attachEvent &&
+    (!window.HTMLImports || window.HTMLImports.ready)) {
+  bootstrap();
+// When loading at other readyStates, wait for the appropriate DOM event to 
+// bootstrap.
+} else {
+  var loadEvent = window.HTMLImports && !HTMLImports.ready ?
+      'HTMLImportsLoaded' : 'DOMContentLoaded';
+  window.addEventListener(loadEvent, bootstrap);
+}
+
+})(window.CustomElements);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+(function() {
+
+// inject style sheet
+var style = document.createElement('style');
+style.textContent = 'element {display: none !important;} /* injected by platform.js */';
+var head = document.querySelector('head');
+head.insertBefore(style, head.firstChild);
+
+if (window.ShadowDOMPolyfill) {
+
+  // ensure wrapped inputs for these functions
+  var fns = ['upgradeAll', 'upgradeSubtree', 'observeDocument',
+      'upgradeDocument'];
+
+  // cache originals
+  var original = {};
+  fns.forEach(function(fn) {
+    original[fn] = CustomElements[fn];
+  });
+
+  // override
+  fns.forEach(function(fn) {
+    CustomElements[fn] = function(inNode) {
+      return original[fn](wrap(inNode));
+    };
+  });
+
+}
+
+})();
+
+/*
+ * Copyright 2014 The Polymer Authors. 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) {
+
+var STYLE_SELECTOR = 'style';
+
+var urlResolver = scope.urlResolver;
+
+var loader = {
+  cacheStyles: function(styles, callback) {
+    var css = [];
+    for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) {
+      css.push(s.textContent);
+    }
+    cacheCssText(css.join('\n'), callback);
+  },
+  xhrStyles: function(styles, callback) {
+    var loaded=0, l = styles.length;
+    // called in the context of the style
+    function loadedStyle(style) {
+      //console.log(style.textContent);
+      loaded++;
+      if (loaded === l && callback) {
+        callback();
+      }
+    }
+    for (var i=0, s; (i<l) && (s=styles[i]); i++) {
+      xhrLoadStyle(s, loadedStyle);
+    }
+  }
+};
+
+// use the platform to preload styles
+var preloadElement = document.createElement('preloader');
+preloadElement.style.display = 'none';
+var preloadRoot = preloadElement.createShadowRoot();
+document.head.appendChild(preloadElement);
+
+function cacheCssText(cssText, callback) {
+  var style = createStyleElement(cssText);
+  if (callback) {
+    style.addEventListener('load', callback);
+    style.addEventListener('error', callback);
+  }
+  preloadRoot.appendChild(style);
+}
+
+function createStyleElement(cssText, scope) {
+  scope = scope || document;
+  scope = scope.createElement ? scope : scope.ownerDocument;
+  var style = scope.createElement('style');
+  style.textContent = cssText;
+  return style;
+}
+
+// TODO(sorvell): use a common loader shared with HTMLImports polyfill
+// currently, this just loads the first @import per style element 
+// and does not recurse into loaded elements; we'll address this with a 
+// generalized loader that's built out of the one in the HTMLImports polyfill.
+// polyfill the loading of a style element's @import via xhr
+function xhrLoadStyle(style, callback) {
+  HTMLImports.xhr.load(atImportUrlFromStyle(style), function (err, resource,
+      url) {
+    replaceAtImportWithCssText(this, url, resource);
+    this.textContent = urlResolver.resolveCssText(this.textContent, url);
+    callback && callback(this);
+  }, style);
+}
+
+var atImportRe = /@import\s[(]?['"]?([^\s'";)]*)/;
+
+// get the first @import rule from a style
+function atImportUrlFromStyle(style) {
+  var matches = style.textContent.match(atImportRe);
+  return matches && matches[1];
+}
+
+function replaceAtImportWithCssText(style, url, cssText) {
+  var re = new RegExp('@import[^;]*' + url + '[^;]*;', 'i');
+  style.textContent = style.textContent.replace(re, cssText);
+}
+
+// exports
+scope.loader = loader;
+
+})(window.Platform);
+
+/*
+ * Copyright 2013 The Polymer Authors. 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) {
+  scope = scope || {};
+  scope.external = scope.external || {};
+  var target = {
+    shadow: function(inEl) {
+      if (inEl) {
+        return inEl.shadowRoot || inEl.webkitShadowRoot;
+      }
+    },
+    canTarget: function(shadow) {
+      return shadow && Boolean(shadow.elementFromPoint);
+    },
+    targetingShadow: function(inEl) {
+      var s = this.shadow(inEl);
+      if (this.canTarget(s)) {
+        return s;
+      }
+    },
+    olderShadow: function(shadow) {
+      var os = shadow.olderShadowRoot;
+      if (!os) {
+        var se = shadow.querySelector('shadow');
+        if (se) {
+          os = se.olderShadowRoot;
+        }
+      }
+      return os;
+    },
+    allShadows: function(element) {
+      var shadows = [], s = this.shadow(element);
+      while(s) {
+        shadows.push(s);
+        s = this.olderShadow(s);
+      }
+      return shadows;
+    },
+    searchRoot: function(inRoot, x, y) {
+      if (inRoot) {
+        var t = inRoot.elementFromPoint(x, y);
+        var st, sr, os;
+        // is element a shadow host?
+        sr = this.targetingShadow(t);
+        while (sr) {
+          // find the the element inside the shadow root
+          st = sr.elementFromPoint(x, y);
+          if (!st) {
+            // check for older shadows
+            sr = this.olderShadow(sr);
+          } else {
+            // shadowed element may contain a shadow root
+            var ssr = this.targetingShadow(st);
+            return this.searchRoot(ssr, x, y) || st;
+          }
+        }
+        // light dom element is the target
+        return t;
+      }
+    },
+    owner: function(element) {
+      var s = element;
+      // walk up until you hit the shadow root or document
+      while (s.parentNode) {
+        s = s.parentNode;
+      }
+      // the owner element is expected to be a Document or ShadowRoot
+      if (s.nodeType != Node.DOCUMENT_NODE && s.nodeType != Node.DOCUMENT_FRAGMENT_NODE) {
+        s = document;
+      }
+      return s;
+    },
+    findTarget: function(inEvent) {
+      var x = inEvent.clientX, y = inEvent.clientY;
+      // if the listener is in the shadow root, it is much faster to start there
+      var s = this.owner(inEvent.target);
+      // if x, y is not in this root, fall back to document search
+      if (!s.elementFromPoint(x, y)) {
+        s = document;
+      }
+      return this.searchRoot(s, x, y);
+    }
+  };
+  scope.targetFinding = target;
+  scope.findTarget = target.findTarget.bind(target);
+
+  window.PointerEventsPolyfill = scope;
+})(window.PointerEventsPolyfill);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+(function() {
+  function shadowSelector(v) {
+    return 'body ^^ ' + selector(v);
+  }
+  function selector(v) {
+    return '[touch-action="' + v + '"]';
+  }
+  function rule(v) {
+    return '{ -ms-touch-action: ' + v + '; touch-action: ' + v + '; touch-action-delay: none; }';
+  }
+  var attrib2css = [
+    'none',
+    'auto',
+    'pan-x',
+    'pan-y',
+    {
+      rule: 'pan-x pan-y',
+      selectors: [
+        'pan-x pan-y',
+        'pan-y pan-x'
+      ]
+    }
+  ];
+  var styles = '';
+  attrib2css.forEach(function(r) {
+    if (String(r) === r) {
+      styles += selector(r) + rule(r) + '\n';
+      styles += shadowSelector(r) + rule(r) + '\n';
+    } else {
+      styles += r.selectors.map(selector) + rule(r.rule) + '\n';
+      styles += r.selectors.map(shadowSelector) + rule(r.rule) + '\n';
+    }
+  });
+  var el = document.createElement('style');
+  el.textContent = styles;
+  document.head.appendChild(el);
+})();
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+/**
+ * This is the constructor for new PointerEvents.
+ *
+ * New Pointer Events must be given a type, and an optional dictionary of
+ * initialization properties.
+ *
+ * Due to certain platform requirements, events returned from the constructor
+ * identify as MouseEvents.
+ *
+ * @constructor
+ * @param {String} inType The type of the event to create.
+ * @param {Object} [inDict] An optional dictionary of initial event properties.
+ * @return {Event} A new PointerEvent of type `inType` and initialized with properties from `inDict`.
+ */
+(function(scope) {
+  // test for DOM Level 4 Events
+  var NEW_MOUSE_EVENT = false;
+  var HAS_BUTTONS = false;
+  try {
+    var ev = new MouseEvent('click', {buttons: 1});
+    NEW_MOUSE_EVENT = true;
+    HAS_BUTTONS = ev.buttons === 1;
+  } catch(e) {
+  }
+
+  var MOUSE_PROPS = [
+    'bubbles',
+    'cancelable',
+    'view',
+    'detail',
+    'screenX',
+    'screenY',
+    'clientX',
+    'clientY',
+    'ctrlKey',
+    'altKey',
+    'shiftKey',
+    'metaKey',
+    'button',
+    'relatedTarget',
+  ];
+
+  var MOUSE_DEFAULTS = [
+    false,
+    false,
+    null,
+    null,
+    0,
+    0,
+    0,
+    0,
+    false,
+    false,
+    false,
+    false,
+    0,
+    null
+  ];
+
+  function PointerEvent(inType, inDict) {
+    inDict = inDict || {};
+    // According to the w3c spec,
+    // http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-button
+    // MouseEvent.button == 0 can mean either no mouse button depressed, or the
+    // left mouse button depressed.
+    //
+    // As of now, the only way to distinguish between the two states of
+    // MouseEvent.button is by using the deprecated MouseEvent.which property, as
+    // this maps mouse buttons to positive integers > 0, and uses 0 to mean that
+    // no mouse button is held.
+    //
+    // MouseEvent.which is derived from MouseEvent.button at MouseEvent creation,
+    // but initMouseEvent does not expose an argument with which to set
+    // MouseEvent.which. Calling initMouseEvent with a buttonArg of 0 will set
+    // MouseEvent.button == 0 and MouseEvent.which == 1, breaking the expectations
+    // of app developers.
+    //
+    // The only way to propagate the correct state of MouseEvent.which and
+    // MouseEvent.button to a new MouseEvent.button == 0 and MouseEvent.which == 0
+    // is to call initMouseEvent with a buttonArg value of -1.
+    //
+    // This is fixed with DOM Level 4's use of buttons
+    var buttons;
+    if (inDict.buttons || HAS_BUTTONS) {
+      buttons = inDict.buttons;
+    } else {
+      switch (inDict.which) {
+        case 1: buttons = 1; break;
+        case 2: buttons = 4; break;
+        case 3: buttons = 2; break;
+        default: buttons = 0;
+      }
+    }
+
+    var e;
+    if (NEW_MOUSE_EVENT) {
+      e = new MouseEvent(inType, inDict);
+    } else {
+      e = document.createEvent('MouseEvent');
+
+      // import values from the given dictionary
+      var props = {}, p;
+      for(var i = 0; i < MOUSE_PROPS.length; i++) {
+        p = MOUSE_PROPS[i];
+        props[p] = inDict[p] || MOUSE_DEFAULTS[i];
+      }
+
+      // define the properties inherited from MouseEvent
+      e.initMouseEvent(
+        inType, props.bubbles, props.cancelable, props.view, props.detail,
+        props.screenX, props.screenY, props.clientX, props.clientY, props.ctrlKey,
+        props.altKey, props.shiftKey, props.metaKey, props.button, props.relatedTarget
+      );
+    }
+
+    // make the event pass instanceof checks
+    e.__proto__ = PointerEvent.prototype;
+
+    // define the buttons property according to DOM Level 3 spec
+    if (!HAS_BUTTONS) {
+      // IE 10 has buttons on MouseEvent.prototype as a getter w/o any setting
+      // mechanism
+      Object.defineProperty(e, 'buttons', {get: function(){ return buttons; }, enumerable: true});
+    }
+
+    // Spec requires that pointers without pressure specified use 0.5 for down
+    // state and 0 for up state.
+    var pressure = 0;
+    if (inDict.pressure) {
+      pressure = inDict.pressure;
+    } else {
+      pressure = buttons ? 0.5 : 0;
+    }
+
+    // define the properties of the PointerEvent interface
+    Object.defineProperties(e, {
+      pointerId: { value: inDict.pointerId || 0, enumerable: true },
+      width: { value: inDict.width || 0, enumerable: true },
+      height: { value: inDict.height || 0, enumerable: true },
+      pressure: { value: pressure, enumerable: true },
+      tiltX: { value: inDict.tiltX || 0, enumerable: true },
+      tiltY: { value: inDict.tiltY || 0, enumerable: true },
+      pointerType: { value: inDict.pointerType || '', enumerable: true },
+      hwTimestamp: { value: inDict.hwTimestamp || 0, enumerable: true },
+      isPrimary: { value: inDict.isPrimary || false, enumerable: true }
+    });
+    return e;
+  }
+
+  // PointerEvent extends MouseEvent
+  PointerEvent.prototype = Object.create(MouseEvent.prototype);
+
+  // attach to window
+  if (!scope.PointerEvent) {
+    scope.PointerEvent = PointerEvent;
+  }
+})(window);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+/**
+ * This module implements an map of pointer states
+ */
+(function(scope) {
+  var USE_MAP = window.Map && window.Map.prototype.forEach;
+  var POINTERS_FN = function(){ return this.size; };
+  function PointerMap() {
+    if (USE_MAP) {
+      var m = new Map();
+      m.pointers = POINTERS_FN;
+      return m;
+    } else {
+      this.keys = [];
+      this.values = [];
+    }
+  }
+
+  PointerMap.prototype = {
+    set: function(inId, inEvent) {
+      var i = this.keys.indexOf(inId);
+      if (i > -1) {
+        this.values[i] = inEvent;
+      } else {
+        this.keys.push(inId);
+        this.values.push(inEvent);
+      }
+    },
+    has: function(inId) {
+      return this.keys.indexOf(inId) > -1;
+    },
+    'delete': function(inId) {
+      var i = this.keys.indexOf(inId);
+      if (i > -1) {
+        this.keys.splice(i, 1);
+        this.values.splice(i, 1);
+      }
+    },
+    get: function(inId) {
+      var i = this.keys.indexOf(inId);
+      return this.values[i];
+    },
+    clear: function() {
+      this.keys.length = 0;
+      this.values.length = 0;
+    },
+    // return value, key, map
+    forEach: function(callback, thisArg) {
+      this.values.forEach(function(v, i) {
+        callback.call(thisArg, v, this.keys[i], this);
+      }, this);
+    },
+    pointers: function() {
+      return this.keys.length;
+    }
+  };
+
+  scope.PointerMap = PointerMap;
+})(window.PointerEventsPolyfill);
+
+/*
+ * Copyright 2013 The Polymer Authors. 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) {
+  var CLONE_PROPS = [
+    // MouseEvent
+    'bubbles',
+    'cancelable',
+    'view',
+    'detail',
+    'screenX',
+    'screenY',
+    'clientX',
+    'clientY',
+    'ctrlKey',
+    'altKey',
+    'shiftKey',
+    'metaKey',
+    'button',
+    'relatedTarget',
+    // DOM Level 3
+    'buttons',
+    // PointerEvent
+    'pointerId',
+    'width',
+    'height',
+    'pressure',
+    'tiltX',
+    'tiltY',
+    'pointerType',
+    'hwTimestamp',
+    'isPrimary',
+    // event instance
+    'type',
+    'target',
+    'currentTarget',
+    'which'
+  ];
+
+  var CLONE_DEFAULTS = [
+    // MouseEvent
+    false,
+    false,
+    null,
+    null,
+    0,
+    0,
+    0,
+    0,
+    false,
+    false,
+    false,
+    false,
+    0,
+    null,
+    // DOM Level 3
+    0,
+    // PointerEvent
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    '',
+    0,
+    false,
+    // event instance
+    '',
+    null,
+    null,
+    0
+  ];
+
+  var HAS_SVG_INSTANCE = (typeof SVGElementInstance !== 'undefined');
+
+  /**
+   * This module is for normalizing events. Mouse and Touch events will be
+   * collected here, and fire PointerEvents that have the same semantics, no
+   * matter the source.
+   * Events fired:
+   *   - pointerdown: a pointing is added
+   *   - pointerup: a pointer is removed
+   *   - pointermove: a pointer is moved
+   *   - pointerover: a pointer crosses into an element
+   *   - pointerout: a pointer leaves an element
+   *   - pointercancel: a pointer will no longer generate events
+   */
+  var dispatcher = {
+    targets: new WeakMap(),
+    handledEvents: new WeakMap(),
+    pointermap: new scope.PointerMap(),
+    eventMap: {},
+    // Scope objects for native events.
+    // This exists for ease of testing.
+    eventSources: {},
+    eventSourceList: [],
+    /**
+     * Add a new event source that will generate pointer events.
+     *
+     * `inSource` must contain an array of event names named `events`, and
+     * functions with the names specified in the `events` array.
+     * @param {string} name A name for the event source
+     * @param {Object} source A new source of platform events.
+     */
+    registerSource: function(name, source) {
+      var s = source;
+      var newEvents = s.events;
+      if (newEvents) {
+        newEvents.forEach(function(e) {
+          if (s[e]) {
+            this.eventMap[e] = s[e].bind(s);
+          }
+        }, this);
+        this.eventSources[name] = s;
+        this.eventSourceList.push(s);
+      }
+    },
+    register: function(element) {
+      var l = this.eventSourceList.length;
+      for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) {
+        // call eventsource register
+        es.register.call(es, element);
+      }
+    },
+    unregister: function(element) {
+      var l = this.eventSourceList.length;
+      for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) {
+        // call eventsource register
+        es.unregister.call(es, element);
+      }
+    },
+    contains: scope.external.contains || function(container, contained) {
+      return container.contains(contained);
+    },
+    // EVENTS
+    down: function(inEvent) {
+      this.fireEvent('pointerdown', inEvent);
+    },
+    move: function(inEvent) {
+      this.fireEvent('pointermove', inEvent);
+    },
+    up: function(inEvent) {
+      this.fireEvent('pointerup', inEvent);
+    },
+    enter: function(inEvent) {
+      inEvent.bubbles = false;
+      this.fireEvent('pointerenter', inEvent);
+    },
+    leave: function(inEvent) {
+      inEvent.bubbles = false;
+      this.fireEvent('pointerleave', inEvent);
+    },
+    over: function(inEvent) {
+      inEvent.bubbles = true;
+      this.fireEvent('pointerover', inEvent);
+    },
+    out: function(inEvent) {
+      inEvent.bubbles = true;
+      this.fireEvent('pointerout', inEvent);
+    },
+    cancel: function(inEvent) {
+      this.fireEvent('pointercancel', inEvent);
+    },
+    leaveOut: function(event) {
+      this.out(event);
+      if (!this.contains(event.target, event.relatedTarget)) {
+        this.leave(event);
+      }
+    },
+    enterOver: function(event) {
+      this.over(event);
+      if (!this.contains(event.target, event.relatedTarget)) {
+        this.enter(event);
+      }
+    },
+    // LISTENER LOGIC
+    eventHandler: function(inEvent) {
+      // This is used to prevent multiple dispatch of pointerevents from
+      // platform events. This can happen when two elements in different scopes
+      // are set up to create pointer events, which is relevant to Shadow DOM.
+      if (this.handledEvents.get(inEvent)) {
+        return;
+      }
+      var type = inEvent.type;
+      var fn = this.eventMap && this.eventMap[type];
+      if (fn) {
+        fn(inEvent);
+      }
+      this.handledEvents.set(inEvent, true);
+    },
+    // set up event listeners
+    listen: function(target, events) {
+      events.forEach(function(e) {
+        this.addEvent(target, e);
+      }, this);
+    },
+    // remove event listeners
+    unlisten: function(target, events) {
+      events.forEach(function(e) {
+        this.removeEvent(target, e);
+      }, this);
+    },
+    addEvent: scope.external.addEvent || function(target, eventName) {
+      target.addEventListener(eventName, this.boundHandler);
+    },
+    removeEvent: scope.external.removeEvent || function(target, eventName) {
+      target.removeEventListener(eventName, this.boundHandler);
+    },
+    // EVENT CREATION AND TRACKING
+    /**
+     * Creates a new Event of type `inType`, based on the information in
+     * `inEvent`.
+     *
+     * @param {string} inType A string representing the type of event to create
+     * @param {Event} inEvent A platform event with a target
+     * @return {Event} A PointerEvent of type `inType`
+     */
+    makeEvent: function(inType, inEvent) {
+      // relatedTarget must be null if pointer is captured
+      if (this.captureInfo) {
+        inEvent.relatedTarget = null;
+      }
+      var e = new PointerEvent(inType, inEvent);
+      if (inEvent.preventDefault) {
+        e.preventDefault = inEvent.preventDefault;
+      }
+      this.targets.set(e, this.targets.get(inEvent) || inEvent.target);
+      return e;
+    },
+    // make and dispatch an event in one call
+    fireEvent: function(inType, inEvent) {
+      var e = this.makeEvent(inType, inEvent);
+      return this.dispatchEvent(e);
+    },
+    /**
+     * Returns a snapshot of inEvent, with writable properties.
+     *
+     * @param {Event} inEvent An event that contains properties to copy.
+     * @return {Object} An object containing shallow copies of `inEvent`'s
+     *    properties.
+     */
+    cloneEvent: function(inEvent) {
+      var eventCopy = {}, p;
+      for (var i = 0; i < CLONE_PROPS.length; i++) {
+        p = CLONE_PROPS[i];
+        eventCopy[p] = inEvent[p] || CLONE_DEFAULTS[i];
+        // Work around SVGInstanceElement shadow tree
+        // Return the <use> element that is represented by the instance for Safari, Chrome, IE.
+        // This is the behavior implemented by Firefox.
+        if (HAS_SVG_INSTANCE && (p === 'target' || p === 'relatedTarget')) {
+          if (eventCopy[p] instanceof SVGElementInstance) {
+            eventCopy[p] = eventCopy[p].correspondingUseElement;
+          }
+        }
+      }
+      // keep the semantics of preventDefault
+      if (inEvent.preventDefault) {
+        eventCopy.preventDefault = function() {
+          inEvent.preventDefault();
+        };
+      }
+      return eventCopy;
+    },
+    getTarget: function(inEvent) {
+      // if pointer capture is set, route all events for the specified pointerId
+      // to the capture target
+      if (this.captureInfo) {
+        if (this.captureInfo.id === inEvent.pointerId) {
+          return this.captureInfo.target;
+        }
+      }
+      return this.targets.get(inEvent);
+    },
+    setCapture: function(inPointerId, inTarget) {
+      if (this.captureInfo) {
+        this.releaseCapture(this.captureInfo.id);
+      }
+      this.captureInfo = {id: inPointerId, target: inTarget};
+      var e = new PointerEvent('gotpointercapture', { bubbles: true });
+      this.implicitRelease = this.releaseCapture.bind(this, inPointerId);
+      document.addEventListener('pointerup', this.implicitRelease);
+      document.addEventListener('pointercancel', this.implicitRelease);
+      this.targets.set(e, inTarget);
+      this.asyncDispatchEvent(e);
+    },
+    releaseCapture: function(inPointerId) {
+      if (this.captureInfo && this.captureInfo.id === inPointerId) {
+        var e = new PointerEvent('lostpointercapture', { bubbles: true });
+        var t = this.captureInfo.target;
+        this.captureInfo = null;
+        document.removeEventListener('pointerup', this.implicitRelease);
+        document.removeEventListener('pointercancel', this.implicitRelease);
+        this.targets.set(e, t);
+        this.asyncDispatchEvent(e);
+      }
+    },
+    /**
+     * Dispatches the event to its target.
+     *
+     * @param {Event} inEvent The event to be dispatched.
+     * @return {Boolean} True if an event handler returns true, false otherwise.
+     */
+    dispatchEvent: scope.external.dispatchEvent || function(inEvent) {
+      var t = this.getTarget(inEvent);
+      if (t) {
+        return t.dispatchEvent(inEvent);
+      }
+    },
+    asyncDispatchEvent: function(inEvent) {
+      setTimeout(this.dispatchEvent.bind(this, inEvent), 0);
+    }
+  };
+  dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher);
+  scope.dispatcher = dispatcher;
+  scope.register = dispatcher.register.bind(dispatcher);
+  scope.unregister = dispatcher.unregister.bind(dispatcher);
+})(window.PointerEventsPolyfill);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+/**
+ * This module uses Mutation Observers to dynamically adjust which nodes will
+ * generate Pointer Events.
+ *
+ * All nodes that wish to generate Pointer Events must have the attribute
+ * `touch-action` set to `none`.
+ */
+(function(scope) {
+  var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
+  var map = Array.prototype.map.call.bind(Array.prototype.map);
+  var toArray = Array.prototype.slice.call.bind(Array.prototype.slice);
+  var filter = Array.prototype.filter.call.bind(Array.prototype.filter);
+  var MO = window.MutationObserver || window.WebKitMutationObserver;
+  var SELECTOR = '[touch-action]';
+  var OBSERVER_INIT = {
+    subtree: true,
+    childList: true,
+    attributes: true,
+    attributeOldValue: true,
+    attributeFilter: ['touch-action']
+  };
+
+  function Installer(add, remove, changed, binder) {
+    this.addCallback = add.bind(binder);
+    this.removeCallback = remove.bind(binder);
+    this.changedCallback = changed.bind(binder);
+    if (MO) {
+      this.observer = new MO(this.mutationWatcher.bind(this));
+    }
+  }
+
+  Installer.prototype = {
+    watchSubtree: function(target) {
+      // Only watch scopes that can target find, as these are top-level.
+      // Otherwise we can see duplicate additions and removals that add noise.
+      //
+      // TODO(dfreedman): For some instances with ShadowDOMPolyfill, we can see
+      // a removal without an insertion when a node is redistributed among
+      // shadows. Since it all ends up correct in the document, watching only
+      // the document will yield the correct mutations to watch.
+      if (scope.targetFinding.canTarget(target)) {
+        this.observer.observe(target, OBSERVER_INIT);
+      }
+    },
+    enableOnSubtree: function(target) {
+      this.watchSubtree(target);
+      if (target === document && document.readyState !== 'complete') {
+        this.installOnLoad();
+      } else {
+        this.installNewSubtree(target);
+      }
+    },
+    installNewSubtree: function(target) {
+      forEach(this.findElements(target), this.addElement, this);
+    },
+    findElements: function(target) {
+      if (target.querySelectorAll) {
+        return target.querySelectorAll(SELECTOR);
+      }
+      return [];
+    },
+    removeElement: function(el) {
+      this.removeCallback(el);
+    },
+    addElement: function(el) {
+      this.addCallback(el);
+    },
+    elementChanged: function(el, oldValue) {
+      this.changedCallback(el, oldValue);
+    },
+    concatLists: function(accum, list) {
+      return accum.concat(toArray(list));
+    },
+    // register all touch-action = none nodes on document load
+    installOnLoad: function() {
+      document.addEventListener('DOMContentLoaded', this.installNewSubtree.bind(this, document));
+    },
+    isElement: function(n) {
+      return n.nodeType === Node.ELEMENT_NODE;
+    },
+    flattenMutationTree: function(inNodes) {
+      // find children with touch-action
+      var tree = map(inNodes, this.findElements, this);
+      // make sure the added nodes are accounted for
+      tree.push(filter(inNodes, this.isElement));
+      // flatten the list
+      return tree.reduce(this.concatLists, []);
+    },
+    mutationWatcher: function(mutations) {
+      mutations.forEach(this.mutationHandler, this);
+    },
+    mutationHandler: function(m) {
+      if (m.type === 'childList') {
+        var added = this.flattenMutationTree(m.addedNodes);
+        added.forEach(this.addElement, this);
+        var removed = this.flattenMutationTree(m.removedNodes);
+        removed.forEach(this.removeElement, this);
+      } else if (m.type === 'attributes') {
+        this.elementChanged(m.target, m.oldValue);
+      }
+    }
+  };
+
+  if (!MO) {
+    Installer.prototype.watchSubtree = function(){
+      console.warn('PointerEventsPolyfill: MutationObservers not found, touch-action will not be dynamically detected');
+    };
+  }
+
+  scope.Installer = Installer;
+})(window.PointerEventsPolyfill);
+
+/*
+ * Copyright 2013 The Polymer Authors. 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) {
+  var dispatcher = scope.dispatcher;
+  var pointermap = dispatcher.pointermap;
+  // radius around touchend that swallows mouse events
+  var DEDUP_DIST = 25;
+
+  // handler block for native mouse events
+  var mouseEvents = {
+    POINTER_ID: 1,
+    POINTER_TYPE: 'mouse',
+    events: [
+      'mousedown',
+      'mousemove',
+      'mouseup',
+      'mouseover',
+      'mouseout'
+    ],
+    register: function(target) {
+      dispatcher.listen(target, this.events);
+    },
+    unregister: function(target) {
+      dispatcher.unlisten(target, this.events);
+    },
+    lastTouches: [],
+    // collide with the global mouse listener
+    isEventSimulatedFromTouch: function(inEvent) {
+      var lts = this.lastTouches;
+      var x = inEvent.clientX, y = inEvent.clientY;
+      for (var i = 0, l = lts.length, t; i < l && (t = lts[i]); i++) {
+        // simulated mouse events will be swallowed near a primary touchend
+        var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y);
+        if (dx <= DEDUP_DIST && dy <= DEDUP_DIST) {
+          return true;
+        }
+      }
+    },
+    prepareEvent: function(inEvent) {
+      var e = dispatcher.cloneEvent(inEvent);
+      // forward mouse preventDefault
+      var pd = e.preventDefault;
+      e.preventDefault = function() {
+        inEvent.preventDefault();
+        pd();
+      };
+      e.pointerId = this.POINTER_ID;
+      e.isPrimary = true;
+      e.pointerType = this.POINTER_TYPE;
+      return e;
+    },
+    mousedown: function(inEvent) {
+      if (!this.isEventSimulatedFromTouch(inEvent)) {
+        var p = pointermap.has(this.POINTER_ID);
+        // TODO(dfreedman) workaround for some elements not sending mouseup
+        // http://crbug/149091
+        if (p) {
+          this.cancel(inEvent);
+        }
+        var e = this.prepareEvent(inEvent);
+        pointermap.set(this.POINTER_ID, inEvent);
+        dispatcher.down(e);
+      }
+    },
+    mousemove: function(inEvent) {
+      if (!this.isEventSimulatedFromTouch(inEvent)) {
+        var e = this.prepareEvent(inEvent);
+        dispatcher.move(e);
+      }
+    },
+    mouseup: function(inEvent) {
+      if (!this.isEventSimulatedFromTouch(inEvent)) {
+        var p = pointermap.get(this.POINTER_ID);
+        if (p && p.button === inEvent.button) {
+          var e = this.prepareEvent(inEvent);
+          dispatcher.up(e);
+          this.cleanupMouse();
+        }
+      }
+    },
+    mouseover: function(inEvent) {
+      if (!this.isEventSimulatedFromTouch(inEvent)) {
+        var e = this.prepareEvent(inEvent);
+        dispatcher.enterOver(e);
+      }
+    },
+    mouseout: function(inEvent) {
+      if (!this.isEventSimulatedFromTouch(inEvent)) {
+        var e = this.prepareEvent(inEvent);
+        dispatcher.leaveOut(e);
+      }
+    },
+    cancel: function(inEvent) {
+      var e = this.prepareEvent(inEvent);
+      dispatcher.cancel(e);
+      this.cleanupMouse();
+    },
+    cleanupMouse: function() {
+      pointermap['delete'](this.POINTER_ID);
+    }
+  };
+
+  scope.mouseEvents = mouseEvents;
+})(window.PointerEventsPolyfill);
+
+/*
+ * Copyright 2013 The Polymer Authors. 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) {
+  var dispatcher = scope.dispatcher;
+  var findTarget = scope.findTarget;
+  var allShadows = scope.targetFinding.allShadows.bind(scope.targetFinding);
+  var pointermap = dispatcher.pointermap;
+  var touchMap = Array.prototype.map.call.bind(Array.prototype.map);
+  // This should be long enough to ignore compat mouse events made by touch
+  var DEDUP_TIMEOUT = 2500;
+  var CLICK_COUNT_TIMEOUT = 200;
+  var ATTRIB = 'touch-action';
+  var INSTALLER;
+  // The presence of touch event handlers blocks scrolling, and so we must be careful to
+  // avoid adding handlers unnecessarily.  Chrome plans to add a touch-action-delay property
+  // (crbug.com/329559) to address this, and once we have that we can opt-in to a simpler
+  // handler registration mechanism.  Rather than try to predict how exactly to opt-in to
+  // that we'll just leave this disabled until there is a build of Chrome to test.
+  var HAS_TOUCH_ACTION_DELAY = false;
+  
+  // handler block for native touch events
+  var touchEvents = {
+    scrollType: new WeakMap(),
+    events: [
+      'touchstart',
+      'touchmove',
+      'touchend',
+      'touchcancel'
+    ],
+    register: function(target) {
+      if (HAS_TOUCH_ACTION_DELAY) {
+        dispatcher.listen(target, this.events);
+      } else {
+        INSTALLER.enableOnSubtree(target);
+      }
+    },
+    unregister: function(target) {
+      if (HAS_TOUCH_ACTION_DELAY) {
+        dispatcher.unlisten(target, this.events);
+      } else {
+        // TODO(dfreedman): is it worth it to disconnect the MO?
+      }
+    },
+    elementAdded: function(el) {
+      var a = el.getAttribute(ATTRIB);
+      var st = this.touchActionToScrollType(a);
+      if (st) {
+        this.scrollType.set(el, st);
+        dispatcher.listen(el, this.events);
+        // set touch-action on shadows as well
+        allShadows(el).forEach(function(s) {
+          this.scrollType.set(s, st);
+          dispatcher.listen(s, this.events);
+        }, this);
+      }
+    },
+    elementRemoved: function(el) {
+      this.scrollType['delete'](el);
+      dispatcher.unlisten(el, this.events);
+      // remove touch-action from shadow
+      allShadows(el).forEach(function(s) {
+        this.scrollType['delete'](s);
+        dispatcher.unlisten(s, this.events);
+      }, this);
+    },
+    elementChanged: function(el, oldValue) {
+      var a = el.getAttribute(ATTRIB);
+      var st = this.touchActionToScrollType(a);
+      var oldSt = this.touchActionToScrollType(oldValue);
+      // simply update scrollType if listeners are already established
+      if (st && oldSt) {
+        this.scrollType.set(el, st);
+        allShadows(el).forEach(function(s) {
+          this.scrollType.set(s, st);
+        }, this);
+      } else if (oldSt) {
+        this.elementRemoved(el);
+      } else if (st) {
+        this.elementAdded(el);
+      }
+    },
+    scrollTypes: {
+      EMITTER: 'none',
+      XSCROLLER: 'pan-x',
+      YSCROLLER: 'pan-y',
+      SCROLLER: /^(?:pan-x pan-y)|(?:pan-y pan-x)|auto$/
+    },
+    touchActionToScrollType: function(touchAction) {
+      var t = touchAction;
+      var st = this.scrollTypes;
+      if (t === 'none') {
+        return 'none';
+      } else if (t === st.XSCROLLER) {
+        return 'X';
+      } else if (t === st.YSCROLLER) {
+        return 'Y';
+      } else if (st.SCROLLER.exec(t)) {
+        return 'XY';
+      }
+    },
+    POINTER_TYPE: 'touch',
+    firstTouch: null,
+    isPrimaryTouch: function(inTouch) {
+      return this.firstTouch === inTouch.identifier;
+    },
+    setPrimaryTouch: function(inTouch) {
+      // set primary touch if there no pointers, or the only pointer is the mouse
+      if (pointermap.pointers() === 0 || (pointermap.pointers() === 1 && pointermap.has(1))) {
+        this.firstTouch = inTouch.identifier;
+        this.firstXY = {X: inTouch.clientX, Y: inTouch.clientY};
+        this.scrolling = false;
+        this.cancelResetClickCount();
+      }
+    },
+    removePrimaryPointer: function(inPointer) {
+      if (inPointer.isPrimary) {
+        this.firstTouch = null;
+        this.firstXY = null;
+        this.resetClickCount();
+      }
+    },
+    clickCount: 0,
+    resetId: null,
+    resetClickCount: function() {
+      var fn = function() {
+        this.clickCount = 0;
+        this.resetId = null;
+      }.bind(this);
+      this.resetId = setTimeout(fn, CLICK_COUNT_TIMEOUT);
+    },
+    cancelResetClickCount: function() {
+      if (this.resetId) {
+        clearTimeout(this.resetId);
+      }
+    },
+    touchToPointer: function(inTouch) {
+      var e = dispatcher.cloneEvent(inTouch);
+      // Spec specifies that pointerId 1 is reserved for Mouse.
+      // Touch identifiers can start at 0.
+      // Add 2 to the touch identifier for compatibility.
+      e.pointerId = inTouch.identifier + 2;
+      e.target = findTarget(e);
+      e.bubbles = true;
+      e.cancelable = true;
+      e.detail = this.clickCount;
+      e.button = 0;
+      e.buttons = 1;
+      e.width = inTouch.webkitRadiusX || inTouch.radiusX || 0;
+      e.height = inTouch.webkitRadiusY || inTouch.radiusY || 0;
+      e.pressure = inTouch.webkitForce || inTouch.force || 0.5;
+      e.isPrimary = this.isPrimaryTouch(inTouch);
+      e.pointerType = this.POINTER_TYPE;
+      return e;
+    },
+    processTouches: function(inEvent, inFunction) {
+      var tl = inEvent.changedTouches;
+      var pointers = touchMap(tl, this.touchToPointer, this);
+      // forward touch preventDefaults
+      pointers.forEach(function(p) {
+        p.preventDefault = function() {
+          this.scrolling = false;
+          this.firstXY = null;
+          inEvent.preventDefault();
+        };
+      }, this);
+      pointers.forEach(inFunction, this);
+    },
+    // For single axis scrollers, determines whether the element should emit
+    // pointer events or behave as a scroller
+    shouldScroll: function(inEvent) {
+      if (this.firstXY) {
+        var ret;
+        var scrollAxis = this.scrollType.get(inEvent.currentTarget);
+        if (scrollAxis === 'none') {
+          // this element is a touch-action: none, should never scroll
+          ret = false;
+        } else if (scrollAxis === 'XY') {
+          // this element should always scroll
+          ret = true;
+        } else {
+          var t = inEvent.changedTouches[0];
+          // check the intended scroll axis, and other axis
+          var a = scrollAxis;
+          var oa = scrollAxis === 'Y' ? 'X' : 'Y';
+          var da = Math.abs(t['client' + a] - this.firstXY[a]);
+          var doa = Math.abs(t['client' + oa] - this.firstXY[oa]);
+          // if delta in the scroll axis > delta other axis, scroll instead of
+          // making events
+          ret = da >= doa;
+        }
+        this.firstXY = null;
+        return ret;
+      }
+    },
+    findTouch: function(inTL, inId) {
+      for (var i = 0, l = inTL.length, t; i < l && (t = inTL[i]); i++) {
+        if (t.identifier === inId) {
+          return true;
+        }
+      }
+    },
+    // In some instances, a touchstart can happen without a touchend. This
+    // leaves the pointermap in a broken state.
+    // Therefore, on every touchstart, we remove the touches that did not fire a
+    // touchend event.
+    // To keep state globally consistent, we fire a
+    // pointercancel for this "abandoned" touch
+    vacuumTouches: function(inEvent) {
+      var tl = inEvent.touches;
+      // pointermap.pointers() should be < tl.length here, as the touchstart has not
+      // been processed yet.
+      if (pointermap.pointers() >= tl.length) {
+        var d = [];
+        pointermap.forEach(function(value, key) {
+          // Never remove pointerId == 1, which is mouse.
+          // Touch identifiers are 2 smaller than their pointerId, which is the
+          // index in pointermap.
+          if (key !== 1 && !this.findTouch(tl, key - 2)) {
+            var p = value.out;
+            d.push(this.touchToPointer(p));
+          }
+        }, this);
+        d.forEach(this.cancelOut, this);
+      }
+    },
+    touchstart: function(inEvent) {
+      this.vacuumTouches(inEvent);
+      this.setPrimaryTouch(inEvent.changedTouches[0]);
+      this.dedupSynthMouse(inEvent);
+      if (!this.scrolling) {
+        this.clickCount++;
+        this.processTouches(inEvent, this.overDown);
+      }
+    },
+    overDown: function(inPointer) {
+      var p = pointermap.set(inPointer.pointerId, {
+        target: inPointer.target,
+        out: inPointer,
+        outTarget: inPointer.target
+      });
+      dispatcher.over(inPointer);
+      dispatcher.enter(inPointer);
+      dispatcher.down(inPointer);
+    },
+    touchmove: function(inEvent) {
+      if (!this.scrolling) {
+        if (this.shouldScroll(inEvent)) {
+          this.scrolling = true;
+          this.touchcancel(inEvent);
+        } else {
+          inEvent.preventDefault();
+          this.processTouches(inEvent, this.moveOverOut);
+        }
+      }
+    },
+    moveOverOut: function(inPointer) {
+      var event = inPointer;
+      var pointer = pointermap.get(event.pointerId);
+      // a finger drifted off the screen, ignore it
+      if (!pointer) {
+        return;
+      }
+      var outEvent = pointer.out;
+      var outTarget = pointer.outTarget;
+      dispatcher.move(event);
+      if (outEvent && outTarget !== event.target) {
+        outEvent.relatedTarget = event.target;
+        event.relatedTarget = outTarget;
+        // recover from retargeting by shadow
+        outEvent.target = outTarget;
+        if (event.target) {
+          dispatcher.leaveOut(outEvent);
+          dispatcher.enterOver(event);
+        } else {
+          // clean up case when finger leaves the screen
+          event.target = outTarget;
+          event.relatedTarget = null;
+          this.cancelOut(event);
+        }
+      }
+      pointer.out = event;
+      pointer.outTarget = event.target;
+    },
+    touchend: function(inEvent) {
+      this.dedupSynthMouse(inEvent);
+      this.processTouches(inEvent, this.upOut);
+    },
+    upOut: function(inPointer) {
+      if (!this.scrolling) {
+        dispatcher.up(inPointer);
+        dispatcher.out(inPointer);
+        dispatcher.leave(inPointer);
+      }
+      this.cleanUpPointer(inPointer);
+    },
+    touchcancel: function(inEvent) {
+      this.processTouches(inEvent, this.cancelOut);
+    },
+    cancelOut: function(inPointer) {
+      dispatcher.cancel(inPointer);
+      dispatcher.out(inPointer);
+      dispatcher.leave(inPointer);
+      this.cleanUpPointer(inPointer);
+    },
+    cleanUpPointer: function(inPointer) {
+      pointermap['delete'](inPointer.pointerId);
+      this.removePrimaryPointer(inPointer);
+    },
+    // prevent synth mouse events from creating pointer events
+    dedupSynthMouse: function(inEvent) {
+      var lts = scope.mouseEvents.lastTouches;
+      var t = inEvent.changedTouches[0];
+      // only the primary finger will synth mouse events
+      if (this.isPrimaryTouch(t)) {
+        // remember x/y of last touch
+        var lt = {x: t.clientX, y: t.clientY};
+        lts.push(lt);
+        var fn = (function(lts, lt){
+          var i = lts.indexOf(lt);
+          if (i > -1) {
+            lts.splice(i, 1);
+          }
+        }).bind(null, lts, lt);
+        setTimeout(fn, DEDUP_TIMEOUT);
+      }
+    }
+  };
+
+  if (!HAS_TOUCH_ACTION_DELAY) {
+    INSTALLER = new scope.Installer(touchEvents.elementAdded, touchEvents.elementRemoved, touchEvents.elementChanged, touchEvents);
+  }
+
+  scope.touchEvents = touchEvents;
+})(window.PointerEventsPolyfill);
+
+/*
+ * Copyright 2013 The Polymer Authors. 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) {
+  var dispatcher = scope.dispatcher;
+  var pointermap = dispatcher.pointermap;
+  var HAS_BITMAP_TYPE = window.MSPointerEvent && typeof window.MSPointerEvent.MSPOINTER_TYPE_MOUSE === 'number';
+  var msEvents = {
+    events: [
+      'MSPointerDown',
+      'MSPointerMove',
+      'MSPointerUp',
+      'MSPointerOut',
+      'MSPointerOver',
+      'MSPointerCancel',
+      'MSGotPointerCapture',
+      'MSLostPointerCapture'
+    ],
+    register: function(target) {
+      dispatcher.listen(target, this.events);
+    },
+    unregister: function(target) {
+      dispatcher.unlisten(target, this.events);
+    },
+    POINTER_TYPES: [
+      '',
+      'unavailable',
+      'touch',
+      'pen',
+      'mouse'
+    ],
+    prepareEvent: function(inEvent) {
+      var e = inEvent;
+      if (HAS_BITMAP_TYPE) {
+        e = dispatcher.cloneEvent(inEvent);
+        e.pointerType = this.POINTER_TYPES[inEvent.pointerType];
+      }
+      return e;
+    },
+    cleanup: function(id) {
+      pointermap['delete'](id);
+    },
+    MSPointerDown: function(inEvent) {
+      pointermap.set(inEvent.pointerId, inEvent);
+      var e = this.prepareEvent(inEvent);
+      dispatcher.down(e);
+    },
+    MSPointerMove: function(inEvent) {
+      var e = this.prepareEvent(inEvent);
+      dispatcher.move(e);
+    },
+    MSPointerUp: function(inEvent) {
+      var e = this.prepareEvent(inEvent);
+      dispatcher.up(e);
+      this.cleanup(inEvent.pointerId);
+    },
+    MSPointerOut: function(inEvent) {
+      var e = this.prepareEvent(inEvent);
+      dispatcher.leaveOut(e);
+    },
+    MSPointerOver: function(inEvent) {
+      var e = this.prepareEvent(inEvent);
+      dispatcher.enterOver(e);
+    },
+    MSPointerCancel: function(inEvent) {
+      var e = this.prepareEvent(inEvent);
+      dispatcher.cancel(e);
+      this.cleanup(inEvent.pointerId);
+    },
+    MSLostPointerCapture: function(inEvent) {
+      var e = dispatcher.makeEvent('lostpointercapture', inEvent);
+      dispatcher.dispatchEvent(e);
+    },
+    MSGotPointerCapture: function(inEvent) {
+      var e = dispatcher.makeEvent('gotpointercapture', inEvent);
+      dispatcher.dispatchEvent(e);
+    }
+  };
+
+  scope.msEvents = msEvents;
+})(window.PointerEventsPolyfill);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+/**
+ * This module contains the handlers for native platform events.
+ * From here, the dispatcher is called to create unified pointer events.
+ * Included are touch events (v1), mouse events, and MSPointerEvents.
+ */
+(function(scope) {
+  var dispatcher = scope.dispatcher;
+
+  // only activate if this platform does not have pointer events
+  if (window.navigator.pointerEnabled === undefined) {
+    Object.defineProperty(window.navigator, 'pointerEnabled', {value: true, enumerable: true});
+
+    if (window.navigator.msPointerEnabled) {
+      var tp = window.navigator.msMaxTouchPoints;
+      Object.defineProperty(window.navigator, 'maxTouchPoints', {
+        value: tp,
+        enumerable: true
+      });
+      dispatcher.registerSource('ms', scope.msEvents);
+    } else {
+      dispatcher.registerSource('mouse', scope.mouseEvents);
+      if (window.ontouchstart !== undefined) {
+        dispatcher.registerSource('touch', scope.touchEvents);
+      }
+    }
+
+    dispatcher.register(document);
+  }
+})(window.PointerEventsPolyfill);
+
+/*
+ * Copyright 2013 The Polymer Authors. 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) {
+  var dispatcher = scope.dispatcher;
+  var n = window.navigator;
+  var s, r;
+  function assertDown(id) {
+    if (!dispatcher.pointermap.has(id)) {
+      throw new Error('InvalidPointerId');
+    }
+  }
+  if (n.msPointerEnabled) {
+    s = function(pointerId) {
+      assertDown(pointerId);
+      this.msSetPointerCapture(pointerId);
+    };
+    r = function(pointerId) {
+      assertDown(pointerId);
+      this.msReleasePointerCapture(pointerId);
+    };
+  } else {
+    s = function setPointerCapture(pointerId) {
+      assertDown(pointerId);
+      dispatcher.setCapture(pointerId, this);
+    };
+    r = function releasePointerCapture(pointerId) {
+      assertDown(pointerId);
+      dispatcher.releaseCapture(pointerId, this);
+    };
+  }
+  if (window.Element && !Element.prototype.setPointerCapture) {
+    Object.defineProperties(Element.prototype, {
+      'setPointerCapture': {
+        value: s
+      },
+      'releasePointerCapture': {
+        value: r
+      }
+    });
+  }
+})(window.PointerEventsPolyfill);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+/**
+ * PointerGestureEvent is the constructor for all PointerGesture events.
+ *
+ * @module PointerGestures
+ * @class PointerGestureEvent
+ * @extends UIEvent
+ * @constructor
+ * @param {String} inType Event type
+ * @param {Object} [inDict] Dictionary of properties to initialize on the event
+ */
+
+function PointerGestureEvent(inType, inDict) {
+  var dict = inDict || {};
+  var e = document.createEvent('Event');
+  var props = {
+    bubbles: Boolean(dict.bubbles) === dict.bubbles || true,
+    cancelable: Boolean(dict.cancelable) === dict.cancelable || true
+  };
+
+  e.initEvent(inType, props.bubbles, props.cancelable);
+
+  var keys = Object.keys(dict), k;
+  for (var i = 0; i < keys.length; i++) {
+    k = keys[i];
+    e[k] = dict[k];
+  }
+
+  e.preventTap = this.preventTap;
+
+  return e;
+}
+
+/**
+ * Allows for any gesture to prevent the tap gesture.
+ *
+ * @method preventTap
+ */
+PointerGestureEvent.prototype.preventTap = function() {
+  this.tapPrevented = true;
+};
+
+
+/*
+ * Copyright 2013 The Polymer Authors. 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) {
+  /**
+   * This class contains the gesture recognizers that create the PointerGesture
+   * events.
+   *
+   * @class PointerGestures
+   * @static
+   */
+  scope = scope || {};
+  scope.utils = {
+    LCA: {
+      // Determines the lowest node in the ancestor chain of a and b
+      find: function(a, b) {
+        if (a === b) {
+          return a;
+        }
+        // fast case, a is a direct descendant of b or vice versa
+        if (a.contains) {
+          if (a.contains(b)) {
+            return a;
+          }
+          if (b.contains(a)) {
+            return b;
+          }
+        }
+        var adepth = this.depth(a);
+        var bdepth = this.depth(b);
+        var d = adepth - bdepth;
+        if (d > 0) {
+          a = this.walk(a, d);
+        } else {
+          b = this.walk(b, -d);
+        }
+        while(a && b && a !== b) {
+          a = this.walk(a, 1);
+          b = this.walk(b, 1);
+        }
+        return a;
+      },
+      walk: function(n, u) {
+        for (var i = 0; i < u; i++) {
+          n = n.parentNode;
+        }
+        return n;
+      },
+      depth: function(n) {
+        var d = 0;
+        while(n) {
+          d++;
+          n = n.parentNode;
+        }
+        return d;
+      }
+    }
+  };
+  scope.findLCA = function(a, b) {
+    return scope.utils.LCA.find(a, b);
+  }
+  window.PointerGestures = scope;
+})(window.PointerGestures);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+/**
+ * This module implements an map of pointer states
+ */
+(function(scope) {
+  var USE_MAP = window.Map && window.Map.prototype.forEach;
+  var POINTERS_FN = function(){ return this.size; };
+  function PointerMap() {
+    if (USE_MAP) {
+      var m = new Map();
+      m.pointers = POINTERS_FN;
+      return m;
+    } else {
+      this.keys = [];
+      this.values = [];
+    }
+  }
+
+  PointerMap.prototype = {
+    set: function(inId, inEvent) {
+      var i = this.keys.indexOf(inId);
+      if (i > -1) {
+        this.values[i] = inEvent;
+      } else {
+        this.keys.push(inId);
+        this.values.push(inEvent);
+      }
+    },
+    has: function(inId) {
+      return this.keys.indexOf(inId) > -1;
+    },
+    'delete': function(inId) {
+      var i = this.keys.indexOf(inId);
+      if (i > -1) {
+        this.keys.splice(i, 1);
+        this.values.splice(i, 1);
+      }
+    },
+    get: function(inId) {
+      var i = this.keys.indexOf(inId);
+      return this.values[i];
+    },
+    clear: function() {
+      this.keys.length = 0;
+      this.values.length = 0;
+    },
+    // return value, key, map
+    forEach: function(callback, thisArg) {
+      this.values.forEach(function(v, i) {
+        callback.call(thisArg, v, this.keys[i], this);
+      }, this);
+    },
+    pointers: function() {
+      return this.keys.length;
+    }
+  };
+
+  scope.PointerMap = PointerMap;
+})(window.PointerGestures);
+
+/*
+ * Copyright 2013 The Polymer Authors. 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) {
+  var CLONE_PROPS = [
+    // MouseEvent
+    'bubbles',
+    'cancelable',
+    'view',
+    'detail',
+    'screenX',
+    'screenY',
+    'clientX',
+    'clientY',
+    'ctrlKey',
+    'altKey',
+    'shiftKey',
+    'metaKey',
+    'button',
+    'relatedTarget',
+    // DOM Level 3
+    'buttons',
+    // PointerEvent
+    'pointerId',
+    'width',
+    'height',
+    'pressure',
+    'tiltX',
+    'tiltY',
+    'pointerType',
+    'hwTimestamp',
+    'isPrimary',
+    // event instance
+    'type',
+    'target',
+    'currentTarget',
+    'screenX',
+    'screenY',
+    'pageX',
+    'pageY',
+    'tapPrevented'
+  ];
+
+  var CLONE_DEFAULTS = [
+    // MouseEvent
+    false,
+    false,
+    null,
+    null,
+    0,
+    0,
+    0,
+    0,
+    false,
+    false,
+    false,
+    false,
+    0,
+    null,
+    // DOM Level 3
+    0,
+    // PointerEvent
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    '',
+    0,
+    false,
+    // event instance
+    '',
+    null,
+    null,
+    0,
+    0,
+    0,
+    0
+  ];
+
+  var dispatcher = {
+    handledEvents: new WeakMap(),
+    targets: new WeakMap(),
+    handlers: {},
+    recognizers: {},
+    events: {},
+    // Add a new gesture recognizer to the event listeners.
+    // Recognizer needs an `events` property.
+    registerRecognizer: function(inName, inRecognizer) {
+      var r = inRecognizer;
+      this.recognizers[inName] = r;
+      r.events.forEach(function(e) {
+        if (r[e]) {
+          this.events[e] = true;
+          var f = r[e].bind(r);
+          this.addHandler(e, f);
+        }
+      }, this);
+    },
+    addHandler: function(inEvent, inFn) {
+      var e = inEvent;
+      if (!this.handlers[e]) {
+        this.handlers[e] = [];
+      }
+      this.handlers[e].push(inFn);
+    },
+    // add event listeners for inTarget
+    registerTarget: function(inTarget) {
+      this.listen(Object.keys(this.events), inTarget);
+    },
+    // remove event listeners for inTarget
+    unregisterTarget: function(inTarget) {
+      this.unlisten(Object.keys(this.events), inTarget);
+    },
+    // LISTENER LOGIC
+    eventHandler: function(inEvent) {
+      if (this.handledEvents.get(inEvent)) {
+        return;
+      }
+      var type = inEvent.type, fns = this.handlers[type];
+      if (fns) {
+        this.makeQueue(fns, inEvent);
+      }
+      this.handledEvents.set(inEvent, true);
+    },
+    // queue event for async dispatch
+    makeQueue: function(inHandlerFns, inEvent) {
+      // must clone events to keep the (possibly shadowed) target correct for
+      // async dispatching
+      var e = this.cloneEvent(inEvent);
+      setTimeout(this.runQueue.bind(this, inHandlerFns, e), 0);
+    },
+    // Dispatch the queued events
+    runQueue: function(inHandlers, inEvent) {
+      this.currentPointerId = inEvent.pointerId;
+      for (var i = 0, f, l = inHandlers.length; (i < l) && (f = inHandlers[i]); i++) {
+        f(inEvent);
+      }
+      this.currentPointerId = 0;
+    },
+    // set up event listeners
+    listen: function(inEvents, inTarget) {
+      inEvents.forEach(function(e) {
+        this.addEvent(e, this.boundHandler, false, inTarget);
+      }, this);
+    },
+    // remove event listeners
+    unlisten: function(inEvents) {
+      inEvents.forEach(function(e) {
+        this.removeEvent(e, this.boundHandler, false, inTarget);
+      }, this);
+    },
+    addEvent: function(inEventName, inEventHandler, inCapture, inTarget) {
+      inTarget.addEventListener(inEventName, inEventHandler, inCapture);
+    },
+    removeEvent: function(inEventName, inEventHandler, inCapture, inTarget) {
+      inTarget.removeEventListener(inEventName, inEventHandler, inCapture);
+    },
+    // EVENT CREATION AND TRACKING
+    // Creates a new Event of type `inType`, based on the information in
+    // `inEvent`.
+    makeEvent: function(inType, inDict) {
+      return new PointerGestureEvent(inType, inDict);
+    },
+    /*
+     * Returns a snapshot of inEvent, with writable properties.
+     *
+     * @method cloneEvent
+     * @param {Event} inEvent An event that contains properties to copy.
+     * @return {Object} An object containing shallow copies of `inEvent`'s
+     *    properties.
+     */
+    cloneEvent: function(inEvent) {
+      var eventCopy = {}, p;
+      for (var i = 0; i < CLONE_PROPS.length; i++) {
+        p = CLONE_PROPS[i];
+        eventCopy[p] = inEvent[p] || CLONE_DEFAULTS[i];
+      }
+      return eventCopy;
+    },
+    // Dispatches the event to its target.
+    dispatchEvent: function(inEvent, inTarget) {
+      var t = inTarget || this.targets.get(inEvent);
+      if (t) {
+        t.dispatchEvent(inEvent);
+        if (inEvent.tapPrevented) {
+          this.preventTap(this.currentPointerId);
+        }
+      }
+    },
+    asyncDispatchEvent: function(inEvent, inTarget) {
+      var fn = function() {
+        this.dispatchEvent(inEvent, inTarget);
+      }.bind(this);
+      setTimeout(fn, 0);
+    },
+    preventTap: function(inPointerId) {
+      var t = this.recognizers.tap;
+      if (t){
+        t.preventTap(inPointerId);
+      }
+    }
+  };
+  dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher);
+  scope.dispatcher = dispatcher;
+  var registerQueue = [];
+  var immediateRegister = false;
+  /**
+   * Enable gesture events for a given scope, typically
+   * [ShadowRoots](https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#shadow-root-object).
+   *
+   * @for PointerGestures
+   * @method register
+   * @param {ShadowRoot} scope A top level scope to enable gesture
+   * support on.
+   */
+  scope.register = function(inScope) {
+    if (immediateRegister) {
+      var pe = window.PointerEventsPolyfill;
+      if (pe) {
+        pe.register(inScope);
+      }
+      scope.dispatcher.registerTarget(inScope);
+    } else {
+      registerQueue.push(inScope);
+    }
+  };
+  // wait to register scopes until recognizers load
+  document.addEventListener('DOMContentLoaded', function() {
+    immediateRegister = true;
+    registerQueue.push(document);
+    registerQueue.forEach(scope.register);
+  });
+})(window.PointerGestures);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+/**
+ * This event is fired when a pointer is held down for 200ms.
+ *
+ * @module PointerGestures
+ * @submodule Events
+ * @class hold
+ */
+/**
+ * Milliseconds pointer has been held down.
+ * @type Number
+ * @property holdTime
+ */
+/**
+ * Type of pointer that made the holding event.
+ * @type String
+ * @property pointerType
+ */
+/**
+ * This event is fired every 200ms while a pointer is held down.
+ *
+ * @class holdpulse
+ * @extends hold
+ */
+/**
+ * This event is fired when a held pointer is released or moved.
+ *
+ * @class released
+ */
+/**
+ * Type of pointer that made the holding event.
+ * @type String
+ * @property pointerType
+ */
+
+(function(scope) {
+  var dispatcher = scope.dispatcher;
+  var hold = {
+    // wait at least HOLD_DELAY ms between hold and pulse events
+    HOLD_DELAY: 200,
+    // pointer can move WIGGLE_THRESHOLD pixels before not counting as a hold
+    WIGGLE_THRESHOLD: 16,
+    events: [
+      'pointerdown',
+      'pointermove',
+      'pointerup',
+      'pointercancel'
+    ],
+    heldPointer: null,
+    holdJob: null,
+    pulse: function() {
+      var hold = Date.now() - this.heldPointer.timeStamp;
+      var type = this.held ? 'holdpulse' : 'hold';
+      this.fireHold(type, hold);
+      this.held = true;
+    },
+    cancel: function() {
+      clearInterval(this.holdJob);
+      if (this.held) {
+        this.fireHold('release');
+      }
+      this.held = false;
+      this.heldPointer = null;
+      this.target = null;
+      this.holdJob = null;
+    },
+    pointerdown: function(inEvent) {
+      if (inEvent.isPrimary && !this.heldPointer) {
+        this.heldPointer = inEvent;
+        this.target = inEvent.target;
+        this.holdJob = setInterval(this.pulse.bind(this), this.HOLD_DELAY);
+      }
+    },
+    pointerup: function(inEvent) {
+      if (this.heldPointer && this.heldPointer.pointerId === inEvent.pointerId) {
+        this.cancel();
+      }
+    },
+    pointercancel: function(inEvent) {
+      this.cancel();
+    },
+    pointermove: function(inEvent) {
+      if (this.heldPointer && this.heldPointer.pointerId === inEvent.pointerId) {
+        var x = inEvent.clientX - this.heldPointer.clientX;
+        var y = inEvent.clientY - this.heldPointer.clientY;
+        if ((x * x + y * y) > this.WIGGLE_THRESHOLD) {
+          this.cancel();
+        }
+      }
+    },
+    fireHold: function(inType, inHoldTime) {
+      var p = {
+        pointerType: this.heldPointer.pointerType
+      };
+      if (inHoldTime) {
+        p.holdTime = inHoldTime;
+      }
+      var e = dispatcher.makeEvent(inType, p);
+      dispatcher.dispatchEvent(e, this.target);
+      if (e.tapPrevented) {
+        dispatcher.preventTap(this.heldPointer.pointerId);
+      }
+    }
+  };
+  dispatcher.registerRecognizer('hold', hold);
+})(window.PointerGestures);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+/**
+ * This event denotes the beginning of a series of tracking events.
+ *
+ * @module PointerGestures
+ * @submodule Events
+ * @class trackstart
+ */
+/**
+ * Pixels moved in the x direction since trackstart.
+ * @type Number
+ * @property dx
+ */
+/**
+ * Pixes moved in the y direction since trackstart.
+ * @type Number
+ * @property dy
+ */
+/**
+ * Pixels moved in the x direction since the last track.
+ * @type Number
+ * @property ddx
+ */
+/**
+ * Pixles moved in the y direction since the last track.
+ * @type Number
+ * @property ddy
+ */
+/**
+ * The clientX position of the track gesture.
+ * @type Number
+ * @property clientX
+ */
+/**
+ * The clientY position of the track gesture.
+ * @type Number
+ * @property clientY
+ */
+/**
+ * The pageX position of the track gesture.
+ * @type Number
+ * @property pageX
+ */
+/**
+ * The pageY position of the track gesture.
+ * @type Number
+ * @property pageY
+ */
+/**
+ * The screenX position of the track gesture.
+ * @type Number
+ * @property screenX
+ */
+/**
+ * The screenY position of the track gesture.
+ * @type Number
+ * @property screenY
+ */
+/**
+ * The last x axis direction of the pointer.
+ * @type Number
+ * @property xDirection
+ */
+/**
+ * The last y axis direction of the pointer.
+ * @type Number
+ * @property yDirection
+ */
+/**
+ * A shared object between all tracking events.
+ * @type Object
+ * @property trackInfo
+ */
+/**
+ * The element currently under the pointer.
+ * @type Element
+ * @property relatedTarget
+ */
+/**
+ * The type of pointer that make the track gesture.
+ * @type String
+ * @property pointerType
+ */
+/**
+ *
+ * This event fires for all pointer movement being tracked.
+ *
+ * @class track
+ * @extends trackstart
+ */
+/**
+ * This event fires when the pointer is no longer being tracked.
+ *
+ * @class trackend
+ * @extends trackstart
+ */
+
+ (function(scope) {
+   var dispatcher = scope.dispatcher;
+   var pointermap = new scope.PointerMap();
+   var track = {
+     events: [
+       'pointerdown',
+       'pointermove',
+       'pointerup',
+       'pointercancel'
+     ],
+     WIGGLE_THRESHOLD: 4,
+     clampDir: function(inDelta) {
+       return inDelta > 0 ? 1 : -1;
+     },
+     calcPositionDelta: function(inA, inB) {
+       var x = 0, y = 0;
+       if (inA && inB) {
+         x = inB.pageX - inA.pageX;
+         y = inB.pageY - inA.pageY;
+       }
+       return {x: x, y: y};
+     },
+     fireTrack: function(inType, inEvent, inTrackingData) {
+       var t = inTrackingData;
+       var d = this.calcPositionDelta(t.downEvent, inEvent);
+       var dd = this.calcPositionDelta(t.lastMoveEvent, inEvent);
+       if (dd.x) {
+         t.xDirection = this.clampDir(dd.x);
+       }
+       if (dd.y) {
+         t.yDirection = this.clampDir(dd.y);
+       }
+       var trackData = {
+         dx: d.x,
+         dy: d.y,
+         ddx: dd.x,
+         ddy: dd.y,
+         clientX: inEvent.clientX,
+         clientY: inEvent.clientY,
+         pageX: inEvent.pageX,
+         pageY: inEvent.pageY,
+         screenX: inEvent.screenX,
+         screenY: inEvent.screenY,
+         xDirection: t.xDirection,
+         yDirection: t.yDirection,
+         trackInfo: t.trackInfo,
+         relatedTarget: inEvent.target,
+         pointerType: inEvent.pointerType
+       };
+       var e = dispatcher.makeEvent(inType, trackData);
+       t.lastMoveEvent = inEvent;
+       dispatcher.dispatchEvent(e, t.downTarget);
+     },
+     pointerdown: function(inEvent) {
+       if (inEvent.isPrimary && (inEvent.pointerType === 'mouse' ? inEvent.buttons === 1 : true)) {
+         var p = {
+           downEvent: inEvent,
+           downTarget: inEvent.target,
+           trackInfo: {},
+           lastMoveEvent: null,
+           xDirection: 0,
+           yDirection: 0,
+           tracking: false
+         };
+         pointermap.set(inEvent.pointerId, p);
+       }
+     },
+     pointermove: function(inEvent) {
+       var p = pointermap.get(inEvent.pointerId);
+       if (p) {
+         if (!p.tracking) {
+           var d = this.calcPositionDelta(p.downEvent, inEvent);
+           var move = d.x * d.x + d.y * d.y;
+           // start tracking only if finger moves more than WIGGLE_THRESHOLD
+           if (move > this.WIGGLE_THRESHOLD) {
+             p.tracking = true;
+             this.fireTrack('trackstart', p.downEvent, p);
+             this.fireTrack('track', inEvent, p);
+           }
+         } else {
+           this.fireTrack('track', inEvent, p);
+         }
+       }
+     },
+     pointerup: function(inEvent) {
+       var p = pointermap.get(inEvent.pointerId);
+       if (p) {
+         if (p.tracking) {
+           this.fireTrack('trackend', inEvent, p);
+         }
+         pointermap.delete(inEvent.pointerId);
+       }
+     },
+     pointercancel: function(inEvent) {
+       this.pointerup(inEvent);
+     }
+   };
+   dispatcher.registerRecognizer('track', track);
+ })(window.PointerGestures);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+/**
+ * This event denotes a rapid down/move/up sequence from a pointer.
+ *
+ * The event is sent to the first element the pointer went down on.
+ *
+ * @module PointerGestures
+ * @submodule Events
+ * @class flick
+ */
+/**
+ * Signed velocity of the flick in the x direction.
+ * @property xVelocity
+ * @type Number
+ */
+/**
+ * Signed velocity of the flick in the y direction.
+ * @type Number
+ * @property yVelocity
+ */
+/**
+ * Unsigned total velocity of the flick.
+ * @type Number
+ * @property velocity
+ */
+/**
+ * Angle of the flick in degrees, with 0 along the
+ * positive x axis.
+ * @type Number
+ * @property angle
+ */
+/**
+ * Axis with the greatest absolute velocity. Denoted
+ * with 'x' or 'y'.
+ * @type String
+ * @property majorAxis
+ */
+/**
+ * Type of the pointer that made the flick.
+ * @type String
+ * @property pointerType
+ */
+
+(function(scope) {
+  var dispatcher = scope.dispatcher;
+  var flick = {
+    // TODO(dfreedman): value should be low enough for low speed flicks, but
+    // high enough to remove accidental flicks
+    MIN_VELOCITY: 0.5 /* px/ms */,
+    MAX_QUEUE: 4,
+    moveQueue: [],
+    target: null,
+    pointerId: null,
+    events: [
+      'pointerdown',
+      'pointermove',
+      'pointerup',
+      'pointercancel'
+    ],
+    pointerdown: function(inEvent) {
+      if (inEvent.isPrimary && !this.pointerId) {
+        this.pointerId = inEvent.pointerId;
+        this.target = inEvent.target;
+        this.addMove(inEvent);
+      }
+    },
+    pointermove: function(inEvent) {
+      if (inEvent.pointerId === this.pointerId) {
+        this.addMove(inEvent);
+      }
+    },
+    pointerup: function(inEvent) {
+      if (inEvent.pointerId === this.pointerId) {
+        this.fireFlick(inEvent);
+      }
+      this.cleanup();
+    },
+    pointercancel: function(inEvent) {
+      this.cleanup();
+    },
+    cleanup: function() {
+      this.moveQueue = [];
+      this.target = null;
+      this.pointerId = null;
+    },
+    addMove: function(inEvent) {
+      if (this.moveQueue.length >= this.MAX_QUEUE) {
+        this.moveQueue.shift();
+      }
+      this.moveQueue.push(inEvent);
+    },
+    fireFlick: function(inEvent) {
+      var e = inEvent;
+      var l = this.moveQueue.length;
+      var dt, dx, dy, tx, ty, tv, x = 0, y = 0, v = 0;
+      // flick based off the fastest segment of movement
+      for (var i = 0, m; i < l && (m = this.moveQueue[i]); i++) {
+        dt = e.timeStamp - m.timeStamp;
+        dx = e.clientX - m.clientX, dy = e.clientY - m.clientY;
+        tx = dx / dt, ty = dy / dt, tv = Math.sqrt(tx * tx + ty * ty);
+        if (tv > v) {
+          x = tx, y = ty, v = tv;
+        }
+      }
+      var ma = Math.abs(x) > Math.abs(y) ? 'x' : 'y';
+      var a = this.calcAngle(x, y);
+      if (Math.abs(v) >= this.MIN_VELOCITY) {
+        var ev = dispatcher.makeEvent('flick', {
+          xVelocity: x,
+          yVelocity: y,
+          velocity: v,
+          angle: a,
+          majorAxis: ma,
+          pointerType: inEvent.pointerType
+        });
+        dispatcher.dispatchEvent(ev, this.target);
+      }
+    },
+    calcAngle: function(inX, inY) {
+      return (Math.atan2(inY, inX) * 180 / Math.PI);
+    }
+  };
+  dispatcher.registerRecognizer('flick', flick);
+})(window.PointerGestures);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+/*
+ * Basic strategy: find the farthest apart points, use as diameter of circle
+ * react to size change and rotation of the chord
+ */
+
+/**
+ * @module PointerGestures
+ * @submodule Events
+ * @class pinch
+ */
+/**
+ * Scale of the pinch zoom gesture
+ * @property scale
+ * @type Number
+ */
+/**
+ * Center X position of pointers causing pinch
+ * @property centerX
+ * @type Number
+ */
+/**
+ * Center Y position of pointers causing pinch
+ * @property centerY
+ * @type Number
+ */
+
+/**
+ * @module PointerGestures
+ * @submodule Events
+ * @class rotate
+ */
+/**
+ * Angle (in degrees) of rotation. Measured from starting positions of pointers.
+ * @property angle
+ * @type Number
+ */
+/**
+ * Center X position of pointers causing rotation
+ * @property centerX
+ * @type Number
+ */
+/**
+ * Center Y position of pointers causing rotation
+ * @property centerY
+ * @type Number
+ */
+(function(scope) {
+  var dispatcher = scope.dispatcher;
+  var pointermap = new scope.PointerMap();
+  var RAD_TO_DEG = 180 / Math.PI;
+  var pinch = {
+    events: [
+      'pointerdown',
+      'pointermove',
+      'pointerup',
+      'pointercancel'
+    ],
+    reference: {},
+    pointerdown: function(ev) {
+      pointermap.set(ev.pointerId, ev);
+      if (pointermap.pointers() == 2) {
+        var points = this.calcChord();
+        var angle = this.calcAngle(points);
+        this.reference = {
+          angle: angle,
+          diameter: points.diameter,
+          target: scope.findLCA(points.a.target, points.b.target)
+        };
+      }
+    },
+    pointerup: function(ev) {
+      pointermap.delete(ev.pointerId);
+    },
+    pointermove: function(ev) {
+      if (pointermap.has(ev.pointerId)) {
+        pointermap.set(ev.pointerId, ev);
+        if (pointermap.pointers() > 1) {
+          this.calcPinchRotate();
+        }
+      }
+    },
+    pointercancel: function(ev) {
+      this.pointerup(ev);
+    },
+    dispatchPinch: function(diameter, points) {
+      var zoom = diameter / this.reference.diameter;
+      var ev = dispatcher.makeEvent('pinch', {
+        scale: zoom,
+        centerX: points.center.x,
+        centerY: points.center.y
+      });
+      dispatcher.dispatchEvent(ev, this.reference.target);
+    },
+    dispatchRotate: function(angle, points) {
+      var diff = Math.round((angle - this.reference.angle) % 360);
+      var ev = dispatcher.makeEvent('rotate', {
+        angle: diff,
+        centerX: points.center.x,
+        centerY: points.center.y
+      });
+      dispatcher.dispatchEvent(ev, this.reference.target);
+    },
+    calcPinchRotate: function() {
+      var points = this.calcChord();
+      var diameter = points.diameter;
+      var angle = this.calcAngle(points);
+      if (diameter != this.reference.diameter) {
+        this.dispatchPinch(diameter, points);
+      }
+      if (angle != this.reference.angle) {
+        this.dispatchRotate(angle, points);
+      }
+    },
+    calcChord: function() {
+      var pointers = [];
+      pointermap.forEach(function(p) {
+        pointers.push(p);
+      });
+      var dist = 0;
+      var points = {};
+      var x, y, d;
+      for (var i = 0; i < pointers.length; i++) {
+        var a = pointers[i];
+        for (var j = i + 1; j < pointers.length; j++) {
+          var b = pointers[j];
+          x = Math.abs(a.clientX - b.clientX);
+          y = Math.abs(a.clientY - b.clientY);
+          d = x + y;
+          if (d > dist) {
+            dist = d;
+            points = {a: a, b: b};
+          }
+        }
+      }
+      x = Math.abs(points.a.clientX + points.b.clientX) / 2;
+      y = Math.abs(points.a.clientY + points.b.clientY) / 2;
+      points.center = { x: x, y: y };
+      points.diameter = dist;
+      return points;
+    },
+    calcAngle: function(points) {
+      var x = points.a.clientX - points.b.clientX;
+      var y = points.a.clientY - points.b.clientY;
+      return (360 + Math.atan2(y, x) * RAD_TO_DEG) % 360;
+    },
+  };
+  dispatcher.registerRecognizer('pinch', pinch);
+})(window.PointerGestures);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+/**
+ * This event is fired when a pointer quickly goes down and up, and is used to
+ * denote activation.
+ *
+ * Any gesture event can prevent the tap event from being created by calling
+ * `event.preventTap`.
+ *
+ * Any pointer event can prevent the tap by setting the `tapPrevented` property
+ * on itself.
+ *
+ * @module PointerGestures
+ * @submodule Events
+ * @class tap
+ */
+/**
+ * X axis position of the tap.
+ * @property x
+ * @type Number
+ */
+/**
+ * Y axis position of the tap.
+ * @property y
+ * @type Number
+ */
+/**
+ * Type of the pointer that made the tap.
+ * @property pointerType
+ * @type String
+ */
+(function(scope) {
+  var dispatcher = scope.dispatcher;
+  var pointermap = new scope.PointerMap();
+  var tap = {
+    events: [
+      'pointerdown',
+      'pointermove',
+      'pointerup',
+      'pointercancel',
+      'keyup'
+    ],
+    pointerdown: function(inEvent) {
+      if (inEvent.isPrimary && !inEvent.tapPrevented) {
+        pointermap.set(inEvent.pointerId, {
+          target: inEvent.target,
+          x: inEvent.clientX,
+          y: inEvent.clientY
+        });
+      }
+    },
+    pointermove: function(inEvent) {
+      if (inEvent.isPrimary) {
+        var start = pointermap.get(inEvent.pointerId);
+        if (start) {
+          if (inEvent.tapPrevented) {
+            pointermap.delete(inEvent.pointerId);
+          }
+        }
+      }
+    },
+    pointerup: function(inEvent) {
+      var start = pointermap.get(inEvent.pointerId);
+      if (start && !inEvent.tapPrevented) {
+        var t = scope.findLCA(start.target, inEvent.target);
+        if (t) {
+          var e = dispatcher.makeEvent('tap', {
+            x: inEvent.clientX,
+            y: inEvent.clientY,
+            detail: inEvent.detail,
+            pointerType: inEvent.pointerType
+          });
+          dispatcher.dispatchEvent(e, t);
+        }
+      }
+      pointermap.delete(inEvent.pointerId);
+    },
+    pointercancel: function(inEvent) {
+      pointermap.delete(inEvent.pointerId);
+    },
+    keyup: function(inEvent) {
+      var code = inEvent.keyCode;
+      // 32 == spacebar
+      if (code === 32) {
+        var t = inEvent.target;
+        if (!(t instanceof HTMLInputElement || t instanceof HTMLTextAreaElement)) {
+          dispatcher.dispatchEvent(dispatcher.makeEvent('tap', {
+            x: 0,
+            y: 0,
+            detail: 0,
+            pointerType: 'unavailable'
+          }), t);
+        }
+      }
+    },
+    preventTap: function(inPointerId) {
+      pointermap.delete(inPointerId);
+    }
+  };
+  dispatcher.registerRecognizer('tap', tap);
+})(window.PointerGestures);
+
+// Copyright 2011 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+(function(global) {
+  'use strict';
+
+  var filter = Array.prototype.filter.call.bind(Array.prototype.filter);
+
+  function getTreeScope(node) {
+    while (node.parentNode) {
+      node = node.parentNode;
+    }
+
+    return typeof node.getElementById === 'function' ? node : null;
+  }
+
+  // JScript does not have __proto__. We wrap all object literals with
+  // createObject which uses Object.create, Object.defineProperty and
+  // Object.getOwnPropertyDescriptor to create a new object that does the exact
+  // same thing. The main downside to this solution is that we have to extract
+  // all those property descriptors for IE.
+  var createObject = ('__proto__' in {}) ?
+      function(obj) { return obj; } :
+      function(obj) {
+        var proto = obj.__proto__;
+        if (!proto)
+          return obj;
+        var newObject = Object.create(proto);
+        Object.getOwnPropertyNames(obj).forEach(function(name) {
+          Object.defineProperty(newObject, name,
+                               Object.getOwnPropertyDescriptor(obj, name));
+        });
+        return newObject;
+      };
+
+  // IE does not support have Document.prototype.contains.
+  if (typeof document.contains != 'function') {
+    Document.prototype.contains = function(node) {
+      if (node === this || node.parentNode === this)
+        return true;
+      return this.documentElement.contains(node);
+    }
+  }
+
+  Node.prototype.bind = function(name, observable) {
+    console.error('Unhandled binding to Node: ', this, name, observable);
+  };
+
+  function unbind(node, name) {
+    var bindings = node.bindings;
+    if (!bindings) {
+      node.bindings = {};
+      return;
+    }
+
+    var binding = bindings[name];
+    if (!binding)
+      return;
+
+    binding.close();
+    bindings[name] = undefined;
+  }
+
+  Node.prototype.unbind = function(name) {
+    unbind(this, name);
+  };
+
+  Node.prototype.unbindAll = function() {
+    if (!this.bindings)
+      return;
+    var names = Object.keys(this.bindings);
+    for (var i = 0; i < names.length; i++) {
+      var binding = this.bindings[names[i]];
+      if (binding)
+        binding.close();
+    }
+
+    this.bindings = {};
+  };
+
+  function sanitizeValue(value) {
+    return value == null ? '' : value;
+  }
+
+  function updateText(node, value) {
+    node.data = sanitizeValue(value);
+  }
+
+  function textBinding(node) {
+    return function(value) {
+      return updateText(node, value);
+    };
+  }
+
+  Text.prototype.bind = function(name, value, oneTime) {
+    if (name !== 'textContent')
+      return Node.prototype.bind.call(this, name, value, oneTime);
+
+    if (oneTime)
+      return updateText(this, value);
+
+    unbind(this, 'textContent');
+    updateText(this, value.open(textBinding(this)));
+    return this.bindings.textContent = value;
+  }
+
+  function updateAttribute(el, name, conditional, value) {
+    if (conditional) {
+      if (value)
+        el.setAttribute(name, '');
+      else
+        el.removeAttribute(name);
+      return;
+    }
+
+    el.setAttribute(name, sanitizeValue(value));
+  }
+
+  function attributeBinding(el, name, conditional) {
+    return function(value) {
+      updateAttribute(el, name, conditional, value);
+    };
+  }
+
+  Element.prototype.bind = function(name, value, oneTime) {
+    var conditional = name[name.length - 1] == '?';
+    if (conditional) {
+      this.removeAttribute(name);
+      name = name.slice(0, -1);
+    }
+
+    if (oneTime)
+      return updateAttribute(this, name, conditional, value);
+
+    unbind(this, name);
+    updateAttribute(this, name, conditional,
+        value.open(attributeBinding(this, name, conditional)));
+
+    return this.bindings[name] = value;
+  };
+
+  var checkboxEventType;
+  (function() {
+    // Attempt to feature-detect which event (change or click) is fired first
+    // for checkboxes.
+    var div = document.createElement('div');
+    var checkbox = div.appendChild(document.createElement('input'));
+    checkbox.setAttribute('type', 'checkbox');
+    var first;
+    var count = 0;
+    checkbox.addEventListener('click', function(e) {
+      count++;
+      first = first || 'click';
+    });
+    checkbox.addEventListener('change', function() {
+      count++;
+      first = first || 'change';
+    });
+
+    var event = document.createEvent('MouseEvent');
+    event.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false,
+        false, false, false, 0, null);
+    checkbox.dispatchEvent(event);
+    // WebKit/Blink don't fire the change event if the element is outside the
+    // document, so assume 'change' for that case.
+    checkboxEventType = count == 1 ? 'change' : first;
+  })();
+
+  function getEventForInputType(element) {
+    switch (element.type) {
+      case 'checkbox':
+        return checkboxEventType;
+      case 'radio':
+      case 'select-multiple':
+      case 'select-one':
+        return 'change';
+      default:
+        return 'input';
+    }
+  }
+
+  function updateInput(input, property, value, santizeFn) {
+    input[property] = (santizeFn || sanitizeValue)(value);
+  }
+
+  function inputBinding(input, property, santizeFn) {
+    return function(value) {
+      return updateInput(input, property, value, santizeFn);
+    }
+  }
+
+  function noop() {}
+
+  function bindInputEvent(input, property, observable, postEventFn) {
+    var eventType = getEventForInputType(input);
+
+    function eventHandler() {
+      observable.setValue(input[property]);
+      observable.discardChanges();
+      (postEventFn || noop)(input);
+      Platform.performMicrotaskCheckpoint();
+    }
+    input.addEventListener(eventType, eventHandler);
+
+    var capturedClose = observable.close;
+    observable.close = function() {
+      if (!capturedClose)
+        return;
+      input.removeEventListener(eventType, eventHandler);
+
+      observable.close = capturedClose;
+      observable.close();
+      capturedClose = undefined;
+    }
+  }
+
+  function booleanSanitize(value) {
+    return Boolean(value);
+  }
+
+  // |element| is assumed to be an HTMLInputElement with |type| == 'radio'.
+  // Returns an array containing all radio buttons other than |element| that
+  // have the same |name|, either in the form that |element| belongs to or,
+  // if no form, in the document tree to which |element| belongs.
+  //
+  // This implementation is based upon the HTML spec definition of a
+  // "radio button group":
+  //   http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state.html#radio-button-group
+  //
+  function getAssociatedRadioButtons(element) {
+    if (element.form) {
+      return filter(element.form.elements, function(el) {
+        return el != element &&
+            el.tagName == 'INPUT' &&
+            el.type == 'radio' &&
+            el.name == element.name;
+      });
+    } else {
+      var treeScope = getTreeScope(element);
+      if (!treeScope)
+        return [];
+      var radios = treeScope.querySelectorAll(
+          'input[type="radio"][name="' + element.name + '"]');
+      return filter(radios, function(el) {
+        return el != element && !el.form;
+      });
+    }
+  }
+
+  function checkedPostEvent(input) {
+    // Only the radio button that is getting checked gets an event. We
+    // therefore find all the associated radio buttons and update their
+    // check binding manually.
+    if (input.tagName === 'INPUT' &&
+        input.type === 'radio') {
+      getAssociatedRadioButtons(input).forEach(function(radio) {
+        var checkedBinding = radio.bindings.checked;
+        if (checkedBinding) {
+          // Set the value directly to avoid an infinite call stack.
+          checkedBinding.setValue(false);
+        }
+      });
+    }
+  }
+
+  HTMLInputElement.prototype.bind = function(name, value, oneTime) {
+    if (name !== 'value' && name !== 'checked')
+      return HTMLElement.prototype.bind.call(this, name, value, oneTime);
+
+
+    this.removeAttribute(name);
+    var sanitizeFn = name == 'checked' ? booleanSanitize : sanitizeValue;
+    var postEventFn = name == 'checked' ? checkedPostEvent : noop;
+
+    if (oneTime)
+      return updateInput(this, name, value, sanitizeFn);
+
+    unbind(this, name);
+    bindInputEvent(this, name, value, postEventFn);
+    updateInput(this, name,
+                value.open(inputBinding(this, name, sanitizeFn)),
+                sanitizeFn);
+
+    return this.bindings[name] = value;
+  }
+
+  HTMLTextAreaElement.prototype.bind = function(name, value, oneTime) {
+    if (name !== 'value')
+      return HTMLElement.prototype.bind.call(this, name, value, oneTime);
+
+    this.removeAttribute('value');
+
+    if (oneTime)
+      return updateInput(this, 'value', value);
+
+    unbind(this, 'value');
+    bindInputEvent(this, 'value', value);
+    updateInput(this, 'value',
+                value.open(inputBinding(this, 'value', sanitizeValue)));
+
+    return this.bindings.value = value;
+  }
+
+  function updateOption(option, value) {
+    var parentNode = option.parentNode;;
+    var select;
+    var selectBinding;
+    var oldValue;
+    if (parentNode instanceof HTMLSelectElement &&
+        parentNode.bindings &&
+        parentNode.bindings.value) {
+      select = parentNode;
+      selectBinding = select.bindings.value;
+      oldValue = select.value;
+    }
+
+    option.value = sanitizeValue(value);
+
+    if (select && select.value != oldValue) {
+      selectBinding.setValue(select.value);
+      selectBinding.discardChanges();
+      Platform.performMicrotaskCheckpoint();
+    }
+  }
+
+  function optionBinding(option) {
+    return function(value) {
+      updateOption(option, value);
+    }
+  }
+
+  HTMLOptionElement.prototype.bind = function(name, value, oneTime) {
+    if (name !== 'value')
+      return HTMLElement.prototype.bind.call(this, name, value, oneTime);
+
+    this.removeAttribute('value');
+
+    if (oneTime)
+      return updateOption(this, value);
+
+    unbind(this, 'value');
+    bindInputEvent(this, 'value', value);
+    updateOption(this, value.open(optionBinding(this)));
+    return this.bindings.value = value;
+  }
+
+  HTMLSelectElement.prototype.bind = function(name, value, oneTime) {
+    if (name === 'selectedindex')
+      name = 'selectedIndex';
+
+    if (name !== 'selectedIndex' && name !== 'value')
+      return HTMLElement.prototype.bind.call(this, name, value, oneTime);
+
+    this.removeAttribute(name);
+
+    if (oneTime)
+      return updateInput(this, name, value);
+
+    unbind(this, name);
+    bindInputEvent(this, name, value);
+    updateInput(this, name,
+                value.open(inputBinding(this, name)));
+    return this.bindings[name] = value;
+  }
+})(this);
+
+// Copyright 2011 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+(function(global) {
+  'use strict';
+
+  function assert(v) {
+    if (!v)
+      throw new Error('Assertion failed');
+  }
+
+  var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
+
+  function getFragmentRoot(node) {
+    var p;
+    while (p = node.parentNode) {
+      node = p;
+    }
+
+    return node;
+  }
+
+  function searchRefId(node, id) {
+    if (!id)
+      return;
+
+    var ref;
+    var selector = '#' + id;
+    while (!ref) {
+      node = getFragmentRoot(node);
+
+      if (node.protoContent_)
+        ref = node.protoContent_.querySelector(selector);
+      else if (node.getElementById)
+        ref = node.getElementById(id);
+
+      if (ref || !node.templateCreator_)
+        break
+
+      node = node.templateCreator_;
+    }
+
+    return ref;
+  }
+
+  function getInstanceRoot(node) {
+    while (node.parentNode) {
+      node = node.parentNode;
+    }
+    return node.templateCreator_ ? node : null;
+  }
+
+  var Map;
+  if (global.Map && typeof global.Map.prototype.forEach === 'function') {
+    Map = global.Map;
+  } else {
+    Map = function() {
+      this.keys = [];
+      this.values = [];
+    };
+
+    Map.prototype = {
+      set: function(key, value) {
+        var index = this.keys.indexOf(key);
+        if (index < 0) {
+          this.keys.push(key);
+          this.values.push(value);
+        } else {
+          this.values[index] = value;
+        }
+      },
+
+      get: function(key) {
+        var index = this.keys.indexOf(key);
+        if (index < 0)
+          return;
+
+        return this.values[index];
+      },
+
+      delete: function(key, value) {
+        var index = this.keys.indexOf(key);
+        if (index < 0)
+          return false;
+
+        this.keys.splice(index, 1);
+        this.values.splice(index, 1);
+        return true;
+      },
+
+      forEach: function(f, opt_this) {
+        for (var i = 0; i < this.keys.length; i++)
+          f.call(opt_this || this, this.values[i], this.keys[i], this);
+      }
+    };
+  }
+
+  // JScript does not have __proto__. We wrap all object literals with
+  // createObject which uses Object.create, Object.defineProperty and
+  // Object.getOwnPropertyDescriptor to create a new object that does the exact
+  // same thing. The main downside to this solution is that we have to extract
+  // all those property descriptors for IE.
+  var createObject = ('__proto__' in {}) ?
+      function(obj) { return obj; } :
+      function(obj) {
+        var proto = obj.__proto__;
+        if (!proto)
+          return obj;
+        var newObject = Object.create(proto);
+        Object.getOwnPropertyNames(obj).forEach(function(name) {
+          Object.defineProperty(newObject, name,
+                               Object.getOwnPropertyDescriptor(obj, name));
+        });
+        return newObject;
+      };
+
+  // IE does not support have Document.prototype.contains.
+  if (typeof document.contains != 'function') {
+    Document.prototype.contains = function(node) {
+      if (node === this || node.parentNode === this)
+        return true;
+      return this.documentElement.contains(node);
+    }
+  }
+
+  var BIND = 'bind';
+  var REPEAT = 'repeat';
+  var IF = 'if';
+
+  var templateAttributeDirectives = {
+    'template': true,
+    'repeat': true,
+    'bind': true,
+    'ref': true
+  };
+
+  var semanticTemplateElements = {
+    'THEAD': true,
+    'TBODY': true,
+    'TFOOT': true,
+    'TH': true,
+    'TR': true,
+    'TD': true,
+    'COLGROUP': true,
+    'COL': true,
+    'CAPTION': true,
+    'OPTION': true,
+    'OPTGROUP': true
+  };
+
+  var hasTemplateElement = typeof HTMLTemplateElement !== 'undefined';
+
+  var allTemplatesSelectors = 'template, ' +
+      Object.keys(semanticTemplateElements).map(function(tagName) {
+        return tagName.toLowerCase() + '[template]';
+      }).join(', ');
+
+  function isSVGTemplate(el) {
+    return el.tagName == 'template' &&
+           el.namespaceURI == 'http://www.w3.org/2000/svg';
+  }
+
+  function isHTMLTemplate(el) {
+    return el.tagName == 'TEMPLATE' &&
+           el.namespaceURI == 'http://www.w3.org/1999/xhtml';
+  }
+
+  function isAttributeTemplate(el) {
+    return Boolean(semanticTemplateElements[el.tagName] &&
+                   el.hasAttribute('template'));
+  }
+
+  function isTemplate(el) {
+    if (el.isTemplate_ === undefined)
+      el.isTemplate_ = el.tagName == 'TEMPLATE' || isAttributeTemplate(el);
+
+    return el.isTemplate_;
+  }
+
+  // FIXME: Observe templates being added/removed from documents
+  // FIXME: Expose imperative API to decorate and observe templates in
+  // "disconnected tress" (e.g. ShadowRoot)
+  document.addEventListener('DOMContentLoaded', function(e) {
+    bootstrapTemplatesRecursivelyFrom(document);
+    // FIXME: Is this needed? Seems like it shouldn't be.
+    Platform.performMicrotaskCheckpoint();
+  }, false);
+
+  function forAllTemplatesFrom(node, fn) {
+    var subTemplates = node.querySelectorAll(allTemplatesSelectors);
+
+    if (isTemplate(node))
+      fn(node)
+    forEach(subTemplates, fn);
+  }
+
+  function bootstrapTemplatesRecursivelyFrom(node) {
+    function bootstrap(template) {
+      if (!HTMLTemplateElement.decorate(template))
+        bootstrapTemplatesRecursivelyFrom(template.content);
+    }
+
+    forAllTemplatesFrom(node, bootstrap);
+  }
+
+  if (!hasTemplateElement) {
+    /**
+     * This represents a <template> element.
+     * @constructor
+     * @extends {HTMLElement}
+     */
+    global.HTMLTemplateElement = function() {
+      throw TypeError('Illegal constructor');
+    };
+  }
+
+  var hasProto = '__proto__' in {};
+
+  function mixin(to, from) {
+    Object.getOwnPropertyNames(from).forEach(function(name) {
+      Object.defineProperty(to, name,
+                            Object.getOwnPropertyDescriptor(from, name));
+    });
+  }
+
+  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
+  function getOrCreateTemplateContentsOwner(template) {
+    var doc = template.ownerDocument
+    if (!doc.defaultView)
+      return doc;
+    var d = doc.templateContentsOwner_;
+    if (!d) {
+      // TODO(arv): This should either be a Document or HTMLDocument depending
+      // on doc.
+      d = doc.implementation.createHTMLDocument('');
+      while (d.lastChild) {
+        d.removeChild(d.lastChild);
+      }
+      doc.templateContentsOwner_ = d;
+    }
+    return d;
+  }
+
+  function getTemplateStagingDocument(template) {
+    if (!template.stagingDocument_) {
+      var owner = template.ownerDocument;
+      if (!owner.stagingDocument_) {
+        owner.stagingDocument_ = owner.implementation.createHTMLDocument('');
+        owner.stagingDocument_.stagingDocument_ = owner.stagingDocument_;
+      }
+
+      template.stagingDocument_ = owner.stagingDocument_;
+    }
+
+    return template.stagingDocument_;
+  }
+
+  // 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>
+  //
+  function extractTemplateFromAttributeTemplate(el) {
+    var template = el.ownerDocument.createElement('template');
+    el.parentNode.insertBefore(template, el);
+
+    var attribs = el.attributes;
+    var count = attribs.length;
+    while (count-- > 0) {
+      var attrib = attribs[count];
+      if (templateAttributeDirectives[attrib.name]) {
+        if (attrib.name !== 'template')
+          template.setAttribute(attrib.name, attrib.value);
+        el.removeAttribute(attrib.name);
+      }
+    }
+
+    return template;
+  }
+
+  function extractTemplateFromSVGTemplate(el) {
+    var template = el.ownerDocument.createElement('template');
+    el.parentNode.insertBefore(template, el);
+
+    var attribs = el.attributes;
+    var count = attribs.length;
+    while (count-- > 0) {
+      var attrib = attribs[count];
+      template.setAttribute(attrib.name, attrib.value);
+      el.removeAttribute(attrib.name);
+    }
+
+    el.parentNode.removeChild(el);
+    return template;
+  }
+
+  function liftNonNativeTemplateChildrenIntoContent(template, el, useRoot) {
+    var content = template.content;
+    if (useRoot) {
+      content.appendChild(el);
+      return;
+    }
+
+    var child;
+    while (child = el.firstChild) {
+      content.appendChild(child);
+    }
+  }
+
+  var templateObserver;
+  if (typeof MutationObserver == 'function') {
+    templateObserver = new MutationObserver(function(records) {
+      for (var i = 0; i < records.length; i++) {
+        records[i].target.refChanged_();
+      }
+    });
+  }
+
+  /**
+   * Ensures proper API and content model for template elements.
+   * @param {HTMLTemplateElement} opt_instanceRef The template element which
+   *     |el| template element will return as the value of its ref(), and whose
+   *     content will be used as source when createInstance() is invoked.
+   */
+  HTMLTemplateElement.decorate = function(el, opt_instanceRef) {
+    if (el.templateIsDecorated_)
+      return false;
+
+    var templateElement = el;
+    templateElement.templateIsDecorated_ = true;
+
+    var isNativeHTMLTemplate = isHTMLTemplate(templateElement) &&
+                               hasTemplateElement;
+    var bootstrapContents = isNativeHTMLTemplate;
+    var liftContents = !isNativeHTMLTemplate;
+    var liftRoot = false;
+
+    if (!isNativeHTMLTemplate) {
+      if (isAttributeTemplate(templateElement)) {
+        assert(!opt_instanceRef);
+        templateElement = extractTemplateFromAttributeTemplate(el);
+        templateElement.templateIsDecorated_ = true;
+        isNativeHTMLTemplate = hasTemplateElement;
+        liftRoot = true;
+      } else if (isSVGTemplate(templateElement)) {
+        templateElement = extractTemplateFromSVGTemplate(el);
+        templateElement.templateIsDecorated_ = true;
+        isNativeHTMLTemplate = hasTemplateElement;
+      }
+    }
+
+    if (!isNativeHTMLTemplate) {
+      fixTemplateElementPrototype(templateElement);
+      var doc = getOrCreateTemplateContentsOwner(templateElement);
+      templateElement.content_ = doc.createDocumentFragment();
+    }
+
+    if (opt_instanceRef) {
+      // template is contained within an instance, its direct content must be
+      // empty
+      templateElement.instanceRef_ = opt_instanceRef;
+    } else if (liftContents) {
+      liftNonNativeTemplateChildrenIntoContent(templateElement,
+                                               el,
+                                               liftRoot);
+    } else if (bootstrapContents) {
+      bootstrapTemplatesRecursivelyFrom(templateElement.content);
+    }
+
+    return true;
+  };
+
+  // TODO(rafaelw): This used to decorate recursively all templates from a given
+  // node. This happens by default on 'DOMContentLoaded', but may be needed
+  // in subtrees not descendent from document (e.g. ShadowRoot).
+  // Review whether this is the right public API.
+  HTMLTemplateElement.bootstrap = bootstrapTemplatesRecursivelyFrom;
+
+  var htmlElement = global.HTMLUnknownElement || HTMLElement;
+
+  var contentDescriptor = {
+    get: function() {
+      return this.content_;
+    },
+    enumerable: true,
+    configurable: true
+  };
+
+  if (!hasTemplateElement) {
+    // Gecko is more picky with the prototype than WebKit. Make sure to use the
+    // same prototype as created in the constructor.
+    HTMLTemplateElement.prototype = Object.create(htmlElement.prototype);
+
+    Object.defineProperty(HTMLTemplateElement.prototype, 'content',
+                          contentDescriptor);
+  }
+
+  function fixTemplateElementPrototype(el) {
+    if (hasProto)
+      el.__proto__ = HTMLTemplateElement.prototype;
+    else
+      mixin(el, HTMLTemplateElement.prototype);
+  }
+
+  function ensureSetModelScheduled(template) {
+    if (!template.setModelFn_) {
+      template.setModelFn_ = function() {
+        template.setModelFnScheduled_ = false;
+        var map = getBindings(template,
+            template.delegate_ && template.delegate_.prepareBinding);
+        processBindings(template, map, template.model_);
+      };
+    }
+
+    if (!template.setModelFnScheduled_) {
+      template.setModelFnScheduled_ = true;
+      Observer.runEOM_(template.setModelFn_);
+    }
+  }
+
+  mixin(HTMLTemplateElement.prototype, {
+    bind: function(name, value, oneTime) {
+      if (name != 'ref')
+        return Element.prototype.bind.call(this, name, value, oneTime);
+
+      var self = this;
+      var ref = oneTime ? value : value.open(function(ref) {
+        self.setAttribute('ref', ref);
+        self.refChanged_();
+      });
+
+      this.setAttribute('ref', ref);
+      this.refChanged_();
+      if (oneTime)
+        return;
+
+      this.unbind('ref');
+      return this.bindings.ref = value;
+    },
+
+    processBindingDirectives_: function(directives) {
+      if (this.iterator_)
+        this.iterator_.closeDeps();
+
+      if (!directives.if && !directives.bind && !directives.repeat) {
+        if (this.iterator_) {
+          this.iterator_.close();
+          this.iterator_ = undefined;
+          this.bindings.iterator = undefined;
+        }
+
+        return;
+      }
+
+      if (!this.iterator_) {
+        this.iterator_ = new TemplateIterator(this);
+        this.bindings = this.bindings || {};
+        this.bindings.iterator = this.iterator_;
+      }
+
+      this.iterator_.updateDependencies(directives, this.model_);
+
+      if (templateObserver) {
+        templateObserver.observe(this, { attributes: true,
+                                         attributeFilter: ['ref'] });
+      }
+
+      return this.iterator_;
+    },
+
+    createInstance: function(model, bindingDelegate, delegate_,
+                             instanceBindings_) {
+      if (bindingDelegate)
+        delegate_ = this.newDelegate_(bindingDelegate);
+
+      if (!this.refContent_)
+        this.refContent_ = this.ref_.content;
+      var content = this.refContent_;
+      var map = this.bindingMap_;
+      if (!map || map.content !== content) {
+        // TODO(rafaelw): Setup a MutationObserver on content to detect
+        // when the instanceMap is invalid.
+        map = createInstanceBindingMap(content,
+            delegate_ && delegate_.prepareBinding) || [];
+        map.content = content;
+        this.bindingMap_ = map;
+      }
+
+      var stagingDocument = getTemplateStagingDocument(this);
+      var instance = stagingDocument.createDocumentFragment();
+      instance.templateCreator_ = this;
+      instance.protoContent_ = content;
+
+      var instanceRecord = {
+        firstNode: null,
+        lastNode: null,
+        model: model
+      };
+
+      var i = 0;
+      for (var child = content.firstChild; child; child = child.nextSibling) {
+        var clone = cloneAndBindInstance(child, instance, stagingDocument,
+                                         map.children[i++],
+                                         model,
+                                         delegate_,
+                                         instanceBindings_);
+        clone.templateInstance_ = instanceRecord;
+      }
+
+      instanceRecord.firstNode = instance.firstChild;
+      instanceRecord.lastNode = instance.lastChild;
+      instance.templateCreator_ = undefined;
+      instance.protoContent_ = undefined;
+      return instance;
+    },
+
+    get model() {
+      return this.model_;
+    },
+
+    set model(model) {
+      this.model_ = model;
+      ensureSetModelScheduled(this);
+    },
+
+    get bindingDelegate() {
+      return this.delegate_ && this.delegate_.raw;
+    },
+
+    refChanged_: function() {
+      if (!this.iterator_ || this.refContent_ === this.ref_.content)
+        return;
+
+      this.refContent_ = undefined;
+      this.iterator_.valueChanged();
+      this.iterator_.updateIteratedValue();
+    },
+
+    clear: function() {
+      this.model_ = undefined;
+      this.delegate_ = undefined;
+      this.bindings_ = undefined;
+      this.refContent_ = undefined;
+      if (!this.iterator_)
+        return;
+      this.iterator_.valueChanged();
+      this.iterator_.close()
+      this.iterator_ = undefined;
+    },
+
+    setDelegate_: function(delegate) {
+      this.delegate_ = delegate;
+      this.bindingMap_ = undefined;
+      if (this.iterator_) {
+        this.iterator_.instancePositionChangedFn_ = undefined;
+        this.iterator_.instanceModelFn_ = undefined;
+      }
+    },
+
+    newDelegate_: function(bindingDelegate) {
+      if (!bindingDelegate)
+        return {};
+
+      function delegateFn(name) {
+        var fn = bindingDelegate && bindingDelegate[name];
+        if (typeof fn != 'function')
+          return;
+
+        return function() {
+          return fn.apply(bindingDelegate, arguments);
+        };
+      }
+
+      return {
+        raw: bindingDelegate,
+        prepareBinding: delegateFn('prepareBinding'),
+        prepareInstanceModel: delegateFn('prepareInstanceModel'),
+        prepareInstancePositionChanged:
+            delegateFn('prepareInstancePositionChanged')
+      };
+    },
+
+    // TODO(rafaelw): Assigning .bindingDelegate always succeeds. It may
+    // make sense to issue a warning or even throw if the template is already
+    // "activated", since this would be a strange thing to do.
+    set bindingDelegate(bindingDelegate) {
+      if (this.delegate_) {
+        throw Error('Template must be cleared before a new bindingDelegate ' +
+                    'can be assigned');
+      }
+
+      this.setDelegate_(this.newDelegate_(bindingDelegate));
+    },
+
+    get ref_() {
+      var ref = searchRefId(this, this.getAttribute('ref'));
+      if (!ref)
+        ref = this.instanceRef_;
+
+      if (!ref)
+        return this;
+
+      var nextRef = ref.ref_;
+      return nextRef ? nextRef : ref;
+    }
+  });
+
+  // Returns
+  //   a) undefined if there are no mustaches.
+  //   b) [TEXT, (ONE_TIME?, PATH, DELEGATE_FN, TEXT)+] if there is at least one mustache.
+  function parseMustaches(s, name, node, prepareBindingFn) {
+    if (!s || !s.length)
+      return;
+
+    var tokens;
+    var length = s.length;
+    var startIndex = 0, lastIndex = 0, endIndex = 0;
+    var onlyOneTime = true;
+    while (lastIndex < length) {
+      var startIndex = s.indexOf('{{', lastIndex);
+      var oneTimeStart = s.indexOf('[[', lastIndex);
+      var oneTime = false;
+      var terminator = '}}';
+
+      if (oneTimeStart >= 0 &&
+          (startIndex < 0 || oneTimeStart < startIndex)) {
+        startIndex = oneTimeStart;
+        oneTime = true;
+        terminator = ']]';
+      }
+
+      endIndex = startIndex < 0 ? -1 : s.indexOf(terminator, startIndex + 2);
+
+      if (endIndex < 0) {
+        if (!tokens)
+          return;
+
+        tokens.push(s.slice(lastIndex)); // TEXT
+        break;
+      }
+
+      tokens = tokens || [];
+      tokens.push(s.slice(lastIndex, startIndex)); // TEXT
+      var pathString = s.slice(startIndex + 2, endIndex).trim();
+      tokens.push(oneTime); // ONE_TIME?
+      onlyOneTime = onlyOneTime && oneTime;
+      tokens.push(Path.get(pathString)); // PATH
+      var delegateFn = prepareBindingFn &&
+                       prepareBindingFn(pathString, name, node);
+      tokens.push(delegateFn); // DELEGATE_FN
+      lastIndex = endIndex + 2;
+    }
+
+    if (lastIndex === length)
+      tokens.push(''); // TEXT
+
+    tokens.hasOnePath = tokens.length === 5;
+    tokens.isSimplePath = tokens.hasOnePath &&
+                          tokens[0] == '' &&
+                          tokens[4] == '';
+    tokens.onlyOneTime = onlyOneTime;
+
+    tokens.combinator = function(values) {
+      var newValue = tokens[0];
+
+      for (var i = 1; i < tokens.length; i += 4) {
+        var value = tokens.hasOnePath ? values : values[(i - 1) / 4];
+        if (value !== undefined)
+          newValue += value;
+        newValue += tokens[i + 3];
+      }
+
+      return newValue;
+    }
+
+    return tokens;
+  };
+
+  function processOneTimeBinding(name, tokens, node, model) {
+    if (tokens.hasOnePath) {
+      var delegateFn = tokens[3];
+      var value = delegateFn ? delegateFn(model, node, true) :
+                               tokens[2].getValueFrom(model);
+      return tokens.isSimplePath ? value : tokens.combinator(value);
+    }
+
+    var values = [];
+    for (var i = 1; i < tokens.length; i += 4) {
+      var delegateFn = tokens[i + 2];
+      values[(i - 1) / 4] = delegateFn ? delegateFn(model, node) :
+          tokens[i + 1].getValueFrom(model);
+    }
+
+    return tokens.combinator(values);
+  }
+
+  function processSinglePathBinding(name, tokens, node, model) {
+    var delegateFn = tokens[3];
+    var observer = delegateFn ? delegateFn(model, node, false) :
+        new PathObserver(model, tokens[2]);
+
+    return tokens.isSimplePath ? observer :
+        new ObserverTransform(observer, tokens.combinator);
+  }
+
+  function processBinding(name, tokens, node, model) {
+    if (tokens.onlyOneTime)
+      return processOneTimeBinding(name, tokens, node, model);
+
+    if (tokens.hasOnePath)
+      return processSinglePathBinding(name, tokens, node, model);
+
+    var observer = new CompoundObserver();
+
+    for (var i = 1; i < tokens.length; i += 4) {
+      var oneTime = tokens[i];
+      var delegateFn = tokens[i + 2];
+
+      if (delegateFn) {
+        var value = delegateFn(model, node, oneTime);
+        if (oneTime)
+          observer.addPath(value)
+        else
+          observer.addObserver(value);
+        continue;
+      }
+
+      var path = tokens[i + 1];
+      if (oneTime)
+        observer.addPath(path.getValueFrom(model))
+      else
+        observer.addPath(model, path);
+    }
+
+    return new ObserverTransform(observer, tokens.combinator);
+  }
+
+  function processBindings(node, bindings, model, instanceBindings) {
+    for (var i = 0; i < bindings.length; i += 2) {
+      var name = bindings[i]
+      var tokens = bindings[i + 1];
+      var value = processBinding(name, tokens, node, model);
+      var binding = node.bind(name, value, tokens.onlyOneTime);
+      if (binding && instanceBindings)
+        instanceBindings.push(binding);
+    }
+
+    if (!bindings.isTemplate)
+      return;
+
+    node.model_ = model;
+    var iter = node.processBindingDirectives_(bindings);
+    if (instanceBindings && iter)
+      instanceBindings.push(iter);
+  }
+
+  function parseWithDefault(el, name, prepareBindingFn) {
+    var v = el.getAttribute(name);
+    return parseMustaches(v == '' ? '{{}}' : v, name, el, prepareBindingFn);
+  }
+
+  function parseAttributeBindings(element, prepareBindingFn) {
+    assert(element);
+
+    var bindings = [];
+    var ifFound = false;
+    var bindFound = false;
+
+    for (var i = 0; i < element.attributes.length; i++) {
+      var attr = element.attributes[i];
+      var name = attr.name;
+      var value = attr.value;
+
+      // Allow bindings expressed in attributes to be prefixed with underbars.
+      // We do this to allow correct semantics for browsers that don't implement
+      // <template> where certain attributes might trigger side-effects -- and
+      // for IE which sanitizes certain attributes, disallowing mustache
+      // replacements in their text.
+      while (name[0] === '_') {
+        name = name.substring(1);
+      }
+
+      if (isTemplate(element) &&
+          (name === IF || name === BIND || name === REPEAT)) {
+        continue;
+      }
+
+      var tokens = parseMustaches(value, name, element,
+                                  prepareBindingFn);
+      if (!tokens)
+        continue;
+
+      bindings.push(name, tokens);
+    }
+
+    if (isTemplate(element)) {
+      bindings.isTemplate = true;
+      bindings.if = parseWithDefault(element, IF, prepareBindingFn);
+      bindings.bind = parseWithDefault(element, BIND, prepareBindingFn);
+      bindings.repeat = parseWithDefault(element, REPEAT, prepareBindingFn);
+
+      if (bindings.if && !bindings.bind && !bindings.repeat)
+        bindings.bind = parseMustaches('{{}}', BIND, element, prepareBindingFn);
+    }
+
+    return bindings;
+  }
+
+  function getBindings(node, prepareBindingFn) {
+    if (node.nodeType === Node.ELEMENT_NODE)
+      return parseAttributeBindings(node, prepareBindingFn);
+
+    if (node.nodeType === Node.TEXT_NODE) {
+      var tokens = parseMustaches(node.data, 'textContent', node,
+                                  prepareBindingFn);
+      if (tokens)
+        return ['textContent', tokens];
+    }
+
+    return [];
+  }
+
+  function cloneAndBindInstance(node, parent, stagingDocument, bindings, model,
+                                delegate,
+                                instanceBindings,
+                                instanceRecord) {
+    var clone = parent.appendChild(stagingDocument.importNode(node, false));
+
+    var i = 0;
+    for (var child = node.firstChild; child; child = child.nextSibling) {
+      cloneAndBindInstance(child, clone, stagingDocument,
+                            bindings.children[i++],
+                            model,
+                            delegate,
+                            instanceBindings);
+    }
+
+    if (bindings.isTemplate) {
+      HTMLTemplateElement.decorate(clone, node);
+      if (delegate)
+        clone.setDelegate_(delegate);
+    }
+
+    processBindings(clone, bindings, model, instanceBindings);
+    return clone;
+  }
+
+  function createInstanceBindingMap(node, prepareBindingFn) {
+    var map = getBindings(node, prepareBindingFn);
+    map.children = {};
+    var index = 0;
+    for (var child = node.firstChild; child; child = child.nextSibling) {
+      map.children[index++] = createInstanceBindingMap(child, prepareBindingFn);
+    }
+
+    return map;
+  }
+
+  Object.defineProperty(Node.prototype, 'templateInstance', {
+    get: function() {
+      var instance = this.templateInstance_;
+      return instance ? instance :
+          (this.parentNode ? this.parentNode.templateInstance : undefined);
+    }
+  });
+
+  function TemplateIterator(templateElement) {
+    this.closed = false;
+    this.templateElement_ = templateElement;
+
+    // Flattened array of tuples:
+    //   <instanceTerminatorNode, [bindingsSetupByInstance]>
+    this.terminators = [];
+
+    this.deps = undefined;
+    this.iteratedValue = [];
+    this.presentValue = undefined;
+    this.arrayObserver = undefined;
+  }
+
+  TemplateIterator.prototype = {
+    closeDeps: function() {
+      var deps = this.deps;
+      if (deps) {
+        if (deps.ifOneTime === false)
+          deps.ifValue.close();
+        if (deps.oneTime === false)
+          deps.value.close();
+      }
+    },
+
+    updateDependencies: function(directives, model) {
+      this.closeDeps();
+
+      var deps = this.deps = {};
+      var template = this.templateElement_;
+
+      if (directives.if) {
+        deps.hasIf = true;
+        deps.ifOneTime = directives.if.onlyOneTime;
+        deps.ifValue = processBinding(IF, directives.if, template, model);
+
+        // oneTime if & predicate is false. nothing else to do.
+        if (deps.ifOneTime && !deps.ifValue) {
+          this.updateIteratedValue();
+          return;
+        }
+
+        if (!deps.ifOneTime)
+          deps.ifValue.open(this.updateIteratedValue, this);
+      }
+
+      if (directives.repeat) {
+        deps.repeat = true;
+        deps.oneTime = directives.repeat.onlyOneTime;
+        deps.value = processBinding(REPEAT, directives.repeat, template, model);
+      } else {
+        deps.repeat = false;
+        deps.oneTime = directives.bind.onlyOneTime;
+        deps.value = processBinding(BIND, directives.bind, template, model);
+      }
+
+      if (!deps.oneTime)
+        deps.value.open(this.updateIteratedValue, this);
+
+      this.updateIteratedValue();
+    },
+
+    updateIteratedValue: function() {
+      if (this.deps.hasIf) {
+        var ifValue = this.deps.ifValue;
+        if (!this.deps.ifOneTime)
+          ifValue = ifValue.discardChanges();
+        if (!ifValue) {
+          this.valueChanged();
+          return;
+        }
+      }
+
+      var value = this.deps.value;
+      if (!this.deps.oneTime)
+        value = value.discardChanges();
+      if (!this.deps.repeat)
+        value = [value];
+      var observe = this.deps.repeat &&
+                    !this.deps.oneTime &&
+                    Array.isArray(value);
+      this.valueChanged(value, observe);
+    },
+
+    valueChanged: function(value, observeValue) {
+      if (!Array.isArray(value))
+        value = [];
+
+      if (value === this.iteratedValue)
+        return;
+
+      this.unobserve();
+      this.presentValue = value;
+      if (observeValue) {
+        this.arrayObserver = new ArrayObserver(this.presentValue);
+        this.arrayObserver.open(this.handleSplices, this);
+      }
+
+      this.handleSplices(ArrayObserver.calculateSplices(this.presentValue,
+                                                        this.iteratedValue));
+    },
+
+    getTerminatorAt: function(index) {
+      if (index == -1)
+        return this.templateElement_;
+      var terminator = this.terminators[index*2];
+      if (terminator.nodeType !== Node.ELEMENT_NODE ||
+          this.templateElement_ === terminator) {
+        return terminator;
+      }
+
+      var subIterator = terminator.iterator_;
+      if (!subIterator)
+        return terminator;
+
+      return subIterator.getTerminatorAt(subIterator.terminators.length/2 - 1);
+    },
+
+    // TODO(rafaelw): If we inserting sequences of instances we can probably
+    // avoid lots of calls to getTerminatorAt(), or cache its result.
+    insertInstanceAt: function(index, fragment, instanceNodes,
+                               instanceBindings) {
+      var previousTerminator = this.getTerminatorAt(index - 1);
+      var terminator = previousTerminator;
+      if (fragment)
+        terminator = fragment.lastChild || terminator;
+      else if (instanceNodes)
+        terminator = instanceNodes[instanceNodes.length - 1] || terminator;
+
+      this.terminators.splice(index*2, 0, terminator, instanceBindings);
+      var parent = this.templateElement_.parentNode;
+      var insertBeforeNode = previousTerminator.nextSibling;
+
+      if (fragment) {
+        parent.insertBefore(fragment, insertBeforeNode);
+      } else if (instanceNodes) {
+        for (var i = 0; i < instanceNodes.length; i++)
+          parent.insertBefore(instanceNodes[i], insertBeforeNode);
+      }
+    },
+
+    extractInstanceAt: function(index) {
+      var instanceNodes = [];
+      var previousTerminator = this.getTerminatorAt(index - 1);
+      var terminator = this.getTerminatorAt(index);
+      instanceNodes.instanceBindings = this.terminators[index*2 + 1];
+      this.terminators.splice(index*2, 2);
+
+      var parent = this.templateElement_.parentNode;
+      while (terminator !== previousTerminator) {
+        var node = previousTerminator.nextSibling;
+        if (node == terminator)
+          terminator = previousTerminator;
+
+        parent.removeChild(node);
+        instanceNodes.push(node);
+      }
+
+      return instanceNodes;
+    },
+
+    getDelegateFn: function(fn) {
+      fn = fn && fn(this.templateElement_);
+      return typeof fn === 'function' ? fn : null;
+    },
+
+    handleSplices: function(splices) {
+      if (this.closed || !splices.length)
+        return;
+
+      var template = this.templateElement_;
+
+      if (!template.parentNode) {
+        this.close();
+        return;
+      }
+
+      ArrayObserver.applySplices(this.iteratedValue, this.presentValue,
+                                 splices);
+
+      var delegate = template.delegate_;
+      if (this.instanceModelFn_ === undefined) {
+        this.instanceModelFn_ =
+            this.getDelegateFn(delegate && delegate.prepareInstanceModel);
+      }
+
+      if (this.instancePositionChangedFn_ === undefined) {
+        this.instancePositionChangedFn_ =
+            this.getDelegateFn(delegate &&
+                               delegate.prepareInstancePositionChanged);
+      }
+
+      var instanceCache = new Map;
+      var removeDelta = 0;
+      splices.forEach(function(splice) {
+        splice.removed.forEach(function(model) {
+          var instanceNodes =
+              this.extractInstanceAt(splice.index + removeDelta);
+          instanceCache.set(model, instanceNodes);
+        }, this);
+
+        removeDelta -= splice.addedCount;
+      }, this);
+
+      splices.forEach(function(splice) {
+        var addIndex = splice.index;
+        for (; addIndex < splice.index + splice.addedCount; addIndex++) {
+          var model = this.iteratedValue[addIndex];
+          var fragment = undefined;
+          var instanceNodes = instanceCache.get(model);
+          var instanceBindings;
+          if (instanceNodes) {
+            instanceCache.delete(model);
+            instanceBindings = instanceNodes.instanceBindings;
+          } else {
+            instanceBindings = [];
+            if (this.instanceModelFn_)
+              model = this.instanceModelFn_(model);
+
+            if (model !== undefined) {
+              fragment = template.createInstance(model, undefined, delegate,
+                                                 instanceBindings);
+            }
+          }
+
+          this.insertInstanceAt(addIndex, fragment, instanceNodes,
+                                instanceBindings);
+        }
+      }, this);
+
+      instanceCache.forEach(function(instanceNodes) {
+        this.closeInstanceBindings(instanceNodes.instanceBindings);
+      }, this);
+
+      if (this.instancePositionChangedFn_)
+        this.reportInstancesMoved(splices);
+    },
+
+    reportInstanceMoved: function(index) {
+      var previousTerminator = this.getTerminatorAt(index - 1);
+      var terminator = this.getTerminatorAt(index);
+      if (previousTerminator === terminator)
+        return; // instance has zero nodes.
+
+      // We must use the first node of the instance, because any subsequent
+      // nodes may have been generated by sub-templates.
+      // TODO(rafaelw): This is brittle WRT instance mutation -- e.g. if the
+      // first node was removed by script.
+      var templateInstance = previousTerminator.nextSibling.templateInstance;
+      this.instancePositionChangedFn_(templateInstance, index);
+    },
+
+    reportInstancesMoved: function(splices) {
+      var index = 0;
+      var offset = 0;
+      for (var i = 0; i < splices.length; i++) {
+        var splice = splices[i];
+        if (offset != 0) {
+          while (index < splice.index) {
+            this.reportInstanceMoved(index);
+            index++;
+          }
+        } else {
+          index = splice.index;
+        }
+
+        while (index < splice.index + splice.addedCount) {
+          this.reportInstanceMoved(index);
+          index++;
+        }
+
+        offset += splice.addedCount - splice.removed.length;
+      }
+
+      if (offset == 0)
+        return;
+
+      var length = this.terminators.length / 2;
+      while (index < length) {
+        this.reportInstanceMoved(index);
+        index++;
+      }
+    },
+
+    closeInstanceBindings: function(instanceBindings) {
+      for (var i = 0; i < instanceBindings.length; i++) {
+        instanceBindings[i].close();
+      }
+    },
+
+    unobserve: function() {
+      if (!this.arrayObserver)
+        return;
+
+      this.arrayObserver.close();
+      this.arrayObserver = undefined;
+    },
+
+    close: function() {
+      if (this.closed)
+        return;
+      this.unobserve();
+      for (var i = 1; i < this.terminators.length; i += 2) {
+        this.closeInstanceBindings(this.terminators[i]);
+      }
+
+      this.terminators.length = 0;
+      this.closeDeps();
+      this.templateElement_.iterator_ = undefined;
+      this.closed = true;
+    }
+  };
+
+  // Polyfill-specific API.
+  HTMLTemplateElement.forAllTemplatesFrom_ = forAllTemplatesFrom;
+})(this);
+
+/*
+  Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com>
+  Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com>
+  Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
+  Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
+  Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
+  Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
+  Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
+  Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
+  Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+  ON ANY 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.
+*/
+
+(function (global) {
+    'use strict';
+
+    var Token,
+        TokenName,
+        Syntax,
+        Messages,
+        source,
+        index,
+        length,
+        delegate,
+        lookahead,
+        state;
+
+    Token = {
+        BooleanLiteral: 1,
+        EOF: 2,
+        Identifier: 3,
+        Keyword: 4,
+        NullLiteral: 5,
+        NumericLiteral: 6,
+        Punctuator: 7,
+        StringLiteral: 8
+    };
+
+    TokenName = {};
+    TokenName[Token.BooleanLiteral] = 'Boolean';
+    TokenName[Token.EOF] = '<end>';
+    TokenName[Token.Identifier] = 'Identifier';
+    TokenName[Token.Keyword] = 'Keyword';
+    TokenName[Token.NullLiteral] = 'Null';
+    TokenName[Token.NumericLiteral] = 'Numeric';
+    TokenName[Token.Punctuator] = 'Punctuator';
+    TokenName[Token.StringLiteral] = 'String';
+
+    Syntax = {
+        ArrayExpression: 'ArrayExpression',
+        BinaryExpression: 'BinaryExpression',
+        CallExpression: 'CallExpression',
+        ConditionalExpression: 'ConditionalExpression',
+        EmptyStatement: 'EmptyStatement',
+        ExpressionStatement: 'ExpressionStatement',
+        Identifier: 'Identifier',
+        Literal: 'Literal',
+        LabeledStatement: 'LabeledStatement',
+        LogicalExpression: 'LogicalExpression',
+        MemberExpression: 'MemberExpression',
+        ObjectExpression: 'ObjectExpression',
+        Program: 'Program',
+        Property: 'Property',
+        ThisExpression: 'ThisExpression',
+        UnaryExpression: 'UnaryExpression'
+    };
+
+    // Error messages should be identical to V8.
+    Messages = {
+        UnexpectedToken:  'Unexpected token %0',
+        UnknownLabel: 'Undefined label \'%0\'',
+        Redeclaration: '%0 \'%1\' has already been declared'
+    };
+
+    // Ensure the condition is true, otherwise throw an error.
+    // This is only to have a better contract semantic, i.e. another safety net
+    // to catch a logic error. The condition shall be fulfilled in normal case.
+    // Do NOT use this to enforce a certain condition on any user input.
+
+    function assert(condition, message) {
+        if (!condition) {
+            throw new Error('ASSERT: ' + message);
+        }
+    }
+
+    function isDecimalDigit(ch) {
+        return (ch >= 48 && ch <= 57);   // 0..9
+    }
+
+
+    // 7.2 White Space
+
+    function isWhiteSpace(ch) {
+        return (ch === 32) ||  // space
+            (ch === 9) ||      // tab
+            (ch === 0xB) ||
+            (ch === 0xC) ||
+            (ch === 0xA0) ||
+            (ch >= 0x1680 && '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(String.fromCharCode(ch)) > 0);
+    }
+
+    // 7.3 Line Terminators
+
+    function isLineTerminator(ch) {
+        return (ch === 10) || (ch === 13) || (ch === 0x2028) || (ch === 0x2029);
+    }
+
+    // 7.6 Identifier Names and Identifiers
+
+    function isIdentifierStart(ch) {
+        return (ch === 36) || (ch === 95) ||  // $ (dollar) and _ (underscore)
+            (ch >= 65 && ch <= 90) ||         // A..Z
+            (ch >= 97 && ch <= 122);          // a..z
+    }
+
+    function isIdentifierPart(ch) {
+        return (ch === 36) || (ch === 95) ||  // $ (dollar) and _ (underscore)
+            (ch >= 65 && ch <= 90) ||         // A..Z
+            (ch >= 97 && ch <= 122) ||        // a..z
+            (ch >= 48 && ch <= 57);           // 0..9
+    }
+
+    // 7.6.1.1 Keywords
+
+    function isKeyword(id) {
+        return (id === 'this')
+    }
+
+    // 7.4 Comments
+
+    function skipWhitespace() {
+        while (index < length && isWhiteSpace(source.charCodeAt(index))) {
+           ++index;
+        }
+    }
+
+    function getIdentifier() {
+        var start, ch;
+
+        start = index++;
+        while (index < length) {
+            ch = source.charCodeAt(index);
+            if (isIdentifierPart(ch)) {
+                ++index;
+            } else {
+                break;
+            }
+        }
+
+        return source.slice(start, index);
+    }
+
+    function scanIdentifier() {
+        var start, id, type;
+
+        start = index;
+
+        id = getIdentifier();
+
+        // There is no keyword or literal with only one character.
+        // Thus, it must be an identifier.
+        if (id.length === 1) {
+            type = Token.Identifier;
+        } else if (isKeyword(id)) {
+            type = Token.Keyword;
+        } else if (id === 'null') {
+            type = Token.NullLiteral;
+        } else if (id === 'true' || id === 'false') {
+            type = Token.BooleanLiteral;
+        } else {
+            type = Token.Identifier;
+        }
+
+        return {
+            type: type,
+            value: id,
+            range: [start, index]
+        };
+    }
+
+
+    // 7.7 Punctuators
+
+    function scanPunctuator() {
+        var start = index,
+            code = source.charCodeAt(index),
+            code2,
+            ch1 = source[index],
+            ch2;
+
+        switch (code) {
+
+        // Check for most common single-character punctuators.
+        case 46:   // . dot
+        case 40:   // ( open bracket
+        case 41:   // ) close bracket
+        case 59:   // ; semicolon
+        case 44:   // , comma
+        case 123:  // { open curly brace
+        case 125:  // } close curly brace
+        case 91:   // [
+        case 93:   // ]
+        case 58:   // :
+        case 63:   // ?
+            ++index;
+            return {
+                type: Token.Punctuator,
+                value: String.fromCharCode(code),
+                range: [start, index]
+            };
+
+        default:
+            code2 = source.charCodeAt(index + 1);
+
+            // '=' (char #61) marks an assignment or comparison operator.
+            if (code2 === 61) {
+                switch (code) {
+                case 37:  // %
+                case 38:  // &
+                case 42:  // *:
+                case 43:  // +
+                case 45:  // -
+                case 47:  // /
+                case 60:  // <
+                case 62:  // >
+                case 124: // |
+                    index += 2;
+                    return {
+                        type: Token.Punctuator,
+                        value: String.fromCharCode(code) + String.fromCharCode(code2),
+                        range: [start, index]
+                    };
+
+                case 33: // !
+                case 61: // =
+                    index += 2;
+
+                    // !== and ===
+                    if (source.charCodeAt(index) === 61) {
+                        ++index;
+                    }
+                    return {
+                        type: Token.Punctuator,
+                        value: source.slice(start, index),
+                        range: [start, index]
+                    };
+                default:
+                    break;
+                }
+            }
+            break;
+        }
+
+        // Peek more characters.
+
+        ch2 = source[index + 1];
+
+        // Other 2-character punctuators: && ||
+
+        if (ch1 === ch2 && ('&|'.indexOf(ch1) >= 0)) {
+            index += 2;
+            return {
+                type: Token.Punctuator,
+                value: ch1 + ch2,
+                range: [start, index]
+            };
+        }
+
+        if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
+            ++index;
+            return {
+                type: Token.Punctuator,
+                value: ch1,
+                range: [start, index]
+            };
+        }
+
+        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+    }
+
+    // 7.8.3 Numeric Literals
+    function scanNumericLiteral() {
+        var number, start, ch;
+
+        ch = source[index];
+        assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'),
+            'Numeric literal must start with a decimal digit or a decimal point');
+
+        start = index;
+        number = '';
+        if (ch !== '.') {
+            number = source[index++];
+            ch = source[index];
+
+            // Hex number starts with '0x'.
+            // Octal number starts with '0'.
+            if (number === '0') {
+                // decimal number starts with '0' such as '09' is illegal.
+                if (ch && isDecimalDigit(ch.charCodeAt(0))) {
+                    throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+                }
+            }
+
+            while (isDecimalDigit(source.charCodeAt(index))) {
+                number += source[index++];
+            }
+            ch = source[index];
+        }
+
+        if (ch === '.') {
+            number += source[index++];
+            while (isDecimalDigit(source.charCodeAt(index))) {
+                number += source[index++];
+            }
+            ch = source[index];
+        }
+
+        if (ch === 'e' || ch === 'E') {
+            number += source[index++];
+
+            ch = source[index];
+            if (ch === '+' || ch === '-') {
+                number += source[index++];
+            }
+            if (isDecimalDigit(source.charCodeAt(index))) {
+                while (isDecimalDigit(source.charCodeAt(index))) {
+                    number += source[index++];
+                }
+            } else {
+                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+            }
+        }
+
+        if (isIdentifierStart(source.charCodeAt(index))) {
+            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+        }
+
+        return {
+            type: Token.NumericLiteral,
+            value: parseFloat(number),
+            range: [start, index]
+        };
+    }
+
+    // 7.8.4 String Literals
+
+    function scanStringLiteral() {
+        var str = '', quote, start, ch, octal = false;
+
+        quote = source[index];
+        assert((quote === '\'' || quote === '"'),
+            'String literal must starts with a quote');
+
+        start = index;
+        ++index;
+
+        while (index < length) {
+            ch = source[index++];
+
+            if (ch === quote) {
+                quote = '';
+                break;
+            } else if (ch === '\\') {
+                ch = source[index++];
+                if (!ch || !isLineTerminator(ch.charCodeAt(0))) {
+                    switch (ch) {
+                    case 'n':
+                        str += '\n';
+                        break;
+                    case 'r':
+                        str += '\r';
+                        break;
+                    case 't':
+                        str += '\t';
+                        break;
+                    case 'b':
+                        str += '\b';
+                        break;
+                    case 'f':
+                        str += '\f';
+                        break;
+                    case 'v':
+                        str += '\x0B';
+                        break;
+
+                    default:
+                        str += ch;
+                        break;
+                    }
+                } else {
+                    if (ch ===  '\r' && source[index] === '\n') {
+                        ++index;
+                    }
+                }
+            } else if (isLineTerminator(ch.charCodeAt(0))) {
+                break;
+            } else {
+                str += ch;
+            }
+        }
+
+        if (quote !== '') {
+            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+        }
+
+        return {
+            type: Token.StringLiteral,
+            value: str,
+            octal: octal,
+            range: [start, index]
+        };
+    }
+
+    function isIdentifierName(token) {
+        return token.type === Token.Identifier ||
+            token.type === Token.Keyword ||
+            token.type === Token.BooleanLiteral ||
+            token.type === Token.NullLiteral;
+    }
+
+    function advance() {
+        var ch;
+
+        skipWhitespace();
+
+        if (index >= length) {
+            return {
+                type: Token.EOF,
+                range: [index, index]
+            };
+        }
+
+        ch = source.charCodeAt(index);
+
+        // Very common: ( and ) and ;
+        if (ch === 40 || ch === 41 || ch === 58) {
+            return scanPunctuator();
+        }
+
+        // String literal starts with single quote (#39) or double quote (#34).
+        if (ch === 39 || ch === 34) {
+            return scanStringLiteral();
+        }
+
+        if (isIdentifierStart(ch)) {
+            return scanIdentifier();
+        }
+
+        // Dot (.) char #46 can also start a floating-point number, hence the need
+        // to check the next character.
+        if (ch === 46) {
+            if (isDecimalDigit(source.charCodeAt(index + 1))) {
+                return scanNumericLiteral();
+            }
+            return scanPunctuator();
+        }
+
+        if (isDecimalDigit(ch)) {
+            return scanNumericLiteral();
+        }
+
+        return scanPunctuator();
+    }
+
+    function lex() {
+        var token;
+
+        token = lookahead;
+        index = token.range[1];
+
+        lookahead = advance();
+
+        index = token.range[1];
+
+        return token;
+    }
+
+    function peek() {
+        var pos;
+
+        pos = index;
+        lookahead = advance();
+        index = pos;
+    }
+
+    // Throw an exception
+
+    function throwError(token, messageFormat) {
+        var error,
+            args = Array.prototype.slice.call(arguments, 2),
+            msg = messageFormat.replace(
+                /%(\d)/g,
+                function (whole, index) {
+                    assert(index < args.length, 'Message reference must be in range');
+                    return args[index];
+                }
+            );
+
+        error = new Error(msg);
+        error.index = index;
+        error.description = msg;
+        throw error;
+    }
+
+    // Throw an exception because of the token.
+
+    function throwUnexpected(token) {
+        throwError(token, Messages.UnexpectedToken, token.value);
+    }
+
+    // Expect the next token to match the specified punctuator.
+    // If not, an exception will be thrown.
+
+    function expect(value) {
+        var token = lex();
+        if (token.type !== Token.Punctuator || token.value !== value) {
+            throwUnexpected(token);
+        }
+    }
+
+    // Return true if the next token matches the specified punctuator.
+
+    function match(value) {
+        return lookahead.type === Token.Punctuator && lookahead.value === value;
+    }
+
+    // Return true if the next token matches the specified keyword
+
+    function matchKeyword(keyword) {
+        return lookahead.type === Token.Keyword && lookahead.value === keyword;
+    }
+
+    function consumeSemicolon() {
+        // Catch the very common case first: immediately a semicolon (char #59).
+        if (source.charCodeAt(index) === 59) {
+            lex();
+            return;
+        }
+
+        skipWhitespace();
+
+        if (match(';')) {
+            lex();
+            return;
+        }
+
+        if (lookahead.type !== Token.EOF && !match('}')) {
+            throwUnexpected(lookahead);
+        }
+    }
+
+    // 11.1.4 Array Initialiser
+
+    function parseArrayInitialiser() {
+        var elements = [];
+
+        expect('[');
+
+        while (!match(']')) {
+            if (match(',')) {
+                lex();
+                elements.push(null);
+            } else {
+                elements.push(parseExpression());
+
+                if (!match(']')) {
+                    expect(',');
+                }
+            }
+        }
+
+        expect(']');
+
+        return delegate.createArrayExpression(elements);
+    }
+
+    // 11.1.5 Object Initialiser
+
+    function parseObjectPropertyKey() {
+        var token;
+
+        skipWhitespace();
+        token = lex();
+
+        // Note: This function is called only from parseObjectProperty(), where
+        // EOF and Punctuator tokens are already filtered out.
+        if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {
+            return delegate.createLiteral(token);
+        }
+
+        return delegate.createIdentifier(token.value);
+    }
+
+    function parseObjectProperty() {
+        var token, key;
+
+        token = lookahead;
+        skipWhitespace();
+
+        if (token.type === Token.EOF || token.type === Token.Punctuator) {
+            throwUnexpected(token);
+        }
+
+        key = parseObjectPropertyKey();
+        expect(':');
+        return delegate.createProperty('init', key, parseExpression());
+    }
+
+    function parseObjectInitialiser() {
+        var properties = [];
+
+        expect('{');
+
+        while (!match('}')) {
+            properties.push(parseObjectProperty());
+
+            if (!match('}')) {
+                expect(',');
+            }
+        }
+
+        expect('}');
+
+        return delegate.createObjectExpression(properties);
+    }
+
+    // 11.1.6 The Grouping Operator
+
+    function parseGroupExpression() {
+        var expr;
+
+        expect('(');
+
+        expr = parseExpression();
+
+        expect(')');
+
+        return expr;
+    }
+
+
+    // 11.1 Primary Expressions
+
+    function parsePrimaryExpression() {
+        var type, token, expr;
+
+        if (match('(')) {
+            return parseGroupExpression();
+        }
+
+        type = lookahead.type;
+
+        if (type === Token.Identifier) {
+            expr = delegate.createIdentifier(lex().value);
+        } else if (type === Token.StringLiteral || type === Token.NumericLiteral) {
+            expr = delegate.createLiteral(lex());
+        } else if (type === Token.Keyword) {
+            if (matchKeyword('this')) {
+                lex();
+                expr = delegate.createThisExpression();
+            }
+        } else if (type === Token.BooleanLiteral) {
+            token = lex();
+            token.value = (token.value === 'true');
+            expr = delegate.createLiteral(token);
+        } else if (type === Token.NullLiteral) {
+            token = lex();
+            token.value = null;
+            expr = delegate.createLiteral(token);
+        } else if (match('[')) {
+            expr = parseArrayInitialiser();
+        } else if (match('{')) {
+            expr = parseObjectInitialiser();
+        }
+
+        if (expr) {
+            return expr;
+        }
+
+        throwUnexpected(lex());
+    }
+
+    // 11.2 Left-Hand-Side Expressions
+
+    function parseArguments() {
+        var args = [];
+
+        expect('(');
+
+        if (!match(')')) {
+            while (index < length) {
+                args.push(parseExpression());
+                if (match(')')) {
+                    break;
+                }
+                expect(',');
+            }
+        }
+
+        expect(')');
+
+        return args;
+    }
+
+    function parseNonComputedProperty() {
+        var token;
+
+        token = lex();
+
+        if (!isIdentifierName(token)) {
+            throwUnexpected(token);
+        }
+
+        return delegate.createIdentifier(token.value);
+    }
+
+    function parseNonComputedMember() {
+        expect('.');
+
+        return parseNonComputedProperty();
+    }
+
+    function parseComputedMember() {
+        var expr;
+
+        expect('[');
+
+        expr = parseExpression();
+
+        expect(']');
+
+        return expr;
+    }
+
+    function parseLeftHandSideExpression() {
+        var expr, property;
+
+        expr = parsePrimaryExpression();
+
+        while (match('.') || match('[')) {
+            if (match('[')) {
+                property = parseComputedMember();
+                expr = delegate.createMemberExpression('[', expr, property);
+            } else {
+                property = parseNonComputedMember();
+                expr = delegate.createMemberExpression('.', expr, property);
+            }
+        }
+
+        return expr;
+    }
+
+    // 11.3 Postfix Expressions
+
+    var parsePostfixExpression = parseLeftHandSideExpression;
+
+    // 11.4 Unary Operators
+
+    function parseUnaryExpression() {
+        var token, expr;
+
+        if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) {
+            expr = parsePostfixExpression();
+        } else if (match('+') || match('-') || match('!')) {
+            token = lex();
+            expr = parseUnaryExpression();
+            expr = delegate.createUnaryExpression(token.value, expr);
+        } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
+            throwError({}, Messages.UnexpectedToken);
+        } else {
+            expr = parsePostfixExpression();
+        }
+
+        return expr;
+    }
+
+    function binaryPrecedence(token) {
+        var prec = 0;
+
+        if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
+            return 0;
+        }
+
+        switch (token.value) {
+        case '||':
+            prec = 1;
+            break;
+
+        case '&&':
+            prec = 2;
+            break;
+
+        case '==':
+        case '!=':
+        case '===':
+        case '!==':
+            prec = 6;
+            break;
+
+        case '<':
+        case '>':
+        case '<=':
+        case '>=':
+        case 'instanceof':
+            prec = 7;
+            break;
+
+        case 'in':
+            prec = 7;
+            break;
+
+        case '+':
+        case '-':
+            prec = 9;
+            break;
+
+        case '*':
+        case '/':
+        case '%':
+            prec = 11;
+            break;
+
+        default:
+            break;
+        }
+
+        return prec;
+    }
+
+    // 11.5 Multiplicative Operators
+    // 11.6 Additive Operators
+    // 11.7 Bitwise Shift Operators
+    // 11.8 Relational Operators
+    // 11.9 Equality Operators
+    // 11.10 Binary Bitwise Operators
+    // 11.11 Binary Logical Operators
+
+    function parseBinaryExpression() {
+        var expr, token, prec, stack, right, operator, left, i;
+
+        left = parseUnaryExpression();
+
+        token = lookahead;
+        prec = binaryPrecedence(token);
+        if (prec === 0) {
+            return left;
+        }
+        token.prec = prec;
+        lex();
+
+        right = parseUnaryExpression();
+
+        stack = [left, token, right];
+
+        while ((prec = binaryPrecedence(lookahead)) > 0) {
+
+            // Reduce: make a binary expression from the three topmost entries.
+            while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
+                right = stack.pop();
+                operator = stack.pop().value;
+                left = stack.pop();
+                expr = delegate.createBinaryExpression(operator, left, right);
+                stack.push(expr);
+            }
+
+            // Shift.
+            token = lex();
+            token.prec = prec;
+            stack.push(token);
+            expr = parseUnaryExpression();
+            stack.push(expr);
+        }
+
+        // Final reduce to clean-up the stack.
+        i = stack.length - 1;
+        expr = stack[i];
+        while (i > 1) {
+            expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
+            i -= 2;
+        }
+
+        return expr;
+    }
+
+
+    // 11.12 Conditional Operator
+
+    function parseConditionalExpression() {
+        var expr, consequent, alternate;
+
+        expr = parseBinaryExpression();
+
+        if (match('?')) {
+            lex();
+            consequent = parseConditionalExpression();
+            expect(':');
+            alternate = parseConditionalExpression();
+
+            expr = delegate.createConditionalExpression(expr, consequent, alternate);
+        }
+
+        return expr;
+    }
+
+    // Simplification since we do not support AssignmentExpression.
+    var parseExpression = parseConditionalExpression;
+
+    // Polymer Syntax extensions
+
+    // Filter ::
+    //   Identifier
+    //   Identifier "(" ")"
+    //   Identifier "(" FilterArguments ")"
+
+    function parseFilter() {
+        var identifier, args;
+
+        identifier = lex();
+
+        if (identifier.type !== Token.Identifier) {
+            throwUnexpected(identifier);
+        }
+
+        args = match('(') ? parseArguments() : [];
+
+        return delegate.createFilter(identifier.value, args);
+    }
+
+    // Filters ::
+    //   "|" Filter
+    //   Filters "|" Filter
+
+    function parseFilters() {
+        while (match('|')) {
+            lex();
+            parseFilter();
+        }
+    }
+
+    // TopLevel ::
+    //   LabelledExpressions
+    //   AsExpression
+    //   InExpression
+    //   FilterExpression
+
+    // AsExpression ::
+    //   FilterExpression as Identifier
+
+    // InExpression ::
+    //   Identifier, Identifier in FilterExpression
+    //   Identifier in FilterExpression
+
+    // FilterExpression ::
+    //   Expression
+    //   Expression Filters
+
+    function parseTopLevel() {
+        skipWhitespace();
+        peek();
+
+        var expr = parseExpression();
+        if (expr) {
+            if (lookahead.value === ',' || lookahead.value == 'in' &&
+                       expr.type === Syntax.Identifier) {
+                parseInExpression(expr);
+            } else {
+                parseFilters();
+                if (lookahead.value === 'as') {
+                    parseAsExpression(expr);
+                } else {
+                    delegate.createTopLevel(expr);
+                }
+            }
+        }
+
+        if (lookahead.type !== Token.EOF) {
+            throwUnexpected(lookahead);
+        }
+    }
+
+    function parseAsExpression(expr) {
+        lex();  // as
+        var identifier = lex().value;
+        delegate.createAsExpression(expr, identifier);
+    }
+
+    function parseInExpression(identifier) {
+        var indexName;
+        if (lookahead.value === ',') {
+            lex();
+            if (lookahead.type !== Token.Identifier)
+                throwUnexpected(lookahead);
+            indexName = lex().value;
+        }
+
+        lex();  // in
+        var expr = parseExpression();
+        parseFilters();
+        delegate.createInExpression(identifier.name, indexName, expr);
+    }
+
+    function parse(code, inDelegate) {
+        delegate = inDelegate;
+        source = code;
+        index = 0;
+        length = source.length;
+        lookahead = null;
+        state = {
+            labelSet: {}
+        };
+
+        return parseTopLevel();
+    }
+
+    global.esprima = {
+        parse: parse
+    };
+})(this);
+
+// Copyright 2013 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+(function (global) {
+  'use strict';
+
+  // JScript does not have __proto__. We wrap all object literals with
+  // createObject which uses Object.create, Object.defineProperty and
+  // Object.getOwnPropertyDescriptor to create a new object that does the exact
+  // same thing. The main downside to this solution is that we have to extract
+  // all those property descriptors for IE.
+  var createObject = ('__proto__' in {}) ?
+      function(obj) { return obj; } :
+      function(obj) {
+        var proto = obj.__proto__;
+        if (!proto)
+          return obj;
+        var newObject = Object.create(proto);
+        Object.getOwnPropertyNames(obj).forEach(function(name) {
+          Object.defineProperty(newObject, name,
+                               Object.getOwnPropertyDescriptor(obj, name));
+        });
+        return newObject;
+      };
+
+  function prepareBinding(expressionText, name, node, filterRegistry) {
+    var expression;
+    try {
+      expression = getExpression(expressionText);
+      if (expression.scopeIdent &&
+          (node.nodeType !== Node.ELEMENT_NODE ||
+           node.tagName !== 'TEMPLATE' ||
+           (name !== 'bind' && name !== 'repeat'))) {
+        throw Error('as and in can only be used within <template bind/repeat>');
+      }
+    } catch (ex) {
+      console.error('Invalid expression syntax: ' + expressionText, ex);
+      return;
+    }
+
+    return function(model, node, oneTime) {
+      var binding = expression.getBinding(model, filterRegistry, oneTime);
+      if (expression.scopeIdent && binding) {
+        node.polymerExpressionScopeIdent_ = expression.scopeIdent;
+        if (expression.indexIdent)
+          node.polymerExpressionIndexIdent_ = expression.indexIdent;
+      }
+
+      return binding;
+    }
+  }
+
+  // TODO(rafaelw): Implement simple LRU.
+  var expressionParseCache = Object.create(null);
+
+  function getExpression(expressionText) {
+    var expression = expressionParseCache[expressionText];
+    if (!expression) {
+      var delegate = new ASTDelegate();
+      esprima.parse(expressionText, delegate);
+      expression = new Expression(delegate);
+      expressionParseCache[expressionText] = expression;
+    }
+    return expression;
+  }
+
+  function Literal(value) {
+    this.value = value;
+    this.valueFn_ = undefined;
+  }
+
+  Literal.prototype = {
+    valueFn: function() {
+      if (!this.valueFn_) {
+        var value = this.value;
+        this.valueFn_ = function() {
+          return value;
+        }
+      }
+
+      return this.valueFn_;
+    }
+  }
+
+  function IdentPath(name) {
+    this.name = name;
+    this.path = Path.get(name);
+  }
+
+  IdentPath.prototype = {
+    valueFn: function() {
+      if (!this.valueFn_) {
+        var name = this.name;
+        var path = this.path;
+        this.valueFn_ = function(model, observer) {
+          if (observer)
+            observer.addPath(model, path);
+
+          return path.getValueFrom(model);
+        }
+      }
+
+      return this.valueFn_;
+    },
+
+    setValue: function(model, newValue) {
+      if (this.path.length == 1);
+        model = findScope(model, this.path[0]);
+
+      return this.path.setValueFrom(model, newValue);
+    }
+  };
+
+  function MemberExpression(object, property, accessor) {
+    // convert literal computed property access where literal value is a value
+    // path to ident dot-access.
+    if (accessor == '[' &&
+        property instanceof Literal &&
+        Path.get(property.value).valid) {
+      accessor = '.';
+      property = new IdentPath(property.value);
+    }
+
+    this.dynamicDeps = typeof object == 'function' || object.dynamic;
+
+    this.dynamic = typeof property == 'function' ||
+                   property.dynamic ||
+                   accessor == '[';
+
+    this.simplePath =
+        !this.dynamic &&
+        !this.dynamicDeps &&
+        property instanceof IdentPath &&
+        (object instanceof MemberExpression || object instanceof IdentPath);
+
+    this.object = this.simplePath ? object : getFn(object);
+    this.property = accessor == '.' ? property : getFn(property);
+  }
+
+  MemberExpression.prototype = {
+    get fullPath() {
+      if (!this.fullPath_) {
+        var last = this.object instanceof IdentPath ?
+            this.object.name : this.object.fullPath;
+        this.fullPath_ = Path.get(last + '.' + this.property.name);
+      }
+
+      return this.fullPath_;
+    },
+
+    valueFn: function() {
+      if (!this.valueFn_) {
+        var object = this.object;
+
+        if (this.simplePath) {
+          var path = this.fullPath;
+
+          this.valueFn_ = function(model, observer) {
+            if (observer)
+              observer.addPath(model, path);
+
+            return path.getValueFrom(model);
+          };
+        } else if (this.property instanceof IdentPath) {
+          var path = Path.get(this.property.name);
+
+          this.valueFn_ = function(model, observer) {
+            var context = object(model, observer);
+
+            if (observer)
+              observer.addPath(context, path);
+
+            return path.getValueFrom(context);
+          }
+        } else {
+          // Computed property.
+          var property = this.property;
+
+          this.valueFn_ = function(model, observer) {
+            var context = object(model, observer);
+            var propName = property(model, observer);
+            if (observer)
+              observer.addPath(context, propName);
+
+            return context ? context[propName] : undefined;
+          };
+        }
+      }
+      return this.valueFn_;
+    },
+
+    setValue: function(model, newValue) {
+      if (this.simplePath) {
+        this.fullPath.setValueFrom(model, newValue);
+        return newValue;
+      }
+
+      var object = this.object(model);
+      var propName = this.property instanceof IdentPath ? this.property.name :
+          this.property(model);
+      return object[propName] = newValue;
+    }
+  };
+
+  function Filter(name, args) {
+    this.name = name;
+    this.args = [];
+    for (var i = 0; i < args.length; i++) {
+      this.args[i] = getFn(args[i]);
+    }
+  }
+
+  Filter.prototype = {
+    transform: function(value, toModelDirection, filterRegistry, model,
+                        observer) {
+      var fn = filterRegistry[this.name];
+      var context = model;
+      if (fn) {
+        context = undefined;
+      } else {
+        fn = context[this.name];
+        if (!fn) {
+          console.error('Cannot find filter: ' + this.name);
+          return;
+        }
+      }
+
+      // If toModelDirection is falsey, then the "normal" (dom-bound) direction
+      // is used. Otherwise, it looks for a 'toModel' property function on the
+      // object.
+      if (toModelDirection) {
+        fn = fn.toModel;
+      } else if (typeof fn.toDOM == 'function') {
+        fn = fn.toDOM;
+      }
+
+      if (typeof fn != 'function') {
+        console.error('No ' + (toModelDirection ? 'toModel' : 'toDOM') +
+                      ' found on' + this.name);
+        return;
+      }
+
+      var args = [value];
+      for (var i = 0; i < this.args.length; i++) {
+        args[i + 1] = getFn(this.args[i])(model, observer);
+      }
+
+      return fn.apply(context, args);
+    }
+  };
+
+  function notImplemented() { throw Error('Not Implemented'); }
+
+  var unaryOperators = {
+    '+': function(v) { return +v; },
+    '-': function(v) { return -v; },
+    '!': function(v) { return !v; }
+  };
+
+  var binaryOperators = {
+    '+': function(l, r) { return l+r; },
+    '-': function(l, r) { return l-r; },
+    '*': function(l, r) { return l*r; },
+    '/': function(l, r) { return l/r; },
+    '%': function(l, r) { return l%r; },
+    '<': function(l, r) { return l<r; },
+    '>': function(l, r) { return l>r; },
+    '<=': function(l, r) { return l<=r; },
+    '>=': function(l, r) { return l>=r; },
+    '==': function(l, r) { return l==r; },
+    '!=': function(l, r) { return l!=r; },
+    '===': function(l, r) { return l===r; },
+    '!==': function(l, r) { return l!==r; },
+    '&&': function(l, r) { return l&&r; },
+    '||': function(l, r) { return l||r; },
+  };
+
+  function getFn(arg) {
+    return typeof arg == 'function' ? arg : arg.valueFn();
+  }
+
+  function ASTDelegate() {
+    this.expression = null;
+    this.filters = [];
+    this.deps = {};
+    this.currentPath = undefined;
+    this.scopeIdent = undefined;
+    this.indexIdent = undefined;
+    this.dynamicDeps = false;
+  }
+
+  ASTDelegate.prototype = {
+    createUnaryExpression: function(op, argument) {
+      if (!unaryOperators[op])
+        throw Error('Disallowed operator: ' + op);
+
+      argument = getFn(argument);
+
+      return function(model, observer) {
+        return unaryOperators[op](argument(model, observer));
+      };
+    },
+
+    createBinaryExpression: function(op, left, right) {
+      if (!binaryOperators[op])
+        throw Error('Disallowed operator: ' + op);
+
+      left = getFn(left);
+      right = getFn(right);
+
+      return function(model, observer) {
+        return binaryOperators[op](left(model, observer),
+                                   right(model, observer));
+      };
+    },
+
+    createConditionalExpression: function(test, consequent, alternate) {
+      test = getFn(test);
+      consequent = getFn(consequent);
+      alternate = getFn(alternate);
+
+      return function(model, observer) {
+        return test(model, observer) ?
+            consequent(model, observer) : alternate(model, observer);
+      }
+    },
+
+    createIdentifier: function(name) {
+      var ident = new IdentPath(name);
+      ident.type = 'Identifier';
+      return ident;
+    },
+
+    createMemberExpression: function(accessor, object, property) {
+      var ex = new MemberExpression(object, property, accessor);
+      if (ex.dynamicDeps)
+        this.dynamicDeps = true;
+      return ex;
+    },
+
+    createLiteral: function(token) {
+      return new Literal(token.value);
+    },
+
+    createArrayExpression: function(elements) {
+      for (var i = 0; i < elements.length; i++)
+        elements[i] = getFn(elements[i]);
+
+      return function(model, observer) {
+        var arr = []
+        for (var i = 0; i < elements.length; i++)
+          arr.push(elements[i](model, observer));
+        return arr;
+      }
+    },
+
+    createProperty: function(kind, key, value) {
+      return {
+        key: key instanceof IdentPath ? key.name : key.value,
+        value: value
+      };
+    },
+
+    createObjectExpression: function(properties) {
+      for (var i = 0; i < properties.length; i++)
+        properties[i].value = getFn(properties[i].value);
+
+      return function(model, observer) {
+        var obj = {};
+        for (var i = 0; i < properties.length; i++)
+          obj[properties[i].key] = properties[i].value(model, observer);
+        return obj;
+      }
+    },
+
+    createFilter: function(name, args) {
+      this.filters.push(new Filter(name, args));
+    },
+
+    createAsExpression: function(expression, scopeIdent) {
+      this.expression = expression;
+      this.scopeIdent = scopeIdent;
+    },
+
+    createInExpression: function(scopeIdent, indexIdent, expression) {
+      this.expression = expression;
+      this.scopeIdent = scopeIdent;
+      this.indexIdent = indexIdent;
+    },
+
+    createTopLevel: function(expression) {
+      this.expression = expression;
+    },
+
+    createThisExpression: notImplemented
+  }
+
+  function ConstantObservable(value) {
+    this.value_ = value;
+  }
+
+  ConstantObservable.prototype = {
+    open: function() { return this.value_; },
+    discardChanges: function() { return this.value_; },
+    deliver: function() {},
+    close: function() {},
+  }
+
+  function Expression(delegate) {
+    this.scopeIdent = delegate.scopeIdent;
+    this.indexIdent = delegate.indexIdent;
+
+    if (!delegate.expression)
+      throw Error('No expression found.');
+
+    this.expression = delegate.expression;
+    getFn(this.expression); // forces enumeration of path dependencies
+
+    this.filters = delegate.filters;
+    this.dynamicDeps = delegate.dynamicDeps;
+  }
+
+  Expression.prototype = {
+    getBinding: function(model, filterRegistry, oneTime) {
+      if (oneTime)
+        return this.getValue(model, undefined, filterRegistry);
+
+      var observer = new CompoundObserver();
+      this.getValue(model, observer, filterRegistry);  // captures deps.
+      var self = this;
+
+      function valueFn() {
+        if (self.dynamicDeps)
+          observer.startReset();
+
+        var value = self.getValue(model,
+                                  self.dynamicDeps ? observer : undefined,
+                                  filterRegistry);
+        if (self.dynamicDeps)
+          observer.finishReset();
+
+        return value;
+      }
+
+      function setValueFn(newValue) {
+        self.setValue(model, newValue, filterRegistry);
+        return newValue;
+      }
+
+      return new ObserverTransform(observer, valueFn, setValueFn, true);
+    },
+
+    getValue: function(model, observer, filterRegistry) {
+      var value = getFn(this.expression)(model, observer);
+      for (var i = 0; i < this.filters.length; i++) {
+        value = this.filters[i].transform(value, false, filterRegistry, model,
+                                          observer);
+      }
+
+      return value;
+    },
+
+    setValue: function(model, newValue, filterRegistry) {
+      var count = this.filters ? this.filters.length : 0;
+      while (count-- > 0) {
+        newValue = this.filters[count].transform(newValue, true, filterRegistry,
+                                                 model);
+      }
+
+      if (this.expression.setValue)
+        return this.expression.setValue(model, newValue);
+    }
+  }
+
+  /**
+   * Converts a style property name to a css property name. For example:
+   * "WebkitUserSelect" to "-webkit-user-select"
+   */
+  function convertStylePropertyName(name) {
+    return String(name).replace(/[A-Z]/g, function(c) {
+      return '-' + c.toLowerCase();
+    });
+  }
+
+  function isEventHandler(name) {
+    return name[0] === 'o' &&
+           name[1] === 'n' &&
+           name[2] === '-';
+  }
+
+  var mixedCaseEventTypes = {};
+  [
+    'webkitAnimationStart',
+    'webkitAnimationEnd',
+    'webkitTransitionEnd',
+    'DOMFocusOut',
+    'DOMFocusIn',
+    'DOMMouseScroll'
+  ].forEach(function(e) {
+    mixedCaseEventTypes[e.toLowerCase()] = e;
+  });
+
+  var parentScopeName = '@' + Math.random().toString(36).slice(2);
+
+  // Single ident paths must bind directly to the appropriate scope object.
+  // I.e. Pushed values in two-bindings need to be assigned to the actual model
+  // object.
+  function findScope(model, prop) {
+    while (model[parentScopeName] &&
+           !Object.prototype.hasOwnProperty.call(model, prop)) {
+      model = model[parentScopeName];
+    }
+
+    return model;
+  }
+
+  function resolveEventReceiver(model, path, node) {
+    if (path.length == 0)
+      return undefined;
+
+    if (path.length == 1)
+      return findScope(model, path[0]);
+
+    for (var i = 0; model != null && i < path.length - 1; i++) {
+      model = model[path[i]];
+    }
+
+    return model;
+  }
+
+  function prepareEventBinding(path, name, polymerExpressions) {
+    var eventType = name.substring(3);
+    eventType = mixedCaseEventTypes[eventType] || eventType;
+
+    return function(model, node, oneTime) {
+      var fn, receiver, handler;
+      if (typeof polymerExpressions.resolveEventHandler == 'function') {
+        handler = function(e) {
+          fn = fn || polymerExpressions.resolveEventHandler(model, path, node);
+          fn(e, e.detail, e.currentTarget);
+
+          if (Platform && typeof Platform.flush == 'function')
+            Platform.flush();
+        };
+      } else {
+        handler = function(e) {
+          fn = fn || path.getValueFrom(model);
+          receiver = receiver || resolveEventReceiver(model, path, node);
+
+          fn.apply(receiver, [e, e.detail, e.currentTarget]);
+
+          if (Platform && typeof Platform.flush == 'function')
+            Platform.flush();
+        };
+      }
+
+      node.addEventListener(eventType, handler);
+
+      if (oneTime)
+        return;
+
+      function bindingValue() {
+        return '{{ ' + path + ' }}';
+      }
+
+      return {
+        open: bindingValue,
+        discardChanges: bindingValue,
+        close: function() {
+          node.removeEventListener(eventType, handler);
+        }
+      };
+    }
+  }
+
+  function PolymerExpressions() {}
+
+  PolymerExpressions.prototype = {
+    // "built-in" filters
+    styleObject: function(value) {
+      var parts = [];
+      for (var key in value) {
+        parts.push(convertStylePropertyName(key) + ': ' + value[key]);
+      }
+      return parts.join('; ');
+    },
+
+    tokenList: function(value) {
+      var tokens = [];
+      for (var key in value) {
+        if (value[key])
+          tokens.push(key);
+      }
+      return tokens.join(' ');
+    },
+
+    // binding delegate API
+    prepareInstancePositionChanged: function(template) {
+      var indexIdent = template.polymerExpressionIndexIdent_;
+      if (!indexIdent)
+        return;
+
+      return function(templateInstance, index) {
+        templateInstance.model[indexIdent] = index;
+      };
+    },
+
+    prepareBinding: function(pathString, name, node) {
+      var path = Path.get(pathString);
+      if (isEventHandler(name)) {
+        if (!path.valid) {
+          console.error('on-* bindings must be simple path expressions');
+          return;
+        }
+
+        return prepareEventBinding(path, name, this);
+      }
+
+      if (path.valid) {
+        if (path.length == 1) {
+          return function(model, node, oneTime) {
+            if (oneTime)
+              return path.getValueFrom(model);
+
+            var scope = findScope(model, path[0]);
+            return new PathObserver(scope, path);
+          }
+        }
+
+        return; // bail out early if pathString is simple path.
+      }
+
+      return prepareBinding(pathString, name, node, this);
+    },
+
+    prepareInstanceModel: function(template) {
+      var scopeName = template.polymerExpressionScopeIdent_;
+      if (!scopeName)
+        return;
+
+      var parentScope = template.templateInstance ?
+          template.templateInstance.model :
+          template.model;
+
+      var indexName = template.polymerExpressionIndexIdent_;
+
+      return function(model) {
+        var scope = Object.create(parentScope);
+        scope[scopeName] = model;
+        scope[indexName] = undefined;
+        scope[parentScopeName] = parentScope;
+        return scope;
+      };
+    }
+  };
+
+  global.PolymerExpressions = PolymerExpressions;
+  if (global.exposeGetExpression)
+    global.getExpression_ = getExpression;
+
+  global.PolymerExpressions.prepareEventBinding = prepareEventBinding;
+})(this);
+
+/*
+ * Copyright 2013 The Polymer Authors. 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) {
+
+// inject style sheet
+var style = document.createElement('style');
+style.textContent = 'template {display: none !important;} /* injected by platform.js */';
+var head = document.querySelector('head');
+head.insertBefore(style, head.firstChild);
+
+// flush (with logging)
+var flushing;
+function flush() {
+  if (!flushing) {
+    flushing = true;
+    scope.endOfMicrotask(function() {
+      flushing = false;
+      logFlags.data && console.group('Platform.flush()');
+      scope.performMicrotaskCheckpoint();
+      logFlags.data && console.groupEnd();
+    });
+  }
+};
+
+// polling dirty checker
+var FLUSH_POLL_INTERVAL = 125;
+window.addEventListener('WebComponentsReady', function() {
+  flush();
+  // flush periodically if platform does not have object observe.
+  if (!Observer.hasObjectObserve) {
+    scope.flushPoll = setInterval(flush, FLUSH_POLL_INTERVAL);
+  }
+});
+
+if (window.CustomElements && !CustomElements.useNative) {
+  var originalImportNode = Document.prototype.importNode;
+  Document.prototype.importNode = function(node, deep) {
+    var imported = originalImportNode.call(this, node, deep);
+    CustomElements.upgradeAll(imported);
+    return imported;
+  }
+}
+
+// exports
+scope.flush = flush;
+
+})(window.Platform);
+
+
+//# sourceMappingURL=platform.concat.js.map
\ No newline at end of file
diff --git a/pkg/web_components/lib/platform.concat.js.map b/pkg/web_components/lib/platform.concat.js.map
new file mode 100644
index 0000000..71ae9a2
--- /dev/null
+++ b/pkg/web_components/lib/platform.concat.js.map
@@ -0,0 +1,192 @@
+{
+  "version": 3,
+  "file": "platform.concat.js",
+  "sources": [
+    "../WeakMap/weakmap.js",
+    "../observe-js/src/observe.js",
+    "build/if-poly.js",
+    "../ShadowDOM/src/wrappers.js",
+    "../ShadowDOM/src/microtask.js",
+    "../ShadowDOM/src/MutationObserver.js",
+    "../ShadowDOM/src/wrappers/events.js",
+    "../ShadowDOM/src/wrappers/NodeList.js",
+    "../ShadowDOM/src/wrappers/Node.js",
+    "../ShadowDOM/src/querySelector.js",
+    "../ShadowDOM/src/wrappers/node-interfaces.js",
+    "../ShadowDOM/src/wrappers/CharacterData.js",
+    "../ShadowDOM/src/wrappers/Text.js",
+    "../ShadowDOM/src/wrappers/Element.js",
+    "../ShadowDOM/src/wrappers/HTMLElement.js",
+    "../ShadowDOM/src/wrappers/HTMLCanvasElement.js",
+    "../ShadowDOM/src/wrappers/HTMLContentElement.js",
+    "../ShadowDOM/src/wrappers/HTMLImageElement.js",
+    "../ShadowDOM/src/wrappers/HTMLShadowElement.js",
+    "../ShadowDOM/src/wrappers/HTMLTemplateElement.js",
+    "../ShadowDOM/src/wrappers/HTMLMediaElement.js",
+    "../ShadowDOM/src/wrappers/HTMLAudioElement.js",
+    "../ShadowDOM/src/wrappers/HTMLOptionElement.js",
+    "../ShadowDOM/src/wrappers/HTMLUnknownElement.js",
+    "../ShadowDOM/src/wrappers/SVGElement.js",
+    "../ShadowDOM/src/wrappers/SVGUseElement.js",
+    "../ShadowDOM/src/wrappers/SVGElementInstance.js",
+    "../ShadowDOM/src/wrappers/CanvasRenderingContext2D.js",
+    "../ShadowDOM/src/wrappers/WebGLRenderingContext.js",
+    "../ShadowDOM/src/wrappers/Range.js",
+    "../ShadowDOM/src/wrappers/generic.js",
+    "../ShadowDOM/src/wrappers/ShadowRoot.js",
+    "../ShadowDOM/src/ShadowRenderer.js",
+    "../ShadowDOM/src/wrappers/elements-with-form-property.js",
+    "../ShadowDOM/src/wrappers/Selection.js",
+    "../ShadowDOM/src/wrappers/Document.js",
+    "../ShadowDOM/src/wrappers/Window.js",
+    "../ShadowDOM/src/wrappers/override-constructors.js",
+    "src/patches-shadowdom-polyfill.js",
+    "src/ShadowCSS.js",
+    "build/else.js",
+    "src/patches-shadowdom-native.js",
+    "build/end-if.js",
+    "../URL/url.js",
+    "src/lang.js",
+    "src/dom.js",
+    "src/template.js",
+    "src/inspector.js",
+    "src/unresolved.js",
+    "src/module.js",
+    "src/microtask.js",
+    "src/url.js",
+    "../MutationObservers/MutationObserver.js",
+    "../HTMLImports/src/scope.js",
+    "../HTMLImports/src/Loader.js",
+    "../HTMLImports/src/Parser.js",
+    "../HTMLImports/src/HTMLImports.js",
+    "../HTMLImports/src/Observer.js",
+    "../HTMLImports/src/boot.js",
+    "../CustomElements/src/scope.js",
+    "../CustomElements/src/Observer.js",
+    "../CustomElements/src/CustomElements.js",
+    "../CustomElements/src/Parser.js",
+    "../CustomElements/src/boot.js",
+    "src/patches-custom-elements.js",
+    "src/loader.js",
+    "../PointerEvents/src/boot.js",
+    "../PointerEvents/src/touch-action.js",
+    "../PointerEvents/src/PointerEvent.js",
+    "../PointerEvents/src/pointermap.js",
+    "../PointerEvents/src/dispatcher.js",
+    "../PointerEvents/src/installer.js",
+    "../PointerEvents/src/mouse.js",
+    "../PointerEvents/src/touch.js",
+    "../PointerEvents/src/ms.js",
+    "../PointerEvents/src/platform-events.js",
+    "../PointerEvents/src/capture.js",
+    "../PointerGestures/src/PointerGestureEvent.js",
+    "../PointerGestures/src/initialize.js",
+    "../PointerGestures/src/pointermap.js",
+    "../PointerGestures/src/dispatcher.js",
+    "../PointerGestures/src/hold.js",
+    "../PointerGestures/src/track.js",
+    "../PointerGestures/src/flick.js",
+    "../PointerGestures/src/pinch.js",
+    "../PointerGestures/src/tap.js",
+    "../NodeBind/src/NodeBind.js",
+    "../TemplateBinding/src/TemplateBinding.js",
+    "../polymer-expressions/third_party/esprima/esprima.js",
+    "../polymer-expressions/src/polymer-expressions.js",
+    "src/patches-mdv.js"
+  ],
+  "names": [],
+  "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5kDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1YA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACryBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9sBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1TA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvpBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oB;AClmBA,Q;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,K;AC1DA,C;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpjBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oB;AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7LA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,W;AC9CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjiBA;AACA;AACA;AACA;AACA;AACA,sD;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9PA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvDA;AACA;AACA;AACA;AACA;AACA,4D;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0B;AC/DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChrCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5gCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChqBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A",
+  "sourcesContent": [
+    "/*\n * Copyright 2012 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nif (typeof WeakMap === 'undefined') {\n  (function() {\n    var defineProperty = Object.defineProperty;\n    var counter = Date.now() % 1e9;\n\n    var WeakMap = function() {\n      this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__');\n    };\n\n    WeakMap.prototype = {\n      set: function(key, value) {\n        var entry = key[this.name];\n        if (entry && entry[0] === key)\n          entry[1] = value;\n        else\n          defineProperty(key, this.name, {value: [key, value], writable: true});\n      },\n      get: function(key) {\n        var entry;\n        return (entry = key[this.name]) && entry[0] === key ?\n            entry[1] : undefined;\n      },\n      delete: function(key) {\n        this.set(key, undefined);\n      }\n    };\n\n    window.WeakMap = WeakMap;\n  })();\n}\n",
+    "// Copyright 2012 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n(function(global) {\n  'use strict';\n\n  var PROP_ADD_TYPE = 'add';\n  var PROP_UPDATE_TYPE = 'update';\n  var PROP_RECONFIGURE_TYPE = 'reconfigure';\n  var PROP_DELETE_TYPE = 'delete';\n  var ARRAY_SPLICE_TYPE = 'splice';\n\n  // Detect and do basic sanity checking on Object/Array.observe.\n  function detectObjectObserve() {\n    if (typeof Object.observe !== 'function' ||\n        typeof Array.observe !== 'function') {\n      return false;\n    }\n\n    var records = [];\n\n    function callback(recs) {\n      records = recs;\n    }\n\n    var test = {};\n    Object.observe(test, callback);\n    test.id = 1;\n    test.id = 2;\n    delete test.id;\n    Object.deliverChangeRecords(callback);\n    if (records.length !== 3)\n      return false;\n\n    // TODO(rafaelw): Remove this when new change record type names make it to\n    // chrome release.\n    if (records[0].type == 'new' &&\n        records[1].type == 'updated' &&\n        records[2].type == 'deleted') {\n      PROP_ADD_TYPE = 'new';\n      PROP_UPDATE_TYPE = 'updated';\n      PROP_RECONFIGURE_TYPE = 'reconfigured';\n      PROP_DELETE_TYPE = 'deleted';\n    } else if (records[0].type != 'add' ||\n               records[1].type != 'update' ||\n               records[2].type != 'delete') {\n      console.error('Unexpected change record names for Object.observe. ' +\n                    'Using dirty-checking instead');\n      return false;\n    }\n    Object.unobserve(test, callback);\n\n    test = [0];\n    Array.observe(test, callback);\n    test[1] = 1;\n    test.length = 0;\n    Object.deliverChangeRecords(callback);\n    if (records.length != 2)\n      return false;\n    if (records[0].type != ARRAY_SPLICE_TYPE ||\n        records[1].type != ARRAY_SPLICE_TYPE) {\n      return false;\n    }\n    Array.unobserve(test, callback);\n\n    return true;\n  }\n\n  var hasObserve = detectObjectObserve();\n\n  function detectEval() {\n    // don't test for eval if document has CSP securityPolicy object and we can see that\n    // eval is not supported. This avoids an error message in console even when the exception\n    // is caught\n    if (global.document &&\n        'securityPolicy' in global.document &&\n        !global.document.securityPolicy.allowsEval) {\n      return false;\n    }\n\n    try {\n      var f = new Function('', 'return true;');\n      return f();\n    } catch (ex) {\n      return false;\n    }\n  }\n\n  var hasEval = detectEval();\n\n  function isIndex(s) {\n    return +s === s >>> 0;\n  }\n\n  function toNumber(s) {\n    return +s;\n  }\n\n  function isObject(obj) {\n    return obj === Object(obj);\n  }\n\n  var numberIsNaN = global.Number.isNaN || function isNaN(value) {\n    return typeof value === 'number' && global.isNaN(value);\n  }\n\n  function areSameValue(left, right) {\n    if (left === right)\n      return left !== 0 || 1 / left === 1 / right;\n    if (numberIsNaN(left) && numberIsNaN(right))\n      return true;\n\n    return left !== left && right !== right;\n  }\n\n  var createObject = ('__proto__' in {}) ?\n    function(obj) { return obj; } :\n    function(obj) {\n      var proto = obj.__proto__;\n      if (!proto)\n        return obj;\n      var newObject = Object.create(proto);\n      Object.getOwnPropertyNames(obj).forEach(function(name) {\n        Object.defineProperty(newObject, name,\n                             Object.getOwnPropertyDescriptor(obj, name));\n      });\n      return newObject;\n    };\n\n  var identStart = '[\\$_a-zA-Z]';\n  var identPart = '[\\$_a-zA-Z0-9]';\n  var ident = identStart + '+' + identPart + '*';\n  var elementIndex = '(?:[0-9]|[1-9]+[0-9]+)';\n  var identOrElementIndex = '(?:' + ident + '|' + elementIndex + ')';\n  var path = '(?:' + identOrElementIndex + ')(?:\\\\s*\\\\.\\\\s*' + identOrElementIndex + ')*';\n  var pathRegExp = new RegExp('^' + path + '$');\n\n  function isPathValid(s) {\n    if (typeof s != 'string')\n      return false;\n    s = s.trim();\n\n    if (s == '')\n      return true;\n\n    if (s[0] == '.')\n      return false;\n\n    return pathRegExp.test(s);\n  }\n\n  var constructorIsPrivate = {};\n\n  function Path(s, privateToken) {\n    if (privateToken !== constructorIsPrivate)\n      throw Error('Use Path.get to retrieve path objects');\n\n    if (s.trim() == '')\n      return this;\n\n    if (isIndex(s)) {\n      this.push(s);\n      return this;\n    }\n\n    s.split(/\\s*\\.\\s*/).filter(function(part) {\n      return part;\n    }).forEach(function(part) {\n      this.push(part);\n    }, this);\n\n    if (hasEval && this.length) {\n      this.getValueFrom = this.compiledGetValueFromFn();\n    }\n  }\n\n  // TODO(rafaelw): Make simple LRU cache\n  var pathCache = {};\n\n  function getPath(pathString) {\n    if (pathString instanceof Path)\n      return pathString;\n\n    if (pathString == null)\n      pathString = '';\n\n    if (typeof pathString !== 'string')\n      pathString = String(pathString);\n\n    var path = pathCache[pathString];\n    if (path)\n      return path;\n    if (!isPathValid(pathString))\n      return invalidPath;\n    var path = new Path(pathString, constructorIsPrivate);\n    pathCache[pathString] = path;\n    return path;\n  }\n\n  Path.get = getPath;\n\n  Path.prototype = createObject({\n    __proto__: [],\n    valid: true,\n\n    toString: function() {\n      return this.join('.');\n    },\n\n    getValueFrom: function(obj, directObserver) {\n      for (var i = 0; i < this.length; i++) {\n        if (obj == null)\n          return;\n        obj = obj[this[i]];\n      }\n      return obj;\n    },\n\n    iterateObjects: function(obj, observe) {\n      for (var i = 0; i < this.length; i++) {\n        if (i)\n          obj = obj[this[i - 1]];\n        if (!obj)\n          return;\n        observe(obj);\n      }\n    },\n\n    compiledGetValueFromFn: function() {\n      var accessors = this.map(function(ident) {\n        return isIndex(ident) ? '[\"' + ident + '\"]' : '.' + ident;\n      });\n\n      var str = '';\n      var pathString = 'obj';\n      str += 'if (obj != null';\n      var i = 0;\n      for (; i < (this.length - 1); i++) {\n        var ident = this[i];\n        pathString += accessors[i];\n        str += ' &&\\n     ' + pathString + ' != null';\n      }\n      str += ')\\n';\n\n      pathString += accessors[i];\n\n      str += '  return ' + pathString + ';\\nelse\\n  return undefined;';\n      return new Function('obj', str);\n    },\n\n    setValueFrom: function(obj, value) {\n      if (!this.length)\n        return false;\n\n      for (var i = 0; i < this.length - 1; i++) {\n        if (!isObject(obj))\n          return false;\n        obj = obj[this[i]];\n      }\n\n      if (!isObject(obj))\n        return false;\n\n      obj[this[i]] = value;\n      return true;\n    }\n  });\n\n  var invalidPath = new Path('', constructorIsPrivate);\n  invalidPath.valid = false;\n  invalidPath.getValueFrom = invalidPath.setValueFrom = function() {};\n\n  var MAX_DIRTY_CHECK_CYCLES = 1000;\n\n  function dirtyCheck(observer) {\n    var cycles = 0;\n    while (cycles < MAX_DIRTY_CHECK_CYCLES && observer.check_()) {\n      cycles++;\n    }\n    if (global.testingExposeCycleCount)\n      global.dirtyCheckCycleCount = cycles;\n\n    return cycles > 0;\n  }\n\n  function objectIsEmpty(object) {\n    for (var prop in object)\n      return false;\n    return true;\n  }\n\n  function diffIsEmpty(diff) {\n    return objectIsEmpty(diff.added) &&\n           objectIsEmpty(diff.removed) &&\n           objectIsEmpty(diff.changed);\n  }\n\n  function diffObjectFromOldObject(object, oldObject) {\n    var added = {};\n    var removed = {};\n    var changed = {};\n\n    for (var prop in oldObject) {\n      var newValue = object[prop];\n\n      if (newValue !== undefined && newValue === oldObject[prop])\n        continue;\n\n      if (!(prop in object)) {\n        removed[prop] = undefined;\n        continue;\n      }\n\n      if (newValue !== oldObject[prop])\n        changed[prop] = newValue;\n    }\n\n    for (var prop in object) {\n      if (prop in oldObject)\n        continue;\n\n      added[prop] = object[prop];\n    }\n\n    if (Array.isArray(object) && object.length !== oldObject.length)\n      changed.length = object.length;\n\n    return {\n      added: added,\n      removed: removed,\n      changed: changed\n    };\n  }\n\n  var eomTasks = [];\n  function runEOMTasks() {\n    if (!eomTasks.length)\n      return false;\n\n    for (var i = 0; i < eomTasks.length; i++) {\n      eomTasks[i]();\n    }\n    eomTasks.length = 0;\n    return true;\n  }\n\n  var runEOM = hasObserve ? (function(){\n    var eomObj = { pingPong: true };\n    var eomRunScheduled = false;\n\n    Object.observe(eomObj, function() {\n      runEOMTasks();\n      eomRunScheduled = false;\n    });\n\n    return function(fn) {\n      eomTasks.push(fn);\n      if (!eomRunScheduled) {\n        eomRunScheduled = true;\n        eomObj.pingPong = !eomObj.pingPong;\n      }\n    };\n  })() :\n  (function() {\n    return function(fn) {\n      eomTasks.push(fn);\n    };\n  })();\n\n  var observedObjectCache = [];\n\n  function newObservedObject() {\n    var observer;\n    var object;\n    var discardRecords = false;\n    var first = true;\n\n    function callback(records) {\n      if (observer && observer.state_ === OPENED && !discardRecords)\n        observer.check_(records);\n    }\n\n    return {\n      open: function(obs) {\n        if (observer)\n          throw Error('ObservedObject in use');\n\n        if (!first)\n          Object.deliverChangeRecords(callback);\n\n        observer = obs;\n        first = false;\n      },\n      observe: function(obj, arrayObserve) {\n        object = obj;\n        if (arrayObserve)\n          Array.observe(object, callback);\n        else\n          Object.observe(object, callback);\n      },\n      deliver: function(discard) {\n        discardRecords = discard;\n        Object.deliverChangeRecords(callback);\n        discardRecords = false;\n      },\n      close: function() {\n        observer = undefined;\n        Object.unobserve(object, callback);\n        observedObjectCache.push(this);\n      }\n    };\n  }\n\n  function getObservedObject(observer, object, arrayObserve) {\n    var dir = observedObjectCache.pop() || newObservedObject();\n    dir.open(observer);\n    dir.observe(object, arrayObserve);\n    return dir;\n  }\n\n  var emptyArray = [];\n  var observedSetCache = [];\n\n  function newObservedSet() {\n    var observers = [];\n    var observerCount = 0;\n    var objects = [];\n    var toRemove = emptyArray;\n    var resetNeeded = false;\n    var resetScheduled = false;\n\n    function observe(obj) {\n      if (!isObject(obj))\n        return;\n\n      var index = toRemove.indexOf(obj);\n      if (index >= 0) {\n        toRemove[index] = undefined;\n        objects.push(obj);\n      } else if (objects.indexOf(obj) < 0) {\n        objects.push(obj);\n        Object.observe(obj, callback);\n      }\n\n      observe(Object.getPrototypeOf(obj));\n    }\n\n    function reset() {\n      resetScheduled = false;\n      if (!resetNeeded)\n        return;\n\n      var objs = toRemove === emptyArray ? [] : toRemove;\n      toRemove = objects;\n      objects = objs;\n\n      var observer;\n      for (var id in observers) {\n        observer = observers[id];\n        if (!observer || observer.state_ != OPENED)\n          continue;\n\n        observer.iterateObjects_(observe);\n      }\n\n      for (var i = 0; i < toRemove.length; i++) {\n        var obj = toRemove[i];\n        if (obj)\n          Object.unobserve(obj, callback);\n      }\n\n      toRemove.length = 0;\n    }\n\n    function scheduleReset() {\n      if (resetScheduled)\n        return;\n\n      resetNeeded = true;\n      resetScheduled = true;\n      runEOM(reset);\n    }\n\n    function callback() {\n      var observer;\n\n      for (var id in observers) {\n        observer = observers[id];\n        if (!observer || observer.state_ != OPENED)\n          continue;\n\n        observer.check_();\n      }\n\n      scheduleReset();\n    }\n\n    var record = {\n      object: undefined,\n      objects: objects,\n      open: function(obs) {\n        observers[obs.id_] = obs;\n        observerCount++;\n        obs.iterateObjects_(observe);\n      },\n      close: function(obs) {\n        var anyLeft = false;\n\n        observers[obs.id_] = undefined;\n        observerCount--;\n\n        if (observerCount) {\n          scheduleReset();\n          return;\n        }\n        resetNeeded = false;\n\n        for (var i = 0; i < objects.length; i++) {\n          Object.unobserve(objects[i], callback);\n          Observer.unobservedCount++;\n        }\n\n        observers.length = 0;\n        objects.length = 0;\n        observedSetCache.push(this);\n      },\n      reset: scheduleReset\n    };\n\n    return record;\n  }\n\n  var lastObservedSet;\n\n  function getObservedSet(observer, obj) {\n    if (!lastObservedSet || lastObservedSet.object !== obj) {\n      lastObservedSet = observedSetCache.pop() || newObservedSet();\n      lastObservedSet.object = obj;\n    }\n    lastObservedSet.open(observer);\n    return lastObservedSet;\n  }\n\n  var UNOPENED = 0;\n  var OPENED = 1;\n  var CLOSED = 2;\n  var RESETTING = 3;\n\n  var nextObserverId = 1;\n\n  function Observer() {\n    this.state_ = UNOPENED;\n    this.callback_ = undefined;\n    this.target_ = undefined; // TODO(rafaelw): Should be WeakRef\n    this.directObserver_ = undefined;\n    this.value_ = undefined;\n    this.id_ = nextObserverId++;\n  }\n\n  Observer.prototype = {\n    open: function(callback, target) {\n      if (this.state_ != UNOPENED)\n        throw Error('Observer has already been opened.');\n\n      addToAll(this);\n      this.callback_ = callback;\n      this.target_ = target;\n      this.state_ = OPENED;\n      this.connect_();\n      return this.value_;\n    },\n\n    close: function() {\n      if (this.state_ != OPENED)\n        return;\n\n      removeFromAll(this);\n      this.state_ = CLOSED;\n      this.disconnect_();\n      this.value_ = undefined;\n      this.callback_ = undefined;\n      this.target_ = undefined;\n    },\n\n    deliver: function() {\n      if (this.state_ != OPENED)\n        return;\n\n      dirtyCheck(this);\n    },\n\n    report_: function(changes) {\n      try {\n        this.callback_.apply(this.target_, changes);\n      } catch (ex) {\n        Observer._errorThrownDuringCallback = true;\n        console.error('Exception caught during observer callback: ' +\n                       (ex.stack || ex));\n      }\n    },\n\n    discardChanges: function() {\n      this.check_(undefined, true);\n      return this.value_;\n    }\n  }\n\n  var collectObservers = !hasObserve;\n  var allObservers;\n  Observer._allObserversCount = 0;\n\n  if (collectObservers) {\n    allObservers = [];\n  }\n\n  function addToAll(observer) {\n    Observer._allObserversCount++;\n    if (!collectObservers)\n      return;\n\n    allObservers.push(observer);\n  }\n\n  function removeFromAll(observer) {\n    Observer._allObserversCount--;\n  }\n\n  var runningMicrotaskCheckpoint = false;\n\n  var hasDebugForceFullDelivery = typeof Object.deliverAllChangeRecords == 'function';\n\n  global.Platform = global.Platform || {};\n\n  global.Platform.performMicrotaskCheckpoint = function() {\n    if (runningMicrotaskCheckpoint)\n      return;\n\n    if (hasDebugForceFullDelivery) {\n      Object.deliverAllChangeRecords();\n      return;\n    }\n\n    if (!collectObservers)\n      return;\n\n    runningMicrotaskCheckpoint = true;\n\n    var cycles = 0;\n    var anyChanged, toCheck;\n\n    do {\n      cycles++;\n      toCheck = allObservers;\n      allObservers = [];\n      anyChanged = false;\n\n      for (var i = 0; i < toCheck.length; i++) {\n        var observer = toCheck[i];\n        if (observer.state_ != OPENED)\n          continue;\n\n        if (observer.check_())\n          anyChanged = true;\n\n        allObservers.push(observer);\n      }\n      if (runEOMTasks())\n        anyChanged = true;\n    } while (cycles < MAX_DIRTY_CHECK_CYCLES && anyChanged);\n\n    if (global.testingExposeCycleCount)\n      global.dirtyCheckCycleCount = cycles;\n\n    runningMicrotaskCheckpoint = false;\n  };\n\n  if (collectObservers) {\n    global.Platform.clearObservers = function() {\n      allObservers = [];\n    };\n  }\n\n  function ObjectObserver(object) {\n    Observer.call(this);\n    this.value_ = object;\n    this.oldObject_ = undefined;\n  }\n\n  ObjectObserver.prototype = createObject({\n    __proto__: Observer.prototype,\n\n    arrayObserve: false,\n\n    connect_: function(callback, target) {\n      if (hasObserve) {\n        this.directObserver_ = getObservedObject(this, this.value_,\n                                                 this.arrayObserve);\n      } else {\n        this.oldObject_ = this.copyObject(this.value_);\n      }\n\n    },\n\n    copyObject: function(object) {\n      var copy = Array.isArray(object) ? [] : {};\n      for (var prop in object) {\n        copy[prop] = object[prop];\n      };\n      if (Array.isArray(object))\n        copy.length = object.length;\n      return copy;\n    },\n\n    check_: function(changeRecords, skipChanges) {\n      var diff;\n      var oldValues;\n      if (hasObserve) {\n        if (!changeRecords)\n          return false;\n\n        oldValues = {};\n        diff = diffObjectFromChangeRecords(this.value_, changeRecords,\n                                           oldValues);\n      } else {\n        oldValues = this.oldObject_;\n        diff = diffObjectFromOldObject(this.value_, this.oldObject_);\n      }\n\n      if (diffIsEmpty(diff))\n        return false;\n\n      if (!hasObserve)\n        this.oldObject_ = this.copyObject(this.value_);\n\n      this.report_([\n        diff.added || {},\n        diff.removed || {},\n        diff.changed || {},\n        function(property) {\n          return oldValues[property];\n        }\n      ]);\n\n      return true;\n    },\n\n    disconnect_: function() {\n      if (hasObserve) {\n        this.directObserver_.close();\n        this.directObserver_ = undefined;\n      } else {\n        this.oldObject_ = undefined;\n      }\n    },\n\n    deliver: function() {\n      if (this.state_ != OPENED)\n        return;\n\n      if (hasObserve)\n        this.directObserver_.deliver(false);\n      else\n        dirtyCheck(this);\n    },\n\n    discardChanges: function() {\n      if (this.directObserver_)\n        this.directObserver_.deliver(true);\n      else\n        this.oldObject_ = this.copyObject(this.value_);\n\n      return this.value_;\n    }\n  });\n\n  function ArrayObserver(array) {\n    if (!Array.isArray(array))\n      throw Error('Provided object is not an Array');\n    ObjectObserver.call(this, array);\n  }\n\n  ArrayObserver.prototype = createObject({\n\n    __proto__: ObjectObserver.prototype,\n\n    arrayObserve: true,\n\n    copyObject: function(arr) {\n      return arr.slice();\n    },\n\n    check_: function(changeRecords) {\n      var splices;\n      if (hasObserve) {\n        if (!changeRecords)\n          return false;\n        splices = projectArraySplices(this.value_, changeRecords);\n      } else {\n        splices = calcSplices(this.value_, 0, this.value_.length,\n                              this.oldObject_, 0, this.oldObject_.length);\n      }\n\n      if (!splices || !splices.length)\n        return false;\n\n      if (!hasObserve)\n        this.oldObject_ = this.copyObject(this.value_);\n\n      this.report_([splices]);\n      return true;\n    }\n  });\n\n  ArrayObserver.applySplices = function(previous, current, splices) {\n    splices.forEach(function(splice) {\n      var spliceArgs = [splice.index, splice.removed.length];\n      var addIndex = splice.index;\n      while (addIndex < splice.index + splice.addedCount) {\n        spliceArgs.push(current[addIndex]);\n        addIndex++;\n      }\n\n      Array.prototype.splice.apply(previous, spliceArgs);\n    });\n  };\n\n  function PathObserver(object, path) {\n    Observer.call(this);\n\n    this.object_ = object;\n    this.path_ = path instanceof Path ? path : getPath(path);\n    this.directObserver_ = undefined;\n  }\n\n  PathObserver.prototype = createObject({\n    __proto__: Observer.prototype,\n\n    connect_: function() {\n      if (hasObserve)\n        this.directObserver_ = getObservedSet(this, this.object_);\n\n      this.check_(undefined, true);\n    },\n\n    disconnect_: function() {\n      this.value_ = undefined;\n\n      if (this.directObserver_) {\n        this.directObserver_.close(this);\n        this.directObserver_ = undefined;\n      }\n    },\n\n    iterateObjects_: function(observe) {\n      this.path_.iterateObjects(this.object_, observe);\n    },\n\n    check_: function(changeRecords, skipChanges) {\n      var oldValue = this.value_;\n      this.value_ = this.path_.getValueFrom(this.object_);\n      if (skipChanges || areSameValue(this.value_, oldValue))\n        return false;\n\n      this.report_([this.value_, oldValue]);\n      return true;\n    },\n\n    setValue: function(newValue) {\n      if (this.path_)\n        this.path_.setValueFrom(this.object_, newValue);\n    }\n  });\n\n  function CompoundObserver() {\n    Observer.call(this);\n\n    this.value_ = [];\n    this.directObserver_ = undefined;\n    this.observed_ = [];\n  }\n\n  var observerSentinel = {};\n\n  CompoundObserver.prototype = createObject({\n    __proto__: Observer.prototype,\n\n    connect_: function() {\n      this.check_(undefined, true);\n\n      if (!hasObserve)\n        return;\n\n      var object;\n      var needsDirectObserver = false;\n      for (var i = 0; i < this.observed_.length; i += 2) {\n        object = this.observed_[i]\n        if (object !== observerSentinel) {\n          needsDirectObserver = true;\n          break;\n        }\n      }\n\n      if (this.directObserver_) {\n        if (needsDirectObserver) {\n          this.directObserver_.reset();\n          return;\n        }\n        this.directObserver_.close();\n        this.directObserver_ = undefined;\n        return;\n      }\n\n      if (needsDirectObserver)\n        this.directObserver_ = getObservedSet(this, object);\n    },\n\n    closeObservers_: function() {\n      for (var i = 0; i < this.observed_.length; i += 2) {\n        if (this.observed_[i] === observerSentinel)\n          this.observed_[i + 1].close();\n      }\n      this.observed_.length = 0;\n    },\n\n    disconnect_: function() {\n      this.value_ = undefined;\n\n      if (this.directObserver_) {\n        this.directObserver_.close(this);\n        this.directObserver_ = undefined;\n      }\n\n      this.closeObservers_();\n    },\n\n    addPath: function(object, path) {\n      if (this.state_ != UNOPENED && this.state_ != RESETTING)\n        throw Error('Cannot add paths once started.');\n\n      this.observed_.push(object, path instanceof Path ? path : getPath(path));\n    },\n\n    addObserver: function(observer) {\n      if (this.state_ != UNOPENED && this.state_ != RESETTING)\n        throw Error('Cannot add observers once started.');\n\n      observer.open(this.deliver, this);\n      this.observed_.push(observerSentinel, observer);\n    },\n\n    startReset: function() {\n      if (this.state_ != OPENED)\n        throw Error('Can only reset while open');\n\n      this.state_ = RESETTING;\n      this.closeObservers_();\n    },\n\n    finishReset: function() {\n      if (this.state_ != RESETTING)\n        throw Error('Can only finishReset after startReset');\n      this.state_ = OPENED;\n      this.connect_();\n\n      return this.value_;\n    },\n\n    iterateObjects_: function(observe) {\n      var object;\n      for (var i = 0; i < this.observed_.length; i += 2) {\n        object = this.observed_[i]\n        if (object !== observerSentinel)\n          this.observed_[i + 1].iterateObjects(object, observe)\n      }\n    },\n\n    check_: function(changeRecords, skipChanges) {\n      var oldValues;\n      for (var i = 0; i < this.observed_.length; i += 2) {\n        var pathOrObserver = this.observed_[i+1];\n        var object = this.observed_[i];\n        var value = object === observerSentinel ?\n            pathOrObserver.discardChanges() :\n            pathOrObserver.getValueFrom(object)\n\n        if (skipChanges) {\n          this.value_[i / 2] = value;\n          continue;\n        }\n\n        if (areSameValue(value, this.value_[i / 2]))\n          continue;\n\n        oldValues = oldValues || [];\n        oldValues[i / 2] = this.value_[i / 2];\n        this.value_[i / 2] = value;\n      }\n\n      if (!oldValues)\n        return false;\n\n      // TODO(rafaelw): Having observed_ as the third callback arg here is\n      // pretty lame API. Fix.\n      this.report_([this.value_, oldValues, this.observed_]);\n      return true;\n    }\n  });\n\n  function identFn(value) { return value; }\n\n  function ObserverTransform(observable, getValueFn, setValueFn,\n                             dontPassThroughSet) {\n    this.callback_ = undefined;\n    this.target_ = undefined;\n    this.value_ = undefined;\n    this.observable_ = observable;\n    this.getValueFn_ = getValueFn || identFn;\n    this.setValueFn_ = setValueFn || identFn;\n    // TODO(rafaelw): This is a temporary hack. PolymerExpressions needs this\n    // at the moment because of a bug in it's dependency tracking.\n    this.dontPassThroughSet_ = dontPassThroughSet;\n  }\n\n  ObserverTransform.prototype = {\n    open: function(callback, target) {\n      this.callback_ = callback;\n      this.target_ = target;\n      this.value_ =\n          this.getValueFn_(this.observable_.open(this.observedCallback_, this));\n      return this.value_;\n    },\n\n    observedCallback_: function(value) {\n      value = this.getValueFn_(value);\n      if (areSameValue(value, this.value_))\n        return;\n      var oldValue = this.value_;\n      this.value_ = value;\n      this.callback_.call(this.target_, this.value_, oldValue);\n    },\n\n    discardChanges: function() {\n      this.value_ = this.getValueFn_(this.observable_.discardChanges());\n      return this.value_;\n    },\n\n    deliver: function() {\n      return this.observable_.deliver();\n    },\n\n    setValue: function(value) {\n      value = this.setValueFn_(value);\n      if (!this.dontPassThroughSet_ && this.observable_.setValue)\n        return this.observable_.setValue(value);\n    },\n\n    close: function() {\n      if (this.observable_)\n        this.observable_.close();\n      this.callback_ = undefined;\n      this.target_ = undefined;\n      this.observable_ = undefined;\n      this.value_ = undefined;\n      this.getValueFn_ = undefined;\n      this.setValueFn_ = undefined;\n    }\n  }\n\n  var expectedRecordTypes = {};\n  expectedRecordTypes[PROP_ADD_TYPE] = true;\n  expectedRecordTypes[PROP_UPDATE_TYPE] = true;\n  expectedRecordTypes[PROP_DELETE_TYPE] = true;\n\n  function notifyFunction(object, name) {\n    if (typeof Object.observe !== 'function')\n      return;\n\n    var notifier = Object.getNotifier(object);\n    return function(type, oldValue) {\n      var changeRecord = {\n        object: object,\n        type: type,\n        name: name\n      };\n      if (arguments.length === 2)\n        changeRecord.oldValue = oldValue;\n      notifier.notify(changeRecord);\n    }\n  }\n\n  Observer.defineComputedProperty = function(target, name, observable) {\n    var notify = notifyFunction(target, name);\n    var value = observable.open(function(newValue, oldValue) {\n      value = newValue;\n      if (notify)\n        notify(PROP_UPDATE_TYPE, oldValue);\n    });\n\n    Object.defineProperty(target, name, {\n      get: function() {\n        observable.deliver();\n        return value;\n      },\n      set: function(newValue) {\n        observable.setValue(newValue);\n        return newValue;\n      },\n      configurable: true\n    });\n\n    return {\n      close: function() {\n        observable.close();\n        Object.defineProperty(target, name, {\n          value: value,\n          writable: true,\n          configurable: true\n        });\n      }\n    };\n  }\n\n  function diffObjectFromChangeRecords(object, changeRecords, oldValues) {\n    var added = {};\n    var removed = {};\n\n    for (var i = 0; i < changeRecords.length; i++) {\n      var record = changeRecords[i];\n      if (!expectedRecordTypes[record.type]) {\n        console.error('Unknown changeRecord type: ' + record.type);\n        console.error(record);\n        continue;\n      }\n\n      if (!(record.name in oldValues))\n        oldValues[record.name] = record.oldValue;\n\n      if (record.type == PROP_UPDATE_TYPE)\n        continue;\n\n      if (record.type == PROP_ADD_TYPE) {\n        if (record.name in removed)\n          delete removed[record.name];\n        else\n          added[record.name] = true;\n\n        continue;\n      }\n\n      // type = 'delete'\n      if (record.name in added) {\n        delete added[record.name];\n        delete oldValues[record.name];\n      } else {\n        removed[record.name] = true;\n      }\n    }\n\n    for (var prop in added)\n      added[prop] = object[prop];\n\n    for (var prop in removed)\n      removed[prop] = undefined;\n\n    var changed = {};\n    for (var prop in oldValues) {\n      if (prop in added || prop in removed)\n        continue;\n\n      var newValue = object[prop];\n      if (oldValues[prop] !== newValue)\n        changed[prop] = newValue;\n    }\n\n    return {\n      added: added,\n      removed: removed,\n      changed: changed\n    };\n  }\n\n  function newSplice(index, removed, addedCount) {\n    return {\n      index: index,\n      removed: removed,\n      addedCount: addedCount\n    };\n  }\n\n  var EDIT_LEAVE = 0;\n  var EDIT_UPDATE = 1;\n  var EDIT_ADD = 2;\n  var EDIT_DELETE = 3;\n\n  function ArraySplice() {}\n\n  ArraySplice.prototype = {\n\n    // Note: This function is *based* on the computation of the Levenshtein\n    // \"edit\" distance. The one change is that \"updates\" are treated as two\n    // edits - not one. With Array splices, an update is really a delete\n    // followed by an add. By retaining this, we optimize for \"keeping\" the\n    // maximum array items in the original array. For example:\n    //\n    //   'xxxx123' -> '123yyyy'\n    //\n    // With 1-edit updates, the shortest path would be just to update all seven\n    // characters. With 2-edit updates, we delete 4, leave 3, and add 4. This\n    // leaves the substring '123' intact.\n    calcEditDistances: function(current, currentStart, currentEnd,\n                                old, oldStart, oldEnd) {\n      // \"Deletion\" columns\n      var rowCount = oldEnd - oldStart + 1;\n      var columnCount = currentEnd - currentStart + 1;\n      var distances = new Array(rowCount);\n\n      // \"Addition\" rows. Initialize null column.\n      for (var i = 0; i < rowCount; i++) {\n        distances[i] = new Array(columnCount);\n        distances[i][0] = i;\n      }\n\n      // Initialize null row\n      for (var j = 0; j < columnCount; j++)\n        distances[0][j] = j;\n\n      for (var i = 1; i < rowCount; i++) {\n        for (var j = 1; j < columnCount; j++) {\n          if (this.equals(current[currentStart + j - 1], old[oldStart + i - 1]))\n            distances[i][j] = distances[i - 1][j - 1];\n          else {\n            var north = distances[i - 1][j] + 1;\n            var west = distances[i][j - 1] + 1;\n            distances[i][j] = north < west ? north : west;\n          }\n        }\n      }\n\n      return distances;\n    },\n\n    // This starts at the final weight, and walks \"backward\" by finding\n    // the minimum previous weight recursively until the origin of the weight\n    // matrix.\n    spliceOperationsFromEditDistances: function(distances) {\n      var i = distances.length - 1;\n      var j = distances[0].length - 1;\n      var current = distances[i][j];\n      var edits = [];\n      while (i > 0 || j > 0) {\n        if (i == 0) {\n          edits.push(EDIT_ADD);\n          j--;\n          continue;\n        }\n        if (j == 0) {\n          edits.push(EDIT_DELETE);\n          i--;\n          continue;\n        }\n        var northWest = distances[i - 1][j - 1];\n        var west = distances[i - 1][j];\n        var north = distances[i][j - 1];\n\n        var min;\n        if (west < north)\n          min = west < northWest ? west : northWest;\n        else\n          min = north < northWest ? north : northWest;\n\n        if (min == northWest) {\n          if (northWest == current) {\n            edits.push(EDIT_LEAVE);\n          } else {\n            edits.push(EDIT_UPDATE);\n            current = northWest;\n          }\n          i--;\n          j--;\n        } else if (min == west) {\n          edits.push(EDIT_DELETE);\n          i--;\n          current = west;\n        } else {\n          edits.push(EDIT_ADD);\n          j--;\n          current = north;\n        }\n      }\n\n      edits.reverse();\n      return edits;\n    },\n\n    /**\n     * Splice Projection functions:\n     *\n     * A splice map is a representation of how a previous array of items\n     * was transformed into a new array of items. Conceptually it is a list of\n     * tuples of\n     *\n     *   <index, removed, addedCount>\n     *\n     * which are kept in ascending index order of. The tuple represents that at\n     * the |index|, |removed| sequence of items were removed, and counting forward\n     * from |index|, |addedCount| items were added.\n     */\n\n    /**\n     * Lacking individual splice mutation information, the minimal set of\n     * splices can be synthesized given the previous state and final state of an\n     * array. The basic approach is to calculate the edit distance matrix and\n     * choose the shortest path through it.\n     *\n     * Complexity: O(l * p)\n     *   l: The length of the current array\n     *   p: The length of the old array\n     */\n    calcSplices: function(current, currentStart, currentEnd,\n                          old, oldStart, oldEnd) {\n      var prefixCount = 0;\n      var suffixCount = 0;\n\n      var minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart);\n      if (currentStart == 0 && oldStart == 0)\n        prefixCount = this.sharedPrefix(current, old, minLength);\n\n      if (currentEnd == current.length && oldEnd == old.length)\n        suffixCount = this.sharedSuffix(current, old, minLength - prefixCount);\n\n      currentStart += prefixCount;\n      oldStart += prefixCount;\n      currentEnd -= suffixCount;\n      oldEnd -= suffixCount;\n\n      if (currentEnd - currentStart == 0 && oldEnd - oldStart == 0)\n        return [];\n\n      if (currentStart == currentEnd) {\n        var splice = newSplice(currentStart, [], 0);\n        while (oldStart < oldEnd)\n          splice.removed.push(old[oldStart++]);\n\n        return [ splice ];\n      } else if (oldStart == oldEnd)\n        return [ newSplice(currentStart, [], currentEnd - currentStart) ];\n\n      var ops = this.spliceOperationsFromEditDistances(\n          this.calcEditDistances(current, currentStart, currentEnd,\n                                 old, oldStart, oldEnd));\n\n      var splice = undefined;\n      var splices = [];\n      var index = currentStart;\n      var oldIndex = oldStart;\n      for (var i = 0; i < ops.length; i++) {\n        switch(ops[i]) {\n          case EDIT_LEAVE:\n            if (splice) {\n              splices.push(splice);\n              splice = undefined;\n            }\n\n            index++;\n            oldIndex++;\n            break;\n          case EDIT_UPDATE:\n            if (!splice)\n              splice = newSplice(index, [], 0);\n\n            splice.addedCount++;\n            index++;\n\n            splice.removed.push(old[oldIndex]);\n            oldIndex++;\n            break;\n          case EDIT_ADD:\n            if (!splice)\n              splice = newSplice(index, [], 0);\n\n            splice.addedCount++;\n            index++;\n            break;\n          case EDIT_DELETE:\n            if (!splice)\n              splice = newSplice(index, [], 0);\n\n            splice.removed.push(old[oldIndex]);\n            oldIndex++;\n            break;\n        }\n      }\n\n      if (splice) {\n        splices.push(splice);\n      }\n      return splices;\n    },\n\n    sharedPrefix: function(current, old, searchLength) {\n      for (var i = 0; i < searchLength; i++)\n        if (!this.equals(current[i], old[i]))\n          return i;\n      return searchLength;\n    },\n\n    sharedSuffix: function(current, old, searchLength) {\n      var index1 = current.length;\n      var index2 = old.length;\n      var count = 0;\n      while (count < searchLength && this.equals(current[--index1], old[--index2]))\n        count++;\n\n      return count;\n    },\n\n    calculateSplices: function(current, previous) {\n      return this.calcSplices(current, 0, current.length, previous, 0,\n                              previous.length);\n    },\n\n    equals: function(currentValue, previousValue) {\n      return currentValue === previousValue;\n    }\n  };\n\n  var arraySplice = new ArraySplice();\n\n  function calcSplices(current, currentStart, currentEnd,\n                       old, oldStart, oldEnd) {\n    return arraySplice.calcSplices(current, currentStart, currentEnd,\n                                   old, oldStart, oldEnd);\n  }\n\n  function intersect(start1, end1, start2, end2) {\n    // Disjoint\n    if (end1 < start2 || end2 < start1)\n      return -1;\n\n    // Adjacent\n    if (end1 == start2 || end2 == start1)\n      return 0;\n\n    // Non-zero intersect, span1 first\n    if (start1 < start2) {\n      if (end1 < end2)\n        return end1 - start2; // Overlap\n      else\n        return end2 - start2; // Contained\n    } else {\n      // Non-zero intersect, span2 first\n      if (end2 < end1)\n        return end2 - start1; // Overlap\n      else\n        return end1 - start1; // Contained\n    }\n  }\n\n  function mergeSplice(splices, index, removed, addedCount) {\n\n    var splice = newSplice(index, removed, addedCount);\n\n    var inserted = false;\n    var insertionOffset = 0;\n\n    for (var i = 0; i < splices.length; i++) {\n      var current = splices[i];\n      current.index += insertionOffset;\n\n      if (inserted)\n        continue;\n\n      var intersectCount = intersect(splice.index,\n                                     splice.index + splice.removed.length,\n                                     current.index,\n                                     current.index + current.addedCount);\n\n      if (intersectCount >= 0) {\n        // Merge the two splices\n\n        splices.splice(i, 1);\n        i--;\n\n        insertionOffset -= current.addedCount - current.removed.length;\n\n        splice.addedCount += current.addedCount - intersectCount;\n        var deleteCount = splice.removed.length +\n                          current.removed.length - intersectCount;\n\n        if (!splice.addedCount && !deleteCount) {\n          // merged splice is a noop. discard.\n          inserted = true;\n        } else {\n          var removed = current.removed;\n\n          if (splice.index < current.index) {\n            // some prefix of splice.removed is prepended to current.removed.\n            var prepend = splice.removed.slice(0, current.index - splice.index);\n            Array.prototype.push.apply(prepend, removed);\n            removed = prepend;\n          }\n\n          if (splice.index + splice.removed.length > current.index + current.addedCount) {\n            // some suffix of splice.removed is appended to current.removed.\n            var append = splice.removed.slice(current.index + current.addedCount - splice.index);\n            Array.prototype.push.apply(removed, append);\n          }\n\n          splice.removed = removed;\n          if (current.index < splice.index) {\n            splice.index = current.index;\n          }\n        }\n      } else if (splice.index < current.index) {\n        // Insert splice here.\n\n        inserted = true;\n\n        splices.splice(i, 0, splice);\n        i++;\n\n        var offset = splice.addedCount - splice.removed.length\n        current.index += offset;\n        insertionOffset += offset;\n      }\n    }\n\n    if (!inserted)\n      splices.push(splice);\n  }\n\n  function createInitialSplices(array, changeRecords) {\n    var splices = [];\n\n    for (var i = 0; i < changeRecords.length; i++) {\n      var record = changeRecords[i];\n      switch(record.type) {\n        case ARRAY_SPLICE_TYPE:\n          mergeSplice(splices, record.index, record.removed.slice(), record.addedCount);\n          break;\n        case PROP_ADD_TYPE:\n        case PROP_UPDATE_TYPE:\n        case PROP_DELETE_TYPE:\n          if (!isIndex(record.name))\n            continue;\n          var index = toNumber(record.name);\n          if (index < 0)\n            continue;\n          mergeSplice(splices, index, [record.oldValue], 1);\n          break;\n        default:\n          console.error('Unexpected record type: ' + JSON.stringify(record));\n          break;\n      }\n    }\n\n    return splices;\n  }\n\n  function projectArraySplices(array, changeRecords) {\n    var splices = [];\n\n    createInitialSplices(array, changeRecords).forEach(function(splice) {\n      if (splice.addedCount == 1 && splice.removed.length == 1) {\n        if (splice.removed[0] !== array[splice.index])\n          splices.push(splice);\n\n        return\n      };\n\n      splices = splices.concat(calcSplices(array, splice.index, splice.index + splice.addedCount,\n                                           splice.removed, 0, splice.removed.length));\n    });\n\n    return splices;\n  }\n\n  global.Observer = Observer;\n  global.Observer.runEOM_ = runEOM;\n  global.Observer.hasObjectObserve = hasObserve;\n  global.ArrayObserver = ArrayObserver;\n  global.ArrayObserver.calculateSplices = function(current, previous) {\n    return arraySplice.calculateSplices(current, previous);\n  };\n\n  global.ArraySplice = ArraySplice;\n  global.ObjectObserver = ObjectObserver;\n  global.PathObserver = PathObserver;\n  global.CompoundObserver = CompoundObserver;\n  global.Path = Path;\n  global.ObserverTransform = ObserverTransform;\n\n  // TODO(rafaelw): Only needed for testing until new change record names\n  // make it to release.\n  global.Observer.changeRecordTypes = {\n    add: PROP_ADD_TYPE,\n    update: PROP_UPDATE_TYPE,\n    reconfigure: PROP_RECONFIGURE_TYPE,\n    'delete': PROP_DELETE_TYPE,\n    splice: ARRAY_SPLICE_TYPE\n  };\n})(typeof global !== 'undefined' && global && typeof module !== 'undefined' && module ? global : this || window);\n",
+    "// prepoulate window.Platform.flags for default controls\r\nwindow.Platform = window.Platform || {};\r\n// prepopulate window.logFlags if necessary\r\nwindow.logFlags = window.logFlags || {};\r\n// process flags\r\n(function(scope){\r\n  // import\r\n  var flags = scope.flags || {};\r\n  // populate flags from location\r\n  location.search.slice(1).split('&').forEach(function(o) {\r\n    o = o.split('=');\r\n    o[0] && (flags[o[0]] = o[1] || true);\r\n  });\r\n  var entryPoint = document.currentScript || document.querySelector('script[src*=\"platform.js\"]');\r\n  if (entryPoint) {\r\n    var a = entryPoint.attributes;\r\n    for (var i = 0, n; i < a.length; i++) {\r\n      n = a[i];\r\n      if (n.name !== 'src') {\r\n        flags[n.name] = n.value || true;\r\n      }\r\n    }\r\n  }\r\n  if (flags.log) {\r\n    flags.log.split(',').forEach(function(f) {\r\n      window.logFlags[f] = true;\r\n    });\r\n  }\r\n  // If any of these flags match 'native', then force native ShadowDOM; any\r\n  // other truthy value, or failure to detect native\r\n  // ShadowDOM, results in polyfill\r\n  flags.shadow = (flags.shadow || flags.shadowdom || flags.polyfill);\r\n  if (flags.shadow === 'native') {\r\n    flags.shadow = false;\r\n  } else {\r\n    flags.shadow = flags.shadow || !HTMLElement.prototype.createShadowRoot;\r\n  }\r\n\r\n  // CustomElements polyfill flag\r\n  if (flags.register) {\r\n    window.CustomElements = window.CustomElements || {flags: {}};\r\n    window.CustomElements.flags.register = flags.register;\r\n  }\r\n\r\n  if (flags.imports) {\r\n    window.HTMLImports = window.HTMLImports || {flags: {}};\r\n    window.HTMLImports.flags.imports = flags.imports;\r\n  }\r\n\r\n  // export\r\n  scope.flags = flags;\r\n})(Platform);\r\n\r\n// select ShadowDOM impl\r\nif (Platform.flags.shadow) {\r\n",
+    "// Copyright 2012 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\nwindow.ShadowDOMPolyfill = {};\n\n(function(scope) {\n  'use strict';\n\n  var constructorTable = new WeakMap();\n  var nativePrototypeTable = new WeakMap();\n  var wrappers = Object.create(null);\n\n  // Don't test for eval if document has CSP securityPolicy object and we can\n  // see that eval is not supported. This avoids an error message in console\n  // even when the exception is caught\n  var hasEval = !('securityPolicy' in document) ||\n      document.securityPolicy.allowsEval;\n  if (hasEval) {\n    try {\n      var f = new Function('', 'return true;');\n      hasEval = f();\n    } catch (ex) {\n      hasEval = false;\n    }\n  }\n\n  function assert(b) {\n    if (!b)\n      throw new Error('Assertion failed');\n  };\n\n  var defineProperty = Object.defineProperty;\n  var getOwnPropertyNames = Object.getOwnPropertyNames;\n  var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n\n  function mixin(to, from) {\n    getOwnPropertyNames(from).forEach(function(name) {\n      defineProperty(to, name, getOwnPropertyDescriptor(from, name));\n    });\n    return to;\n  };\n\n  function mixinStatics(to, from) {\n    getOwnPropertyNames(from).forEach(function(name) {\n      switch (name) {\n        case 'arguments':\n        case 'caller':\n        case 'length':\n        case 'name':\n        case 'prototype':\n        case 'toString':\n          return;\n      }\n      defineProperty(to, name, getOwnPropertyDescriptor(from, name));\n    });\n    return to;\n  };\n\n  function oneOf(object, propertyNames) {\n    for (var i = 0; i < propertyNames.length; i++) {\n      if (propertyNames[i] in object)\n        return propertyNames[i];\n    }\n  }\n\n  // Mozilla's old DOM bindings are bretty busted:\n  // https://bugzilla.mozilla.org/show_bug.cgi?id=855844\n  // Make sure they are create before we start modifying things.\n  getOwnPropertyNames(window);\n\n  function getWrapperConstructor(node) {\n    var nativePrototype = node.__proto__ || Object.getPrototypeOf(node);\n    var wrapperConstructor = constructorTable.get(nativePrototype);\n    if (wrapperConstructor)\n      return wrapperConstructor;\n\n    var parentWrapperConstructor = getWrapperConstructor(nativePrototype);\n\n    var GeneratedWrapper = createWrapperConstructor(parentWrapperConstructor);\n    registerInternal(nativePrototype, GeneratedWrapper, node);\n\n    return GeneratedWrapper;\n  }\n\n  function addForwardingProperties(nativePrototype, wrapperPrototype) {\n    installProperty(nativePrototype, wrapperPrototype, true);\n  }\n\n  function registerInstanceProperties(wrapperPrototype, instanceObject) {\n    installProperty(instanceObject, wrapperPrototype, false);\n  }\n\n  var isFirefox = /Firefox/.test(navigator.userAgent);\n\n  // This is used as a fallback when getting the descriptor fails in\n  // installProperty.\n  var dummyDescriptor = {\n    get: function() {},\n    set: function(v) {},\n    configurable: true,\n    enumerable: true\n  };\n\n  function isEventHandlerName(name) {\n    return /^on[a-z]+$/.test(name);\n  }\n\n  function isIdentifierName(name) {\n    return /^\\w[a-zA-Z_0-9]*$/.test(name);\n  }\n\n  function getGetter(name) {\n    return hasEval && isIdentifierName(name) ?\n        new Function('return this.impl.' + name) :\n        function() { return this.impl[name]; };\n  }\n\n  function getSetter(name) {\n    return hasEval && isIdentifierName(name) ?\n        new Function('v', 'this.impl.' + name + ' = v') :\n        function(v) { this.impl[name] = v; };\n  }\n\n  function getMethod(name) {\n    return hasEval && isIdentifierName(name) ?\n        new Function('return this.impl.' + name +\n                     '.apply(this.impl, arguments)') :\n        function() { return this.impl[name].apply(this.impl, arguments); };\n  }\n\n  function getDescriptor(source, name) {\n    try {\n      return Object.getOwnPropertyDescriptor(source, name);\n    } catch (ex) {\n      // JSC and V8 both use data properties instead of accessors which can\n      // cause getting the property desciptor to throw an exception.\n      // https://bugs.webkit.org/show_bug.cgi?id=49739\n      return dummyDescriptor;\n    }\n  }\n\n  function installProperty(source, target, allowMethod, opt_blacklist) {\n    var names = getOwnPropertyNames(source);\n    for (var i = 0; i < names.length; i++) {\n      var name = names[i];\n      if (name === 'polymerBlackList_')\n        continue;\n\n      if (name in target)\n        continue;\n\n      if (source.polymerBlackList_ && source.polymerBlackList_[name])\n        continue;\n\n      if (isFirefox) {\n        // Tickle Firefox's old bindings.\n        source.__lookupGetter__(name);\n      }\n      var descriptor = getDescriptor(source, name);\n      var getter, setter;\n      if (allowMethod && typeof descriptor.value === 'function') {\n        target[name] = getMethod(name);\n        continue;\n      }\n\n      var isEvent = isEventHandlerName(name);\n      if (isEvent)\n        getter = scope.getEventHandlerGetter(name);\n      else\n        getter = getGetter(name);\n\n      if (descriptor.writable || descriptor.set) {\n        if (isEvent)\n          setter = scope.getEventHandlerSetter(name);\n        else\n          setter = getSetter(name);\n      }\n\n      defineProperty(target, name, {\n        get: getter,\n        set: setter,\n        configurable: descriptor.configurable,\n        enumerable: descriptor.enumerable\n      });\n    }\n  }\n\n  /**\n   * @param {Function} nativeConstructor\n   * @param {Function} wrapperConstructor\n   * @param {Object=} opt_instance If present, this is used to extract\n   *     properties from an instance object.\n   */\n  function register(nativeConstructor, wrapperConstructor, opt_instance) {\n    var nativePrototype = nativeConstructor.prototype;\n    registerInternal(nativePrototype, wrapperConstructor, opt_instance);\n    mixinStatics(wrapperConstructor, nativeConstructor);\n  }\n\n  function registerInternal(nativePrototype, wrapperConstructor, opt_instance) {\n    var wrapperPrototype = wrapperConstructor.prototype;\n    assert(constructorTable.get(nativePrototype) === undefined);\n\n    constructorTable.set(nativePrototype, wrapperConstructor);\n    nativePrototypeTable.set(wrapperPrototype, nativePrototype);\n\n    addForwardingProperties(nativePrototype, wrapperPrototype);\n    if (opt_instance)\n      registerInstanceProperties(wrapperPrototype, opt_instance);\n    defineProperty(wrapperPrototype, 'constructor', {\n      value: wrapperConstructor,\n      configurable: true,\n      enumerable: false,\n      writable: true\n    });\n  }\n\n  function isWrapperFor(wrapperConstructor, nativeConstructor) {\n    return constructorTable.get(nativeConstructor.prototype) ===\n        wrapperConstructor;\n  }\n\n  /**\n   * Creates a generic wrapper constructor based on |object| and its\n   * constructor.\n   * @param {Node} object\n   * @return {Function} The generated constructor.\n   */\n  function registerObject(object) {\n    var nativePrototype = Object.getPrototypeOf(object);\n\n    var superWrapperConstructor = getWrapperConstructor(nativePrototype);\n    var GeneratedWrapper = createWrapperConstructor(superWrapperConstructor);\n    registerInternal(nativePrototype, GeneratedWrapper, object);\n\n    return GeneratedWrapper;\n  }\n\n  function createWrapperConstructor(superWrapperConstructor) {\n    function GeneratedWrapper(node) {\n      superWrapperConstructor.call(this, node);\n    }\n    GeneratedWrapper.prototype =\n        Object.create(superWrapperConstructor.prototype);\n    GeneratedWrapper.prototype.constructor = GeneratedWrapper;\n\n    return GeneratedWrapper;\n  }\n\n  var OriginalDOMImplementation = window.DOMImplementation;\n  var OriginalEventTarget = window.EventTarget;\n  var OriginalEvent = window.Event;\n  var OriginalNode = window.Node;\n  var OriginalWindow = window.Window;\n  var OriginalRange = window.Range;\n  var OriginalCanvasRenderingContext2D = window.CanvasRenderingContext2D;\n  var OriginalWebGLRenderingContext = window.WebGLRenderingContext;\n  var OriginalSVGElementInstance = window.SVGElementInstance;\n\n  function isWrapper(object) {\n    return object instanceof wrappers.EventTarget ||\n           object instanceof wrappers.Event ||\n           object instanceof wrappers.Range ||\n           object instanceof wrappers.DOMImplementation ||\n           object instanceof wrappers.CanvasRenderingContext2D ||\n           wrappers.WebGLRenderingContext &&\n               object instanceof wrappers.WebGLRenderingContext;\n  }\n\n  function isNative(object) {\n    return OriginalEventTarget && object instanceof OriginalEventTarget ||\n           object instanceof OriginalNode ||\n           object instanceof OriginalEvent ||\n           object instanceof OriginalWindow ||\n           object instanceof OriginalRange ||\n           object instanceof OriginalDOMImplementation ||\n           object instanceof OriginalCanvasRenderingContext2D ||\n           OriginalWebGLRenderingContext &&\n               object instanceof OriginalWebGLRenderingContext ||\n           OriginalSVGElementInstance &&\n               object instanceof OriginalSVGElementInstance;\n  }\n\n  /**\n   * Wraps a node in a WrapperNode. If there already exists a wrapper for the\n   * |node| that wrapper is returned instead.\n   * @param {Node} node\n   * @return {WrapperNode}\n   */\n  function wrap(impl) {\n    if (impl === null)\n      return null;\n\n    assert(isNative(impl));\n    return impl.polymerWrapper_ ||\n        (impl.polymerWrapper_ = new (getWrapperConstructor(impl))(impl));\n  }\n\n  /**\n   * Unwraps a wrapper and returns the node it is wrapping.\n   * @param {WrapperNode} wrapper\n   * @return {Node}\n   */\n  function unwrap(wrapper) {\n    if (wrapper === null)\n      return null;\n    assert(isWrapper(wrapper));\n    return wrapper.impl;\n  }\n\n  /**\n   * Unwraps object if it is a wrapper.\n   * @param {Object} object\n   * @return {Object} The native implementation object.\n   */\n  function unwrapIfNeeded(object) {\n    return object && isWrapper(object) ? unwrap(object) : object;\n  }\n\n  /**\n   * Wraps object if it is not a wrapper.\n   * @param {Object} object\n   * @return {Object} The wrapper for object.\n   */\n  function wrapIfNeeded(object) {\n    return object && !isWrapper(object) ? wrap(object) : object;\n  }\n\n  /**\n   * Overrides the current wrapper (if any) for node.\n   * @param {Node} node\n   * @param {WrapperNode=} wrapper If left out the wrapper will be created as\n   *     needed next time someone wraps the node.\n   */\n  function rewrap(node, wrapper) {\n    if (wrapper === null)\n      return;\n    assert(isNative(node));\n    assert(wrapper === undefined || isWrapper(wrapper));\n    node.polymerWrapper_ = wrapper;\n  }\n\n  function defineGetter(constructor, name, getter) {\n    defineProperty(constructor.prototype, name, {\n      get: getter,\n      configurable: true,\n      enumerable: true\n    });\n  }\n\n  function defineWrapGetter(constructor, name) {\n    defineGetter(constructor, name, function() {\n      return wrap(this.impl[name]);\n    });\n  }\n\n  /**\n   * Forwards existing methods on the native object to the wrapper methods.\n   * This does not wrap any of the arguments or the return value since the\n   * wrapper implementation already takes care of that.\n   * @param {Array.<Function>} constructors\n   * @parem {Array.<string>} names\n   */\n  function forwardMethodsToWrapper(constructors, names) {\n    constructors.forEach(function(constructor) {\n      names.forEach(function(name) {\n        constructor.prototype[name] = function() {\n          var w = wrapIfNeeded(this);\n          return w[name].apply(w, arguments);\n        };\n      });\n    });\n  }\n\n  scope.assert = assert;\n  scope.constructorTable = constructorTable;\n  scope.defineGetter = defineGetter;\n  scope.defineWrapGetter = defineWrapGetter;\n  scope.forwardMethodsToWrapper = forwardMethodsToWrapper;\n  scope.isWrapper = isWrapper;\n  scope.isWrapperFor = isWrapperFor;\n  scope.mixin = mixin;\n  scope.nativePrototypeTable = nativePrototypeTable;\n  scope.oneOf = oneOf;\n  scope.registerObject = registerObject;\n  scope.registerWrapper = register;\n  scope.rewrap = rewrap;\n  scope.unwrap = unwrap;\n  scope.unwrapIfNeeded = unwrapIfNeeded;\n  scope.wrap = wrap;\n  scope.wrapIfNeeded = wrapIfNeeded;\n  scope.wrappers = wrappers;\n\n})(window.ShadowDOMPolyfill);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is goverened by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(context) {\n  'use strict';\n\n  var OriginalMutationObserver = window.MutationObserver;\n  var callbacks = [];\n  var pending = false;\n  var timerFunc;\n\n  function handle() {\n    pending = false;\n    var copies = callbacks.slice(0);\n    callbacks = [];\n    for (var i = 0; i < copies.length; i++) {\n      (0, copies[i])();\n    }\n  }\n\n  if (OriginalMutationObserver) {\n    var counter = 1;\n    var observer = new OriginalMutationObserver(handle);\n    var textNode = document.createTextNode(counter);\n    observer.observe(textNode, {characterData: true});\n\n    timerFunc = function() {\n      counter = (counter + 1) % 2;\n      textNode.data = counter;\n    };\n\n  } else {\n    timerFunc = window.setImmediate || window.setTimeout;\n  }\n\n  function setEndOfMicrotask(func) {\n    callbacks.push(func);\n    if (pending)\n      return;\n    pending = true;\n    timerFunc(handle, 0);\n  }\n\n  context.setEndOfMicrotask = setEndOfMicrotask;\n\n})(window.ShadowDOMPolyfill);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is goverened by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n  'use strict';\n\n  var setEndOfMicrotask = scope.setEndOfMicrotask\n  var wrapIfNeeded = scope.wrapIfNeeded\n  var wrappers = scope.wrappers;\n\n  var registrationsTable = new WeakMap();\n  var globalMutationObservers = [];\n  var isScheduled = false;\n\n  function scheduleCallback(observer) {\n    if (isScheduled)\n      return;\n    setEndOfMicrotask(notifyObservers);\n    isScheduled = true;\n  }\n\n  // http://dom.spec.whatwg.org/#mutation-observers\n  function notifyObservers() {\n    isScheduled = false;\n\n    do {\n      var notifyList = globalMutationObservers.slice();\n      var anyNonEmpty = false;\n      for (var i = 0; i < notifyList.length; i++) {\n        var mo = notifyList[i];\n        var queue = mo.takeRecords();\n        removeTransientObserversFor(mo);\n        if (queue.length) {\n          mo.callback_(queue, mo);\n          anyNonEmpty = true;\n        }\n      }\n    } while (anyNonEmpty);\n  }\n\n  /**\n   * @param {string} type\n   * @param {Node} target\n   * @constructor\n   */\n  function MutationRecord(type, target) {\n    this.type = type;\n    this.target = target;\n    this.addedNodes = new wrappers.NodeList();\n    this.removedNodes = new wrappers.NodeList();\n    this.previousSibling = null;\n    this.nextSibling = null;\n    this.attributeName = null;\n    this.attributeNamespace = null;\n    this.oldValue = null;\n  }\n\n  /**\n   * Registers transient observers to ancestor and its ancesors for the node\n   * which was removed.\n   * @param {!Node} ancestor\n   * @param {!Node} node\n   */\n  function registerTransientObservers(ancestor, node) {\n    for (; ancestor; ancestor = ancestor.parentNode) {\n      var registrations = registrationsTable.get(ancestor);\n      if (!registrations)\n        continue;\n      for (var i = 0; i < registrations.length; i++) {\n        var registration = registrations[i];\n        if (registration.options.subtree)\n          registration.addTransientObserver(node);\n      }\n    }\n  }\n\n  function removeTransientObserversFor(observer) {\n    for (var i = 0; i < observer.nodes_.length; i++) {\n      var node = observer.nodes_[i];\n      var registrations = registrationsTable.get(node);\n      if (!registrations)\n        return;\n      for (var j = 0; j < registrations.length; j++) {\n        var registration = registrations[j];\n        if (registration.observer === observer)\n          registration.removeTransientObservers();\n      }\n    }\n  }\n\n  // http://dom.spec.whatwg.org/#queue-a-mutation-record\n  function enqueueMutation(target, type, data) {\n    // 1.\n    var interestedObservers = Object.create(null);\n    var associatedStrings = Object.create(null);\n\n    // 2.\n    for (var node = target; node; node = node.parentNode) {\n      // 3.\n      var registrations = registrationsTable.get(node);\n      if (!registrations)\n        continue;\n      for (var j = 0; j < registrations.length; j++) {\n        var registration = registrations[j];\n        var options = registration.options;\n        // 1.\n        if (node !== target && !options.subtree)\n          continue;\n\n        // 2.\n        if (type === 'attributes' && !options.attributes)\n          continue;\n\n        // 3. If type is \"attributes\", options's attributeFilter is present, and\n        // either options's attributeFilter does not contain name or namespace\n        // is non-null, continue.\n        if (type === 'attributes' && options.attributeFilter &&\n            (data.namespace !== null ||\n             options.attributeFilter.indexOf(data.name) === -1)) {\n          continue;\n        }\n\n        // 4.\n        if (type === 'characterData' && !options.characterData)\n          continue;\n\n        // 5.\n        if (type === 'childList' && !options.childList)\n          continue;\n\n        // 6.\n        var observer = registration.observer;\n        interestedObservers[observer.uid_] = observer;\n\n        // 7. If either type is \"attributes\" and options's attributeOldValue is\n        // true, or type is \"characterData\" and options's characterDataOldValue\n        // is true, set the paired string of registered observer's observer in\n        // interested observers to oldValue.\n        if (type === 'attributes' && options.attributeOldValue ||\n            type === 'characterData' && options.characterDataOldValue) {\n          associatedStrings[observer.uid_] = data.oldValue;\n        }\n      }\n    }\n\n    var anyRecordsEnqueued = false;\n\n    // 4.\n    for (var uid in interestedObservers) {\n      var observer = interestedObservers[uid];\n      var record = new MutationRecord(type, target);\n\n      // 2.\n      if ('name' in data && 'namespace' in data) {\n        record.attributeName = data.name;\n        record.attributeNamespace = data.namespace;\n      }\n\n      // 3.\n      if (data.addedNodes)\n        record.addedNodes = data.addedNodes;\n\n      // 4.\n      if (data.removedNodes)\n        record.removedNodes = data.removedNodes;\n\n      // 5.\n      if (data.previousSibling)\n        record.previousSibling = data.previousSibling;\n\n      // 6.\n      if (data.nextSibling)\n        record.nextSibling = data.nextSibling;\n\n      // 7.\n      if (associatedStrings[uid] !== undefined)\n        record.oldValue = associatedStrings[uid];\n\n      // 8.\n      observer.records_.push(record);\n\n      anyRecordsEnqueued = true;\n    }\n\n    if (anyRecordsEnqueued)\n      scheduleCallback();\n  }\n\n  var slice = Array.prototype.slice;\n\n  /**\n   * @param {!Object} options\n   * @constructor\n   */\n  function MutationObserverOptions(options) {\n    this.childList = !!options.childList;\n    this.subtree = !!options.subtree;\n\n    // 1. If either options' attributeOldValue or attributeFilter is present\n    // and options' attributes is omitted, set options' attributes to true.\n    if (!('attributes' in options) &&\n        ('attributeOldValue' in options || 'attributeFilter' in options)) {\n      this.attributes = true;\n    } else {\n      this.attributes = !!options.attributes;\n    }\n\n    // 2. If options' characterDataOldValue is present and options'\n    // characterData is omitted, set options' characterData to true.\n    if ('characterDataOldValue' in options && !('characterData' in options))\n      this.characterData = true;\n    else\n      this.characterData = !!options.characterData;\n\n    // 3. & 4.\n    if (!this.attributes &&\n        (options.attributeOldValue || 'attributeFilter' in options) ||\n        // 5.\n        !this.characterData && options.characterDataOldValue) {\n      throw new TypeError();\n    }\n\n    this.characterData = !!options.characterData;\n    this.attributeOldValue = !!options.attributeOldValue;\n    this.characterDataOldValue = !!options.characterDataOldValue;\n    if ('attributeFilter' in options) {\n      if (options.attributeFilter == null ||\n          typeof options.attributeFilter !== 'object') {\n        throw new TypeError();\n      }\n      this.attributeFilter = slice.call(options.attributeFilter);\n    } else {\n      this.attributeFilter = null;\n    }\n  }\n\n  var uidCounter = 0;\n\n  /**\n   * The class that maps to the DOM MutationObserver interface.\n   * @param {Function} callback.\n   * @constructor\n   */\n  function MutationObserver(callback) {\n    this.callback_ = callback;\n    this.nodes_ = [];\n    this.records_ = [];\n    this.uid_ = ++uidCounter;\n\n    // This will leak. There is no way to implement this without WeakRefs :'(\n    globalMutationObservers.push(this);\n  }\n\n  MutationObserver.prototype = {\n    // http://dom.spec.whatwg.org/#dom-mutationobserver-observe\n    observe: function(target, options) {\n      target = wrapIfNeeded(target);\n\n      var newOptions = new MutationObserverOptions(options);\n\n      // 6.\n      var registration;\n      var registrations = registrationsTable.get(target);\n      if (!registrations)\n        registrationsTable.set(target, registrations = []);\n\n      for (var i = 0; i < registrations.length; i++) {\n        if (registrations[i].observer === this) {\n          registration = registrations[i];\n          // 6.1.\n          registration.removeTransientObservers();\n          // 6.2.\n          registration.options = newOptions;\n        }\n      }\n\n      // 7.\n      if (!registration) {\n        registration = new Registration(this, target, newOptions);\n        registrations.push(registration);\n        this.nodes_.push(target);\n      }\n    },\n\n    // http://dom.spec.whatwg.org/#dom-mutationobserver-disconnect\n    disconnect: function() {\n      this.nodes_.forEach(function(node) {\n        var registrations = registrationsTable.get(node);\n        for (var i = 0; i < registrations.length; i++) {\n          var registration = registrations[i];\n          if (registration.observer === this) {\n            registrations.splice(i, 1);\n            // Each node can only have one registered observer associated with\n            // this observer.\n            break;\n          }\n        }\n      }, this);\n      this.records_ = [];\n    },\n\n    takeRecords: function() {\n      var copyOfRecords = this.records_;\n      this.records_ = [];\n      return copyOfRecords;\n    }\n  };\n\n  /**\n   * Class used to represent a registered observer.\n   * @param {MutationObserver} observer\n   * @param {Node} target\n   * @param {MutationObserverOptions} options\n   * @constructor\n   */\n  function Registration(observer, target, options) {\n    this.observer = observer;\n    this.target = target;\n    this.options = options;\n    this.transientObservedNodes = [];\n  }\n\n  Registration.prototype = {\n    /**\n     * Adds a transient observer on node. The transient observer gets removed\n     * next time we deliver the change records.\n     * @param {Node} node\n     */\n    addTransientObserver: function(node) {\n      // Don't add transient observers on the target itself. We already have all\n      // the required listeners set up on the target.\n      if (node === this.target)\n        return;\n\n      this.transientObservedNodes.push(node);\n      var registrations = registrationsTable.get(node);\n      if (!registrations)\n        registrationsTable.set(node, registrations = []);\n\n      // We know that registrations does not contain this because we already\n      // checked if node === this.target.\n      registrations.push(this);\n    },\n\n    removeTransientObservers: function() {\n      var transientObservedNodes = this.transientObservedNodes;\n      this.transientObservedNodes = [];\n\n      for (var i = 0; i < transientObservedNodes.length; i++) {\n        var node = transientObservedNodes[i];\n        var registrations = registrationsTable.get(node);\n        for (var j = 0; j < registrations.length; j++) {\n          if (registrations[j] === this) {\n            registrations.splice(j, 1);\n            // Each node can only have one registered observer associated with\n            // this observer.\n            break;\n          }\n        }\n      }\n    }\n  };\n\n  scope.enqueueMutation = enqueueMutation;\n  scope.registerTransientObservers = registerTransientObservers;\n  scope.wrappers.MutationObserver = MutationObserver;\n  scope.wrappers.MutationRecord = MutationRecord;\n\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var forwardMethodsToWrapper = scope.forwardMethodsToWrapper;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n  var wrappers = scope.wrappers;\n\n  var wrappedFuns = new WeakMap();\n  var listenersTable = new WeakMap();\n  var handledEventsTable = new WeakMap();\n  var currentlyDispatchingEvents = new WeakMap();\n  var targetTable = new WeakMap();\n  var currentTargetTable = new WeakMap();\n  var relatedTargetTable = new WeakMap();\n  var eventPhaseTable = new WeakMap();\n  var stopPropagationTable = new WeakMap();\n  var stopImmediatePropagationTable = new WeakMap();\n  var eventHandlersTable = new WeakMap();\n  var eventPathTable = new WeakMap();\n\n  function isShadowRoot(node) {\n    return node instanceof wrappers.ShadowRoot;\n  }\n\n  function isInsertionPoint(node) {\n    var localName = node.localName;\n    return localName === 'content' || localName === 'shadow';\n  }\n\n  function isShadowHost(node) {\n    return !!node.shadowRoot;\n  }\n\n  function getEventParent(node) {\n    var dv;\n    return node.parentNode || (dv = node.defaultView) && wrap(dv) || null;\n  }\n\n  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-adjusted-parent\n  function calculateParents(node, context, ancestors) {\n    if (ancestors.length)\n      return ancestors.shift();\n\n    // 1.\n    if (isShadowRoot(node))\n      return getInsertionParent(node) || node.host;\n\n    // 2.\n    var eventParents = scope.eventParentsTable.get(node);\n    if (eventParents) {\n      // Copy over the remaining event parents for next iteration.\n      for (var i = 1; i < eventParents.length; i++) {\n        ancestors[i - 1] = eventParents[i];\n      }\n      return eventParents[0];\n    }\n\n    // 3.\n    if (context && isInsertionPoint(node)) {\n      var parentNode = node.parentNode;\n      if (parentNode && isShadowHost(parentNode)) {\n        var trees = scope.getShadowTrees(parentNode);\n        var p = getInsertionParent(context);\n        for (var i = 0; i < trees.length; i++) {\n          if (trees[i].contains(p))\n            return p;\n        }\n      }\n    }\n\n    return getEventParent(node);\n  }\n\n  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#event-retargeting\n  function retarget(node) {\n    var stack = [];  // 1.\n    var ancestor = node;  // 2.\n    var targets = [];\n    var ancestors = [];\n    while (ancestor) {  // 3.\n      var context = null;  // 3.2.\n      // TODO(arv): Change order of these. If the stack is empty we always end\n      // up pushing ancestor, no matter what.\n      if (isInsertionPoint(ancestor)) {  // 3.1.\n        context = topMostNotInsertionPoint(stack);  // 3.1.1.\n        var top = stack[stack.length - 1] || ancestor;  // 3.1.2.\n        stack.push(top);\n      } else if (!stack.length) {\n        stack.push(ancestor);  // 3.3.\n      }\n      var target = stack[stack.length - 1];  // 3.4.\n      targets.push({target: target, currentTarget: ancestor});  // 3.5.\n      if (isShadowRoot(ancestor))  // 3.6.\n        stack.pop();  // 3.6.1.\n\n      ancestor = calculateParents(ancestor, context, ancestors);  // 3.7.\n    }\n    return targets;\n  }\n\n  function topMostNotInsertionPoint(stack) {\n    for (var i = stack.length - 1; i >= 0; i--) {\n      if (!isInsertionPoint(stack[i]))\n        return stack[i];\n    }\n    return null;\n  }\n\n  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-adjusted-related-target\n  function adjustRelatedTarget(target, related) {\n    var ancestors = [];\n    while (target) {  // 3.\n      var stack = [];  // 3.1.\n      var ancestor = related;  // 3.2.\n      var last = undefined;  // 3.3. Needs to be reset every iteration.\n      while (ancestor) {\n        var context = null;\n        if (!stack.length) {\n          stack.push(ancestor);\n        } else {\n          if (isInsertionPoint(ancestor)) {  // 3.4.3.\n            context = topMostNotInsertionPoint(stack);\n            // isDistributed is more general than checking whether last is\n            // assigned into ancestor.\n            if (isDistributed(last)) {  // 3.4.3.2.\n              var head = stack[stack.length - 1];\n              stack.push(head);\n            }\n          }\n        }\n\n        if (inSameTree(ancestor, target))  // 3.4.4.\n          return stack[stack.length - 1];\n\n        if (isShadowRoot(ancestor))  // 3.4.5.\n          stack.pop();\n\n        last = ancestor;  // 3.4.6.\n        ancestor = calculateParents(ancestor, context, ancestors);  // 3.4.7.\n      }\n      if (isShadowRoot(target))  // 3.5.\n        target = target.host;\n      else\n        target = target.parentNode;  // 3.6.\n    }\n  }\n\n  function getInsertionParent(node) {\n    return scope.insertionParentTable.get(node);\n  }\n\n  function isDistributed(node) {\n    return getInsertionParent(node);\n  }\n\n  function rootOfNode(node) {\n    var p;\n    while (p = node.parentNode) {\n      node = p;\n    }\n    return node;\n  }\n\n  function inSameTree(a, b) {\n    return rootOfNode(a) === rootOfNode(b);\n  }\n\n  function enclosedBy(a, b) {\n    if (a === b)\n      return true;\n    if (a instanceof wrappers.ShadowRoot)\n      return enclosedBy(rootOfNode(a.host), b);\n    return false;\n  }\n\n\n  function dispatchOriginalEvent(originalEvent) {\n    // Make sure this event is only dispatched once.\n    if (handledEventsTable.get(originalEvent))\n      return;\n    handledEventsTable.set(originalEvent, true);\n\n    return dispatchEvent(wrap(originalEvent), wrap(originalEvent.target));\n  }\n\n  function dispatchEvent(event, originalWrapperTarget) {\n    if (currentlyDispatchingEvents.get(event))\n      throw new Error('InvalidStateError')\n    currentlyDispatchingEvents.set(event, true);\n\n    // Render to ensure that the event path is correct.\n    scope.renderAllPending();\n    var eventPath = retarget(originalWrapperTarget);\n\n    // For window load events the load event is dispatched at the window but\n    // the target is set to the document.\n    //\n    // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#the-end\n    //\n    // TODO(arv): Find a less hacky way to do this.\n    if (event.type === 'load' &&\n        eventPath.length === 2 &&\n        eventPath[0].target instanceof wrappers.Document) {\n      eventPath.shift();\n    }\n\n    eventPathTable.set(event, eventPath);\n\n    if (dispatchCapturing(event, eventPath)) {\n      if (dispatchAtTarget(event, eventPath)) {\n        dispatchBubbling(event, eventPath);\n      }\n    }\n\n    eventPhaseTable.set(event, Event.NONE);\n    currentTargetTable.delete(event, null);\n    currentlyDispatchingEvents.delete(event);\n\n    return event.defaultPrevented;\n  }\n\n  function dispatchCapturing(event, eventPath) {\n    var phase;\n\n    for (var i = eventPath.length - 1; i > 0; i--) {\n      var target = eventPath[i].target;\n      var currentTarget = eventPath[i].currentTarget;\n      if (target === currentTarget)\n        continue;\n\n      phase = Event.CAPTURING_PHASE;\n      if (!invoke(eventPath[i], event, phase))\n        return false;\n    }\n\n    return true;\n  }\n\n  function dispatchAtTarget(event, eventPath) {\n    var phase = Event.AT_TARGET;\n    return invoke(eventPath[0], event, phase);\n  }\n\n  function dispatchBubbling(event, eventPath) {\n    var bubbles = event.bubbles;\n    var phase;\n\n    for (var i = 1; i < eventPath.length; i++) {\n      var target = eventPath[i].target;\n      var currentTarget = eventPath[i].currentTarget;\n      if (target === currentTarget)\n        phase = Event.AT_TARGET;\n      else if (bubbles && !stopImmediatePropagationTable.get(event))\n        phase = Event.BUBBLING_PHASE;\n      else\n        continue;\n\n      if (!invoke(eventPath[i], event, phase))\n        return;\n    }\n  }\n\n  function invoke(tuple, event, phase) {\n    var target = tuple.target;\n    var currentTarget = tuple.currentTarget;\n\n    var listeners = listenersTable.get(currentTarget);\n    if (!listeners)\n      return true;\n\n    if ('relatedTarget' in event) {\n      var originalEvent = unwrap(event);\n      // X-Tag sets relatedTarget on a CustomEvent. If they do that there is no\n      // way to have relatedTarget return the adjusted target but worse is that\n      // the originalEvent might not have a relatedTarget so we hit an assert\n      // when we try to wrap it.\n      if (originalEvent.relatedTarget) {\n        var relatedTarget = wrap(originalEvent.relatedTarget);\n\n        var adjusted = adjustRelatedTarget(currentTarget, relatedTarget);\n        if (adjusted === target)\n          return true;\n\n        relatedTargetTable.set(event, adjusted);\n      }\n    }\n\n    eventPhaseTable.set(event, phase);\n    var type = event.type;\n\n    var anyRemoved = false;\n    targetTable.set(event, target);\n    currentTargetTable.set(event, currentTarget);\n\n    for (var i = 0; i < listeners.length; i++) {\n      var listener = listeners[i];\n      if (listener.removed) {\n        anyRemoved = true;\n        continue;\n      }\n\n      if (listener.type !== type ||\n          !listener.capture && phase === Event.CAPTURING_PHASE ||\n          listener.capture && phase === Event.BUBBLING_PHASE) {\n        continue;\n      }\n\n      try {\n        if (typeof listener.handler === 'function')\n          listener.handler.call(currentTarget, event);\n        else\n          listener.handler.handleEvent(event);\n\n        if (stopImmediatePropagationTable.get(event))\n          return false;\n\n      } catch (ex) {\n        if (window.onerror)\n          window.onerror(ex.message);\n        else\n          console.error(ex, ex.stack);\n      }\n    }\n\n    if (anyRemoved) {\n      var copy = listeners.slice();\n      listeners.length = 0;\n      for (var i = 0; i < copy.length; i++) {\n        if (!copy[i].removed)\n          listeners.push(copy[i]);\n      }\n    }\n\n    return !stopPropagationTable.get(event);\n  }\n\n  function Listener(type, handler, capture) {\n    this.type = type;\n    this.handler = handler;\n    this.capture = Boolean(capture);\n  }\n  Listener.prototype = {\n    equals: function(that) {\n      return this.handler === that.handler && this.type === that.type &&\n          this.capture === that.capture;\n    },\n    get removed() {\n      return this.handler === null;\n    },\n    remove: function() {\n      this.handler = null;\n    }\n  };\n\n  var OriginalEvent = window.Event;\n  OriginalEvent.prototype.polymerBlackList_ = {\n    returnValue: true,\n    // TODO(arv): keyLocation is part of KeyboardEvent but Firefox does not\n    // support constructable KeyboardEvent so we keep it here for now.\n    keyLocation: true\n  };\n\n  /**\n   * Creates a new Event wrapper or wraps an existin native Event object.\n   * @param {string|Event} type\n   * @param {Object=} options\n   * @constructor\n   */\n  function Event(type, options) {\n    if (type instanceof OriginalEvent)\n      this.impl = type;\n    else\n      return wrap(constructEvent(OriginalEvent, 'Event', type, options));\n  }\n  Event.prototype = {\n    get target() {\n      return targetTable.get(this);\n    },\n    get currentTarget() {\n      return currentTargetTable.get(this);\n    },\n    get eventPhase() {\n      return eventPhaseTable.get(this);\n    },\n    get path() {\n      var nodeList = new wrappers.NodeList();\n      var eventPath = eventPathTable.get(this);\n      if (eventPath) {\n        var index = 0;\n        var lastIndex = eventPath.length - 1;\n        var baseRoot = rootOfNode(currentTargetTable.get(this));\n\n        for (var i = 0; i <= lastIndex; i++) {\n          var currentTarget = eventPath[i].currentTarget;\n          var currentRoot = rootOfNode(currentTarget);\n          if (enclosedBy(baseRoot, currentRoot) &&\n              // Make sure we do not add Window to the path.\n              (i !== lastIndex || currentTarget instanceof wrappers.Node)) {\n            nodeList[index++] = currentTarget;\n          }\n        }\n        nodeList.length = index;\n      }\n      return nodeList;\n    },\n    stopPropagation: function() {\n      stopPropagationTable.set(this, true);\n    },\n    stopImmediatePropagation: function() {\n      stopPropagationTable.set(this, true);\n      stopImmediatePropagationTable.set(this, true);\n    }\n  };\n  registerWrapper(OriginalEvent, Event, document.createEvent('Event'));\n\n  function unwrapOptions(options) {\n    if (!options || !options.relatedTarget)\n      return options;\n    return Object.create(options, {\n      relatedTarget: {value: unwrap(options.relatedTarget)}\n    });\n  }\n\n  function registerGenericEvent(name, SuperEvent, prototype) {\n    var OriginalEvent = window[name];\n    var GenericEvent = function(type, options) {\n      if (type instanceof OriginalEvent)\n        this.impl = type;\n      else\n        return wrap(constructEvent(OriginalEvent, name, type, options));\n    };\n    GenericEvent.prototype = Object.create(SuperEvent.prototype);\n    if (prototype)\n      mixin(GenericEvent.prototype, prototype);\n    if (OriginalEvent) {\n      // - Old versions of Safari fails on new FocusEvent (and others?).\n      // - IE does not support event constructors.\n      // - createEvent('FocusEvent') throws in Firefox.\n      // => Try the best practice solution first and fallback to the old way\n      // if needed.\n      try {\n        registerWrapper(OriginalEvent, GenericEvent, new OriginalEvent('temp'));\n      } catch (ex) {\n        registerWrapper(OriginalEvent, GenericEvent,\n                        document.createEvent(name));\n      }\n    }\n    return GenericEvent;\n  }\n\n  var UIEvent = registerGenericEvent('UIEvent', Event);\n  var CustomEvent = registerGenericEvent('CustomEvent', Event);\n\n  var relatedTargetProto = {\n    get relatedTarget() {\n      return relatedTargetTable.get(this) || wrap(unwrap(this).relatedTarget);\n    }\n  };\n\n  function getInitFunction(name, relatedTargetIndex) {\n    return function() {\n      arguments[relatedTargetIndex] = unwrap(arguments[relatedTargetIndex]);\n      var impl = unwrap(this);\n      impl[name].apply(impl, arguments);\n    };\n  }\n\n  var mouseEventProto = mixin({\n    initMouseEvent: getInitFunction('initMouseEvent', 14)\n  }, relatedTargetProto);\n\n  var focusEventProto = mixin({\n    initFocusEvent: getInitFunction('initFocusEvent', 5)\n  }, relatedTargetProto);\n\n  var MouseEvent = registerGenericEvent('MouseEvent', UIEvent, mouseEventProto);\n  var FocusEvent = registerGenericEvent('FocusEvent', UIEvent, focusEventProto);\n\n  // In case the browser does not support event constructors we polyfill that\n  // by calling `createEvent('Foo')` and `initFooEvent` where the arguments to\n  // `initFooEvent` are derived from the registered default event init dict.\n  var defaultInitDicts = Object.create(null);\n\n  var supportsEventConstructors = (function() {\n    try {\n      new window.FocusEvent('focus');\n    } catch (ex) {\n      return false;\n    }\n    return true;\n  })();\n\n  /**\n   * Constructs a new native event.\n   */\n  function constructEvent(OriginalEvent, name, type, options) {\n    if (supportsEventConstructors)\n      return new OriginalEvent(type, unwrapOptions(options));\n\n    // Create the arguments from the default dictionary.\n    var event = unwrap(document.createEvent(name));\n    var defaultDict = defaultInitDicts[name];\n    var args = [type];\n    Object.keys(defaultDict).forEach(function(key) {\n      var v = options != null && key in options ?\n          options[key] : defaultDict[key];\n      if (key === 'relatedTarget')\n        v = unwrap(v);\n      args.push(v);\n    });\n    event['init' + name].apply(event, args);\n    return event;\n  }\n\n  if (!supportsEventConstructors) {\n    var configureEventConstructor = function(name, initDict, superName) {\n      if (superName) {\n        var superDict = defaultInitDicts[superName];\n        initDict = mixin(mixin({}, superDict), initDict);\n      }\n\n      defaultInitDicts[name] = initDict;\n    };\n\n    // The order of the default event init dictionary keys is important, the\n    // arguments to initFooEvent is derived from that.\n    configureEventConstructor('Event', {bubbles: false, cancelable: false});\n    configureEventConstructor('CustomEvent', {detail: null}, 'Event');\n    configureEventConstructor('UIEvent', {view: null, detail: 0}, 'Event');\n    configureEventConstructor('MouseEvent', {\n      screenX: 0,\n      screenY: 0,\n      clientX: 0,\n      clientY: 0,\n      ctrlKey: false,\n      altKey: false,\n      shiftKey: false,\n      metaKey: false,\n      button: 0,\n      relatedTarget: null\n    }, 'UIEvent');\n    configureEventConstructor('FocusEvent', {relatedTarget: null}, 'UIEvent');\n  }\n\n  function BeforeUnloadEvent(impl) {\n    Event.call(this);\n  }\n  BeforeUnloadEvent.prototype = Object.create(Event.prototype);\n  mixin(BeforeUnloadEvent.prototype, {\n    get returnValue() {\n      return this.impl.returnValue;\n    },\n    set returnValue(v) {\n      this.impl.returnValue = v;\n    }\n  });\n\n  function isValidListener(fun) {\n    if (typeof fun === 'function')\n      return true;\n    return fun && fun.handleEvent;\n  }\n\n  function isMutationEvent(type) {\n    switch (type) {\n      case 'DOMAttrModified':\n      case 'DOMAttributeNameChanged':\n      case 'DOMCharacterDataModified':\n      case 'DOMElementNameChanged':\n      case 'DOMNodeInserted':\n      case 'DOMNodeInsertedIntoDocument':\n      case 'DOMNodeRemoved':\n      case 'DOMNodeRemovedFromDocument':\n      case 'DOMSubtreeModified':\n        return true;\n    }\n    return false;\n  }\n\n  var OriginalEventTarget = window.EventTarget;\n\n  /**\n   * This represents a wrapper for an EventTarget.\n   * @param {!EventTarget} impl The original event target.\n   * @constructor\n   */\n  function EventTarget(impl) {\n    this.impl = impl;\n  }\n\n  // Node and Window have different internal type checks in WebKit so we cannot\n  // use the same method as the original function.\n  var methodNames = [\n    'addEventListener',\n    'removeEventListener',\n    'dispatchEvent'\n  ];\n\n  [Node, Window].forEach(function(constructor) {\n    var p = constructor.prototype;\n    methodNames.forEach(function(name) {\n      Object.defineProperty(p, name + '_', {value: p[name]});\n    });\n  });\n\n  function getTargetToListenAt(wrapper) {\n    if (wrapper instanceof wrappers.ShadowRoot)\n      wrapper = wrapper.host;\n    return unwrap(wrapper);\n  }\n\n  EventTarget.prototype = {\n    addEventListener: function(type, fun, capture) {\n      if (!isValidListener(fun) || isMutationEvent(type))\n        return;\n\n      var listener = new Listener(type, fun, capture);\n      var listeners = listenersTable.get(this);\n      if (!listeners) {\n        listeners = [];\n        listenersTable.set(this, listeners);\n      } else {\n        // Might have a duplicate.\n        for (var i = 0; i < listeners.length; i++) {\n          if (listener.equals(listeners[i]))\n            return;\n        }\n      }\n\n      listeners.push(listener);\n\n      var target = getTargetToListenAt(this);\n      target.addEventListener_(type, dispatchOriginalEvent, true);\n    },\n    removeEventListener: function(type, fun, capture) {\n      capture = Boolean(capture);\n      var listeners = listenersTable.get(this);\n      if (!listeners)\n        return;\n      var count = 0, found = false;\n      for (var i = 0; i < listeners.length; i++) {\n        if (listeners[i].type === type && listeners[i].capture === capture) {\n          count++;\n          if (listeners[i].handler === fun) {\n            found = true;\n            listeners[i].remove();\n          }\n        }\n      }\n\n      if (found && count === 1) {\n        var target = getTargetToListenAt(this);\n        target.removeEventListener_(type, dispatchOriginalEvent, true);\n      }\n    },\n    dispatchEvent: function(event) {\n      // We want to use the native dispatchEvent because it triggers the default\n      // actions (like checking a checkbox). However, if there are no listeners\n      // in the composed tree then there are no events that will trigger and\n      // listeners in the non composed tree that are part of the event path are\n      // not notified.\n      //\n      // If we find out that there are no listeners in the composed tree we add\n      // a temporary listener to the target which makes us get called back even\n      // in that case.\n\n      var nativeEvent = unwrap(event);\n      var eventType = nativeEvent.type;\n\n      // Allow dispatching the same event again. This is safe because if user\n      // code calls this during an existing dispatch of the same event the\n      // native dispatchEvent throws (that is required by the spec).\n      handledEventsTable.set(nativeEvent, false);\n\n      // Force rendering since we prefer native dispatch and that works on the\n      // composed tree.\n      scope.renderAllPending();\n\n      var tempListener;\n      if (!hasListenerInAncestors(this, eventType)) {\n        tempListener = function() {};\n        this.addEventListener(eventType, tempListener, true);\n      }\n\n      try {\n        return unwrap(this).dispatchEvent_(nativeEvent);\n      } finally {\n        if (tempListener)\n          this.removeEventListener(eventType, tempListener, true);\n      }\n    }\n  };\n\n  function hasListener(node, type) {\n    var listeners = listenersTable.get(node);\n    if (listeners) {\n      for (var i = 0; i < listeners.length; i++) {\n        if (!listeners[i].removed && listeners[i].type === type)\n          return true;\n      }\n    }\n    return false;\n  }\n\n  function hasListenerInAncestors(target, type) {\n    for (var node = unwrap(target); node; node = node.parentNode) {\n      if (hasListener(wrap(node), type))\n        return true;\n    }\n    return false;\n  }\n\n  if (OriginalEventTarget)\n    registerWrapper(OriginalEventTarget, EventTarget);\n\n  function wrapEventTargetMethods(constructors) {\n    forwardMethodsToWrapper(constructors, methodNames);\n  }\n\n  var originalElementFromPoint = document.elementFromPoint;\n\n  function elementFromPoint(self, document, x, y) {\n    scope.renderAllPending();\n\n    var element = wrap(originalElementFromPoint.call(document.impl, x, y));\n    var targets = retarget(element, this)\n    for (var i = 0; i < targets.length; i++) {\n      var target = targets[i];\n      if (target.currentTarget === self)\n        return target.target;\n    }\n    return null;\n  }\n\n  /**\n   * Returns a function that is to be used as a getter for `onfoo` properties.\n   * @param {string} name\n   * @return {Function}\n   */\n  function getEventHandlerGetter(name) {\n    return function() {\n      var inlineEventHandlers = eventHandlersTable.get(this);\n      return inlineEventHandlers && inlineEventHandlers[name] &&\n          inlineEventHandlers[name].value || null;\n     };\n  }\n\n  /**\n   * Returns a function that is to be used as a setter for `onfoo` properties.\n   * @param {string} name\n   * @return {Function}\n   */\n  function getEventHandlerSetter(name) {\n    var eventType = name.slice(2);\n    return function(value) {\n      var inlineEventHandlers = eventHandlersTable.get(this);\n      if (!inlineEventHandlers) {\n        inlineEventHandlers = Object.create(null);\n        eventHandlersTable.set(this, inlineEventHandlers);\n      }\n\n      var old = inlineEventHandlers[name];\n      if (old)\n        this.removeEventListener(eventType, old.wrapped, false);\n\n      if (typeof value === 'function') {\n        var wrapped = function(e) {\n          var rv = value.call(this, e);\n          if (rv === false)\n            e.preventDefault();\n          else if (name === 'onbeforeunload' && typeof rv === 'string')\n            e.returnValue = rv;\n          // mouseover uses true for preventDefault but preventDefault for\n          // mouseover is ignored by browsers these day.\n        };\n\n        this.addEventListener(eventType, wrapped, false);\n        inlineEventHandlers[name] = {\n          value: value,\n          wrapped: wrapped\n        };\n      }\n    };\n  }\n\n  scope.adjustRelatedTarget = adjustRelatedTarget;\n  scope.elementFromPoint = elementFromPoint;\n  scope.getEventHandlerGetter = getEventHandlerGetter;\n  scope.getEventHandlerSetter = getEventHandlerSetter;\n  scope.wrapEventTargetMethods = wrapEventTargetMethods;\n  scope.wrappers.BeforeUnloadEvent = BeforeUnloadEvent;\n  scope.wrappers.CustomEvent = CustomEvent;\n  scope.wrappers.Event = Event;\n  scope.wrappers.EventTarget = EventTarget;\n  scope.wrappers.FocusEvent = FocusEvent;\n  scope.wrappers.MouseEvent = MouseEvent;\n  scope.wrappers.UIEvent = UIEvent;\n\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2012 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var wrap = scope.wrap;\n\n  function nonEnum(obj, prop) {\n    Object.defineProperty(obj, prop, {enumerable: false});\n  }\n\n  function NodeList() {\n    this.length = 0;\n    nonEnum(this, 'length');\n  }\n  NodeList.prototype = {\n    item: function(index) {\n      return this[index];\n    }\n  };\n  nonEnum(NodeList.prototype, 'item');\n\n  function wrapNodeList(list) {\n    if (list == null)\n      return list;\n    var wrapperList = new NodeList();\n    for (var i = 0, length = list.length; i < length; i++) {\n      wrapperList[i] = wrap(list[i]);\n    }\n    wrapperList.length = length;\n    return wrapperList;\n  }\n\n  function addWrapNodeListMethod(wrapperConstructor, name) {\n    wrapperConstructor.prototype[name] = function() {\n      return wrapNodeList(this.impl[name].apply(this.impl, arguments));\n    };\n  }\n\n  scope.wrappers.NodeList = NodeList;\n  scope.addWrapNodeListMethod = addWrapNodeListMethod;\n  scope.wrapNodeList = wrapNodeList;\n\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2012 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var EventTarget = scope.wrappers.EventTarget;\n  var NodeList = scope.wrappers.NodeList;\n  var assert = scope.assert;\n  var defineWrapGetter = scope.defineWrapGetter;\n  var enqueueMutation = scope.enqueueMutation;\n  var isWrapper = scope.isWrapper;\n  var mixin = scope.mixin;\n  var registerTransientObservers = scope.registerTransientObservers;\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n  var wrapIfNeeded = scope.wrapIfNeeded;\n  var wrappers = scope.wrappers;\n\n  function assertIsNodeWrapper(node) {\n    assert(node instanceof Node);\n  }\n\n  function createOneElementNodeList(node) {\n    var nodes = new NodeList();\n    nodes[0] = node;\n    nodes.length = 1;\n    return nodes;\n  }\n\n  var surpressMutations = false;\n\n  /**\n   * Called before node is inserted into a node to enqueue its removal from its\n   * old parent.\n   * @param {!Node} node The node that is about to be removed.\n   * @param {!Node} parent The parent node that the node is being removed from.\n   * @param {!NodeList} nodes The collected nodes.\n   */\n  function enqueueRemovalForInsertedNodes(node, parent, nodes) {\n    enqueueMutation(parent, 'childList', {\n      removedNodes: nodes,\n      previousSibling: node.previousSibling,\n      nextSibling: node.nextSibling\n    });\n  }\n\n  function enqueueRemovalForInsertedDocumentFragment(df, nodes) {\n    enqueueMutation(df, 'childList', {\n      removedNodes: nodes\n    });\n  }\n\n  /**\n   * Collects nodes from a DocumentFragment or a Node for removal followed\n   * by an insertion.\n   *\n   * This updates the internal pointers for node, previousNode and nextNode.\n   */\n  function collectNodes(node, parentNode, previousNode, nextNode) {\n    if (node instanceof DocumentFragment) {\n      var nodes = collectNodesForDocumentFragment(node);\n\n      // The extra loop is to work around bugs with DocumentFragments in IE.\n      surpressMutations = true;\n      for (var i = nodes.length - 1; i >= 0; i--) {\n        node.removeChild(nodes[i]);\n        nodes[i].parentNode_ = parentNode;\n      }\n      surpressMutations = false;\n\n      for (var i = 0; i < nodes.length; i++) {\n        nodes[i].previousSibling_ = nodes[i - 1] || previousNode;\n        nodes[i].nextSibling_ = nodes[i + 1] || nextNode;\n      }\n\n      if (previousNode)\n        previousNode.nextSibling_ = nodes[0];\n      if (nextNode)\n        nextNode.previousSibling_ = nodes[nodes.length - 1];\n\n      return nodes;\n    }\n\n    var nodes = createOneElementNodeList(node);\n    var oldParent = node.parentNode;\n    if (oldParent) {\n      // This will enqueue the mutation record for the removal as needed.\n      oldParent.removeChild(node);\n    }\n\n    node.parentNode_ = parentNode;\n    node.previousSibling_ = previousNode;\n    node.nextSibling_ = nextNode;\n    if (previousNode)\n      previousNode.nextSibling_ = node;\n    if (nextNode)\n      nextNode.previousSibling_ = node;\n\n    return nodes;\n  }\n\n  function collectNodesNative(node) {\n    if (node instanceof DocumentFragment)\n      return collectNodesForDocumentFragment(node);\n\n    var nodes = createOneElementNodeList(node);\n    var oldParent = node.parentNode;\n    if (oldParent)\n      enqueueRemovalForInsertedNodes(node, oldParent, nodes);\n    return nodes;\n  }\n\n  function collectNodesForDocumentFragment(node) {\n    var nodes = new NodeList();\n    var i = 0;\n    for (var child = node.firstChild; child; child = child.nextSibling) {\n      nodes[i++] = child;\n    }\n    nodes.length = i;\n    enqueueRemovalForInsertedDocumentFragment(node, nodes);\n    return nodes;\n  }\n\n  function snapshotNodeList(nodeList) {\n    // NodeLists are not live at the moment so just return the same object.\n    return nodeList;\n  }\n\n  // http://dom.spec.whatwg.org/#node-is-inserted\n  function nodeWasAdded(node) {\n    node.nodeIsInserted_();\n  }\n\n  function nodesWereAdded(nodes) {\n    for (var i = 0; i < nodes.length; i++) {\n      nodeWasAdded(nodes[i]);\n    }\n  }\n\n  // http://dom.spec.whatwg.org/#node-is-removed\n  function nodeWasRemoved(node) {\n    // Nothing at this point in time.\n  }\n\n  function nodesWereRemoved(nodes) {\n    // Nothing at this point in time.\n  }\n\n  function ensureSameOwnerDocument(parent, child) {\n    var ownerDoc = parent.nodeType === Node.DOCUMENT_NODE ?\n        parent : parent.ownerDocument;\n    if (ownerDoc !== child.ownerDocument)\n      ownerDoc.adoptNode(child);\n  }\n\n  function adoptNodesIfNeeded(owner, nodes) {\n    if (!nodes.length)\n      return;\n\n    var ownerDoc = owner.ownerDocument;\n\n    // All nodes have the same ownerDocument when we get here.\n    if (ownerDoc === nodes[0].ownerDocument)\n      return;\n\n    for (var i = 0; i < nodes.length; i++) {\n      scope.adoptNodeNoRemove(nodes[i], ownerDoc);\n    }\n  }\n\n  function unwrapNodesForInsertion(owner, nodes) {\n    adoptNodesIfNeeded(owner, nodes);\n    var length = nodes.length;\n\n    if (length === 1)\n      return unwrap(nodes[0]);\n\n    var df = unwrap(owner.ownerDocument.createDocumentFragment());\n    for (var i = 0; i < length; i++) {\n      df.appendChild(unwrap(nodes[i]));\n    }\n    return df;\n  }\n\n  function clearChildNodes(wrapper) {\n    if (wrapper.firstChild_ !== undefined) {\n      var child = wrapper.firstChild_;\n      while (child) {\n        var tmp = child;\n        child = child.nextSibling_;\n        tmp.parentNode_ = tmp.previousSibling_ = tmp.nextSibling_ = undefined;\n      }\n    }\n    wrapper.firstChild_ = wrapper.lastChild_ = undefined;\n  }\n\n  function removeAllChildNodes(wrapper) {\n    if (wrapper.invalidateShadowRenderer()) {\n      var childWrapper = wrapper.firstChild;\n      while (childWrapper) {\n        assert(childWrapper.parentNode === wrapper);\n        var nextSibling = childWrapper.nextSibling;\n        var childNode = unwrap(childWrapper);\n        var parentNode = childNode.parentNode;\n        if (parentNode)\n          originalRemoveChild.call(parentNode, childNode);\n        childWrapper.previousSibling_ = childWrapper.nextSibling_ =\n            childWrapper.parentNode_ = null;\n        childWrapper = nextSibling;\n      }\n      wrapper.firstChild_ = wrapper.lastChild_ = null;\n    } else {\n      var node = unwrap(wrapper);\n      var child = node.firstChild;\n      var nextSibling;\n      while (child) {\n        nextSibling = child.nextSibling;\n        originalRemoveChild.call(node, child);\n        child = nextSibling;\n      }\n    }\n  }\n\n  function invalidateParent(node) {\n    var p = node.parentNode;\n    return p && p.invalidateShadowRenderer();\n  }\n\n  function cleanupNodes(nodes) {\n    for (var i = 0, n; i < nodes.length; i++) {\n      n = nodes[i];\n      n.parentNode.removeChild(n);\n    }\n  }\n\n  var originalImportNode = document.importNode;\n  var originalCloneNode = window.Node.prototype.cloneNode;\n\n  function cloneNode(node, deep, opt_doc) {\n    var clone;\n    if (opt_doc)\n      clone = wrap(originalImportNode.call(opt_doc, node.impl, false));\n    else\n      clone = wrap(originalCloneNode.call(node.impl, false));\n\n    if (deep) {\n      for (var child = node.firstChild; child; child = child.nextSibling) {\n        clone.appendChild(cloneNode(child, true, opt_doc));\n      }\n\n      if (node instanceof wrappers.HTMLTemplateElement) {\n        var cloneContent = clone.content;\n        for (var child = node.content.firstChild;\n             child;\n             child = child.nextSibling) {\n         cloneContent.appendChild(cloneNode(child, true, opt_doc));\n        }\n      }\n    }\n    // TODO(arv): Some HTML elements also clone other data like value.\n    return clone;\n  }\n\n  var OriginalNode = window.Node;\n\n  /**\n   * This represents a wrapper of a native DOM node.\n   * @param {!Node} original The original DOM node, aka, the visual DOM node.\n   * @constructor\n   * @extends {EventTarget}\n   */\n  function Node(original) {\n    assert(original instanceof OriginalNode);\n\n    EventTarget.call(this, original);\n\n    // These properties are used to override the visual references with the\n    // logical ones. If the value is undefined it means that the logical is the\n    // same as the visual.\n\n    /**\n     * @type {Node|undefined}\n     * @private\n     */\n    this.parentNode_ = undefined;\n\n    /**\n     * @type {Node|undefined}\n     * @private\n     */\n    this.firstChild_ = undefined;\n\n    /**\n     * @type {Node|undefined}\n     * @private\n     */\n    this.lastChild_ = undefined;\n\n    /**\n     * @type {Node|undefined}\n     * @private\n     */\n    this.nextSibling_ = undefined;\n\n    /**\n     * @type {Node|undefined}\n     * @private\n     */\n    this.previousSibling_ = undefined;\n  }\n\n  var OriginalDocumentFragment = window.DocumentFragment;\n  var originalAppendChild = OriginalNode.prototype.appendChild;\n  var originalCompareDocumentPosition =\n      OriginalNode.prototype.compareDocumentPosition;\n  var originalInsertBefore = OriginalNode.prototype.insertBefore;\n  var originalRemoveChild = OriginalNode.prototype.removeChild;\n  var originalReplaceChild = OriginalNode.prototype.replaceChild;\n\n  var isIe = /Trident/.test(navigator.userAgent);\n\n  var removeChildOriginalHelper = isIe ?\n      function(parent, child) {\n        try {\n          originalRemoveChild.call(parent, child);\n        } catch (ex) {\n          if (!(parent instanceof OriginalDocumentFragment))\n            throw ex;\n        }\n      } :\n      function(parent, child) {\n        originalRemoveChild.call(parent, child);\n      };\n\n  Node.prototype = Object.create(EventTarget.prototype);\n  mixin(Node.prototype, {\n    appendChild: function(childWrapper) {\n      return this.insertBefore(childWrapper, null);\n    },\n\n    insertBefore: function(childWrapper, refWrapper) {\n      assertIsNodeWrapper(childWrapper);\n\n      var refNode;\n      if (refWrapper) {\n        if (isWrapper(refWrapper)) {\n          refNode = unwrap(refWrapper);\n        } else {\n          refNode = refWrapper;\n          refWrapper = wrap(refNode);\n        }\n      } else {\n        refWrapper = null;\n        refNode = null;\n      }\n\n      refWrapper && assert(refWrapper.parentNode === this);\n\n      var nodes;\n      var previousNode =\n          refWrapper ? refWrapper.previousSibling : this.lastChild;\n\n      var useNative = !this.invalidateShadowRenderer() &&\n                      !invalidateParent(childWrapper);\n\n      if (useNative)\n        nodes = collectNodesNative(childWrapper);\n      else\n        nodes = collectNodes(childWrapper, this, previousNode, refWrapper);\n\n      if (useNative) {\n        ensureSameOwnerDocument(this, childWrapper);\n        clearChildNodes(this);\n        originalInsertBefore.call(this.impl, unwrap(childWrapper), refNode);\n      } else {\n        if (!previousNode)\n          this.firstChild_ = nodes[0];\n        if (!refWrapper)\n          this.lastChild_ = nodes[nodes.length - 1];\n\n        var parentNode = refNode ? refNode.parentNode : this.impl;\n\n        // insertBefore refWrapper no matter what the parent is?\n        if (parentNode) {\n          originalInsertBefore.call(parentNode,\n              unwrapNodesForInsertion(this, nodes), refNode);\n        } else {\n          adoptNodesIfNeeded(this, nodes);\n        }\n      }\n\n      enqueueMutation(this, 'childList', {\n        addedNodes: nodes,\n        nextSibling: refWrapper,\n        previousSibling: previousNode\n      });\n\n      nodesWereAdded(nodes);\n\n      return childWrapper;\n    },\n\n    removeChild: function(childWrapper) {\n      assertIsNodeWrapper(childWrapper);\n      if (childWrapper.parentNode !== this) {\n        // IE has invalid DOM trees at times.\n        var found = false;\n        var childNodes = this.childNodes;\n        for (var ieChild = this.firstChild; ieChild;\n             ieChild = ieChild.nextSibling) {\n          if (ieChild === childWrapper) {\n            found = true;\n            break;\n          }\n        }\n        if (!found) {\n          // TODO(arv): DOMException\n          throw new Error('NotFoundError');\n        }\n      }\n\n      var childNode = unwrap(childWrapper);\n      var childWrapperNextSibling = childWrapper.nextSibling;\n      var childWrapperPreviousSibling = childWrapper.previousSibling;\n\n      if (this.invalidateShadowRenderer()) {\n        // We need to remove the real node from the DOM before updating the\n        // pointers. This is so that that mutation event is dispatched before\n        // the pointers have changed.\n        var thisFirstChild = this.firstChild;\n        var thisLastChild = this.lastChild;\n\n        var parentNode = childNode.parentNode;\n        if (parentNode)\n          removeChildOriginalHelper(parentNode, childNode);\n\n        if (thisFirstChild === childWrapper)\n          this.firstChild_ = childWrapperNextSibling;\n        if (thisLastChild === childWrapper)\n          this.lastChild_ = childWrapperPreviousSibling;\n        if (childWrapperPreviousSibling)\n          childWrapperPreviousSibling.nextSibling_ = childWrapperNextSibling;\n        if (childWrapperNextSibling) {\n          childWrapperNextSibling.previousSibling_ =\n              childWrapperPreviousSibling;\n        }\n\n        childWrapper.previousSibling_ = childWrapper.nextSibling_ =\n            childWrapper.parentNode_ = undefined;\n      } else {\n        clearChildNodes(this);\n        removeChildOriginalHelper(this.impl, childNode);\n      }\n\n      if (!surpressMutations) {\n        enqueueMutation(this, 'childList', {\n          removedNodes: createOneElementNodeList(childWrapper),\n          nextSibling: childWrapperNextSibling,\n          previousSibling: childWrapperPreviousSibling\n        });\n      }\n\n      registerTransientObservers(this, childWrapper);\n\n      return childWrapper;\n    },\n\n    replaceChild: function(newChildWrapper, oldChildWrapper) {\n      assertIsNodeWrapper(newChildWrapper);\n\n      var oldChildNode;\n      if (isWrapper(oldChildWrapper)) {\n        oldChildNode = unwrap(oldChildWrapper);\n      } else {\n        oldChildNode = oldChildWrapper;\n        oldChildWrapper = wrap(oldChildNode);\n      }\n\n      if (oldChildWrapper.parentNode !== this) {\n        // TODO(arv): DOMException\n        throw new Error('NotFoundError');\n      }\n\n      var nextNode = oldChildWrapper.nextSibling;\n      var previousNode = oldChildWrapper.previousSibling;\n      var nodes;\n\n      var useNative = !this.invalidateShadowRenderer() &&\n                      !invalidateParent(newChildWrapper);\n\n      if (useNative) {\n        nodes = collectNodesNative(newChildWrapper);\n      } else {\n        if (nextNode === newChildWrapper)\n          nextNode = newChildWrapper.nextSibling;\n        nodes = collectNodes(newChildWrapper, this, previousNode, nextNode);\n      }\n\n      if (!useNative) {\n        if (this.firstChild === oldChildWrapper)\n          this.firstChild_ = nodes[0];\n        if (this.lastChild === oldChildWrapper)\n          this.lastChild_ = nodes[nodes.length - 1];\n\n        oldChildWrapper.previousSibling_ = oldChildWrapper.nextSibling_ =\n            oldChildWrapper.parentNode_ = undefined;\n\n        // replaceChild no matter what the parent is?\n        if (oldChildNode.parentNode) {\n          originalReplaceChild.call(\n              oldChildNode.parentNode,\n              unwrapNodesForInsertion(this, nodes),\n              oldChildNode);\n        }\n      } else {\n        ensureSameOwnerDocument(this, newChildWrapper);\n        clearChildNodes(this);\n        originalReplaceChild.call(this.impl, unwrap(newChildWrapper),\n                                  oldChildNode);\n      }\n\n      enqueueMutation(this, 'childList', {\n        addedNodes: nodes,\n        removedNodes: createOneElementNodeList(oldChildWrapper),\n        nextSibling: nextNode,\n        previousSibling: previousNode\n      });\n\n      nodeWasRemoved(oldChildWrapper);\n      nodesWereAdded(nodes);\n\n      return oldChildWrapper;\n    },\n\n    /**\n     * Called after a node was inserted. Subclasses override this to invalidate\n     * the renderer as needed.\n     * @private\n     */\n    nodeIsInserted_: function() {\n      for (var child = this.firstChild; child; child = child.nextSibling) {\n        child.nodeIsInserted_();\n      }\n    },\n\n    hasChildNodes: function() {\n      return this.firstChild !== null;\n    },\n\n    /** @type {Node} */\n    get parentNode() {\n      // If the parentNode has not been overridden, use the original parentNode.\n      return this.parentNode_ !== undefined ?\n          this.parentNode_ : wrap(this.impl.parentNode);\n    },\n\n    /** @type {Node} */\n    get firstChild() {\n      return this.firstChild_ !== undefined ?\n          this.firstChild_ : wrap(this.impl.firstChild);\n    },\n\n    /** @type {Node} */\n    get lastChild() {\n      return this.lastChild_ !== undefined ?\n          this.lastChild_ : wrap(this.impl.lastChild);\n    },\n\n    /** @type {Node} */\n    get nextSibling() {\n      return this.nextSibling_ !== undefined ?\n          this.nextSibling_ : wrap(this.impl.nextSibling);\n    },\n\n    /** @type {Node} */\n    get previousSibling() {\n      return this.previousSibling_ !== undefined ?\n          this.previousSibling_ : wrap(this.impl.previousSibling);\n    },\n\n    get parentElement() {\n      var p = this.parentNode;\n      while (p && p.nodeType !== Node.ELEMENT_NODE) {\n        p = p.parentNode;\n      }\n      return p;\n    },\n\n    get textContent() {\n      // TODO(arv): This should fallback to this.impl.textContent if there\n      // are no shadow trees below or above the context node.\n      var s = '';\n      for (var child = this.firstChild; child; child = child.nextSibling) {\n        if (child.nodeType != Node.COMMENT_NODE) {\n          s += child.textContent;\n        }\n      }\n      return s;\n    },\n    set textContent(textContent) {\n      var removedNodes = snapshotNodeList(this.childNodes);\n\n      if (this.invalidateShadowRenderer()) {\n        removeAllChildNodes(this);\n        if (textContent !== '') {\n          var textNode = this.impl.ownerDocument.createTextNode(textContent);\n          this.appendChild(textNode);\n        }\n      } else {\n        clearChildNodes(this);\n        this.impl.textContent = textContent;\n      }\n\n      var addedNodes = snapshotNodeList(this.childNodes);\n\n      enqueueMutation(this, 'childList', {\n        addedNodes: addedNodes,\n        removedNodes: removedNodes\n      });\n\n      nodesWereRemoved(removedNodes);\n      nodesWereAdded(addedNodes);\n    },\n\n    get childNodes() {\n      var wrapperList = new NodeList();\n      var i = 0;\n      for (var child = this.firstChild; child; child = child.nextSibling) {\n        wrapperList[i++] = child;\n      }\n      wrapperList.length = i;\n      return wrapperList;\n    },\n\n    cloneNode: function(deep) {\n      return cloneNode(this, deep);\n    },\n\n    contains: function(child) {\n      if (!child)\n        return false;\n\n      child = wrapIfNeeded(child);\n\n      // TODO(arv): Optimize using ownerDocument etc.\n      if (child === this)\n        return true;\n      var parentNode = child.parentNode;\n      if (!parentNode)\n        return false;\n      return this.contains(parentNode);\n    },\n\n    compareDocumentPosition: function(otherNode) {\n      // This only wraps, it therefore only operates on the composed DOM and not\n      // the logical DOM.\n      return originalCompareDocumentPosition.call(this.impl, unwrap(otherNode));\n    },\n\n    normalize: function() {\n      var nodes = snapshotNodeList(this.childNodes);\n      var remNodes = [];\n      var s = '';\n      var modNode;\n\n      for (var i = 0, n; i < nodes.length; i++) {\n        n = nodes[i];\n        if (n.nodeType === Node.TEXT_NODE) {\n          if (!modNode && !n.data.length)\n            this.removeNode(n);\n          else if (!modNode)\n            modNode = n;\n          else {\n            s += n.data;\n            remNodes.push(n);\n          }\n        } else {\n          if (modNode && remNodes.length) {\n            modNode.data += s;\n            cleanUpNodes(remNodes);\n          }\n          remNodes = [];\n          s = '';\n          modNode = null;\n          if (n.childNodes.length)\n            n.normalize();\n        }\n      }\n\n      // handle case where >1 text nodes are the last children\n      if (modNode && remNodes.length) {\n        modNode.data += s;\n        cleanupNodes(remNodes);\n      }\n    }\n  });\n\n  defineWrapGetter(Node, 'ownerDocument');\n\n  // We use a DocumentFragment as a base and then delete the properties of\n  // DocumentFragment.prototype from the wrapper Node. Since delete makes\n  // objects slow in some JS engines we recreate the prototype object.\n  registerWrapper(OriginalNode, Node, document.createDocumentFragment());\n  delete Node.prototype.querySelector;\n  delete Node.prototype.querySelectorAll;\n  Node.prototype = mixin(Object.create(EventTarget.prototype), Node.prototype);\n\n  scope.nodeWasAdded = nodeWasAdded;\n  scope.nodeWasRemoved = nodeWasRemoved;\n  scope.nodesWereAdded = nodesWereAdded;\n  scope.nodesWereRemoved = nodesWereRemoved;\n  scope.snapshotNodeList = snapshotNodeList;\n  scope.wrappers.Node = Node;\n  scope.cloneNode = cloneNode;\n\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  function findOne(node, selector) {\n    var m, el = node.firstElementChild;\n    while (el) {\n      if (el.matches(selector))\n        return el;\n      m = findOne(el, selector);\n      if (m)\n        return m;\n      el = el.nextElementSibling;\n    }\n    return null;\n  }\n\n  function findAll(node, selector, results) {\n    var el = node.firstElementChild;\n    while (el) {\n      if (el.matches(selector))\n        results[results.length++] = el;\n      findAll(el, selector, results);\n      el = el.nextElementSibling;\n    }\n    return results;\n  }\n\n  // find and findAll will only match Simple Selectors,\n  // Structural Pseudo Classes are not guarenteed to be correct\n  // http://www.w3.org/TR/css3-selectors/#simple-selectors\n\n  var SelectorsInterface = {\n    querySelector: function(selector) {\n      return findOne(this, selector);\n    },\n    querySelectorAll: function(selector) {\n      return findAll(this, selector, new NodeList())\n    }\n  };\n\n  var GetElementsByInterface = {\n    getElementsByTagName: function(tagName) {\n      // TODO(arv): Check tagName?\n      return this.querySelectorAll(tagName);\n    },\n    getElementsByClassName: function(className) {\n      // TODO(arv): Check className?\n      return this.querySelectorAll('.' + className);\n    },\n    getElementsByTagNameNS: function(ns, tagName) {\n      if (ns === '*')\n        return this.getElementsByTagName(tagName);\n\n      // TODO(arv): Check tagName?\n      var result = new NodeList;\n      var els = this.getElementsByTagName(tagName);\n      for (var i = 0, j = 0; i < els.length; i++) {\n        if (els[i].namespaceURI === ns)\n          result[j++] = els[i];\n      }\n      result.length = j;\n      return result;\n    }\n  };\n\n  scope.GetElementsByInterface = GetElementsByInterface;\n  scope.SelectorsInterface = SelectorsInterface;\n\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var NodeList = scope.wrappers.NodeList;\n\n  function forwardElement(node) {\n    while (node && node.nodeType !== Node.ELEMENT_NODE) {\n      node = node.nextSibling;\n    }\n    return node;\n  }\n\n  function backwardsElement(node) {\n    while (node && node.nodeType !== Node.ELEMENT_NODE) {\n      node = node.previousSibling;\n    }\n    return node;\n  }\n\n  var ParentNodeInterface = {\n    get firstElementChild() {\n      return forwardElement(this.firstChild);\n    },\n\n    get lastElementChild() {\n      return backwardsElement(this.lastChild);\n    },\n\n    get childElementCount() {\n      var count = 0;\n      for (var child = this.firstElementChild;\n           child;\n           child = child.nextElementSibling) {\n        count++;\n      }\n      return count;\n    },\n\n    get children() {\n      var wrapperList = new NodeList();\n      var i = 0;\n      for (var child = this.firstElementChild;\n           child;\n           child = child.nextElementSibling) {\n        wrapperList[i++] = child;\n      }\n      wrapperList.length = i;\n      return wrapperList;\n    }\n  };\n\n  var ChildNodeInterface = {\n    get nextElementSibling() {\n      return forwardElement(this.nextSibling);\n    },\n\n    get previousElementSibling() {\n      return backwardsElement(this.previousSibling);\n    }\n  };\n\n  scope.ChildNodeInterface = ChildNodeInterface;\n  scope.ParentNodeInterface = ParentNodeInterface;\n\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var ChildNodeInterface = scope.ChildNodeInterface;\n  var Node = scope.wrappers.Node;\n  var enqueueMutation = scope.enqueueMutation;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n\n  var OriginalCharacterData = window.CharacterData;\n\n  function CharacterData(node) {\n    Node.call(this, node);\n  }\n  CharacterData.prototype = Object.create(Node.prototype);\n  mixin(CharacterData.prototype, {\n    get textContent() {\n      return this.data;\n    },\n    set textContent(value) {\n      this.data = value;\n    },\n    get data() {\n      return this.impl.data;\n    },\n    set data(value) {\n      var oldValue = this.impl.data;\n      enqueueMutation(this, 'characterData', {\n        oldValue: oldValue\n      });\n      this.impl.data = value;\n    }\n  });\n\n  mixin(CharacterData.prototype, ChildNodeInterface);\n\n  registerWrapper(OriginalCharacterData, CharacterData,\n                  document.createTextNode(''));\n\n  scope.wrappers.CharacterData = CharacterData;\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2014 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var CharacterData = scope.wrappers.CharacterData;\n  var enqueueMutation = scope.enqueueMutation;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n\n  function toUInt32(x) {\n    return x >>> 0;\n  }\n\n  var OriginalText = window.Text;\n\n  function Text(node) {\n    CharacterData.call(this, node);\n  }\n  Text.prototype = Object.create(CharacterData.prototype);\n  mixin(Text.prototype, {\n    splitText: function(offset) {\n      offset = toUInt32(offset);\n      var s = this.data;\n      if (offset > s.length)\n        throw new Error('IndexSizeError');\n      var head = s.slice(0, offset);\n      var tail = s.slice(offset);\n      this.data = head;\n      var newTextNode = this.ownerDocument.createTextNode(tail);\n      if (this.parentNode)\n        this.parentNode.insertBefore(newTextNode, this.nextSibling);\n      return newTextNode;\n    }\n  });\n\n  registerWrapper(OriginalText, Text, document.createTextNode(''));\n\n  scope.wrappers.Text = Text;\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var ChildNodeInterface = scope.ChildNodeInterface;\n  var GetElementsByInterface = scope.GetElementsByInterface;\n  var Node = scope.wrappers.Node;\n  var ParentNodeInterface = scope.ParentNodeInterface;\n  var SelectorsInterface = scope.SelectorsInterface;\n  var addWrapNodeListMethod = scope.addWrapNodeListMethod;\n  var enqueueMutation = scope.enqueueMutation;\n  var mixin = scope.mixin;\n  var oneOf = scope.oneOf;\n  var registerWrapper = scope.registerWrapper;\n  var wrappers = scope.wrappers;\n\n  var OriginalElement = window.Element;\n\n  var matchesNames = [\n    'matches',  // needs to come first.\n    'mozMatchesSelector',\n    'msMatchesSelector',\n    'webkitMatchesSelector',\n  ].filter(function(name) {\n    return OriginalElement.prototype[name];\n  });\n\n  var matchesName = matchesNames[0];\n\n  var originalMatches = OriginalElement.prototype[matchesName];\n\n  function invalidateRendererBasedOnAttribute(element, name) {\n    // Only invalidate if parent node is a shadow host.\n    var p = element.parentNode;\n    if (!p || !p.shadowRoot)\n      return;\n\n    var renderer = scope.getRendererForHost(p);\n    if (renderer.dependsOnAttribute(name))\n      renderer.invalidate();\n  }\n\n  function enqueAttributeChange(element, name, oldValue) {\n    // This is not fully spec compliant. We should use localName (which might\n    // have a different case than name) and the namespace (which requires us\n    // to get the Attr object).\n    enqueueMutation(element, 'attributes', {\n      name: name,\n      namespace: null,\n      oldValue: oldValue\n    });\n  }\n\n  function Element(node) {\n    Node.call(this, node);\n  }\n  Element.prototype = Object.create(Node.prototype);\n  mixin(Element.prototype, {\n    createShadowRoot: function() {\n      var newShadowRoot = new wrappers.ShadowRoot(this);\n      this.impl.polymerShadowRoot_ = newShadowRoot;\n\n      var renderer = scope.getRendererForHost(this);\n      renderer.invalidate();\n\n      return newShadowRoot;\n    },\n\n    get shadowRoot() {\n      return this.impl.polymerShadowRoot_ || null;\n    },\n\n    setAttribute: function(name, value) {\n      var oldValue = this.impl.getAttribute(name);\n      this.impl.setAttribute(name, value);\n      enqueAttributeChange(this, name, oldValue);\n      invalidateRendererBasedOnAttribute(this, name);\n    },\n\n    removeAttribute: function(name) {\n      var oldValue = this.impl.getAttribute(name);\n      this.impl.removeAttribute(name);\n      enqueAttributeChange(this, name, oldValue);\n      invalidateRendererBasedOnAttribute(this, name);\n    },\n\n    matches: function(selector) {\n      return originalMatches.call(this.impl, selector);\n    }\n  });\n\n  matchesNames.forEach(function(name) {\n    if (name !== 'matches') {\n      Element.prototype[name] = function(selector) {\n        return this.matches(selector);\n      };\n    }\n  });\n\n  if (OriginalElement.prototype.webkitCreateShadowRoot) {\n    Element.prototype.webkitCreateShadowRoot =\n        Element.prototype.createShadowRoot;\n  }\n\n  /**\n   * Useful for generating the accessor pair for a property that reflects an\n   * attribute.\n   */\n  function setterDirtiesAttribute(prototype, propertyName, opt_attrName) {\n    var attrName = opt_attrName || propertyName;\n    Object.defineProperty(prototype, propertyName, {\n      get: function() {\n        return this.impl[propertyName];\n      },\n      set: function(v) {\n        this.impl[propertyName] = v;\n        invalidateRendererBasedOnAttribute(this, attrName);\n      },\n      configurable: true,\n      enumerable: true\n    });\n  }\n\n  setterDirtiesAttribute(Element.prototype, 'id');\n  setterDirtiesAttribute(Element.prototype, 'className', 'class');\n\n  mixin(Element.prototype, ChildNodeInterface);\n  mixin(Element.prototype, GetElementsByInterface);\n  mixin(Element.prototype, ParentNodeInterface);\n  mixin(Element.prototype, SelectorsInterface);\n\n  registerWrapper(OriginalElement, Element,\n                  document.createElementNS(null, 'x'));\n\n  // TODO(arv): Export setterDirtiesAttribute and apply it to more bindings\n  // that reflect attributes.\n  scope.matchesNames = matchesNames;\n  scope.wrappers.Element = Element;\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var Element = scope.wrappers.Element;\n  var defineGetter = scope.defineGetter;\n  var enqueueMutation = scope.enqueueMutation;\n  var mixin = scope.mixin;\n  var nodesWereAdded = scope.nodesWereAdded;\n  var nodesWereRemoved = scope.nodesWereRemoved;\n  var registerWrapper = scope.registerWrapper;\n  var snapshotNodeList = scope.snapshotNodeList;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n  var wrappers = scope.wrappers;\n\n  /////////////////////////////////////////////////////////////////////////////\n  // innerHTML and outerHTML\n\n  // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#escapingString\n  var escapeAttrRegExp = /[&\\u00A0\"]/g;\n  var escapeDataRegExp = /[&\\u00A0<>]/g;\n\n  function escapeReplace(c) {\n    switch (c) {\n      case '&':\n        return '&amp;';\n      case '<':\n        return '&lt;';\n      case '>':\n        return '&gt;';\n      case '\"':\n        return '&quot;'\n      case '\\u00A0':\n        return '&nbsp;';\n    }\n  }\n\n  function escapeAttr(s) {\n    return s.replace(escapeAttrRegExp, escapeReplace);\n  }\n\n  function escapeData(s) {\n    return s.replace(escapeDataRegExp, escapeReplace);\n  }\n\n  function makeSet(arr) {\n    var set = {};\n    for (var i = 0; i < arr.length; i++) {\n      set[arr[i]] = true;\n    }\n    return set;\n  }\n\n  // http://www.whatwg.org/specs/web-apps/current-work/#void-elements\n  var voidElements = makeSet([\n    'area',\n    'base',\n    'br',\n    'col',\n    'command',\n    'embed',\n    'hr',\n    'img',\n    'input',\n    'keygen',\n    'link',\n    'meta',\n    'param',\n    'source',\n    'track',\n    'wbr'\n  ]);\n\n  var plaintextParents = makeSet([\n    'style',\n    'script',\n    'xmp',\n    'iframe',\n    'noembed',\n    'noframes',\n    'plaintext',\n    'noscript'\n  ]);\n\n  function getOuterHTML(node, parentNode) {\n    switch (node.nodeType) {\n      case Node.ELEMENT_NODE:\n        var tagName = node.tagName.toLowerCase();\n        var s = '<' + tagName;\n        var attrs = node.attributes;\n        for (var i = 0, attr; attr = attrs[i]; i++) {\n          s += ' ' + attr.name + '=\"' + escapeAttr(attr.value) + '\"';\n        }\n        s += '>';\n        if (voidElements[tagName])\n          return s;\n\n        return s + getInnerHTML(node) + '</' + tagName + '>';\n\n      case Node.TEXT_NODE:\n        var data = node.data;\n        if (parentNode && plaintextParents[parentNode.localName])\n          return data;\n        return escapeData(data);\n\n      case Node.COMMENT_NODE:\n        return '<!--' + node.data + '-->';\n\n      default:\n        console.error(node);\n        throw new Error('not implemented');\n    }\n  }\n\n  function getInnerHTML(node) {\n    if (node instanceof wrappers.HTMLTemplateElement)\n      node = node.content;\n\n    var s = '';\n    for (var child = node.firstChild; child; child = child.nextSibling) {\n      s += getOuterHTML(child, node);\n    }\n    return s;\n  }\n\n  function setInnerHTML(node, value, opt_tagName) {\n    var tagName = opt_tagName || 'div';\n    node.textContent = '';\n    var tempElement = unwrap(node.ownerDocument.createElement(tagName));\n    tempElement.innerHTML = value;\n    var firstChild;\n    while (firstChild = tempElement.firstChild) {\n      node.appendChild(wrap(firstChild));\n    }\n  }\n\n  // IE11 does not have MSIE in the user agent string.\n  var oldIe = /MSIE/.test(navigator.userAgent);\n\n  var OriginalHTMLElement = window.HTMLElement;\n  var OriginalHTMLTemplateElement = window.HTMLTemplateElement;\n\n  function HTMLElement(node) {\n    Element.call(this, node);\n  }\n  HTMLElement.prototype = Object.create(Element.prototype);\n  mixin(HTMLElement.prototype, {\n    get innerHTML() {\n      return getInnerHTML(this);\n    },\n    set innerHTML(value) {\n      // IE9 does not handle set innerHTML correctly on plaintextParents. It\n      // creates element children. For example\n      //\n      //   scriptElement.innerHTML = '<a>test</a>'\n      //\n      // Creates a single HTMLAnchorElement child.\n      if (oldIe && plaintextParents[this.localName]) {\n        this.textContent = value;\n        return;\n      }\n\n      var removedNodes = snapshotNodeList(this.childNodes);\n\n      if (this.invalidateShadowRenderer()) {\n        if (this instanceof wrappers.HTMLTemplateElement)\n          setInnerHTML(this.content, value);\n        else\n          setInnerHTML(this, value, this.tagName);\n\n      // If we have a non native template element we need to handle this\n      // manually since setting impl.innerHTML would add the html as direct\n      // children and not be moved over to the content fragment.\n      } else if (!OriginalHTMLTemplateElement &&\n                 this instanceof wrappers.HTMLTemplateElement) {\n        setInnerHTML(this.content, value);\n      } else {\n        this.impl.innerHTML = value;\n      }\n\n      var addedNodes = snapshotNodeList(this.childNodes);\n\n      enqueueMutation(this, 'childList', {\n        addedNodes: addedNodes,\n        removedNodes: removedNodes\n      });\n\n      nodesWereRemoved(removedNodes);\n      nodesWereAdded(addedNodes);\n    },\n\n    get outerHTML() {\n      return getOuterHTML(this, this.parentNode);\n    },\n    set outerHTML(value) {\n      var p = this.parentNode;\n      if (p) {\n        p.invalidateShadowRenderer();\n        var df = frag(p, value);\n        p.replaceChild(df, this);\n      }\n    },\n\n    insertAdjacentHTML: function(position, text) {\n      var contextElement, refNode;\n      switch (String(position).toLowerCase()) {\n        case 'beforebegin':\n          contextElement = this.parentNode;\n          refNode = this;\n          break;\n        case 'afterend':\n          contextElement = this.parentNode;\n          refNode = this.nextSibling;\n          break;\n        case 'afterbegin':\n          contextElement = this;\n          refNode = this.firstChild;\n          break;\n        case 'beforeend':\n          contextElement = this;\n          refNode = null;\n          break;\n        default:\n          return;\n      }\n\n      var df = frag(contextElement, text);\n      contextElement.insertBefore(df, refNode);\n    }\n  });\n\n  function frag(contextElement, html) {\n    // TODO(arv): This does not work with SVG and other non HTML elements.\n    var p = unwrap(contextElement.cloneNode(false));\n    p.innerHTML = html;\n    var df = unwrap(document.createDocumentFragment());\n    var c;\n    while (c = p.firstChild) {\n      df.appendChild(c);\n    }\n    return wrap(df);\n  }\n\n  function getter(name) {\n    return function() {\n      scope.renderAllPending();\n      return this.impl[name];\n    };\n  }\n\n  function getterRequiresRendering(name) {\n    defineGetter(HTMLElement, name, getter(name));\n  }\n\n  [\n    'clientHeight',\n    'clientLeft',\n    'clientTop',\n    'clientWidth',\n    'offsetHeight',\n    'offsetLeft',\n    'offsetTop',\n    'offsetWidth',\n    'scrollHeight',\n    'scrollWidth',\n  ].forEach(getterRequiresRendering);\n\n  function getterAndSetterRequiresRendering(name) {\n    Object.defineProperty(HTMLElement.prototype, name, {\n      get: getter(name),\n      set: function(v) {\n        scope.renderAllPending();\n        this.impl[name] = v;\n      },\n      configurable: true,\n      enumerable: true\n    });\n  }\n\n  [\n    'scrollLeft',\n    'scrollTop',\n  ].forEach(getterAndSetterRequiresRendering);\n\n  function methodRequiresRendering(name) {\n    Object.defineProperty(HTMLElement.prototype, name, {\n      value: function() {\n        scope.renderAllPending();\n        return this.impl[name].apply(this.impl, arguments);\n      },\n      configurable: true,\n      enumerable: true\n    });\n  }\n\n  [\n    'getBoundingClientRect',\n    'getClientRects',\n    'scrollIntoView'\n  ].forEach(methodRequiresRendering);\n\n  // HTMLElement is abstract so we use a subclass that has no members.\n  registerWrapper(OriginalHTMLElement, HTMLElement,\n                  document.createElement('b'));\n\n  scope.wrappers.HTMLElement = HTMLElement;\n\n  // TODO: Find a better way to share these two with WrapperShadowRoot.\n  scope.getInnerHTML = getInnerHTML;\n  scope.setInnerHTML = setInnerHTML\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLElement = scope.wrappers.HTMLElement;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var wrap = scope.wrap;\n\n  var OriginalHTMLCanvasElement = window.HTMLCanvasElement;\n\n  function HTMLCanvasElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLCanvasElement.prototype = Object.create(HTMLElement.prototype);\n\n  mixin(HTMLCanvasElement.prototype, {\n    getContext: function() {\n      var context = this.impl.getContext.apply(this.impl, arguments);\n      return context && wrap(context);\n    }\n  });\n\n  registerWrapper(OriginalHTMLCanvasElement, HTMLCanvasElement,\n                  document.createElement('canvas'));\n\n  scope.wrappers.HTMLCanvasElement = HTMLCanvasElement;\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLElement = scope.wrappers.HTMLElement;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n\n  var OriginalHTMLContentElement = window.HTMLContentElement;\n\n  function HTMLContentElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLContentElement.prototype = Object.create(HTMLElement.prototype);\n  mixin(HTMLContentElement.prototype, {\n    get select() {\n      return this.getAttribute('select');\n    },\n    set select(value) {\n      this.setAttribute('select', value);\n    },\n\n    setAttribute: function(n, v) {\n      HTMLElement.prototype.setAttribute.call(this, n, v);\n      if (String(n).toLowerCase() === 'select')\n        this.invalidateShadowRenderer(true);\n    }\n\n    // getDistributedNodes is added in ShadowRenderer\n\n    // TODO: attribute boolean resetStyleInheritance;\n  });\n\n  if (OriginalHTMLContentElement)\n    registerWrapper(OriginalHTMLContentElement, HTMLContentElement);\n\n  scope.wrappers.HTMLContentElement = HTMLContentElement;\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLElement = scope.wrappers.HTMLElement;\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var rewrap = scope.rewrap;\n\n  var OriginalHTMLImageElement = window.HTMLImageElement;\n\n  function HTMLImageElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLImageElement.prototype = Object.create(HTMLElement.prototype);\n\n  registerWrapper(OriginalHTMLImageElement, HTMLImageElement,\n                  document.createElement('img'));\n\n  function Image(width, height) {\n    if (!(this instanceof Image)) {\n      throw new TypeError(\n          'DOM object constructor cannot be called as a function.');\n    }\n\n    var node = unwrap(document.createElement('img'));\n    HTMLElement.call(this, node);\n    rewrap(node, this);\n\n    if (width !== undefined)\n      node.width = width;\n    if (height !== undefined)\n      node.height = height;\n  }\n\n  Image.prototype = HTMLImageElement.prototype;\n\n  scope.wrappers.HTMLImageElement = HTMLImageElement;\n  scope.wrappers.Image = Image;\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLElement = scope.wrappers.HTMLElement;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n\n  var OriginalHTMLShadowElement = window.HTMLShadowElement;\n\n  function HTMLShadowElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLShadowElement.prototype = Object.create(HTMLElement.prototype);\n  mixin(HTMLShadowElement.prototype, {\n    // TODO: attribute boolean resetStyleInheritance;\n  });\n\n  if (OriginalHTMLShadowElement)\n    registerWrapper(OriginalHTMLShadowElement, HTMLShadowElement);\n\n  scope.wrappers.HTMLShadowElement = HTMLShadowElement;\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLElement = scope.wrappers.HTMLElement;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n\n  var contentTable = new WeakMap();\n  var templateContentsOwnerTable = new WeakMap();\n\n  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner\n  function getTemplateContentsOwner(doc) {\n    if (!doc.defaultView)\n      return doc;\n    var d = templateContentsOwnerTable.get(doc);\n    if (!d) {\n      // TODO(arv): This should either be a Document or HTMLDocument depending\n      // on doc.\n      d = doc.implementation.createHTMLDocument('');\n      while (d.lastChild) {\n        d.removeChild(d.lastChild);\n      }\n      templateContentsOwnerTable.set(doc, d);\n    }\n    return d;\n  }\n\n  function extractContent(templateElement) {\n    // templateElement is not a wrapper here.\n    var doc = getTemplateContentsOwner(templateElement.ownerDocument);\n    var df = unwrap(doc.createDocumentFragment());\n    var child;\n    while (child = templateElement.firstChild) {\n      df.appendChild(child);\n    }\n    return df;\n  }\n\n  var OriginalHTMLTemplateElement = window.HTMLTemplateElement;\n\n  function HTMLTemplateElement(node) {\n    HTMLElement.call(this, node);\n    if (!OriginalHTMLTemplateElement) {\n      var content = extractContent(node);\n      contentTable.set(this, wrap(content));\n    }\n  }\n  HTMLTemplateElement.prototype = Object.create(HTMLElement.prototype);\n\n  mixin(HTMLTemplateElement.prototype, {\n    get content() {\n      if (OriginalHTMLTemplateElement)\n        return wrap(this.impl.content);\n      return contentTable.get(this);\n    },\n\n    // TODO(arv): cloneNode needs to clone content.\n\n  });\n\n  if (OriginalHTMLTemplateElement)\n    registerWrapper(OriginalHTMLTemplateElement, HTMLTemplateElement);\n\n  scope.wrappers.HTMLTemplateElement = HTMLTemplateElement;\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLElement = scope.wrappers.HTMLElement;\n  var registerWrapper = scope.registerWrapper;\n\n  var OriginalHTMLMediaElement = window.HTMLMediaElement;\n\n  function HTMLMediaElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLMediaElement.prototype = Object.create(HTMLElement.prototype);\n\n  registerWrapper(OriginalHTMLMediaElement, HTMLMediaElement,\n                  document.createElement('audio'));\n\n  scope.wrappers.HTMLMediaElement = HTMLMediaElement;\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLMediaElement = scope.wrappers.HTMLMediaElement;\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var rewrap = scope.rewrap;\n\n  var OriginalHTMLAudioElement = window.HTMLAudioElement;\n\n  function HTMLAudioElement(node) {\n    HTMLMediaElement.call(this, node);\n  }\n  HTMLAudioElement.prototype = Object.create(HTMLMediaElement.prototype);\n\n  registerWrapper(OriginalHTMLAudioElement, HTMLAudioElement,\n                  document.createElement('audio'));\n\n  function Audio(src) {\n    if (!(this instanceof Audio)) {\n      throw new TypeError(\n          'DOM object constructor cannot be called as a function.');\n    }\n\n    var node = unwrap(document.createElement('audio'));\n    HTMLMediaElement.call(this, node);\n    rewrap(node, this);\n\n    node.setAttribute('preload', 'auto');\n    if (src !== undefined)\n      node.setAttribute('src', src);\n  }\n\n  Audio.prototype = HTMLAudioElement.prototype;\n\n  scope.wrappers.HTMLAudioElement = HTMLAudioElement;\n  scope.wrappers.Audio = Audio;\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLElement = scope.wrappers.HTMLElement;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var rewrap = scope.rewrap;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n\n  var OriginalHTMLOptionElement = window.HTMLOptionElement;\n\n  function trimText(s) {\n    return s.replace(/\\s+/g, ' ').trim();\n  }\n\n  function HTMLOptionElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLOptionElement.prototype = Object.create(HTMLElement.prototype);\n  mixin(HTMLOptionElement.prototype, {\n    get text() {\n      return trimText(this.textContent);\n    },\n    set text(value) {\n      this.textContent = trimText(String(value));\n    },\n    get form() {\n      return wrap(unwrap(this).form);\n    }\n  });\n\n  registerWrapper(OriginalHTMLOptionElement, HTMLOptionElement,\n                  document.createElement('option'));\n\n  function Option(text, value, defaultSelected, selected) {\n    if (!(this instanceof Option)) {\n      throw new TypeError(\n          'DOM object constructor cannot be called as a function.');\n    }\n\n    var node = unwrap(document.createElement('option'));\n    HTMLElement.call(this, node);\n    rewrap(node, this);\n\n    if (text !== undefined)\n      node.text = text;\n    if (value !== undefined)\n      node.setAttribute('value', value);\n    if (defaultSelected === true)\n      node.setAttribute('selected', '');\n    node.selected = selected === true;\n  }\n\n  Option.prototype = HTMLOptionElement.prototype;\n\n  scope.wrappers.HTMLOptionElement = HTMLOptionElement;\n  scope.wrappers.Option = Option;\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLContentElement = scope.wrappers.HTMLContentElement;\n  var HTMLElement = scope.wrappers.HTMLElement;\n  var HTMLShadowElement = scope.wrappers.HTMLShadowElement;\n  var HTMLTemplateElement = scope.wrappers.HTMLTemplateElement;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n\n  var OriginalHTMLUnknownElement = window.HTMLUnknownElement;\n\n  function HTMLUnknownElement(node) {\n    switch (node.localName) {\n      case 'content':\n        return new HTMLContentElement(node);\n      case 'shadow':\n        return new HTMLShadowElement(node);\n      case 'template':\n        return new HTMLTemplateElement(node);\n    }\n    HTMLElement.call(this, node);\n  }\n  HTMLUnknownElement.prototype = Object.create(HTMLElement.prototype);\n  registerWrapper(OriginalHTMLUnknownElement, HTMLUnknownElement);\n  scope.wrappers.HTMLUnknownElement = HTMLUnknownElement;\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2014 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var registerObject = scope.registerObject;\n\n  var SVG_NS = 'http://www.w3.org/2000/svg';\n  var svgTitleElement = document.createElementNS(SVG_NS, 'title');\n  var SVGTitleElement = registerObject(svgTitleElement);\n  var SVGElement = Object.getPrototypeOf(SVGTitleElement.prototype).constructor;\n\n  scope.wrappers.SVGElement = SVGElement;\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2014 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n\n  var OriginalSVGUseElement = window.SVGUseElement;\n\n  // IE uses SVGElement as parent interface, SVG2 (Blink & Gecko) uses\n  // SVGGraphicsElement. Use the <g> element to get the right prototype.\n\n  var SVG_NS = 'http://www.w3.org/2000/svg';\n  var gWrapper = wrap(document.createElementNS(SVG_NS, 'g'));\n  var useElement = document.createElementNS(SVG_NS, 'use');\n  var SVGGElement = gWrapper.constructor;\n  var parentInterfacePrototype = Object.getPrototypeOf(SVGGElement.prototype);\n  var parentInterface = parentInterfacePrototype.constructor;\n\n  function SVGUseElement(impl) {\n    parentInterface.call(this, impl);\n  }\n\n  SVGUseElement.prototype = Object.create(parentInterfacePrototype);\n\n  // Firefox does not expose instanceRoot.\n  if ('instanceRoot' in useElement) {\n    mixin(SVGUseElement.prototype, {\n      get instanceRoot() {\n        return wrap(unwrap(this).instanceRoot);\n      },\n      get animatedInstanceRoot() {\n        return wrap(unwrap(this).animatedInstanceRoot);\n      },\n    });\n  }\n\n  registerWrapper(OriginalSVGUseElement, SVGUseElement, useElement);\n\n  scope.wrappers.SVGUseElement = SVGUseElement;\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2014 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var EventTarget = scope.wrappers.EventTarget;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var wrap = scope.wrap;\n\n  var OriginalSVGElementInstance = window.SVGElementInstance;\n  if (!OriginalSVGElementInstance)\n    return;\n\n  function SVGElementInstance(impl) {\n    EventTarget.call(this, impl);\n  }\n\n  SVGElementInstance.prototype = Object.create(EventTarget.prototype);\n  mixin(SVGElementInstance.prototype, {\n    /** @type {SVGElement} */\n    get correspondingElement() {\n      return wrap(this.impl.correspondingElement);\n    },\n\n    /** @type {SVGUseElement} */\n    get correspondingUseElement() {\n      return wrap(this.impl.correspondingUseElement);\n    },\n\n    /** @type {SVGElementInstance} */\n    get parentNode() {\n      return wrap(this.impl.parentNode);\n    },\n\n    /** @type {SVGElementInstanceList} */\n    get childNodes() {\n      throw new Error('Not implemented');\n    },\n\n    /** @type {SVGElementInstance} */\n    get firstChild() {\n      return wrap(this.impl.firstChild);\n    },\n\n    /** @type {SVGElementInstance} */\n    get lastChild() {\n      return wrap(this.impl.lastChild);\n    },\n\n    /** @type {SVGElementInstance} */\n    get previousSibling() {\n      return wrap(this.impl.previousSibling);\n    },\n\n    /** @type {SVGElementInstance} */\n    get nextSibling() {\n      return wrap(this.impl.nextSibling);\n    }\n  });\n\n  registerWrapper(OriginalSVGElementInstance, SVGElementInstance);\n\n  scope.wrappers.SVGElementInstance = SVGElementInstance;\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var unwrapIfNeeded = scope.unwrapIfNeeded;\n  var wrap = scope.wrap;\n\n  var OriginalCanvasRenderingContext2D = window.CanvasRenderingContext2D;\n\n  function CanvasRenderingContext2D(impl) {\n    this.impl = impl;\n  }\n\n  mixin(CanvasRenderingContext2D.prototype, {\n    get canvas() {\n      return wrap(this.impl.canvas);\n    },\n\n    drawImage: function() {\n      arguments[0] = unwrapIfNeeded(arguments[0]);\n      this.impl.drawImage.apply(this.impl, arguments);\n    },\n\n    createPattern: function() {\n      arguments[0] = unwrap(arguments[0]);\n      return this.impl.createPattern.apply(this.impl, arguments);\n    }\n  });\n\n  registerWrapper(OriginalCanvasRenderingContext2D, CanvasRenderingContext2D,\n                  document.createElement('canvas').getContext('2d'));\n\n  scope.wrappers.CanvasRenderingContext2D = CanvasRenderingContext2D;\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var unwrapIfNeeded = scope.unwrapIfNeeded;\n  var wrap = scope.wrap;\n\n  var OriginalWebGLRenderingContext = window.WebGLRenderingContext;\n\n  // IE10 does not have WebGL.\n  if (!OriginalWebGLRenderingContext)\n    return;\n\n  function WebGLRenderingContext(impl) {\n    this.impl = impl;\n  }\n\n  mixin(WebGLRenderingContext.prototype, {\n    get canvas() {\n      return wrap(this.impl.canvas);\n    },\n\n    texImage2D: function() {\n      arguments[5] = unwrapIfNeeded(arguments[5]);\n      this.impl.texImage2D.apply(this.impl, arguments);\n    },\n\n    texSubImage2D: function() {\n      arguments[6] = unwrapIfNeeded(arguments[6]);\n      this.impl.texSubImage2D.apply(this.impl, arguments);\n    }\n  });\n\n  // Blink/WebKit has broken DOM bindings. Usually we would create an instance\n  // of the object and pass it into registerWrapper as a \"blueprint\" but\n  // creating WebGL contexts is expensive and might fail so we use a dummy\n  // object with dummy instance properties for these broken browsers.\n  var instanceProperties = /WebKit/.test(navigator.userAgent) ?\n      {drawingBufferHeight: null, drawingBufferWidth: null} : {};\n\n  registerWrapper(OriginalWebGLRenderingContext, WebGLRenderingContext,\n      instanceProperties);\n\n  scope.wrappers.WebGLRenderingContext = WebGLRenderingContext;\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var unwrapIfNeeded = scope.unwrapIfNeeded;\n  var wrap = scope.wrap;\n\n  var OriginalRange = window.Range;\n\n  function Range(impl) {\n    this.impl = impl;\n  }\n  Range.prototype = {\n    get startContainer() {\n      return wrap(this.impl.startContainer);\n    },\n    get endContainer() {\n      return wrap(this.impl.endContainer);\n    },\n    get commonAncestorContainer() {\n      return wrap(this.impl.commonAncestorContainer);\n    },\n    setStart: function(refNode,offset) {\n      this.impl.setStart(unwrapIfNeeded(refNode), offset);\n    },\n    setEnd: function(refNode,offset) {\n      this.impl.setEnd(unwrapIfNeeded(refNode), offset);\n    },\n    setStartBefore: function(refNode) {\n      this.impl.setStartBefore(unwrapIfNeeded(refNode));\n    },\n    setStartAfter: function(refNode) {\n      this.impl.setStartAfter(unwrapIfNeeded(refNode));\n    },\n    setEndBefore: function(refNode) {\n      this.impl.setEndBefore(unwrapIfNeeded(refNode));\n    },\n    setEndAfter: function(refNode) {\n      this.impl.setEndAfter(unwrapIfNeeded(refNode));\n    },\n    selectNode: function(refNode) {\n      this.impl.selectNode(unwrapIfNeeded(refNode));\n    },\n    selectNodeContents: function(refNode) {\n      this.impl.selectNodeContents(unwrapIfNeeded(refNode));\n    },\n    compareBoundaryPoints: function(how, sourceRange) {\n      return this.impl.compareBoundaryPoints(how, unwrap(sourceRange));\n    },\n    extractContents: function() {\n      return wrap(this.impl.extractContents());\n    },\n    cloneContents: function() {\n      return wrap(this.impl.cloneContents());\n    },\n    insertNode: function(node) {\n      this.impl.insertNode(unwrapIfNeeded(node));\n    },\n    surroundContents: function(newParent) {\n      this.impl.surroundContents(unwrapIfNeeded(newParent));\n    },\n    cloneRange: function() {\n      return wrap(this.impl.cloneRange());\n    },\n    isPointInRange: function(node, offset) {\n      return this.impl.isPointInRange(unwrapIfNeeded(node), offset);\n    },\n    comparePoint: function(node, offset) {\n      return this.impl.comparePoint(unwrapIfNeeded(node), offset);\n    },\n    intersectsNode: function(node) {\n      return this.impl.intersectsNode(unwrapIfNeeded(node));\n    },\n    toString: function() {\n      return this.impl.toString();\n    }\n  };\n\n  // IE9 does not have createContextualFragment.\n  if (OriginalRange.prototype.createContextualFragment) {\n    Range.prototype.createContextualFragment = function(html) {\n      return wrap(this.impl.createContextualFragment(html));\n    };\n  }\n\n  registerWrapper(window.Range, Range, document.createRange());\n\n  scope.wrappers.Range = Range;\n\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var GetElementsByInterface = scope.GetElementsByInterface;\n  var ParentNodeInterface = scope.ParentNodeInterface;\n  var SelectorsInterface = scope.SelectorsInterface;\n  var mixin = scope.mixin;\n  var registerObject = scope.registerObject;\n\n  var DocumentFragment = registerObject(document.createDocumentFragment());\n  mixin(DocumentFragment.prototype, ParentNodeInterface);\n  mixin(DocumentFragment.prototype, SelectorsInterface);\n  mixin(DocumentFragment.prototype, GetElementsByInterface);\n\n  var Comment = registerObject(document.createComment(''));\n\n  scope.wrappers.Comment = Comment;\n  scope.wrappers.DocumentFragment = DocumentFragment;\n\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var DocumentFragment = scope.wrappers.DocumentFragment;\n  var elementFromPoint = scope.elementFromPoint;\n  var getInnerHTML = scope.getInnerHTML;\n  var mixin = scope.mixin;\n  var rewrap = scope.rewrap;\n  var setInnerHTML = scope.setInnerHTML;\n  var unwrap = scope.unwrap;\n\n  var shadowHostTable = new WeakMap();\n  var nextOlderShadowTreeTable = new WeakMap();\n\n  var spaceCharRe = /[ \\t\\n\\r\\f]/;\n\n  function ShadowRoot(hostWrapper) {\n    var node = unwrap(hostWrapper.impl.ownerDocument.createDocumentFragment());\n    DocumentFragment.call(this, node);\n\n    // createDocumentFragment associates the node with a wrapper\n    // DocumentFragment instance. Override that.\n    rewrap(node, this);\n\n    var oldShadowRoot = hostWrapper.shadowRoot;\n    nextOlderShadowTreeTable.set(this, oldShadowRoot);\n\n    shadowHostTable.set(this, hostWrapper);\n  }\n  ShadowRoot.prototype = Object.create(DocumentFragment.prototype);\n  mixin(ShadowRoot.prototype, {\n    get innerHTML() {\n      return getInnerHTML(this);\n    },\n    set innerHTML(value) {\n      setInnerHTML(this, value);\n      this.invalidateShadowRenderer();\n    },\n\n    get olderShadowRoot() {\n      return nextOlderShadowTreeTable.get(this) || null;\n    },\n\n    get host() {\n      return shadowHostTable.get(this) || null;\n    },\n\n    invalidateShadowRenderer: function() {\n      return shadowHostTable.get(this).invalidateShadowRenderer();\n    },\n\n    elementFromPoint: function(x, y) {\n      return elementFromPoint(this, this.ownerDocument, x, y);\n    },\n\n    getElementById: function(id) {\n      if (spaceCharRe.test(id))\n        return null;\n      return this.querySelector('[id=\"' + id + '\"]');\n    }\n  });\n\n  scope.wrappers.ShadowRoot = ShadowRoot;\n\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var Element = scope.wrappers.Element;\n  var HTMLContentElement = scope.wrappers.HTMLContentElement;\n  var HTMLShadowElement = scope.wrappers.HTMLShadowElement;\n  var Node = scope.wrappers.Node;\n  var ShadowRoot = scope.wrappers.ShadowRoot;\n  var assert = scope.assert;\n  var mixin = scope.mixin;\n  var oneOf = scope.oneOf;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n\n  /**\n   * Updates the fields of a wrapper to a snapshot of the logical DOM as needed.\n   * Up means parentNode\n   * Sideways means previous and next sibling.\n   * @param {!Node} wrapper\n   */\n  function updateWrapperUpAndSideways(wrapper) {\n    wrapper.previousSibling_ = wrapper.previousSibling;\n    wrapper.nextSibling_ = wrapper.nextSibling;\n    wrapper.parentNode_ = wrapper.parentNode;\n  }\n\n  /**\n   * Updates the fields of a wrapper to a snapshot of the logical DOM as needed.\n   * Down means first and last child\n   * @param {!Node} wrapper\n   */\n  function updateWrapperDown(wrapper) {\n    wrapper.firstChild_ = wrapper.firstChild;\n    wrapper.lastChild_ = wrapper.lastChild;\n  }\n\n  function updateAllChildNodes(parentNodeWrapper) {\n    assert(parentNodeWrapper instanceof Node);\n    for (var childWrapper = parentNodeWrapper.firstChild;\n         childWrapper;\n         childWrapper = childWrapper.nextSibling) {\n      updateWrapperUpAndSideways(childWrapper);\n    }\n    updateWrapperDown(parentNodeWrapper);\n  }\n\n  function insertBefore(parentNodeWrapper, newChildWrapper, refChildWrapper) {\n    var parentNode = unwrap(parentNodeWrapper);\n    var newChild = unwrap(newChildWrapper);\n    var refChild = refChildWrapper ? unwrap(refChildWrapper) : null;\n\n    remove(newChildWrapper);\n    updateWrapperUpAndSideways(newChildWrapper);\n\n    if (!refChildWrapper) {\n      parentNodeWrapper.lastChild_ = parentNodeWrapper.lastChild;\n      if (parentNodeWrapper.lastChild === parentNodeWrapper.firstChild)\n        parentNodeWrapper.firstChild_ = parentNodeWrapper.firstChild;\n\n      var lastChildWrapper = wrap(parentNode.lastChild);\n      if (lastChildWrapper)\n        lastChildWrapper.nextSibling_ = lastChildWrapper.nextSibling;\n    } else {\n      if (parentNodeWrapper.firstChild === refChildWrapper)\n        parentNodeWrapper.firstChild_ = refChildWrapper;\n\n      refChildWrapper.previousSibling_ = refChildWrapper.previousSibling;\n    }\n\n    parentNode.insertBefore(newChild, refChild);\n  }\n\n  function remove(nodeWrapper) {\n    var node = unwrap(nodeWrapper)\n    var parentNode = node.parentNode;\n    if (!parentNode)\n      return;\n\n    var parentNodeWrapper = wrap(parentNode);\n    updateWrapperUpAndSideways(nodeWrapper);\n\n    if (nodeWrapper.previousSibling)\n      nodeWrapper.previousSibling.nextSibling_ = nodeWrapper;\n    if (nodeWrapper.nextSibling)\n      nodeWrapper.nextSibling.previousSibling_ = nodeWrapper;\n\n    if (parentNodeWrapper.lastChild === nodeWrapper)\n      parentNodeWrapper.lastChild_ = nodeWrapper;\n    if (parentNodeWrapper.firstChild === nodeWrapper)\n      parentNodeWrapper.firstChild_ = nodeWrapper;\n\n    parentNode.removeChild(node);\n  }\n\n  var distributedChildNodesTable = new WeakMap();\n  var eventParentsTable = new WeakMap();\n  var insertionParentTable = new WeakMap();\n  var rendererForHostTable = new WeakMap();\n\n  function distributeChildToInsertionPoint(child, insertionPoint) {\n    getDistributedChildNodes(insertionPoint).push(child);\n    assignToInsertionPoint(child, insertionPoint);\n\n    var eventParents = eventParentsTable.get(child);\n    if (!eventParents)\n      eventParentsTable.set(child, eventParents = []);\n    eventParents.push(insertionPoint);\n  }\n\n  function resetDistributedChildNodes(insertionPoint) {\n    distributedChildNodesTable.set(insertionPoint, []);\n  }\n\n  function getDistributedChildNodes(insertionPoint) {\n    return distributedChildNodesTable.get(insertionPoint);\n  }\n\n  function getChildNodesSnapshot(node) {\n    var result = [], i = 0;\n    for (var child = node.firstChild; child; child = child.nextSibling) {\n      result[i++] = child;\n    }\n    return result;\n  }\n\n  /**\n   * Visits all nodes in the tree that fulfils the |predicate|. If the |visitor|\n   * function returns |false| the traversal is aborted.\n   * @param {!Node} tree\n   * @param {function(!Node) : boolean} predicate\n   * @param {function(!Node) : *} visitor\n   */\n  function visit(tree, predicate, visitor) {\n    // This operates on logical DOM.\n    for (var node = tree.firstChild; node; node = node.nextSibling) {\n      if (predicate(node)) {\n        if (visitor(node) === false)\n          return;\n      } else {\n        visit(node, predicate, visitor);\n      }\n    }\n  }\n\n  // Matching Insertion Points\n  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#matching-insertion-points\n\n  // TODO(arv): Verify this... I don't remember why I picked this regexp.\n  var selectorMatchRegExp = /^[*.:#[a-zA-Z_|]/;\n\n  var allowedPseudoRegExp = new RegExp('^:(' + [\n    'link',\n    'visited',\n    'target',\n    'enabled',\n    'disabled',\n    'checked',\n    'indeterminate',\n    'nth-child',\n    'nth-last-child',\n    'nth-of-type',\n    'nth-last-of-type',\n    'first-child',\n    'last-child',\n    'first-of-type',\n    'last-of-type',\n    'only-of-type',\n  ].join('|') + ')');\n\n\n  /**\n   * @param {Element} node\n   * @oaram {Element} point The insertion point element.\n   * @return {boolean} Whether the node matches the insertion point.\n   */\n  function matchesCriteria(node, point) {\n    var select = point.getAttribute('select');\n    if (!select)\n      return true;\n\n    // Here we know the select attribute is a non empty string.\n    select = select.trim();\n    if (!select)\n      return true;\n\n    if (!(node instanceof Element))\n      return false;\n\n    // The native matches function in IE9 does not correctly work with elements\n    // that are not in the document.\n    // TODO(arv): Implement matching in JS.\n    // https://github.com/Polymer/ShadowDOM/issues/361\n    if (select === '*' || select === node.localName)\n      return true;\n\n    // TODO(arv): This does not seem right. Need to check for a simple selector.\n    if (!selectorMatchRegExp.test(select))\n      return false;\n\n    // TODO(arv): This no longer matches the spec.\n    if (select[0] === ':' && !allowedPseudoRegExp.test(select))\n      return false;\n\n    try {\n      return node.matches(select);\n    } catch (ex) {\n      // Invalid selector.\n      return false;\n    }\n  }\n\n  var request = oneOf(window, [\n    'requestAnimationFrame',\n    'mozRequestAnimationFrame',\n    'webkitRequestAnimationFrame',\n    'setTimeout'\n  ]);\n\n  var pendingDirtyRenderers = [];\n  var renderTimer;\n\n  function renderAllPending() {\n    for (var i = 0; i < pendingDirtyRenderers.length; i++) {\n      pendingDirtyRenderers[i].render();\n    }\n    pendingDirtyRenderers = [];\n  }\n\n  function handleRequestAnimationFrame() {\n    renderTimer = null;\n    renderAllPending();\n  }\n\n  /**\n   * Returns existing shadow renderer for a host or creates it if it is needed.\n   * @params {!Element} host\n   * @return {!ShadowRenderer}\n   */\n  function getRendererForHost(host) {\n    var renderer = rendererForHostTable.get(host);\n    if (!renderer) {\n      renderer = new ShadowRenderer(host);\n      rendererForHostTable.set(host, renderer);\n    }\n    return renderer;\n  }\n\n  function getShadowRootAncestor(node) {\n    for (; node; node = node.parentNode) {\n      if (node instanceof ShadowRoot)\n        return node;\n    }\n    return null;\n  }\n\n  function getRendererForShadowRoot(shadowRoot) {\n    return getRendererForHost(shadowRoot.host);\n  }\n\n  var spliceDiff = new ArraySplice();\n  spliceDiff.equals = function(renderNode, rawNode) {\n    return unwrap(renderNode.node) === rawNode;\n  };\n\n  /**\n   * RenderNode is used as an in memory \"render tree\". When we render the\n   * composed tree we create a tree of RenderNodes, then we diff this against\n   * the real DOM tree and make minimal changes as needed.\n   */\n  function RenderNode(node) {\n    this.skip = false;\n    this.node = node;\n    this.childNodes = [];\n  }\n\n  RenderNode.prototype = {\n    append: function(node) {\n      var rv = new RenderNode(node);\n      this.childNodes.push(rv);\n      return rv;\n    },\n\n    sync: function(opt_added) {\n      if (this.skip)\n        return;\n\n      var nodeWrapper = this.node;\n      // plain array of RenderNodes\n      var newChildren = this.childNodes;\n      // plain array of real nodes.\n      var oldChildren = getChildNodesSnapshot(unwrap(nodeWrapper));\n      var added = opt_added || new WeakMap();\n\n      var splices = spliceDiff.calculateSplices(newChildren, oldChildren);\n\n      var newIndex = 0, oldIndex = 0;\n      var lastIndex = 0;\n      for (var i = 0; i < splices.length; i++) {\n        var splice = splices[i];\n        for (; lastIndex < splice.index; lastIndex++) {\n          oldIndex++;\n          newChildren[newIndex++].sync(added);\n        }\n\n        var removedCount = splice.removed.length;\n        for (var j = 0; j < removedCount; j++) {\n          var wrapper = wrap(oldChildren[oldIndex++]);\n          if (!added.get(wrapper))\n            remove(wrapper);\n        }\n\n        var addedCount = splice.addedCount;\n        var refNode = oldChildren[oldIndex] && wrap(oldChildren[oldIndex]);\n        for (var j = 0; j < addedCount; j++) {\n          var newChildRenderNode = newChildren[newIndex++];\n          var newChildWrapper = newChildRenderNode.node;\n          insertBefore(nodeWrapper, newChildWrapper, refNode);\n\n          // Keep track of added so that we do not remove the node after it\n          // has been added.\n          added.set(newChildWrapper, true);\n\n          newChildRenderNode.sync(added);\n        }\n\n        lastIndex += addedCount;\n      }\n\n      for (var i = lastIndex; i < newChildren.length; i++) {\n        newChildren[i].sync(added);\n      }\n    }\n  };\n\n  function ShadowRenderer(host) {\n    this.host = host;\n    this.dirty = false;\n    this.invalidateAttributes();\n    this.associateNode(host);\n  }\n\n  ShadowRenderer.prototype = {\n\n    // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#rendering-shadow-trees\n    render: function(opt_renderNode) {\n      if (!this.dirty)\n        return;\n\n      this.invalidateAttributes();\n      this.treeComposition();\n\n      var host = this.host;\n      var shadowRoot = host.shadowRoot;\n\n      this.associateNode(host);\n      var topMostRenderer = !renderNode;\n      var renderNode = opt_renderNode || new RenderNode(host);\n\n      for (var node = shadowRoot.firstChild; node; node = node.nextSibling) {\n        this.renderNode(shadowRoot, renderNode, node, false);\n      }\n\n      if (topMostRenderer)\n        renderNode.sync();\n\n      this.dirty = false;\n    },\n\n    invalidate: function() {\n      if (!this.dirty) {\n        this.dirty = true;\n        pendingDirtyRenderers.push(this);\n        if (renderTimer)\n          return;\n        renderTimer = window[request](handleRequestAnimationFrame, 0);\n      }\n    },\n\n    renderNode: function(shadowRoot, renderNode, node, isNested) {\n      if (isShadowHost(node)) {\n        renderNode = renderNode.append(node);\n        var renderer = getRendererForHost(node);\n        renderer.dirty = true;  // Need to rerender due to reprojection.\n        renderer.render(renderNode);\n      } else if (isInsertionPoint(node)) {\n        this.renderInsertionPoint(shadowRoot, renderNode, node, isNested);\n      } else if (isShadowInsertionPoint(node)) {\n        this.renderShadowInsertionPoint(shadowRoot, renderNode, node);\n      } else {\n        this.renderAsAnyDomTree(shadowRoot, renderNode, node, isNested);\n      }\n    },\n\n    renderAsAnyDomTree: function(shadowRoot, renderNode, node, isNested) {\n      renderNode = renderNode.append(node);\n\n      if (isShadowHost(node)) {\n        var renderer = getRendererForHost(node);\n        renderNode.skip = !renderer.dirty;\n        renderer.render(renderNode);\n      } else {\n        for (var child = node.firstChild; child; child = child.nextSibling) {\n          this.renderNode(shadowRoot, renderNode, child, isNested);\n        }\n      }\n    },\n\n    renderInsertionPoint: function(shadowRoot, renderNode, insertionPoint,\n                                   isNested) {\n      var distributedChildNodes = getDistributedChildNodes(insertionPoint);\n      if (distributedChildNodes.length) {\n        this.associateNode(insertionPoint);\n\n        for (var i = 0; i < distributedChildNodes.length; i++) {\n          var child = distributedChildNodes[i];\n          if (isInsertionPoint(child) && isNested)\n            this.renderInsertionPoint(shadowRoot, renderNode, child, isNested);\n          else\n            this.renderAsAnyDomTree(shadowRoot, renderNode, child, isNested);\n        }\n      } else {\n        this.renderFallbackContent(shadowRoot, renderNode, insertionPoint);\n      }\n      this.associateNode(insertionPoint.parentNode);\n    },\n\n    renderShadowInsertionPoint: function(shadowRoot, renderNode,\n                                         shadowInsertionPoint) {\n      var nextOlderTree = shadowRoot.olderShadowRoot;\n      if (nextOlderTree) {\n        assignToInsertionPoint(nextOlderTree, shadowInsertionPoint);\n        this.associateNode(shadowInsertionPoint.parentNode);\n        for (var node = nextOlderTree.firstChild;\n             node;\n             node = node.nextSibling) {\n          this.renderNode(nextOlderTree, renderNode, node, true);\n        }\n      } else {\n        this.renderFallbackContent(shadowRoot, renderNode,\n                                   shadowInsertionPoint);\n      }\n    },\n\n    renderFallbackContent: function(shadowRoot, renderNode, fallbackHost) {\n      this.associateNode(fallbackHost);\n      this.associateNode(fallbackHost.parentNode);\n      for (var node = fallbackHost.firstChild; node; node = node.nextSibling) {\n        this.renderAsAnyDomTree(shadowRoot, renderNode, node, false);\n      }\n    },\n\n    /**\n     * Invalidates the attributes used to keep track of which attributes may\n     * cause the renderer to be invalidated.\n     */\n    invalidateAttributes: function() {\n      this.attributes = Object.create(null);\n    },\n\n    /**\n     * Parses the selector and makes this renderer dependent on the attribute\n     * being used in the selector.\n     * @param {string} selector\n     */\n    updateDependentAttributes: function(selector) {\n      if (!selector)\n        return;\n\n      var attributes = this.attributes;\n\n      // .class\n      if (/\\.\\w+/.test(selector))\n        attributes['class'] = true;\n\n      // #id\n      if (/#\\w+/.test(selector))\n        attributes['id'] = true;\n\n      selector.replace(/\\[\\s*([^\\s=\\|~\\]]+)/g, function(_, name) {\n        attributes[name] = true;\n      });\n\n      // Pseudo selectors have been removed from the spec.\n    },\n\n    dependsOnAttribute: function(name) {\n      return this.attributes[name];\n    },\n\n    // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-distribution-algorithm\n    distribute: function(tree, pool) {\n      var self = this;\n\n      visit(tree, isActiveInsertionPoint,\n          function(insertionPoint) {\n            resetDistributedChildNodes(insertionPoint);\n            self.updateDependentAttributes(\n                insertionPoint.getAttribute('select'));\n\n            for (var i = 0; i < pool.length; i++) {  // 1.2\n              var node = pool[i];  // 1.2.1\n              if (node === undefined)  // removed\n                continue;\n              if (matchesCriteria(node, insertionPoint)) {  // 1.2.2\n                distributeChildToInsertionPoint(node, insertionPoint);  // 1.2.2.1\n                pool[i] = undefined;  // 1.2.2.2\n              }\n            }\n          });\n    },\n\n    // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-tree-composition\n    treeComposition: function () {\n      var shadowHost = this.host;\n      var tree = shadowHost.shadowRoot;  // 1.\n      var pool = [];  // 2.\n\n      for (var child = shadowHost.firstChild;\n           child;\n           child = child.nextSibling) {  // 3.\n        if (isInsertionPoint(child)) {  // 3.2.\n          var reprojected = getDistributedChildNodes(child);  // 3.2.1.\n          // if reprojected is undef... reset it?\n          if (!reprojected || !reprojected.length)  // 3.2.2.\n            reprojected = getChildNodesSnapshot(child);\n          pool.push.apply(pool, reprojected);  // 3.2.3.\n        } else {\n          pool.push(child); // 3.3.\n        }\n      }\n\n      var shadowInsertionPoint, point;\n      while (tree) {  // 4.\n        // 4.1.\n        shadowInsertionPoint = undefined;  // Reset every iteration.\n        visit(tree, isActiveShadowInsertionPoint, function(point) {\n          shadowInsertionPoint = point;\n          return false;\n        });\n        point = shadowInsertionPoint;\n\n        this.distribute(tree, pool);  // 4.2.\n        if (point) {  // 4.3.\n          var nextOlderTree = tree.olderShadowRoot;  // 4.3.1.\n          if (!nextOlderTree) {\n            break;  // 4.3.1.1.\n          } else {\n            tree = nextOlderTree;  // 4.3.2.2.\n            assignToInsertionPoint(tree, point);  // 4.3.2.2.\n            continue;  // 4.3.2.3.\n          }\n        } else {\n          break;  // 4.4.\n        }\n      }\n    },\n\n    associateNode: function(node) {\n      node.impl.polymerShadowRenderer_ = this;\n    }\n  };\n\n  function isInsertionPoint(node) {\n    // Should this include <shadow>?\n    return node instanceof HTMLContentElement;\n  }\n\n  function isActiveInsertionPoint(node) {\n    // <content> inside another <content> or <shadow> is considered inactive.\n    return node instanceof HTMLContentElement;\n  }\n\n  function isShadowInsertionPoint(node) {\n    return node instanceof HTMLShadowElement;\n  }\n\n  function isActiveShadowInsertionPoint(node) {\n    // <shadow> inside another <content> or <shadow> is considered inactive.\n    return node instanceof HTMLShadowElement;\n  }\n\n  function isShadowHost(shadowHost) {\n    return shadowHost.shadowRoot;\n  }\n\n  function getShadowTrees(host) {\n    var trees = [];\n\n    for (var tree = host.shadowRoot; tree; tree = tree.olderShadowRoot) {\n      trees.push(tree);\n    }\n    return trees;\n  }\n\n  function assignToInsertionPoint(tree, point) {\n    insertionParentTable.set(tree, point);\n  }\n\n  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#rendering-shadow-trees\n  function render(host) {\n    new ShadowRenderer(host).render();\n  };\n\n  // Need to rerender shadow host when:\n  //\n  // - a direct child to the ShadowRoot is added or removed\n  // - a direct child to the host is added or removed\n  // - a new shadow root is created\n  // - a direct child to a content/shadow element is added or removed\n  // - a sibling to a content/shadow element is added or removed\n  // - content[select] is changed\n  // - an attribute in a direct child to a host is modified\n\n  /**\n   * This gets called when a node was added or removed to it.\n   */\n  Node.prototype.invalidateShadowRenderer = function(force) {\n    var renderer = this.impl.polymerShadowRenderer_;\n    if (renderer) {\n      renderer.invalidate();\n      return true;\n    }\n\n    return false;\n  };\n\n  HTMLContentElement.prototype.getDistributedNodes = function() {\n    // TODO(arv): We should only rerender the dirty ancestor renderers (from\n    // the root and down).\n    renderAllPending();\n    return getDistributedChildNodes(this);\n  };\n\n  HTMLShadowElement.prototype.nodeIsInserted_ =\n  HTMLContentElement.prototype.nodeIsInserted_ = function() {\n    // Invalidate old renderer if any.\n    this.invalidateShadowRenderer();\n\n    var shadowRoot = getShadowRootAncestor(this);\n    var renderer;\n    if (shadowRoot)\n      renderer = getRendererForShadowRoot(shadowRoot);\n    this.impl.polymerShadowRenderer_ = renderer;\n    if (renderer)\n      renderer.invalidate();\n  };\n\n  scope.eventParentsTable = eventParentsTable;\n  scope.getRendererForHost = getRendererForHost;\n  scope.getShadowTrees = getShadowTrees;\n  scope.insertionParentTable = insertionParentTable;\n  scope.renderAllPending = renderAllPending;\n\n  // Exposed for testing\n  scope.visual = {\n    insertBefore: insertBefore,\n    remove: remove,\n  };\n\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLElement = scope.wrappers.HTMLElement;\n  var assert = scope.assert;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n\n  var elementsWithFormProperty = [\n    'HTMLButtonElement',\n    'HTMLFieldSetElement',\n    'HTMLInputElement',\n    'HTMLKeygenElement',\n    'HTMLLabelElement',\n    'HTMLLegendElement',\n    'HTMLObjectElement',\n    // HTMLOptionElement is handled in HTMLOptionElement.js\n    'HTMLOutputElement',\n    'HTMLSelectElement',\n    'HTMLTextAreaElement',\n  ];\n\n  function createWrapperConstructor(name) {\n    if (!window[name])\n      return;\n\n    // Ensure we are not overriding an already existing constructor.\n    assert(!scope.wrappers[name]);\n\n    var GeneratedWrapper = function(node) {\n      // At this point all of them extend HTMLElement.\n      HTMLElement.call(this, node);\n    }\n    GeneratedWrapper.prototype = Object.create(HTMLElement.prototype);\n    mixin(GeneratedWrapper.prototype, {\n      get form() {\n        return wrap(unwrap(this).form);\n      },\n    });\n\n    registerWrapper(window[name], GeneratedWrapper,\n        document.createElement(name.slice(4, -7)));\n    scope.wrappers[name] = GeneratedWrapper;\n  }\n\n  elementsWithFormProperty.forEach(createWrapperConstructor);\n\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2014 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var unwrapIfNeeded = scope.unwrapIfNeeded;\n  var wrap = scope.wrap;\n\n  var OriginalSelection = window.Selection;\n\n  function Selection(impl) {\n    this.impl = impl;\n  }\n  Selection.prototype = {\n    get anchorNode() {\n      return wrap(this.impl.anchorNode);\n    },\n    get focusNode() {\n      return wrap(this.impl.focusNode);\n    },\n    addRange: function(range) {\n      this.impl.addRange(unwrap(range));\n    },\n    collapse: function(node, index) {\n      this.impl.collapse(unwrapIfNeeded(node), index);\n    },\n    containsNode: function(node, allowPartial) {\n      return this.impl.containsNode(unwrapIfNeeded(node), allowPartial);\n    },\n    extend: function(node, offset) {\n      this.impl.extend(unwrapIfNeeded(node), offset);\n    },\n    getRangeAt: function(index) {\n      return wrap(this.impl.getRangeAt(index));\n    },\n    removeRange: function(range) {\n      this.impl.removeRange(unwrap(range));\n    },\n    selectAllChildren: function(node) {\n      this.impl.selectAllChildren(unwrapIfNeeded(node));\n    },\n    toString: function() {\n      return this.impl.toString();\n    }\n  };\n\n  // WebKit extensions. Not implemented.\n  // readonly attribute Node baseNode;\n  // readonly attribute long baseOffset;\n  // readonly attribute Node extentNode;\n  // readonly attribute long extentOffset;\n  // [RaisesException] void setBaseAndExtent([Default=Undefined] optional Node baseNode,\n  //                       [Default=Undefined] optional long baseOffset,\n  //                       [Default=Undefined] optional Node extentNode,\n  //                       [Default=Undefined] optional long extentOffset);\n  // [RaisesException, ImplementedAs=collapse] void setPosition([Default=Undefined] optional Node node,\n  //                  [Default=Undefined] optional long offset);\n\n  registerWrapper(window.Selection, Selection, window.getSelection());\n\n  scope.wrappers.Selection = Selection;\n\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var GetElementsByInterface = scope.GetElementsByInterface;\n  var Node = scope.wrappers.Node;\n  var ParentNodeInterface = scope.ParentNodeInterface;\n  var Selection = scope.wrappers.Selection;\n  var SelectorsInterface = scope.SelectorsInterface;\n  var ShadowRoot = scope.wrappers.ShadowRoot;\n  var cloneNode = scope.cloneNode;\n  var defineWrapGetter = scope.defineWrapGetter;\n  var elementFromPoint = scope.elementFromPoint;\n  var forwardMethodsToWrapper = scope.forwardMethodsToWrapper;\n  var matchesNames = scope.matchesNames;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var renderAllPending = scope.renderAllPending;\n  var rewrap = scope.rewrap;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n  var wrapEventTargetMethods = scope.wrapEventTargetMethods;\n  var wrapNodeList = scope.wrapNodeList;\n\n  var implementationTable = new WeakMap();\n\n  function Document(node) {\n    Node.call(this, node);\n  }\n  Document.prototype = Object.create(Node.prototype);\n\n  defineWrapGetter(Document, 'documentElement');\n\n  // Conceptually both body and head can be in a shadow but suporting that seems\n  // overkill at this point.\n  defineWrapGetter(Document, 'body');\n  defineWrapGetter(Document, 'head');\n\n  // document cannot be overridden so we override a bunch of its methods\n  // directly on the instance.\n\n  function wrapMethod(name) {\n    var original = document[name];\n    Document.prototype[name] = function() {\n      return wrap(original.apply(this.impl, arguments));\n    };\n  }\n\n  [\n    'createComment',\n    'createDocumentFragment',\n    'createElement',\n    'createElementNS',\n    'createEvent',\n    'createEventNS',\n    'createRange',\n    'createTextNode',\n    'getElementById'\n  ].forEach(wrapMethod);\n\n  var originalAdoptNode = document.adoptNode;\n\n  function adoptNodeNoRemove(node, doc) {\n    originalAdoptNode.call(doc.impl, unwrap(node));\n    adoptSubtree(node, doc);\n  }\n\n  function adoptSubtree(node, doc) {\n    if (node.shadowRoot)\n      doc.adoptNode(node.shadowRoot);\n    if (node instanceof ShadowRoot)\n      adoptOlderShadowRoots(node, doc);\n    for (var child = node.firstChild; child; child = child.nextSibling) {\n      adoptSubtree(child, doc);\n    }\n  }\n\n  function adoptOlderShadowRoots(shadowRoot, doc) {\n    var oldShadowRoot = shadowRoot.olderShadowRoot;\n    if (oldShadowRoot)\n      doc.adoptNode(oldShadowRoot);\n  }\n\n  var originalGetSelection = document.getSelection;\n\n  mixin(Document.prototype, {\n    adoptNode: function(node) {\n      if (node.parentNode)\n        node.parentNode.removeChild(node);\n      adoptNodeNoRemove(node, this);\n      return node;\n    },\n    elementFromPoint: function(x, y) {\n      return elementFromPoint(this, this, x, y);\n    },\n    importNode: function(node, deep) {\n      return cloneNode(node, deep, this.impl);\n    },\n    getSelection: function() {\n      renderAllPending();\n      return new Selection(originalGetSelection.call(unwrap(this)));\n    }\n  });\n\n  if (document.registerElement) {\n    var originalRegisterElement = document.registerElement;\n    Document.prototype.registerElement = function(tagName, object) {\n      var prototype = object.prototype;\n\n      // If we already used the object as a prototype for another custom\n      // element.\n      if (scope.nativePrototypeTable.get(prototype)) {\n        // TODO(arv): DOMException\n        throw new Error('NotSupportedError');\n      }\n\n      // Find first object on the prototype chain that already have a native\n      // prototype. Keep track of all the objects before that so we can create\n      // a similar structure for the native case.\n      var proto = Object.getPrototypeOf(prototype);\n      var nativePrototype;\n      var prototypes = [];\n      while (proto) {\n        nativePrototype = scope.nativePrototypeTable.get(proto);\n        if (nativePrototype)\n          break;\n        prototypes.push(proto);\n        proto = Object.getPrototypeOf(proto);\n      }\n\n      if (!nativePrototype) {\n        // TODO(arv): DOMException\n        throw new Error('NotSupportedError');\n      }\n\n      // This works by creating a new prototype object that is empty, but has\n      // the native prototype as its proto. The original prototype object\n      // passed into register is used as the wrapper prototype.\n\n      var newPrototype = Object.create(nativePrototype);\n      for (var i = prototypes.length - 1; i >= 0; i--) {\n        newPrototype = Object.create(newPrototype);\n      }\n\n      // Add callbacks if present.\n      // Names are taken from:\n      //   https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.cpp&sq=package:chromium&type=cs&l=156\n      // and not from the spec since the spec is out of date.\n      [\n        'createdCallback',\n        'attachedCallback',\n        'detachedCallback',\n        'attributeChangedCallback',\n      ].forEach(function(name) {\n        var f = prototype[name];\n        if (!f)\n          return;\n        newPrototype[name] = function() {\n          // if this element has been wrapped prior to registration,\n          // the wrapper is stale; in this case rewrap\n          if (!(wrap(this) instanceof CustomElementConstructor)) {\n            rewrap(this);\n          }\n          f.apply(wrap(this), arguments);\n        };\n      });\n\n      var p = {prototype: newPrototype};\n      if (object.extends)\n        p.extends = object.extends;\n\n      function CustomElementConstructor(node) {\n        if (!node) {\n          if (object.extends) {\n            return document.createElement(object.extends, tagName);\n          } else {\n            return document.createElement(tagName);\n          }\n        }\n        this.impl = node;\n      }\n      CustomElementConstructor.prototype = prototype;\n      CustomElementConstructor.prototype.constructor = CustomElementConstructor;\n\n      scope.constructorTable.set(newPrototype, CustomElementConstructor);\n      scope.nativePrototypeTable.set(prototype, newPrototype);\n\n      // registration is synchronous so do it last\n      var nativeConstructor = originalRegisterElement.call(unwrap(this),\n          tagName, p);\n      return CustomElementConstructor;\n    };\n\n    forwardMethodsToWrapper([\n      window.HTMLDocument || window.Document,  // Gecko adds these to HTMLDocument\n    ], [\n      'registerElement',\n    ]);\n  }\n\n  // We also override some of the methods on document.body and document.head\n  // for convenience.\n  forwardMethodsToWrapper([\n    window.HTMLBodyElement,\n    window.HTMLDocument || window.Document,  // Gecko adds these to HTMLDocument\n    window.HTMLHeadElement,\n    window.HTMLHtmlElement,\n  ], [\n    'appendChild',\n    'compareDocumentPosition',\n    'contains',\n    'getElementsByClassName',\n    'getElementsByTagName',\n    'getElementsByTagNameNS',\n    'insertBefore',\n    'querySelector',\n    'querySelectorAll',\n    'removeChild',\n    'replaceChild',\n  ].concat(matchesNames));\n\n  forwardMethodsToWrapper([\n    window.HTMLDocument || window.Document,  // Gecko adds these to HTMLDocument\n  ], [\n    'adoptNode',\n    'importNode',\n    'contains',\n    'createComment',\n    'createDocumentFragment',\n    'createElement',\n    'createElementNS',\n    'createEvent',\n    'createEventNS',\n    'createRange',\n    'createTextNode',\n    'elementFromPoint',\n    'getElementById',\n    'getSelection',\n  ]);\n\n  mixin(Document.prototype, GetElementsByInterface);\n  mixin(Document.prototype, ParentNodeInterface);\n  mixin(Document.prototype, SelectorsInterface);\n\n  mixin(Document.prototype, {\n    get implementation() {\n      var implementation = implementationTable.get(this);\n      if (implementation)\n        return implementation;\n      implementation =\n          new DOMImplementation(unwrap(this).implementation);\n      implementationTable.set(this, implementation);\n      return implementation;\n    }\n  });\n\n  registerWrapper(window.Document, Document,\n      document.implementation.createHTMLDocument(''));\n\n  // Both WebKit and Gecko uses HTMLDocument for document. HTML5/DOM only has\n  // one Document interface and IE implements the standard correctly.\n  if (window.HTMLDocument)\n    registerWrapper(window.HTMLDocument, Document);\n\n  wrapEventTargetMethods([\n    window.HTMLBodyElement,\n    window.HTMLDocument || window.Document,  // Gecko adds these to HTMLDocument\n    window.HTMLHeadElement,\n  ]);\n\n  function DOMImplementation(impl) {\n    this.impl = impl;\n  }\n\n  function wrapImplMethod(constructor, name) {\n    var original = document.implementation[name];\n    constructor.prototype[name] = function() {\n      return wrap(original.apply(this.impl, arguments));\n    };\n  }\n\n  function forwardImplMethod(constructor, name) {\n    var original = document.implementation[name];\n    constructor.prototype[name] = function() {\n      return original.apply(this.impl, arguments);\n    };\n  }\n\n  wrapImplMethod(DOMImplementation, 'createDocumentType');\n  wrapImplMethod(DOMImplementation, 'createDocument');\n  wrapImplMethod(DOMImplementation, 'createHTMLDocument');\n  forwardImplMethod(DOMImplementation, 'hasFeature');\n\n  registerWrapper(window.DOMImplementation, DOMImplementation);\n\n  forwardMethodsToWrapper([\n    window.DOMImplementation,\n  ], [\n    'createDocumentType',\n    'createDocument',\n    'createHTMLDocument',\n    'hasFeature',\n  ]);\n\n  scope.adoptNodeNoRemove = adoptNodeNoRemove;\n  scope.wrappers.DOMImplementation = DOMImplementation;\n  scope.wrappers.Document = Document;\n\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var EventTarget = scope.wrappers.EventTarget;\n  var Selection = scope.wrappers.Selection;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var renderAllPending = scope.renderAllPending;\n  var unwrap = scope.unwrap;\n  var unwrapIfNeeded = scope.unwrapIfNeeded;\n  var wrap = scope.wrap;\n\n  var OriginalWindow = window.Window;\n  var originalGetComputedStyle = window.getComputedStyle;\n  var originalGetSelection = window.getSelection;\n\n  function Window(impl) {\n    EventTarget.call(this, impl);\n  }\n  Window.prototype = Object.create(EventTarget.prototype);\n\n  OriginalWindow.prototype.getComputedStyle = function(el, pseudo) {\n    return wrap(this || window).getComputedStyle(unwrapIfNeeded(el), pseudo);\n  };\n\n  OriginalWindow.prototype.getSelection = function() {\n    return wrap(this || window).getSelection();\n  };\n\n  // Work around for https://bugzilla.mozilla.org/show_bug.cgi?id=943065\n  delete window.getComputedStyle;\n  delete window.getSelection;\n\n  ['addEventListener', 'removeEventListener', 'dispatchEvent'].forEach(\n      function(name) {\n        OriginalWindow.prototype[name] = function() {\n          var w = wrap(this || window);\n          return w[name].apply(w, arguments);\n        };\n\n        // Work around for https://bugzilla.mozilla.org/show_bug.cgi?id=943065\n        delete window[name];\n      });\n\n  mixin(Window.prototype, {\n    getComputedStyle: function(el, pseudo) {\n      renderAllPending();\n      return originalGetComputedStyle.call(unwrap(this), unwrapIfNeeded(el),\n                                           pseudo);\n    },\n    getSelection: function() {\n      renderAllPending();\n      return new Selection(originalGetSelection.call(unwrap(this)));\n    },\n  });\n\n  registerWrapper(OriginalWindow, Window);\n\n  scope.wrappers.Window = Window;\n\n})(window.ShadowDOMPolyfill);\n",
+    "// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var isWrapperFor = scope.isWrapperFor;\n\n  // This is a list of the elements we currently override the global constructor\n  // for.\n  var elements = {\n    'a': 'HTMLAnchorElement',\n\n    // Do not create an applet element by default since it shows a warning in\n    // IE.\n    // https://github.com/Polymer/polymer/issues/217\n    // 'applet': 'HTMLAppletElement',\n\n    'area': 'HTMLAreaElement',\n    'br': 'HTMLBRElement',\n    'base': 'HTMLBaseElement',\n    'body': 'HTMLBodyElement',\n    'button': 'HTMLButtonElement',\n    // 'command': 'HTMLCommandElement',  // Not fully implemented in Gecko.\n    'dl': 'HTMLDListElement',\n    'datalist': 'HTMLDataListElement',\n    'data': 'HTMLDataElement',\n    'dir': 'HTMLDirectoryElement',\n    'div': 'HTMLDivElement',\n    'embed': 'HTMLEmbedElement',\n    'fieldset': 'HTMLFieldSetElement',\n    'font': 'HTMLFontElement',\n    'form': 'HTMLFormElement',\n    'frame': 'HTMLFrameElement',\n    'frameset': 'HTMLFrameSetElement',\n    'hr': 'HTMLHRElement',\n    'head': 'HTMLHeadElement',\n    'h1': 'HTMLHeadingElement',\n    'html': 'HTMLHtmlElement',\n    'iframe': 'HTMLIFrameElement',\n    'input': 'HTMLInputElement',\n    'li': 'HTMLLIElement',\n    'label': 'HTMLLabelElement',\n    'legend': 'HTMLLegendElement',\n    'link': 'HTMLLinkElement',\n    'map': 'HTMLMapElement',\n    'marquee': 'HTMLMarqueeElement',\n    'menu': 'HTMLMenuElement',\n    'menuitem': 'HTMLMenuItemElement',\n    'meta': 'HTMLMetaElement',\n    'meter': 'HTMLMeterElement',\n    'del': 'HTMLModElement',\n    'ol': 'HTMLOListElement',\n    'object': 'HTMLObjectElement',\n    'optgroup': 'HTMLOptGroupElement',\n    'option': 'HTMLOptionElement',\n    'output': 'HTMLOutputElement',\n    'p': 'HTMLParagraphElement',\n    'param': 'HTMLParamElement',\n    'pre': 'HTMLPreElement',\n    'progress': 'HTMLProgressElement',\n    'q': 'HTMLQuoteElement',\n    'script': 'HTMLScriptElement',\n    'select': 'HTMLSelectElement',\n    'source': 'HTMLSourceElement',\n    'span': 'HTMLSpanElement',\n    'style': 'HTMLStyleElement',\n    'time': 'HTMLTimeElement',\n    'caption': 'HTMLTableCaptionElement',\n    // WebKit and Moz are wrong:\n    // https://bugs.webkit.org/show_bug.cgi?id=111469\n    // https://bugzilla.mozilla.org/show_bug.cgi?id=848096\n    // 'td': 'HTMLTableCellElement',\n    'col': 'HTMLTableColElement',\n    'table': 'HTMLTableElement',\n    'tr': 'HTMLTableRowElement',\n    'thead': 'HTMLTableSectionElement',\n    'tbody': 'HTMLTableSectionElement',\n    'textarea': 'HTMLTextAreaElement',\n    'track': 'HTMLTrackElement',\n    'title': 'HTMLTitleElement',\n    'ul': 'HTMLUListElement',\n    'video': 'HTMLVideoElement',\n  };\n\n  function overrideConstructor(tagName) {\n    var nativeConstructorName = elements[tagName];\n    var nativeConstructor = window[nativeConstructorName];\n    if (!nativeConstructor)\n      return;\n    var element = document.createElement(tagName);\n    var wrapperConstructor = element.constructor;\n    window[nativeConstructorName] = wrapperConstructor;\n  }\n\n  Object.keys(elements).forEach(overrideConstructor);\n\n  Object.getOwnPropertyNames(scope.wrappers).forEach(function(name) {\n    window[name] = scope.wrappers[name]\n  });\n\n  // Export for testing.\n  scope.knownElements = elements;\n\n})(window.ShadowDOMPolyfill);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function() {\n\n  // convenient global\n  window.wrap = ShadowDOMPolyfill.wrapIfNeeded;\n  window.unwrap = ShadowDOMPolyfill.unwrapIfNeeded;\n\n  // users may want to customize other types\n  // TODO(sjmiles): 'button' is now supported by ShadowDOMPolyfill, but\n  // I've left this code here in case we need to temporarily patch another\n  // type\n  /*\n  (function() {\n    var elts = {HTMLButtonElement: 'button'};\n    for (var c in elts) {\n      window[c] = function() { throw 'Patched Constructor'; };\n      window[c].prototype = Object.getPrototypeOf(\n          document.createElement(elts[c]));\n    }\n  })();\n  */\n\n  // patch in prefixed name\n  Object.defineProperty(Element.prototype, 'webkitShadowRoot',\n      Object.getOwnPropertyDescriptor(Element.prototype, 'shadowRoot'));\n\n  var originalCreateShadowRoot = Element.prototype.createShadowRoot;\n  Element.prototype.createShadowRoot = function() {\n    var root = originalCreateShadowRoot.call(this);\n    CustomElements.watchShadow(this);\n    return root;\n  };\n\n  Element.prototype.webkitCreateShadowRoot = Element.prototype.createShadowRoot;\n})();\n",
+    "/*\n * Copyright 2012 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/*\n  This is a limited shim for ShadowDOM css styling.\n  https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#styles\n  \n  The intention here is to support only the styling features which can be \n  relatively simply implemented. The goal is to allow users to avoid the \n  most obvious pitfalls and do so without compromising performance significantly. \n  For ShadowDOM styling that's not covered here, a set of best practices\n  can be provided that should allow users to accomplish more complex styling.\n\n  The following is a list of specific ShadowDOM styling features and a brief\n  discussion of the approach used to shim.\n\n  Shimmed features:\n\n  * :host, :ancestor: ShadowDOM allows styling of the shadowRoot's host\n  element using the :host rule. To shim this feature, the :host styles are \n  reformatted and prefixed with a given scope name and promoted to a \n  document level stylesheet.\n  For example, given a scope name of .foo, a rule like this:\n  \n    :host {\n        background: red;\n      }\n    }\n  \n  becomes:\n  \n    .foo {\n      background: red;\n    }\n  \n  * encapsultion: Styles defined within ShadowDOM, apply only to \n  dom inside the ShadowDOM. Polymer uses one of two techniques to imlement\n  this feature.\n  \n  By default, rules are prefixed with the host element tag name \n  as a descendant selector. This ensures styling does not leak out of the 'top'\n  of the element's ShadowDOM. For example,\n\n  div {\n      font-weight: bold;\n    }\n  \n  becomes:\n\n  x-foo div {\n      font-weight: bold;\n    }\n  \n  becomes:\n\n\n  Alternatively, if Platform.ShadowCSS.strictStyling is set to true then \n  selectors are scoped by adding an attribute selector suffix to each\n  simple selector that contains the host element tag name. Each element \n  in the element's ShadowDOM template is also given the scope attribute. \n  Thus, these rules match only elements that have the scope attribute.\n  For example, given a scope name of x-foo, a rule like this:\n  \n    div {\n      font-weight: bold;\n    }\n  \n  becomes:\n  \n    div[x-foo] {\n      font-weight: bold;\n    }\n\n  Note that elements that are dynamically added to a scope must have the scope\n  selector added to them manually.\n\n  * upper/lower bound encapsulation: Styles which are defined outside a\n  shadowRoot should not cross the ShadowDOM boundary and should not apply\n  inside a shadowRoot.\n\n  This styling behavior is not emulated. Some possible ways to do this that \n  were rejected due to complexity and/or performance concerns include: (1) reset\n  every possible property for every possible selector for a given scope name;\n  (2) re-implement css in javascript.\n  \n  As an alternative, users should make sure to use selectors\n  specific to the scope in which they are working.\n  \n  * ::distributed: This behavior is not emulated. It's often not necessary\n  to style the contents of a specific insertion point and instead, descendants\n  of the host element can be styled selectively. Users can also create an \n  extra node around an insertion point and style that node's contents\n  via descendent selectors. For example, with a shadowRoot like this:\n  \n    <style>\n      ::content(div) {\n        background: red;\n      }\n    </style>\n    <content></content>\n  \n  could become:\n  \n    <style>\n      / *@polyfill .content-container div * / \n      ::content(div) {\n        background: red;\n      }\n    </style>\n    <div class=\"content-container\">\n      <content></content>\n    </div>\n  \n  Note the use of @polyfill in the comment above a ShadowDOM specific style\n  declaration. This is a directive to the styling shim to use the selector \n  in comments in lieu of the next selector when running under polyfill.\n*/\n(function(scope) {\n\nvar ShadowCSS = {\n  strictStyling: false,\n  registry: {},\n  // Shim styles for a given root associated with a name and extendsName\n  // 1. cache root styles by name\n  // 2. optionally tag root nodes with scope name\n  // 3. shim polyfill directives /* @polyfill */ and /* @polyfill-rule */\n  // 4. shim :host and scoping\n  shimStyling: function(root, name, extendsName) {\n    var typeExtension = this.isTypeExtension(extendsName);\n    // use caching to make working with styles nodes easier and to facilitate\n    // lookup of extendee\n    var def = this.registerDefinition(root, name, extendsName);\n    // find styles and apply shimming...\n    if (this.strictStyling) {\n      this.applyScopeToContent(root, name);\n    }\n    var cssText = this.stylesToShimmedCssText(def.rootStyles, def.scopeStyles,\n        name, typeExtension);\n    // provide shimmedStyle for user extensibility\n    def.shimmedStyle = cssTextToStyle(cssText);\n    if (root) {\n      root.shimmedStyle = def.shimmedStyle;\n    }\n    // remove existing style elements\n    for (var i=0, l=def.rootStyles.length, s; (i<l) && (s=def.rootStyles[i]); \n        i++) {\n      s.parentNode.removeChild(s);\n    }\n    // add style to document\n    addCssToDocument(cssText);\n  },\n  // apply @polyfill rules + :host and scope shimming\n  stylesToShimmedCssText: function(rootStyles, scopeStyles, name,\n      typeExtension) {\n    name = name || '';\n    // insert @polyfill and @polyfill-rule rules into style elements\n    // scoping process takes care of shimming these\n    this.insertPolyfillDirectives(rootStyles);\n    this.insertPolyfillRules(rootStyles);\n    var cssText = this.shimScoping(scopeStyles, name, typeExtension);\n    // note: we only need to do rootStyles since these are unscoped.\n    cssText += this.extractPolyfillUnscopedRules(rootStyles);\n    return cssText.trim();\n  },\n  registerDefinition: function(root, name, extendsName) {\n    var def = this.registry[name] = {\n      root: root,\n      name: name,\n      extendsName: extendsName\n    }\n    var styles = root ? root.querySelectorAll('style') : [];\n    styles = styles ? Array.prototype.slice.call(styles, 0) : [];\n    def.rootStyles = styles;\n    def.scopeStyles = def.rootStyles;\n    var extendee = this.registry[def.extendsName];\n    if (extendee && (!root || root.querySelector('shadow'))) {\n      def.scopeStyles = extendee.scopeStyles.concat(def.scopeStyles);\n    }\n    return def;\n  },\n  isTypeExtension: function(extendsName) {\n    return extendsName && extendsName.indexOf('-') < 0;\n  },\n  applyScopeToContent: function(root, name) {\n    if (root) {\n      // add the name attribute to each node in root.\n      Array.prototype.forEach.call(root.querySelectorAll('*'),\n          function(node) {\n            node.setAttribute(name, '');\n          });\n      // and template contents too\n      Array.prototype.forEach.call(root.querySelectorAll('template'),\n          function(template) {\n            this.applyScopeToContent(template.content, name);\n          },\n          this);\n    }\n  },\n  /*\n   * Process styles to convert native ShadowDOM rules that will trip\n   * up the css parser; we rely on decorating the stylesheet with comments.\n   * \n   * For example, we convert this rule:\n   * \n   * (comment start) @polyfill :host menu-item (comment end)\n   * shadow::-webkit-distributed(menu-item) {\n   * \n   * to this:\n   * \n   * scopeName menu-item {\n   *\n  **/\n  insertPolyfillDirectives: function(styles) {\n    if (styles) {\n      Array.prototype.forEach.call(styles, function(s) {\n        s.textContent = this.insertPolyfillDirectivesInCssText(s.textContent);\n      }, this);\n    }\n  },\n  insertPolyfillDirectivesInCssText: function(cssText) {\n    return cssText.replace(cssPolyfillCommentRe, function(match, p1) {\n      // remove end comment delimiter and add block start\n      return p1.slice(0, -2) + '{';\n    });\n  },\n  /*\n   * Process styles to add rules which will only apply under the polyfill\n   * \n   * For example, we convert this rule:\n   * \n   * (comment start) @polyfill-rule :host menu-item { \n   * ... } (comment end)\n   * \n   * to this:\n   * \n   * scopeName menu-item {...}\n   *\n  **/\n  insertPolyfillRules: function(styles) {\n    if (styles) {\n      Array.prototype.forEach.call(styles, function(s) {\n        s.textContent = this.insertPolyfillRulesInCssText(s.textContent);\n      }, this);\n    }\n  },\n  insertPolyfillRulesInCssText: function(cssText) {\n    return cssText.replace(cssPolyfillRuleCommentRe, function(match, p1) {\n      // remove end comment delimiter\n      return p1.slice(0, -1);\n    });\n  },\n  /*\n   * Process styles to add rules which will only apply under the polyfill\n   * and do not process via CSSOM. (CSSOM is destructive to rules on rare \n   * occasions, e.g. -webkit-calc on Safari.)\n   * For example, we convert this rule:\n   * \n   * (comment start) @polyfill-unscoped-rule menu-item { \n   * ... } (comment end)\n   * \n   * to this:\n   * \n   * menu-item {...}\n   *\n  **/\n  extractPolyfillUnscopedRules: function(styles) {\n    var cssText = '';\n    if (styles) {\n      Array.prototype.forEach.call(styles, function(s) {\n        cssText += this.extractPolyfillUnscopedRulesFromCssText(\n            s.textContent) + '\\n\\n';\n      }, this);\n    }\n    return cssText;\n  },\n  extractPolyfillUnscopedRulesFromCssText: function(cssText) {\n    var r = '', matches;\n    while (matches = cssPolyfillUnscopedRuleCommentRe.exec(cssText)) {\n      r += matches[1].slice(0, -1) + '\\n\\n';\n    }\n    return r;\n  },\n  /* Ensure styles are scoped. Pseudo-scoping takes a rule like:\n   * \n   *  .foo {... } \n   *  \n   *  and converts this to\n   *  \n   *  scopeName .foo { ... }\n  */\n  shimScoping: function(styles, name, typeExtension) {\n    if (styles) {\n      return this.convertScopedStyles(styles, name, typeExtension);\n    }\n  },\n  convertScopedStyles: function(styles, name, typeExtension) {\n    var cssText = stylesToCssText(styles);\n    cssText = this.insertPolyfillHostInCssText(cssText);\n    cssText = this.convertColonHost(cssText);\n    cssText = this.convertColonAncestor(cssText);\n    cssText = this.convertCombinators(cssText);\n    if (name) {\n      var rules = cssToRules(cssText);\n      cssText = this.scopeRules(rules, name, typeExtension);\n    }\n    return cssText;\n  },\n  /*\n   * convert a rule like :host(.foo) > .bar { }\n   *\n   * to\n   *\n   * scopeName.foo > .bar\n  */\n  convertColonHost: function(cssText) {\n    return this.convertColonRule(cssText, cssColonHostRe,\n        this.colonHostPartReplacer);\n  },\n  /*\n   * convert a rule like :ancestor(.foo) > .bar { }\n   *\n   * to\n   *\n   * scopeName.foo > .bar, .foo scopeName > .bar { }\n   * \n   * and\n   *\n   * :ancestor(.foo:host) .bar { ... }\n   * \n   * to\n   * \n   * scopeName.foo .bar { ... }\n  */\n  convertColonAncestor: function(cssText) {\n    return this.convertColonRule(cssText, cssColonAncestorRe,\n        this.colonAncestorPartReplacer);\n  },\n  convertColonRule: function(cssText, regExp, partReplacer) {\n    // p1 = :host, p2 = contents of (), p3 rest of rule\n    return cssText.replace(regExp, function(m, p1, p2, p3) {\n      p1 = polyfillHostNoCombinator;\n      if (p2) {\n        var parts = p2.split(','), r = [];\n        for (var i=0, l=parts.length, p; (i<l) && (p=parts[i]); i++) {\n          p = p.trim();\n          r.push(partReplacer(p1, p, p3));\n        }\n        return r.join(',');\n      } else {\n        return p1 + p3;\n      }\n    });\n  },\n  colonAncestorPartReplacer: function(host, part, suffix) {\n    if (part.match(polyfillHost)) {\n      return this.colonHostPartReplacer(host, part, suffix);\n    } else {\n      return host + part + suffix + ', ' + part + ' ' + host + suffix;\n    }\n  },\n  colonHostPartReplacer: function(host, part, suffix) {\n    return host + part.replace(polyfillHost, '') + suffix;\n  },\n  /*\n   * Convert ^ and ^^ combinators by replacing with space.\n  */\n  convertCombinators: function(cssText) {\n    return cssText.replace(/\\^\\^/g, ' ').replace(/\\^/g, ' ');\n  },\n  // change a selector like 'div' to 'name div'\n  scopeRules: function(cssRules, name, typeExtension) {\n    var cssText = '';\n    Array.prototype.forEach.call(cssRules, function(rule) {\n      if (rule.selectorText && (rule.style && rule.style.cssText)) {\n        cssText += this.scopeSelector(rule.selectorText, name, typeExtension, \n          this.strictStyling) + ' {\\n\\t';\n        cssText += this.propertiesFromRule(rule) + '\\n}\\n\\n';\n      } else if (rule.media) {\n        cssText += '@media ' + rule.media.mediaText + ' {\\n';\n        cssText += this.scopeRules(rule.cssRules, name, typeExtension);\n        cssText += '\\n}\\n\\n';\n      } else if (rule.cssText) {\n        cssText += rule.cssText + '\\n\\n';\n      }\n    }, this);\n    return cssText;\n  },\n  scopeSelector: function(selector, name, typeExtension, strict) {\n    var r = [], parts = selector.split(',');\n    parts.forEach(function(p) {\n      p = p.trim();\n      if (this.selectorNeedsScoping(p, name, typeExtension)) {\n        p = (strict && !p.match(polyfillHostNoCombinator)) ? \n            this.applyStrictSelectorScope(p, name) :\n            this.applySimpleSelectorScope(p, name, typeExtension);\n      }\n      r.push(p);\n    }, this);\n    return r.join(', ');\n  },\n  selectorNeedsScoping: function(selector, name, typeExtension) {\n    var re = this.makeScopeMatcher(name, typeExtension);\n    return !selector.match(re);\n  },\n  makeScopeMatcher: function(name, typeExtension) {\n    var matchScope = typeExtension ? '\\\\[is=[\\'\"]?' + name + '[\\'\"]?\\\\]' : name;\n    return new RegExp('^(' + matchScope + ')' + selectorReSuffix, 'm');\n  },\n  // scope via name and [is=name]\n  applySimpleSelectorScope: function(selector, name, typeExtension) {\n    var scoper = typeExtension ? '[is=' + name + ']' : name;\n    if (selector.match(polyfillHostRe)) {\n      selector = selector.replace(polyfillHostNoCombinator, scoper);\n      return selector.replace(polyfillHostRe, scoper + ' ');\n    } else {\n      return scoper + ' ' + selector;\n    }\n  },\n  // return a selector with [name] suffix on each simple selector\n  // e.g. .foo.bar > .zot becomes .foo[name].bar[name] > .zot[name]\n  applyStrictSelectorScope: function(selector, name) {\n    var splits = [' ', '>', '+', '~'],\n      scoped = selector,\n      attrName = '[' + name + ']';\n    splits.forEach(function(sep) {\n      var parts = scoped.split(sep);\n      scoped = parts.map(function(p) {\n        // remove :host since it should be unnecessary\n        var t = p.trim().replace(polyfillHostRe, '');\n        if (t && (splits.indexOf(t) < 0) && (t.indexOf(attrName) < 0)) {\n          p = t.replace(/([^:]*)(:*)(.*)/, '$1' + attrName + '$2$3')\n        }\n        return p;\n      }).join(sep);\n    });\n    return scoped;\n  },\n  insertPolyfillHostInCssText: function(selector) {\n    return selector.replace(hostRe, polyfillHost).replace(colonHostRe,\n        polyfillHost).replace(colonAncestorRe, polyfillAncestor);\n  },\n  propertiesFromRule: function(rule) {\n    // TODO(sorvell): Safari cssom incorrectly removes quotes from the content\n    // property. (https://bugs.webkit.org/show_bug.cgi?id=118045)\n    if (rule.style.content && !rule.style.content.match(/['\"]+/)) {\n      return rule.style.cssText.replace(/content:[^;]*;/g, 'content: \\'' + \n          rule.style.content + '\\';');\n    }\n    return rule.style.cssText;\n  }\n};\n\nvar selectorRe = /([^{]*)({[\\s\\S]*?})/gim,\n    cssCommentRe = /\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\//gim,\n    cssPolyfillCommentRe = /\\/\\*\\s*@polyfill ([^*]*\\*+([^/*][^*]*\\*+)*\\/)([^{]*?){/gim,\n    cssPolyfillRuleCommentRe = /\\/\\*\\s@polyfill-rule([^*]*\\*+([^/*][^*]*\\*+)*)\\//gim,\n    cssPolyfillUnscopedRuleCommentRe = /\\/\\*\\s@polyfill-unscoped-rule([^*]*\\*+([^/*][^*]*\\*+)*)\\//gim,\n    cssPseudoRe = /::(x-[^\\s{,(]*)/gim,\n    cssPartRe = /::part\\(([^)]*)\\)/gim,\n    // note: :host pre-processed to -shadowcsshost.\n    polyfillHost = '-shadowcsshost',\n    // note: :ancestor pre-processed to -shadowcssancestor.\n    polyfillAncestor = '-shadowcssancestor',\n    parenSuffix = ')(?:\\\\((' +\n        '(?:\\\\([^)(]*\\\\)|[^)(]*)+?' +\n        ')\\\\))?([^,{]*)';\n    cssColonHostRe = new RegExp('(' + polyfillHost + parenSuffix, 'gim'),\n    cssColonAncestorRe = new RegExp('(' + polyfillAncestor + parenSuffix, 'gim'),\n    selectorReSuffix = '([>\\\\s~+\\[.,{:][\\\\s\\\\S]*)?$',\n    hostRe = /@host/gim,\n    colonHostRe = /\\:host/gim,\n    colonAncestorRe = /\\:ancestor/gim,\n    /* host name without combinator */\n    polyfillHostNoCombinator = polyfillHost + '-no-combinator',\n    polyfillHostRe = new RegExp(polyfillHost, 'gim');\n    polyfillAncestorRe = new RegExp(polyfillAncestor, 'gim');\n\nfunction stylesToCssText(styles, preserveComments) {\n  var cssText = '';\n  Array.prototype.forEach.call(styles, function(s) {\n    cssText += s.textContent + '\\n\\n';\n  });\n  // strip comments for easier processing\n  if (!preserveComments) {\n    cssText = cssText.replace(cssCommentRe, '');\n  }\n  return cssText;\n}\n\nfunction cssTextToStyle(cssText) {\n  var style = document.createElement('style');\n  style.textContent = cssText;\n  return style;\n}\n\nfunction cssToRules(cssText) {\n  var style = cssTextToStyle(cssText);\n  document.head.appendChild(style);\n  var rules = style.sheet.cssRules;\n  style.parentNode.removeChild(style);\n  return rules;\n}\n\nfunction rulesToCss(cssRules) {\n  for (var i=0, css=[]; i < cssRules.length; i++) {\n    css.push(cssRules[i].cssText);\n  }\n  return css.join('\\n\\n');\n}\n\nfunction addCssToDocument(cssText) {\n  if (cssText) {\n    getSheet().appendChild(document.createTextNode(cssText));\n  }\n}\n\nvar SHIM_ATTRIBUTE = 'shim-shadowdom';\nvar SHIMMED_ATTRIBUTE = 'shim-shadowdom-css';\n\nvar sheet;\nfunction getSheet() {\n  if (!sheet) {\n    sheet = document.createElement(\"style\");\n    sheet.setAttribute(SHIMMED_ATTRIBUTE, '');\n    sheet[SHIMMED_ATTRIBUTE] = true;\n  }\n  return sheet;\n}\n\n// add polyfill stylesheet to document\nif (window.ShadowDOMPolyfill) {\n  addCssToDocument('style { display: none !important; }\\n');\n  var doc = wrap(document);\n  var head = doc.querySelector('head');\n  head.insertBefore(getSheet(), head.childNodes[0]);\n\n  // TODO(sorvell): monkey-patching HTMLImports is abusive;\n  // consider a better solution.\n  document.addEventListener('DOMContentLoaded', function() {\n    var urlResolver = scope.urlResolver;\n    \n    if (window.HTMLImports && !HTMLImports.useNative) {\n      var SHIM_SHEET_SELECTOR = 'link[rel=stylesheet]' +\n          '[' + SHIM_ATTRIBUTE + ']';\n      var SHIM_STYLE_SELECTOR = 'style[' + SHIM_ATTRIBUTE + ']';\n      HTMLImports.importer.documentPreloadSelectors += ',' + SHIM_SHEET_SELECTOR;\n      HTMLImports.importer.importsPreloadSelectors += ',' + SHIM_SHEET_SELECTOR;\n\n      HTMLImports.parser.documentSelectors = [\n        HTMLImports.parser.documentSelectors,\n        SHIM_SHEET_SELECTOR,\n        SHIM_STYLE_SELECTOR\n      ].join(',');\n  \n      var originalParseGeneric = HTMLImports.parser.parseGeneric;\n\n      HTMLImports.parser.parseGeneric = function(elt) {\n        if (elt[SHIMMED_ATTRIBUTE]) {\n          return;\n        }\n        var style = elt.__importElement || elt;\n        if (!style.hasAttribute(SHIM_ATTRIBUTE)) {\n          originalParseGeneric.call(this, elt);\n          return;\n        }\n        if (elt.__resource) {\n          style = elt.ownerDocument.createElement('style');\n          style.textContent = urlResolver.resolveCssText(\n              elt.__resource, elt.href);\n        } else {\n          urlResolver.resolveStyle(style);  \n        }\n        var styles = [style];\n        style.textContent = ShadowCSS.stylesToShimmedCssText(styles, styles);\n        style.removeAttribute(SHIM_ATTRIBUTE, '');\n        style.setAttribute(SHIMMED_ATTRIBUTE, '');\n        style[SHIMMED_ATTRIBUTE] = true;\n        // place in document\n        if (style.parentNode !== head) {\n          // replace links in head\n          if (elt.parentNode === head) {\n            head.replaceChild(style, elt);\n          } else {\n            head.appendChild(style);\n          }\n        }\n        style.__importParsed = true;\n        this.markParsingComplete(elt);\n      }\n\n      var hasResource = HTMLImports.parser.hasResource;\n      HTMLImports.parser.hasResource = function(node) {\n        if (node.localName === 'link' && node.rel === 'stylesheet' &&\n            node.hasAttribute(SHIM_ATTRIBUTE)) {\n          return (node.__resource);\n        } else {\n          return hasResource.call(this, node);\n        }\n      }\n\n    }\n  });\n}\n\n// exports\nscope.ShadowCSS = ShadowCSS;\n\n})(window.Platform);",
+    "} else {",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function() {\n\n  // poor man's adapter for template.content on various platform scenarios\n  window.templateContent = window.templateContent || function(inTemplate) {\n    return inTemplate.content;\n  };\n\n  // so we can call wrap/unwrap without testing for ShadowDOMPolyfill\n\n  window.wrap = window.unwrap = function(n){\n    return n;\n  }\n\n  var originalCreateShadowRoot = Element.prototype.webkitCreateShadowRoot;\n  Element.prototype.webkitCreateShadowRoot = function() {\n    var elderRoot = this.webkitShadowRoot;\n    var root = originalCreateShadowRoot.call(this);\n    root.olderShadowRoot = elderRoot;\n    root.host = this;\n    CustomElements.watchShadow(this);\n    return root;\n  }\n\n  Object.defineProperties(Element.prototype, {\n    shadowRoot: {\n      get: function() {\n        return this.webkitShadowRoot;\n      }\n    },\n    createShadowRoot: {\n      value: function() {\n        return this.webkitCreateShadowRoot();\n      }\n    }\n  });\n\n  window.templateContent = function(inTemplate) {\n    // if MDV exists, it may need to boostrap this template to reveal content\n    if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) {\n      HTMLTemplateElement.bootstrap(inTemplate);\n    }\n    // fallback when there is no Shadow DOM polyfill, no MDV polyfill, and no\n    // native template support\n    if (!inTemplate.content && !inTemplate._content) {\n      var frag = document.createDocumentFragment();\n      while (inTemplate.firstChild) {\n        frag.appendChild(inTemplate.firstChild);\n      }\n      inTemplate._content = frag;\n    }\n    return inTemplate.content || inTemplate._content;\n  };\n\n})();",
+    "}",
+    "/* Any copyright is dedicated to the Public Domain.\n * http://creativecommons.org/publicdomain/zero/1.0/ */\n\n(function(scope) {\n  'use strict';\n\n  // feature detect for URL constructor\n  var hasWorkingUrl = false;\n  if (!scope.forceJURL) {\n    try {\n      var u = new URL('b', 'http://a');\n      hasWorkingUrl = u.href === 'http://a/b';\n    } catch(e) {}\n  }\n\n  if (hasWorkingUrl)\n    return;\n\n  var relative = Object.create(null);\n  relative['ftp'] = 21;\n  relative['file'] = 0;\n  relative['gopher'] = 70;\n  relative['http'] = 80;\n  relative['https'] = 443;\n  relative['ws'] = 80;\n  relative['wss'] = 443;\n\n  var relativePathDotMapping = Object.create(null);\n  relativePathDotMapping['%2e'] = '.';\n  relativePathDotMapping['.%2e'] = '..';\n  relativePathDotMapping['%2e.'] = '..';\n  relativePathDotMapping['%2e%2e'] = '..';\n\n  function isRelativeScheme(scheme) {\n    return relative[scheme] !== undefined;\n  }\n\n  function invalid() {\n    clear.call(this);\n    this._isInvalid = true;\n  }\n\n  function IDNAToASCII(h) {\n    if ('' == h) {\n      invalid.call(this)\n    }\n    // XXX\n    return h.toLowerCase()\n  }\n\n  function percentEscape(c) {\n    var unicode = c.charCodeAt(0);\n    if (unicode > 0x20 &&\n       unicode < 0x7F &&\n       // \" # < > ? `\n       [0x22, 0x23, 0x3C, 0x3E, 0x3F, 0x60].indexOf(unicode) == -1\n      ) {\n      return c;\n    }\n    return encodeURIComponent(c);\n  }\n\n  function percentEscapeQuery(c) {\n    // XXX This actually needs to encode c using encoding and then\n    // convert the bytes one-by-one.\n\n    var unicode = c.charCodeAt(0);\n    if (unicode > 0x20 &&\n       unicode < 0x7F &&\n       // \" # < > ` (do not escape '?')\n       [0x22, 0x23, 0x3C, 0x3E, 0x60].indexOf(unicode) == -1\n      ) {\n      return c;\n    }\n    return encodeURIComponent(c);\n  }\n\n  var EOF = undefined,\n      ALPHA = /[a-zA-Z]/,\n      ALPHANUMERIC = /[a-zA-Z0-9\\+\\-\\.]/;\n\n  function parse(input, stateOverride, base) {\n    function err(message) {\n      errors.push(message)\n    }\n\n    var state = stateOverride || 'scheme start',\n        cursor = 0,\n        buffer = '',\n        seenAt = false,\n        seenBracket = false,\n        errors = [];\n\n    loop: while ((input[cursor - 1] != EOF || cursor == 0) && !this._isInvalid) {\n      var c = input[cursor];\n      switch (state) {\n        case 'scheme start':\n          if (c && ALPHA.test(c)) {\n            buffer += c.toLowerCase(); // ASCII-safe\n            state = 'scheme';\n          } else if (!stateOverride) {\n            buffer = '';\n            state = 'no scheme';\n            continue;\n          } else {\n            err('Invalid scheme.');\n            break loop;\n          }\n          break;\n\n        case 'scheme':\n          if (c && ALPHANUMERIC.test(c)) {\n            buffer += c.toLowerCase(); // ASCII-safe\n          } else if (':' == c) {\n            this._scheme = buffer;\n            buffer = '';\n            if (stateOverride) {\n              break loop;\n            }\n            if (isRelativeScheme(this._scheme)) {\n              this._isRelative = true;\n            }\n            if ('file' == this._scheme) {\n              state = 'relative';\n            } else if (this._isRelative && base && base._scheme == this._scheme) {\n              state = 'relative or authority';\n            } else if (this._isRelative) {\n              state = 'authority first slash';\n            } else {\n              state = 'scheme data';\n            }\n          } else if (!stateOverride) {\n            buffer = '';\n            cursor = 0;\n            state = 'no scheme';\n            continue;\n          } else if (EOF == c) {\n            break loop;\n          } else {\n            err('Code point not allowed in scheme: ' + c)\n            break loop;\n          }\n          break;\n\n        case 'scheme data':\n          if ('?' == c) {\n            query = '?';\n            state = 'query';\n          } else if ('#' == c) {\n            this._fragment = '#';\n            state = 'fragment';\n          } else {\n            // XXX error handling\n            if (EOF != c && '\\t' != c && '\\n' != c && '\\r' != c) {\n              this._schemeData += percentEscape(c);\n            }\n          }\n          break;\n\n        case 'no scheme':\n          if (!base || !(isRelativeScheme(base._scheme))) {\n            err('Missing scheme.');\n            invalid.call(this);\n          } else {\n            state = 'relative';\n            continue;\n          }\n          break;\n\n        case 'relative or authority':\n          if ('/' == c && '/' == input[cursor+1]) {\n            state = 'authority ignore slashes';\n          } else {\n            err('Expected /, got: ' + c);\n            state = 'relative';\n            continue\n          }\n          break;\n\n        case 'relative':\n          this._isRelative = true;\n          if ('file' != this._scheme)\n            this._scheme = base._scheme;\n          if (EOF == c) {\n            this._host = base._host;\n            this._port = base._port;\n            this._path = base._path.slice();\n            this._query = base._query;\n            break loop;\n          } else if ('/' == c || '\\\\' == c) {\n            if ('\\\\' == c)\n              err('\\\\ is an invalid code point.');\n            state = 'relative slash';\n          } else if ('?' == c) {\n            this._host = base._host;\n            this._port = base._port;\n            this._path = base._path.slice();\n            this._query = '?';\n            state = 'query';\n          } else if ('#' == c) {\n            this._host = base._host;\n            this._port = base._port;\n            this._path = base._path.slice();\n            this._query = base._query;\n            this._fragment = '#';\n            state = 'fragment';\n          } else {\n            var nextC = input[cursor+1]\n            var nextNextC = input[cursor+2]\n            if (\n              'file' != this._scheme || !ALPHA.test(c) ||\n              (nextC != ':' && nextC != '|') ||\n              (EOF != nextNextC && '/' != nextNextC && '\\\\' != nextNextC && '?' != nextNextC && '#' != nextNextC)) {\n              this._host = base._host;\n              this._port = base._port;\n              this._path = base._path.slice();\n              this._path.pop();\n            }\n            state = 'relative path';\n            continue;\n          }\n          break;\n\n        case 'relative slash':\n          if ('/' == c || '\\\\' == c) {\n            if ('\\\\' == c) {\n              err('\\\\ is an invalid code point.');\n            }\n            if ('file' == this._scheme) {\n              state = 'file host';\n            } else {\n              state = 'authority ignore slashes';\n            }\n          } else {\n            if ('file' != this._scheme) {\n              this._host = base._host;\n              this._port = base._port;\n            }\n            state = 'relative path';\n            continue;\n          }\n          break;\n\n        case 'authority first slash':\n          if ('/' == c) {\n            state = 'authority second slash';\n          } else {\n            err(\"Expected '/', got: \" + c);\n            state = 'authority ignore slashes';\n            continue;\n          }\n          break;\n\n        case 'authority second slash':\n          state = 'authority ignore slashes';\n          if ('/' != c) {\n            err(\"Expected '/', got: \" + c);\n            continue;\n          }\n          break;\n\n        case 'authority ignore slashes':\n          if ('/' != c && '\\\\' != c) {\n            state = 'authority';\n            continue;\n          } else {\n            err('Expected authority, got: ' + c);\n          }\n          break;\n\n        case 'authority':\n          if ('@' == c) {\n            if (seenAt) {\n              err('@ already seen.');\n              buffer += '%40';\n            }\n            seenAt = true;\n            for (var i = 0; i < buffer.length; i++) {\n              var cp = buffer[i];\n              if ('\\t' == cp || '\\n' == cp || '\\r' == cp) {\n                err('Invalid whitespace in authority.');\n                continue;\n              }\n              // XXX check URL code points\n              if (':' == cp && null === this._password) {\n                this._password = '';\n                continue;\n              }\n              var tempC = percentEscape(cp);\n              (null !== this._password) ? this._password += tempC : this._username += tempC;\n            }\n            buffer = '';\n          } else if (EOF == c || '/' == c || '\\\\' == c || '?' == c || '#' == c) {\n            cursor -= buffer.length;\n            buffer = '';\n            state = 'host';\n            continue;\n          } else {\n            buffer += c;\n          }\n          break;\n\n        case 'file host':\n          if (EOF == c || '/' == c || '\\\\' == c || '?' == c || '#' == c) {\n            if (buffer.length == 2 && ALPHA.test(buffer[0]) && (buffer[1] == ':' || buffer[1] == '|')) {\n              state = 'relative path';\n            } else if (buffer.length == 0) {\n              state = 'relative path start';\n            } else {\n              this._host = IDNAToASCII.call(this, buffer);\n              buffer = '';\n              state = 'relative path start';\n            }\n            continue;\n          } else if ('\\t' == c || '\\n' == c || '\\r' == c) {\n            err('Invalid whitespace in file host.');\n          } else {\n            buffer += c;\n          }\n          break;\n\n        case 'host':\n        case 'hostname':\n          if (':' == c && !seenBracket) {\n            // XXX host parsing\n            this._host = IDNAToASCII.call(this, buffer);\n            buffer = '';\n            state = 'port';\n            if ('hostname' == stateOverride) {\n              break loop;\n            }\n          } else if (EOF == c || '/' == c || '\\\\' == c || '?' == c || '#' == c) {\n            this._host = IDNAToASCII.call(this, buffer);\n            buffer = '';\n            state = 'relative path start';\n            if (stateOverride) {\n              break loop;\n            }\n            continue;\n          } else if ('\\t' != c && '\\n' != c && '\\r' != c) {\n            if ('[' == c) {\n              seenBracket = true;\n            } else if (']' == c) {\n              seenBracket = false;\n            }\n            buffer += c;\n          } else {\n            err('Invalid code point in host/hostname: ' + c);\n          }\n          break;\n\n        case 'port':\n          if (/[0-9]/.test(c)) {\n            buffer += c;\n          } else if (EOF == c || '/' == c || '\\\\' == c || '?' == c || '#' == c || stateOverride) {\n            if ('' != buffer) {\n              var temp = parseInt(buffer, 10);\n              if (temp != relative[this._scheme]) {\n                this._port = temp + '';\n              }\n              buffer = '';\n            }\n            if (stateOverride) {\n              break loop;\n            }\n            state = 'relative path start';\n            continue;\n          } else if ('\\t' == c || '\\n' == c || '\\r' == c) {\n            err('Invalid code point in port: ' + c);\n          } else {\n            invalid.call(this);\n          }\n          break;\n\n        case 'relative path start':\n          if ('\\\\' == c)\n            err(\"'\\\\' not allowed in path.\");\n          state = 'relative path';\n          if ('/' != c && '\\\\' != c) {\n            continue;\n          }\n          break;\n\n        case 'relative path':\n          if (EOF == c || '/' == c || '\\\\' == c || (!stateOverride && ('?' == c || '#' == c))) {\n            if ('\\\\' == c) {\n              err('\\\\ not allowed in relative path.');\n            }\n            var tmp;\n            if (tmp = relativePathDotMapping[buffer.toLowerCase()]) {\n              buffer = tmp;\n            }\n            if ('..' == buffer) {\n              this._path.pop();\n              if ('/' != c && '\\\\' != c) {\n                this._path.push('');\n              }\n            } else if ('.' == buffer && '/' != c && '\\\\' != c) {\n              this._path.push('');\n            } else if ('.' != buffer) {\n              if ('file' == this._scheme && this._path.length == 0 && buffer.length == 2 && ALPHA.test(buffer[0]) && buffer[1] == '|') {\n                buffer = buffer[0] + ':';\n              }\n              this._path.push(buffer);\n            }\n            buffer = '';\n            if ('?' == c) {\n              this._query = '?';\n              state = 'query';\n            } else if ('#' == c) {\n              this._fragment = '#';\n              state = 'fragment';\n            }\n          } else if ('\\t' != c && '\\n' != c && '\\r' != c) {\n            buffer += percentEscape(c);\n          }\n          break;\n\n        case 'query':\n          if (!stateOverride && '#' == c) {\n            this._fragment = '#';\n            state = 'fragment';\n          } else if (EOF != c && '\\t' != c && '\\n' != c && '\\r' != c) {\n            this._query += percentEscapeQuery(c);\n          }\n          break;\n\n        case 'fragment':\n          if (EOF != c && '\\t' != c && '\\n' != c && '\\r' != c) {\n            this._fragment += c;\n          }\n          break;\n      }\n\n      cursor++;\n    }\n  }\n\n  function clear() {\n    this._scheme = '';\n    this._schemeData = '';\n    this._username = '';\n    this._password = null;\n    this._host = '';\n    this._port = '';\n    this._path = [];\n    this._query = '';\n    this._fragment = '';\n    this._isInvalid = false;\n    this._isRelative = false;\n  }\n\n  // Does not process domain names or IP addresses.\n  // Does not handle encoding for the query parameter.\n  function jURL(url, base /* , encoding */) {\n    if (base !== undefined && !(base instanceof jURL))\n      base = new jURL(String(base));\n\n    this._url = url;\n    clear.call(this);\n\n    var input = url.replace(/^[ \\t\\r\\n\\f]+|[ \\t\\r\\n\\f]+$/g, '');\n    // encoding = encoding || 'utf-8'\n\n    parse.call(this, input, null, base);\n  }\n\n  jURL.prototype = {\n    get href() {\n      if (this._isInvalid)\n        return this._url;\n\n      var authority = '';\n      if ('' != this._username || null != this._password) {\n        authority = this._username +\n            (null != this._password ? ':' + this._password : '') + '@';\n      }\n\n      return this.protocol +\n          (this._isRelative ? '//' + authority + this.host : '') +\n          this.pathname + this._query + this._fragment;\n    },\n    set href(href) {\n      clear.call(this);\n      parse.call(this, href);\n    },\n\n    get protocol() {\n      return this._scheme + ':';\n    },\n    set protocol(protocol) {\n      if (this._isInvalid)\n        return;\n      parse.call(this, protocol + ':', 'scheme start');\n    },\n\n    get host() {\n      return this._isInvalid ? '' : this._port ?\n          this._host + ':' + this._port : this._host;\n    },\n    set host(host) {\n      if (this._isInvalid || !this._isRelative)\n        return;\n      parse.call(this, host, 'host');\n    },\n\n    get hostname() {\n      return this._host;\n    },\n    set hostname(hostname) {\n      if (this._isInvalid || !this._isRelative)\n        return;\n      parse.call(this, hostname, 'hostname');\n    },\n\n    get port() {\n      return this._port;\n    },\n    set port(port) {\n      if (this._isInvalid || !this._isRelative)\n        return;\n      parse.call(this, port, 'port');\n    },\n\n    get pathname() {\n      return this._isInvalid ? '' : this._isRelative ?\n          '/' + this._path.join('/') : this._schemeData;\n    },\n    set pathname(pathname) {\n      if (this._isInvalid || !this._isRelative)\n        return;\n      this._path = [];\n      parse.call(this, pathname, 'relative path start');\n    },\n\n    get search() {\n      return this._isInvalid || !this._query || '?' == this._query ?\n          '' : this._query;\n    },\n    set search(search) {\n      if (this._isInvalid || !this._isRelative)\n        return;\n      this._query = '?';\n      if ('?' == search[0])\n        search = search.slice(1);\n      parse.call(this, search, 'query');\n    },\n\n    get hash() {\n      return this._isInvalid || !this._fragment || '#' == this._fragment ?\n          '' : this._fragment;\n    },\n    set hash(hash) {\n      if (this._isInvalid)\n        return;\n      this._fragment = '#';\n      if ('#' == hash[0])\n        hash = hash.slice(1);\n      parse.call(this, hash, 'fragment');\n    }\n  };\n\n  scope.URL = jURL;\n\n})(window);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n\n// Old versions of iOS do not have bind.\n\nif (!Function.prototype.bind) {\n  Function.prototype.bind = function(scope) {\n    var self = this;\n    var args = Array.prototype.slice.call(arguments, 1);\n    return function() {\n      var args2 = args.slice();\n      args2.push.apply(args2, arguments);\n      return self.apply(scope, args2);\n    };\n  };\n}\n\n// mixin\n\n// copy all properties from inProps (et al) to inObj\nfunction mixin(inObj/*, inProps, inMoreProps, ...*/) {\n  var obj = inObj || {};\n  for (var i = 1; i < arguments.length; i++) {\n    var p = arguments[i];\n    try {\n      for (var n in p) {\n        copyProperty(n, p, obj);\n      }\n    } catch(x) {\n    }\n  }\n  return obj;\n}\n\n// copy property inName from inSource object to inTarget object\nfunction copyProperty(inName, inSource, inTarget) {\n  var pd = getPropertyDescriptor(inSource, inName);\n  Object.defineProperty(inTarget, inName, pd);\n}\n\n// get property descriptor for inName on inObject, even if\n// inName exists on some link in inObject's prototype chain\nfunction getPropertyDescriptor(inObject, inName) {\n  if (inObject) {\n    var pd = Object.getOwnPropertyDescriptor(inObject, inName);\n    return pd || getPropertyDescriptor(Object.getPrototypeOf(inObject), inName);\n  }\n}\n\n// export\n\nscope.mixin = mixin;\n\n})(window.Platform);",
+    "// Copyright 2011 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n(function(scope) {\n\n  'use strict';\n\n  // polyfill DOMTokenList\n  // * add/remove: allow these methods to take multiple classNames\n  // * toggle: add a 2nd argument which forces the given state rather\n  //  than toggling.\n\n  var add = DOMTokenList.prototype.add;\n  var remove = DOMTokenList.prototype.remove;\n  DOMTokenList.prototype.add = function() {\n    for (var i = 0; i < arguments.length; i++) {\n      add.call(this, arguments[i]);\n    }\n  };\n  DOMTokenList.prototype.remove = function() {\n    for (var i = 0; i < arguments.length; i++) {\n      remove.call(this, arguments[i]);\n    }\n  };\n  DOMTokenList.prototype.toggle = function(name, bool) {\n    if (arguments.length == 1) {\n      bool = !this.contains(name);\n    }\n    bool ? this.add(name) : this.remove(name);\n  };\n  DOMTokenList.prototype.switch = function(oldName, newName) {\n    oldName && this.remove(oldName);\n    newName && this.add(newName);\n  };\n\n  // add array() to NodeList, NamedNodeMap, HTMLCollection\n\n  var ArraySlice = function() {\n    return Array.prototype.slice.call(this);\n  };\n\n  var namedNodeMap = (window.NamedNodeMap || window.MozNamedAttrMap || {});\n\n  NodeList.prototype.array = ArraySlice;\n  namedNodeMap.prototype.array = ArraySlice;\n  HTMLCollection.prototype.array = ArraySlice;\n\n  // polyfill performance.now\n\n  if (!window.performance) {\n    var start = Date.now();\n    // only at millisecond precision\n    window.performance = {now: function(){ return Date.now() - start }};\n  }\n\n  // polyfill for requestAnimationFrame\n\n  if (!window.requestAnimationFrame) {\n    window.requestAnimationFrame = (function() {\n      var nativeRaf = window.webkitRequestAnimationFrame ||\n        window.mozRequestAnimationFrame;\n\n      return nativeRaf ?\n        function(callback) {\n          return nativeRaf(function() {\n            callback(performance.now());\n          });\n        } :\n        function( callback ){\n          return window.setTimeout(callback, 1000 / 60);\n        };\n    })();\n  }\n\n  if (!window.cancelAnimationFrame) {\n    window.cancelAnimationFrame = (function() {\n      return  window.webkitCancelAnimationFrame ||\n        window.mozCancelAnimationFrame ||\n        function(id) {\n          clearTimeout(id);\n        };\n    })();\n  }\n\n  // TODO(sorvell): workaround for bug:\n  // https://code.google.com/p/chromium/issues/detail?id=229142\n  // remove when this bug is addressed\n  // give main document templates a base that allows them to fetch eagerly\n  // resolved paths relative to the main document\n  var template = document.createElement('template');\n  var base = document.createElement('base');\n  base.href = document.baseURI;\n  template.content.ownerDocument.appendChild(base);\n  \n\n  // utility\n\n  function createDOM(inTagOrNode, inHTML, inAttrs) {\n    var dom = typeof inTagOrNode == 'string' ?\n        document.createElement(inTagOrNode) : inTagOrNode.cloneNode(true);\n    dom.innerHTML = inHTML;\n    if (inAttrs) {\n      for (var n in inAttrs) {\n        dom.setAttribute(n, inAttrs[n]);\n      }\n    }\n    return dom;\n  }\n  // Make a stub for Polymer() for polyfill purposes; under the HTMLImports\n  // polyfill, scripts in the main document run before imports. That means\n  // if (1) polymer is imported and (2) Polymer() is called in the main document\n  // in a script after the import, 2 occurs before 1. We correct this here\n  // by specfiically patching Polymer(); this is not necessary under native\n  // HTMLImports.\n  var elementDeclarations = [];\n\n  var polymerStub = function(name, dictionary) {\n    elementDeclarations.push(arguments);\n  }\n  window.Polymer = polymerStub;\n\n  // deliver queued delcarations\n  scope.deliverDeclarations = function() {\n    scope.deliverDeclarations = null;\n    return elementDeclarations;\n  }\n\n  // Once DOMContent has loaded, any main document scripts that depend on\n  // Polymer() should have run. Calling Polymer() now is an error until\n  // polymer is imported.\n  window.addEventListener('DOMContentLoaded', function() {\n    if (window.Polymer === polymerStub) {\n      window.Polymer = function() {\n        console.error('You tried to use polymer without loading it first. To ' +\n          'load polymer, <link rel=\"import\" href=\"' + \n          'components/polymer/polymer.html\">');\n      };\n    }\n  });\n\n  // exports\n  scope.createDOM = createDOM;\n\n})(window.Platform);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n// poor man's adapter for template.content on various platform scenarios\nwindow.templateContent = window.templateContent || function(inTemplate) {\n  return inTemplate.content;\n};",
+    "(function(scope) {\n  \n  scope = scope || (window.Inspector = {});\n  \n  var inspector;\n\n  window.sinspect = function(inNode, inProxy) {\n    if (!inspector) {\n      inspector = window.open('', 'ShadowDOM Inspector', null, true);\n      inspector.document.write(inspectorHTML);\n      //inspector.document.close();\n      inspector.api = {\n        shadowize: shadowize\n      };\n    }\n    inspect(inNode || wrap(document.body), inProxy);\n  };\n\n  var inspectorHTML = [\n    '<!DOCTYPE html>',\n    '<html>',\n    '  <head>',\n    '    <title>ShadowDOM Inspector</title>',\n    '    <style>',\n    '      body {',\n    '      }',\n    '      pre {',\n    '        font: 9pt \"Courier New\", monospace;',\n    '        line-height: 1.5em;',\n    '      }',\n    '      tag {',\n    '        color: purple;',\n    '      }',\n    '      ul {',\n    '         margin: 0;',\n    '         padding: 0;',\n    '         list-style: none;',\n    '      }',\n    '      li {',\n    '         display: inline-block;',\n    '         background-color: #f1f1f1;',\n    '         padding: 4px 6px;',\n    '         border-radius: 4px;',\n    '         margin-right: 4px;',\n    '      }',\n    '    </style>',\n    '  </head>',\n    '  <body>',\n    '    <ul id=\"crumbs\">',\n    '    </ul>',\n    '    <div id=\"tree\"></div>',\n    '  </body>',\n    '</html>'\n  ].join('\\n');\n  \n  var crumbs = [];\n\n  var displayCrumbs = function() {\n    // alias our document\n    var d = inspector.document;\n    // get crumbbar\n    var cb = d.querySelector('#crumbs');\n    // clear crumbs\n    cb.textContent = '';\n    // build new crumbs\n    for (var i=0, c; c=crumbs[i]; i++) {\n      var a = d.createElement('a');\n      a.href = '#';\n      a.textContent = c.localName;\n      a.idx = i;\n      a.onclick = function(event) {\n        var c;\n        while (crumbs.length > this.idx) {\n          c = crumbs.pop();\n        }\n        inspect(c.shadow || c, c);\n        event.preventDefault();\n      };\n      cb.appendChild(d.createElement('li')).appendChild(a);\n    }\n  };\n\n  var inspect = function(inNode, inProxy) {\n    // alias our document\n    var d = inspector.document;\n    // reset list of drillable nodes\n    drillable = [];\n    // memoize our crumb proxy\n    var proxy = inProxy || inNode;\n    crumbs.push(proxy);\n    // update crumbs\n    displayCrumbs();\n    // reflect local tree\n    d.body.querySelector('#tree').innerHTML =\n        '<pre>' + output(inNode, inNode.childNodes) + '</pre>';\n  };\n\n  var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);\n\n  var blacklisted = {STYLE:1, SCRIPT:1, \"#comment\": 1, TEMPLATE: 1};\n  var blacklist = function(inNode) {\n    return blacklisted[inNode.nodeName];\n  };\n\n  var output = function(inNode, inChildNodes, inIndent) {\n    if (blacklist(inNode)) {\n      return '';\n    }\n    var indent = inIndent || '';\n    if (inNode.localName || inNode.nodeType == 11) {\n      var name = inNode.localName || 'shadow-root';\n      //inChildNodes = ShadowDOM.localNodes(inNode);\n      var info = indent + describe(inNode);\n      // if only textNodes\n      // TODO(sjmiles): make correct for ShadowDOM\n      /*if (!inNode.children.length && inNode.localName !== 'content' && inNode.localName !== 'shadow') {\n        info += catTextContent(inChildNodes);\n      } else*/ {\n        // TODO(sjmiles): native <shadow> has no reference to its projection\n        if (name == 'content' /*|| name == 'shadow'*/) {\n          inChildNodes = inNode.getDistributedNodes();\n        }\n        info += '<br/>';\n        var ind = indent + '&nbsp;&nbsp;';\n        forEach(inChildNodes, function(n) {\n          info += output(n, n.childNodes, ind);\n        });\n        info += indent;\n      }\n      if (!({br:1}[name])) {\n        info += '<tag>&lt;/' + name + '&gt;</tag>';\n        info += '<br/>';\n      }\n    } else {\n      var text = inNode.textContent.trim();\n      info = text ? indent + '\"' + text + '\"' + '<br/>' : '';\n    }\n    return info;\n  };\n\n  var catTextContent = function(inChildNodes) {\n    var info = '';\n    forEach(inChildNodes, function(n) {\n      info += n.textContent.trim();\n    });\n    return info;\n  };\n\n  var drillable = [];\n\n  var describe = function(inNode) {\n    var tag = '<tag>' + '&lt;';\n    var name = inNode.localName || 'shadow-root';\n    if (inNode.webkitShadowRoot || inNode.shadowRoot) {\n      tag += ' <button idx=\"' + drillable.length +\n        '\" onclick=\"api.shadowize.call(this)\">' + name + '</button>';\n      drillable.push(inNode);\n    } else {\n      tag += name || 'shadow-root';\n    }\n    if (inNode.attributes) {\n      forEach(inNode.attributes, function(a) {\n        tag += ' ' + a.name + (a.value ? '=\"' + a.value + '\"' : '');\n      });\n    }\n    tag += '&gt;'+ '</tag>';\n    return tag;\n  };\n\n  // remote api\n\n  shadowize = function() {\n    var idx = Number(this.attributes.idx.value);\n    //alert(idx);\n    var node = drillable[idx];\n    if (node) {\n      inspect(node.webkitShadowRoot || node.shadowRoot, node)\n    } else {\n      console.log(\"bad shadowize node\");\n      console.dir(this);\n    }\n  };\n  \n  // export\n  \n  scope.output = output;\n  \n})(window.Inspector);\n\n\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function(scope) {\n\n  // TODO(sorvell): It's desireable to provide a default stylesheet \n  // that's convenient for styling unresolved elements, but\n  // it's cumbersome to have to include this manually in every page.\n  // It would make sense to put inside some HTMLImport but \n  // the HTMLImports polyfill does not allow loading of stylesheets \n  // that block rendering. Therefore this injection is tolerated here.\n\n  var style = document.createElement('style');\n  style.textContent = ''\n      + 'body {'\n      + 'transition: opacity ease-in 0.2s;' \n      + ' } \\n'\n      + 'body[unresolved] {'\n      + 'opacity: 0; display: block; overflow: hidden;' \n      + ' } \\n'\n      ;\n  var head = document.querySelector('head');\n  head.insertBefore(style, head.firstChild);\n\n})(Platform);\n",
+    "(function(scope) {\n\n  function withDependencies(task, depends) {\n    depends = depends || [];\n    if (!depends.map) {\n      depends = [depends];\n    }\n    return task.apply(this, depends.map(marshal));\n  }\n\n  function module(name, dependsOrFactory, moduleFactory) {\n    var module;\n    switch (arguments.length) {\n      case 0:\n        return;\n      case 1:\n        module = null;\n        break;\n      case 2:\n        module = dependsOrFactory.apply(this);\n        break;\n      default:\n        module = withDependencies(moduleFactory, dependsOrFactory);\n        break;\n    }\n    modules[name] = module;\n  };\n\n  function marshal(name) {\n    return modules[name];\n  }\n\n  var modules = {};\n\n  function using(depends, task) {\n    HTMLImports.whenImportsReady(function() {\n      withDependencies(task, depends);\n    });\n  };\n\n  // exports\n\n  scope.marshal = marshal;\n  scope.module = module;\n  scope.using = using;\n\n})(window);",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function(scope) {\n\nvar iterations = 0;\nvar callbacks = [];\nvar twiddle = document.createTextNode('');\n\nfunction endOfMicrotask(callback) {\n  twiddle.textContent = iterations++;\n  callbacks.push(callback);\n}\n\nfunction atEndOfMicrotask() {\n  while (callbacks.length) {\n    callbacks.shift()();\n  }\n}\n\nnew (window.MutationObserver || JsMutationObserver)(atEndOfMicrotask)\n  .observe(twiddle, {characterData: true})\n  ;\n\n// exports\n\nscope.endOfMicrotask = endOfMicrotask;\n\n})(Platform);\n\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n\nvar urlResolver = {\n  resolveDom: function(root, url) {\n    url = url || root.ownerDocument.baseURI;\n    this.resolveAttributes(root, url);\n    this.resolveStyles(root, url);\n    // handle template.content\n    var templates = root.querySelectorAll('template');\n    if (templates) {\n      for (var i = 0, l = templates.length, t; (i < l) && (t = templates[i]); i++) {\n        if (t.content) {\n          this.resolveDom(t.content, url);\n        }\n      }\n    }\n  },\n  resolveStyles: function(root, url) {\n    var styles = root.querySelectorAll('style');\n    if (styles) {\n      for (var i = 0, l = styles.length, s; (i < l) && (s = styles[i]); i++) {\n        this.resolveStyle(s, url);\n      }\n    }\n  },\n  resolveStyle: function(style, url) {\n    url = url || style.ownerDocument.baseURI;\n    style.textContent = this.resolveCssText(style.textContent, url);\n  },\n  resolveCssText: function(cssText, baseUrl) {\n    cssText = replaceUrlsInCssText(cssText, baseUrl, CSS_URL_REGEXP);\n    return replaceUrlsInCssText(cssText, baseUrl, CSS_IMPORT_REGEXP);\n  },\n  resolveAttributes: function(root, url) {\n    if (root.hasAttributes && root.hasAttributes()) {\n      this.resolveElementAttributes(root, url);\n    }\n    // search for attributes that host urls\n    var nodes = root && root.querySelectorAll(URL_ATTRS_SELECTOR);\n    if (nodes) {\n      for (var i = 0, l = nodes.length, n; (i < l) && (n = nodes[i]); i++) {\n        this.resolveElementAttributes(n, url);\n      }\n    }\n  },\n  resolveElementAttributes: function(node, url) {\n    url = url || node.ownerDocument.baseURI;\n    URL_ATTRS.forEach(function(v) {\n      var attr = node.attributes[v];\n      if (attr && attr.value &&\n         (attr.value.search(URL_TEMPLATE_SEARCH) < 0)) {\n        var urlPath = resolveRelativeUrl(url, attr.value);\n        attr.value = urlPath;\n      }\n    });\n  }\n};\n\nvar CSS_URL_REGEXP = /(url\\()([^)]*)(\\))/g;\nvar CSS_IMPORT_REGEXP = /(@import[\\s]+(?!url\\())([^;]*)(;)/g;\nvar URL_ATTRS = ['href', 'src', 'action'];\nvar URL_ATTRS_SELECTOR = '[' + URL_ATTRS.join('],[') + ']';\nvar URL_TEMPLATE_SEARCH = '{{.*}}';\n\nfunction replaceUrlsInCssText(cssText, baseUrl, regexp) {\n  return cssText.replace(regexp, function(m, pre, url, post) {\n    var urlPath = url.replace(/[\"']/g, '');\n    urlPath = resolveRelativeUrl(baseUrl, urlPath);\n    return pre + '\\'' + urlPath + '\\'' + post;\n  });\n}\n\nfunction resolveRelativeUrl(baseUrl, url) {\n  var u = new URL(url, baseUrl);\n  return makeDocumentRelPath(u.href);\n}\n\nfunction makeDocumentRelPath(url) {\n  var root = document.baseURI;\n  var u = new URL(url, root);\n  if (u.host === root.host && u.port === root.port &&\n      u.protocol === root.protocol) {\n    return makeRelPath(root.pathname, u.pathname);\n  } else {\n    return url;\n  }\n}\n\n// make a relative path from source to target\nfunction makeRelPath(source, target) {\n  var s = source.split('/');\n  var t = target.split('/');\n  while (s.length && s[0] === t[0]){\n    s.shift();\n    t.shift();\n  }\n  for (var i = 0, l = s.length - 1; i < l; i++) {\n    t.unshift('..');\n  }\n  return t.join('/');\n}\n\n// exports\nscope.urlResolver = urlResolver;\n\n})(Platform);\n",
+    "/*\n * Copyright 2012 The Polymer Authors. All rights reserved.\n * Use of this source code is goverened by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(global) {\n\n  var registrationsTable = new WeakMap();\n\n  // We use setImmediate or postMessage for our future callback.\n  var setImmediate = window.msSetImmediate;\n\n  // Use post message to emulate setImmediate.\n  if (!setImmediate) {\n    var setImmediateQueue = [];\n    var sentinel = String(Math.random());\n    window.addEventListener('message', function(e) {\n      if (e.data === sentinel) {\n        var queue = setImmediateQueue;\n        setImmediateQueue = [];\n        queue.forEach(function(func) {\n          func();\n        });\n      }\n    });\n    setImmediate = function(func) {\n      setImmediateQueue.push(func);\n      window.postMessage(sentinel, '*');\n    };\n  }\n\n  // This is used to ensure that we never schedule 2 callas to setImmediate\n  var isScheduled = false;\n\n  // Keep track of observers that needs to be notified next time.\n  var scheduledObservers = [];\n\n  /**\n   * Schedules |dispatchCallback| to be called in the future.\n   * @param {MutationObserver} observer\n   */\n  function scheduleCallback(observer) {\n    scheduledObservers.push(observer);\n    if (!isScheduled) {\n      isScheduled = true;\n      setImmediate(dispatchCallbacks);\n    }\n  }\n\n  function wrapIfNeeded(node) {\n    return window.ShadowDOMPolyfill &&\n        window.ShadowDOMPolyfill.wrapIfNeeded(node) ||\n        node;\n  }\n\n  function dispatchCallbacks() {\n    // http://dom.spec.whatwg.org/#mutation-observers\n\n    isScheduled = false; // Used to allow a new setImmediate call above.\n\n    var observers = scheduledObservers;\n    scheduledObservers = [];\n    // Sort observers based on their creation UID (incremental).\n    observers.sort(function(o1, o2) {\n      return o1.uid_ - o2.uid_;\n    });\n\n    var anyNonEmpty = false;\n    observers.forEach(function(observer) {\n\n      // 2.1, 2.2\n      var queue = observer.takeRecords();\n      // 2.3. Remove all transient registered observers whose observer is mo.\n      removeTransientObserversFor(observer);\n\n      // 2.4\n      if (queue.length) {\n        observer.callback_(queue, observer);\n        anyNonEmpty = true;\n      }\n    });\n\n    // 3.\n    if (anyNonEmpty)\n      dispatchCallbacks();\n  }\n\n  function removeTransientObserversFor(observer) {\n    observer.nodes_.forEach(function(node) {\n      var registrations = registrationsTable.get(node);\n      if (!registrations)\n        return;\n      registrations.forEach(function(registration) {\n        if (registration.observer === observer)\n          registration.removeTransientObservers();\n      });\n    });\n  }\n\n  /**\n   * This function is used for the \"For each registered observer observer (with\n   * observer's options as options) in target's list of registered observers,\n   * run these substeps:\" and the \"For each ancestor ancestor of target, and for\n   * each registered observer observer (with options options) in ancestor's list\n   * of registered observers, run these substeps:\" part of the algorithms. The\n   * |options.subtree| is checked to ensure that the callback is called\n   * correctly.\n   *\n   * @param {Node} target\n   * @param {function(MutationObserverInit):MutationRecord} callback\n   */\n  function forEachAncestorAndObserverEnqueueRecord(target, callback) {\n    for (var node = target; node; node = node.parentNode) {\n      var registrations = registrationsTable.get(node);\n\n      if (registrations) {\n        for (var j = 0; j < registrations.length; j++) {\n          var registration = registrations[j];\n          var options = registration.options;\n\n          // Only target ignores subtree.\n          if (node !== target && !options.subtree)\n            continue;\n\n          var record = callback(options);\n          if (record)\n            registration.enqueue(record);\n        }\n      }\n    }\n  }\n\n  var uidCounter = 0;\n\n  /**\n   * The class that maps to the DOM MutationObserver interface.\n   * @param {Function} callback.\n   * @constructor\n   */\n  function JsMutationObserver(callback) {\n    this.callback_ = callback;\n    this.nodes_ = [];\n    this.records_ = [];\n    this.uid_ = ++uidCounter;\n  }\n\n  JsMutationObserver.prototype = {\n    observe: function(target, options) {\n      target = wrapIfNeeded(target);\n\n      // 1.1\n      if (!options.childList && !options.attributes && !options.characterData ||\n\n          // 1.2\n          options.attributeOldValue && !options.attributes ||\n\n          // 1.3\n          options.attributeFilter && options.attributeFilter.length &&\n              !options.attributes ||\n\n          // 1.4\n          options.characterDataOldValue && !options.characterData) {\n\n        throw new SyntaxError();\n      }\n\n      var registrations = registrationsTable.get(target);\n      if (!registrations)\n        registrationsTable.set(target, registrations = []);\n\n      // 2\n      // If target's list of registered observers already includes a registered\n      // observer associated with the context object, replace that registered\n      // observer's options with options.\n      var registration;\n      for (var i = 0; i < registrations.length; i++) {\n        if (registrations[i].observer === this) {\n          registration = registrations[i];\n          registration.removeListeners();\n          registration.options = options;\n          break;\n        }\n      }\n\n      // 3.\n      // Otherwise, add a new registered observer to target's list of registered\n      // observers with the context object as the observer and options as the\n      // options, and add target to context object's list of nodes on which it\n      // is registered.\n      if (!registration) {\n        registration = new Registration(this, target, options);\n        registrations.push(registration);\n        this.nodes_.push(target);\n      }\n\n      registration.addListeners();\n    },\n\n    disconnect: function() {\n      this.nodes_.forEach(function(node) {\n        var registrations = registrationsTable.get(node);\n        for (var i = 0; i < registrations.length; i++) {\n          var registration = registrations[i];\n          if (registration.observer === this) {\n            registration.removeListeners();\n            registrations.splice(i, 1);\n            // Each node can only have one registered observer associated with\n            // this observer.\n            break;\n          }\n        }\n      }, this);\n      this.records_ = [];\n    },\n\n    takeRecords: function() {\n      var copyOfRecords = this.records_;\n      this.records_ = [];\n      return copyOfRecords;\n    }\n  };\n\n  /**\n   * @param {string} type\n   * @param {Node} target\n   * @constructor\n   */\n  function MutationRecord(type, target) {\n    this.type = type;\n    this.target = target;\n    this.addedNodes = [];\n    this.removedNodes = [];\n    this.previousSibling = null;\n    this.nextSibling = null;\n    this.attributeName = null;\n    this.attributeNamespace = null;\n    this.oldValue = null;\n  }\n\n  function copyMutationRecord(original) {\n    var record = new MutationRecord(original.type, original.target);\n    record.addedNodes = original.addedNodes.slice();\n    record.removedNodes = original.removedNodes.slice();\n    record.previousSibling = original.previousSibling;\n    record.nextSibling = original.nextSibling;\n    record.attributeName = original.attributeName;\n    record.attributeNamespace = original.attributeNamespace;\n    record.oldValue = original.oldValue;\n    return record;\n  };\n\n  // We keep track of the two (possibly one) records used in a single mutation.\n  var currentRecord, recordWithOldValue;\n\n  /**\n   * Creates a record without |oldValue| and caches it as |currentRecord| for\n   * later use.\n   * @param {string} oldValue\n   * @return {MutationRecord}\n   */\n  function getRecord(type, target) {\n    return currentRecord = new MutationRecord(type, target);\n  }\n\n  /**\n   * Gets or creates a record with |oldValue| based in the |currentRecord|\n   * @param {string} oldValue\n   * @return {MutationRecord}\n   */\n  function getRecordWithOldValue(oldValue) {\n    if (recordWithOldValue)\n      return recordWithOldValue;\n    recordWithOldValue = copyMutationRecord(currentRecord);\n    recordWithOldValue.oldValue = oldValue;\n    return recordWithOldValue;\n  }\n\n  function clearRecords() {\n    currentRecord = recordWithOldValue = undefined;\n  }\n\n  /**\n   * @param {MutationRecord} record\n   * @return {boolean} Whether the record represents a record from the current\n   * mutation event.\n   */\n  function recordRepresentsCurrentMutation(record) {\n    return record === recordWithOldValue || record === currentRecord;\n  }\n\n  /**\n   * Selects which record, if any, to replace the last record in the queue.\n   * This returns |null| if no record should be replaced.\n   *\n   * @param {MutationRecord} lastRecord\n   * @param {MutationRecord} newRecord\n   * @param {MutationRecord}\n   */\n  function selectRecord(lastRecord, newRecord) {\n    if (lastRecord === newRecord)\n      return lastRecord;\n\n    // Check if the the record we are adding represents the same record. If\n    // so, we keep the one with the oldValue in it.\n    if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord))\n      return recordWithOldValue;\n\n    return null;\n  }\n\n  /**\n   * Class used to represent a registered observer.\n   * @param {MutationObserver} observer\n   * @param {Node} target\n   * @param {MutationObserverInit} options\n   * @constructor\n   */\n  function Registration(observer, target, options) {\n    this.observer = observer;\n    this.target = target;\n    this.options = options;\n    this.transientObservedNodes = [];\n  }\n\n  Registration.prototype = {\n    enqueue: function(record) {\n      var records = this.observer.records_;\n      var length = records.length;\n\n      // There are cases where we replace the last record with the new record.\n      // For example if the record represents the same mutation we need to use\n      // the one with the oldValue. If we get same record (this can happen as we\n      // walk up the tree) we ignore the new record.\n      if (records.length > 0) {\n        var lastRecord = records[length - 1];\n        var recordToReplaceLast = selectRecord(lastRecord, record);\n        if (recordToReplaceLast) {\n          records[length - 1] = recordToReplaceLast;\n          return;\n        }\n      } else {\n        scheduleCallback(this.observer);\n      }\n\n      records[length] = record;\n    },\n\n    addListeners: function() {\n      this.addListeners_(this.target);\n    },\n\n    addListeners_: function(node) {\n      var options = this.options;\n      if (options.attributes)\n        node.addEventListener('DOMAttrModified', this, true);\n\n      if (options.characterData)\n        node.addEventListener('DOMCharacterDataModified', this, true);\n\n      if (options.childList)\n        node.addEventListener('DOMNodeInserted', this, true);\n\n      if (options.childList || options.subtree)\n        node.addEventListener('DOMNodeRemoved', this, true);\n    },\n\n    removeListeners: function() {\n      this.removeListeners_(this.target);\n    },\n\n    removeListeners_: function(node) {\n      var options = this.options;\n      if (options.attributes)\n        node.removeEventListener('DOMAttrModified', this, true);\n\n      if (options.characterData)\n        node.removeEventListener('DOMCharacterDataModified', this, true);\n\n      if (options.childList)\n        node.removeEventListener('DOMNodeInserted', this, true);\n\n      if (options.childList || options.subtree)\n        node.removeEventListener('DOMNodeRemoved', this, true);\n    },\n\n    /**\n     * Adds a transient observer on node. The transient observer gets removed\n     * next time we deliver the change records.\n     * @param {Node} node\n     */\n    addTransientObserver: function(node) {\n      // Don't add transient observers on the target itself. We already have all\n      // the required listeners set up on the target.\n      if (node === this.target)\n        return;\n\n      this.addListeners_(node);\n      this.transientObservedNodes.push(node);\n      var registrations = registrationsTable.get(node);\n      if (!registrations)\n        registrationsTable.set(node, registrations = []);\n\n      // We know that registrations does not contain this because we already\n      // checked if node === this.target.\n      registrations.push(this);\n    },\n\n    removeTransientObservers: function() {\n      var transientObservedNodes = this.transientObservedNodes;\n      this.transientObservedNodes = [];\n\n      transientObservedNodes.forEach(function(node) {\n        // Transient observers are never added to the target.\n        this.removeListeners_(node);\n\n        var registrations = registrationsTable.get(node);\n        for (var i = 0; i < registrations.length; i++) {\n          if (registrations[i] === this) {\n            registrations.splice(i, 1);\n            // Each node can only have one registered observer associated with\n            // this observer.\n            break;\n          }\n        }\n      }, this);\n    },\n\n    handleEvent: function(e) {\n      // Stop propagation since we are managing the propagation manually.\n      // This means that other mutation events on the page will not work\n      // correctly but that is by design.\n      e.stopImmediatePropagation();\n\n      switch (e.type) {\n        case 'DOMAttrModified':\n          // http://dom.spec.whatwg.org/#concept-mo-queue-attributes\n\n          var name = e.attrName;\n          var namespace = e.relatedNode.namespaceURI;\n          var target = e.target;\n\n          // 1.\n          var record = new getRecord('attributes', target);\n          record.attributeName = name;\n          record.attributeNamespace = namespace;\n\n          // 2.\n          var oldValue =\n              e.attrChange === MutationEvent.ADDITION ? null : e.prevValue;\n\n          forEachAncestorAndObserverEnqueueRecord(target, function(options) {\n            // 3.1, 4.2\n            if (!options.attributes)\n              return;\n\n            // 3.2, 4.3\n            if (options.attributeFilter && options.attributeFilter.length &&\n                options.attributeFilter.indexOf(name) === -1 &&\n                options.attributeFilter.indexOf(namespace) === -1) {\n              return;\n            }\n            // 3.3, 4.4\n            if (options.attributeOldValue)\n              return getRecordWithOldValue(oldValue);\n\n            // 3.4, 4.5\n            return record;\n          });\n\n          break;\n\n        case 'DOMCharacterDataModified':\n          // http://dom.spec.whatwg.org/#concept-mo-queue-characterdata\n          var target = e.target;\n\n          // 1.\n          var record = getRecord('characterData', target);\n\n          // 2.\n          var oldValue = e.prevValue;\n\n\n          forEachAncestorAndObserverEnqueueRecord(target, function(options) {\n            // 3.1, 4.2\n            if (!options.characterData)\n              return;\n\n            // 3.2, 4.3\n            if (options.characterDataOldValue)\n              return getRecordWithOldValue(oldValue);\n\n            // 3.3, 4.4\n            return record;\n          });\n\n          break;\n\n        case 'DOMNodeRemoved':\n          this.addTransientObserver(e.target);\n          // Fall through.\n        case 'DOMNodeInserted':\n          // http://dom.spec.whatwg.org/#concept-mo-queue-childlist\n          var target = e.relatedNode;\n          var changedNode = e.target;\n          var addedNodes, removedNodes;\n          if (e.type === 'DOMNodeInserted') {\n            addedNodes = [changedNode];\n            removedNodes = [];\n          } else {\n\n            addedNodes = [];\n            removedNodes = [changedNode];\n          }\n          var previousSibling = changedNode.previousSibling;\n          var nextSibling = changedNode.nextSibling;\n\n          // 1.\n          var record = getRecord('childList', target);\n          record.addedNodes = addedNodes;\n          record.removedNodes = removedNodes;\n          record.previousSibling = previousSibling;\n          record.nextSibling = nextSibling;\n\n          forEachAncestorAndObserverEnqueueRecord(target, function(options) {\n            // 2.1, 3.2\n            if (!options.childList)\n              return;\n\n            // 2.2, 3.3\n            return record;\n          });\n\n      }\n\n      clearRecords();\n    }\n  };\n\n  global.JsMutationObserver = JsMutationObserver;\n\n  if (!global.MutationObserver)\n    global.MutationObserver = JsMutationObserver;\n\n\n})(this);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\nwindow.HTMLImports = window.HTMLImports || {flags:{}};",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n\n  // imports\n  var path = scope.path;\n  var xhr = scope.xhr;\n  var flags = scope.flags;\n\n  // TODO(sorvell): this loader supports a dynamic list of urls\n  // and an oncomplete callback that is called when the loader is done.\n  // The polyfill currently does *not* need this dynamism or the onComplete\n  // concept. Because of this, the loader could be simplified quite a bit.\n  var Loader = function(onLoad, onComplete) {\n    this.cache = {};\n    this.onload = onLoad;\n    this.oncomplete = onComplete;\n    this.inflight = 0;\n    this.pending = {};\n  };\n\n  Loader.prototype = {\n    addNodes: function(nodes) {\n      // number of transactions to complete\n      this.inflight += nodes.length;\n      // commence transactions\n      for (var i=0, l=nodes.length, n; (i<l) && (n=nodes[i]); i++) {\n        this.require(n);\n      }\n      // anything to do?\n      this.checkDone();\n    },\n    addNode: function(node) {\n      // number of transactions to complete\n      this.inflight++;\n      // commence transactions\n      this.require(node);\n      // anything to do?\n      this.checkDone();\n    },\n    require: function(elt) {\n      var url = elt.src || elt.href;\n      // ensure we have a standard url that can be used\n      // reliably for deduping.\n      // TODO(sjmiles): ad-hoc\n      elt.__nodeUrl = url;\n      // deduplication\n      if (!this.dedupe(url, elt)) {\n        // fetch this resource\n        this.fetch(url, elt);\n      }\n    },\n    dedupe: function(url, elt) {\n      if (this.pending[url]) {\n        // add to list of nodes waiting for inUrl\n        this.pending[url].push(elt);\n        // don't need fetch\n        return true;\n      }\n      var resource;\n      if (this.cache[url]) {\n        this.onload(url, elt, this.cache[url]);\n        // finished this transaction\n        this.tail();\n        // don't need fetch\n        return true;\n      }\n      // first node waiting for inUrl\n      this.pending[url] = [elt];\n      // need fetch (not a dupe)\n      return false;\n    },\n    fetch: function(url, elt) {\n      flags.load && console.log('fetch', url, elt);\n      var receiveXhr = function(err, resource) {\n        this.receive(url, elt, err, resource);\n      }.bind(this);\n      xhr.load(url, receiveXhr);\n      // TODO(sorvell): blocked on\n      // https://code.google.com/p/chromium/issues/detail?id=257221\n      // xhr'ing for a document makes scripts in imports runnable; otherwise\n      // they are not; however, it requires that we have doctype=html in\n      // the import which is unacceptable. This is only needed on Chrome\n      // to avoid the bug above.\n      /*\n      if (isDocumentLink(elt)) {\n        xhr.loadDocument(url, receiveXhr);\n      } else {\n        xhr.load(url, receiveXhr);\n      }\n      */\n    },\n    receive: function(url, elt, err, resource) {\n      this.cache[url] = resource;\n      var $p = this.pending[url];\n      for (var i=0, l=$p.length, p; (i<l) && (p=$p[i]); i++) {\n        //if (!err) {\n          this.onload(url, p, resource);\n        //}\n        this.tail();\n      }\n      this.pending[url] = null;\n    },\n    tail: function() {\n      --this.inflight;\n      this.checkDone();\n    },\n    checkDone: function() {\n      if (!this.inflight) {\n        this.oncomplete();\n      }\n    }\n  };\n\n  xhr = xhr || {\n    async: true,\n    ok: function(request) {\n      return (request.status >= 200 && request.status < 300)\n          || (request.status === 304)\n          || (request.status === 0);\n    },\n    load: function(url, next, nextContext) {\n      var request = new XMLHttpRequest();\n      if (scope.flags.debug || scope.flags.bust) {\n        url += '?' + Math.random();\n      }\n      request.open('GET', url, xhr.async);\n      request.addEventListener('readystatechange', function(e) {\n        if (request.readyState === 4) {\n          next.call(nextContext, !xhr.ok(request) && request,\n              request.response || request.responseText, url);\n        }\n      });\n      request.send();\n      return request;\n    },\n    loadDocument: function(url, next, nextContext) {\n      this.load(url, next, nextContext).responseType = 'document';\n    }\n  };\n\n  // exports\n  scope.xhr = xhr;\n  scope.Loader = Loader;\n\n})(window.HTMLImports);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n\nvar IMPORT_LINK_TYPE = 'import';\nvar flags = scope.flags;\nvar isIe = /Trident/.test(navigator.userAgent);\n// TODO(sorvell): SD polyfill intrusion\nvar mainDoc = window.ShadowDOMPolyfill ? \n    window.ShadowDOMPolyfill.wrapIfNeeded(document) : document;\n\n// importParser\n// highlander object to manage parsing of imports\n// parses import related elements\n// and ensures proper parse order\n// parse order is enforced by crawling the tree and monitoring which elements\n// have been parsed; async parsing is also supported.\n\n// highlander object for parsing a document tree\nvar importParser = {\n  // parse selectors for main document elements\n  documentSelectors: 'link[rel=' + IMPORT_LINK_TYPE + ']',\n  // parse selectors for import document elements\n  importsSelectors: [\n    'link[rel=' + IMPORT_LINK_TYPE + ']',\n    'link[rel=stylesheet]',\n    'style',\n    'script:not([type])',\n    'script[type=\"text/javascript\"]'\n  ].join(','),\n  map: {\n    link: 'parseLink',\n    script: 'parseScript',\n    style: 'parseStyle'\n  },\n  // try to parse the next import in the tree\n  parseNext: function() {\n    var next = this.nextToParse();\n    if (next) {\n      this.parse(next);\n    }\n  },\n  parse: function(elt) {\n    if (this.isParsed(elt)) {\n      flags.parse && console.log('[%s] is already parsed', elt.localName);\n      return;\n    }\n    var fn = this[this.map[elt.localName]];\n    if (fn) {\n      this.markParsing(elt);\n      fn.call(this, elt);\n    }\n  },\n  // only 1 element may be parsed at a time; parsing is async so, each\n  // parsing implementation must inform the system that parsing is complete\n  // via markParsingComplete.\n  markParsing: function(elt) {\n    flags.parse && console.log('parsing', elt);\n    this.parsingElement = elt;\n  },\n  markParsingComplete: function(elt) {\n    elt.__importParsed = true;\n    if (elt.__importElement) {\n      elt.__importElement.__importParsed = true;\n    }\n    this.parsingElement = null;\n    flags.parse && console.log('completed', elt);\n    this.parseNext();\n  },\n  parseImport: function(elt) {\n    elt.import.__importParsed = true;\n    // TODO(sorvell): consider if there's a better way to do this;\n    // expose an imports parsing hook; this is needed, for example, by the\n    // CustomElements polyfill.\n    if (HTMLImports.__importsParsingHook) {\n      HTMLImports.__importsParsingHook(elt);\n    }\n    // fire load event\n    if (elt.__resource) {\n      elt.dispatchEvent(new CustomEvent('load', {bubbles: false}));    \n    } else {\n      elt.dispatchEvent(new CustomEvent('error', {bubbles: false}));\n    }\n    // TODO(sorvell): workaround for Safari addEventListener not working\n    // for elements not in the main document.\n    if (elt.__pending) {\n      var fn;\n      while (elt.__pending.length) {\n        fn = elt.__pending.shift();\n        if (fn) {\n          fn({target: elt});\n        }\n      }\n    }\n    this.markParsingComplete(elt);\n  },\n  parseLink: function(linkElt) {\n    if (nodeIsImport(linkElt)) {\n      this.parseImport(linkElt);\n    } else {\n      // make href absolute\n      linkElt.href = linkElt.href;\n      this.parseGeneric(linkElt);\n    }\n  },\n  parseStyle: function(elt) {\n    // TODO(sorvell): style element load event can just not fire so clone styles\n    var src = elt;\n    elt = cloneStyle(elt);\n    elt.__importElement = src;\n    this.parseGeneric(elt);\n  },\n  parseGeneric: function(elt) {\n    this.trackElement(elt);\n    document.head.appendChild(elt);\n  },\n  // tracks when a loadable element has loaded\n  trackElement: function(elt) {\n    var self = this;\n    var done = function() {\n      self.markParsingComplete(elt);\n    };\n    elt.addEventListener('load', done);\n    elt.addEventListener('error', done);\n\n    // NOTE: IE does not fire \"load\" event for styles that have already loaded\n    // This is in violation of the spec, so we try our hardest to work around it\n    if (isIe && elt.localName === 'style') {\n      var fakeLoad = false;\n      // If there's not @import in the textContent, assume it has loaded\n      if (elt.textContent.indexOf('@import') == -1) {\n        fakeLoad = true;\n      // if we have a sheet, we have been parsed\n      } else if (elt.sheet) {\n        fakeLoad = true;\n        var csr = elt.sheet.cssRules;\n        var len = csr ? csr.length : 0;\n        // search the rules for @import's\n        for (var i = 0, r; (i < len) && (r = csr[i]); i++) {\n          if (r.type === CSSRule.IMPORT_RULE) {\n            // if every @import has resolved, fake the load\n            fakeLoad = fakeLoad && Boolean(r.styleSheet);\n          }\n        }\n      }\n      // dispatch a fake load event and continue parsing\n      if (fakeLoad) {\n        elt.dispatchEvent(new CustomEvent('load', {bubbles: false}));\n      }\n    }\n  },\n  parseScript: function(scriptElt) {\n    // acquire code to execute\n    var code = (scriptElt.__resource || scriptElt.textContent).trim();\n    if (code) {\n      // calculate source map hint\n      var moniker = scriptElt.__nodeUrl;\n      if (!moniker) {\n        moniker = scriptElt.ownerDocument.baseURI;\n        // there could be more than one script this url\n        var tag = '[' + Math.floor((Math.random()+1)*1000) + ']';\n        // TODO(sjmiles): Polymer hack, should be pluggable if we need to allow \n        // this sort of thing\n        var matches = code.match(/Polymer\\(['\"]([^'\"]*)/);\n        tag = matches && matches[1] || tag;\n        // tag the moniker\n        moniker += '/' + tag + '.js';\n      }\n      // source map hint\n      code += \"\\n//# sourceURL=\" + moniker + \"\\n\";\n      // evaluate the code\n      scope.currentScript = scriptElt;\n      eval.call(window, code);\n      scope.currentScript = null;\n    }\n    this.markParsingComplete(scriptElt);\n  },\n  // determine the next element in the tree which should be parsed\n  nextToParse: function() {\n    return !this.parsingElement && this.nextToParseInDoc(mainDoc);\n  },\n  nextToParseInDoc: function(doc, link) {\n    var nodes = doc.querySelectorAll(this.parseSelectorsForNode(doc));\n    for (var i=0, l=nodes.length, p=0, n; (i<l) && (n=nodes[i]); i++) {\n      if (!this.isParsed(n)) {\n        if (this.hasResource(n)) {\n          return nodeIsImport(n) ? this.nextToParseInDoc(n.import, n) : n;\n        } else {\n          return;\n        }\n      }\n    }\n    // all nodes have been parsed, ready to parse import, if any\n    return link;\n  },\n  // return the set of parse selectors relevant for this node.\n  parseSelectorsForNode: function(node) {\n    var doc = node.ownerDocument || node;\n    return doc === mainDoc ? this.documentSelectors : this.importsSelectors;\n  },\n  isParsed: function(node) {\n    return node.__importParsed;\n  },\n  hasResource: function(node) {\n    if (nodeIsImport(node) && !node.import) {\n      return false;\n    }\n    if (node.localName === 'script' && node.src && !node.__resource) {\n      return false;\n    }\n    return true;\n  }\n};\n\nfunction nodeIsImport(elt) {\n  return (elt.localName === 'link') && (elt.rel === IMPORT_LINK_TYPE);\n}\n\n// style/stylesheet handling\n\n// clone style with proper path resolution for main document\n// NOTE: styles are the only elements that require direct path fixup.\nfunction cloneStyle(style) {\n  var clone = style.ownerDocument.createElement('style');\n  clone.textContent = style.textContent;\n  path.resolveUrlsInStyle(clone);\n  return clone;\n}\n\n// path fixup: style elements in imports must be made relative to the main \n// document. We fixup url's in url() and @import.\nvar CSS_URL_REGEXP = /(url\\()([^)]*)(\\))/g;\nvar CSS_IMPORT_REGEXP = /(@import[\\s]+(?!url\\())([^;]*)(;)/g;\n\nvar path = {\n  resolveUrlsInStyle: function(style) {\n    var doc = style.ownerDocument;\n    var resolver = doc.createElement('a');\n    style.textContent = this.resolveUrlsInCssText(style.textContent, resolver);\n    return style;  \n  },\n  resolveUrlsInCssText: function(cssText, urlObj) {\n    var r = this.replaceUrls(cssText, urlObj, CSS_URL_REGEXP);\n    r = this.replaceUrls(r, urlObj, CSS_IMPORT_REGEXP);\n    return r;\n  },\n  replaceUrls: function(text, urlObj, regexp) {\n    return text.replace(regexp, function(m, pre, url, post) {\n      var urlPath = url.replace(/[\"']/g, '');\n      urlObj.href = urlPath;\n      urlPath = urlObj.href;\n      return pre + '\\'' + urlPath + '\\'' + post;\n    });    \n  }\n}\n\n// exports\nscope.parser = importParser;\nscope.path = path;\nscope.isIE = isIe;\n\n})(HTMLImports);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n\nvar hasNative = ('import' in document.createElement('link'));\nvar useNative = hasNative;\nvar flags = scope.flags;\nvar IMPORT_LINK_TYPE = 'import';\n\n// TODO(sorvell): SD polyfill intrusion\nvar mainDoc = window.ShadowDOMPolyfill ? \n    ShadowDOMPolyfill.wrapIfNeeded(document) : document;\n\nif (!useNative) {\n\n  // imports\n  var xhr = scope.xhr;\n  var Loader = scope.Loader;\n  var parser = scope.parser;\n\n  // importer\n  // highlander object to manage loading of imports\n\n  // for any document, importer:\n  // - loads any linked import documents (with deduping)\n  // for any import document, importer also:\n  // - loads text of external script tags\n\n  var importer = {\n    documents: {},\n    // nodes to load in the mian document\n    documentPreloadSelectors: 'link[rel=' + IMPORT_LINK_TYPE + ']',\n    // nodes to load in imports\n    importsPreloadSelectors: [\n        'link[rel=' + IMPORT_LINK_TYPE + ']',\n        'script[src]:not([type])',\n        'script[src][type=\"text/javascript\"]'\n    ].join(','),\n    loadNode: function(node) {\n      importLoader.addNode(node);\n    },\n    // load all loadable elements within the parent element\n    loadSubtree: function(parent) {\n      var nodes = this.marshalNodes(parent);\n      // add these nodes to loader's queue\n      importLoader.addNodes(nodes);\n    },\n    marshalNodes: function(parent) {\n      // all preloadable nodes in inDocument\n      return parent.querySelectorAll(this.loadSelectorsForNode(parent));\n    },\n    // find the proper set of load selectors for a given node\n    loadSelectorsForNode: function(node) {\n      var doc = node.ownerDocument || node;\n      return doc === mainDoc ? this.documentPreloadSelectors :\n          this.importsPreloadSelectors;\n    },\n    loaded: function(url, elt, resource) {\n      flags.load && console.log('loaded', url, elt);\n      // store generic resource\n      // TODO(sorvell): fails for nodes inside <template>.content\n      // see https://code.google.com/p/chromium/issues/detail?id=249381.\n      elt.__resource = resource;\n      if (isDocumentLink(elt)) {\n        var doc = this.documents[url];\n        // if we've never seen a document at this url\n        if (!doc) {\n          // generate an HTMLDocument from data\n          doc = makeDocument(resource, url);\n          doc.__importLink = elt;\n          // TODO(sorvell): we cannot use MO to detect parsed nodes because\n          // SD polyfill does not report these as mutations.\n          this.bootDocument(doc);\n          // cache document\n          this.documents[url] = doc;\n        }\n        // don't store import record until we're actually loaded\n        // store document resource\n        elt.import = doc;\n      }\n      parser.parseNext();\n    },\n    bootDocument: function(doc) {\n      this.loadSubtree(doc);\n      this.observe(doc);\n      parser.parseNext();\n    },\n    loadedAll: function() {\n      parser.parseNext();\n    }\n  };\n\n  // loader singleton\n  var importLoader = new Loader(importer.loaded.bind(importer), \n      importer.loadedAll.bind(importer));\n\n  function isDocumentLink(elt) {\n    return isLinkRel(elt, IMPORT_LINK_TYPE);\n  }\n\n  function isLinkRel(elt, rel) {\n    return elt.localName === 'link' && elt.getAttribute('rel') === rel;\n  }\n\n  function isScript(elt) {\n    return elt.localName === 'script';\n  }\n\n  function makeDocument(resource, url) {\n    // create a new HTML document\n    var doc = resource;\n    if (!(doc instanceof Document)) {\n      doc = document.implementation.createHTMLDocument(IMPORT_LINK_TYPE);\n    }\n    // cache the new document's source url\n    doc._URL = url;\n    // establish a relative path via <base>\n    var base = doc.createElement('base');\n    base.setAttribute('href', url);\n    // add baseURI support to browsers (IE) that lack it.\n    if (!doc.baseURI) {\n      doc.baseURI = url;\n    }\n    doc.head.appendChild(base);\n    // install HTML last as it may trigger CustomElement upgrades\n    // TODO(sjmiles): problem wrt to template boostrapping below,\n    // template bootstrapping must (?) come before element upgrade\n    // but we cannot bootstrap templates until they are in a document\n    // which is too late\n    if (!(resource instanceof Document)) {\n      // install html\n      doc.body.innerHTML = resource;\n    }\n    // TODO(sorvell): ideally this code is not aware of Template polyfill,\n    // but for now the polyfill needs help to bootstrap these templates\n    if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) {\n      HTMLTemplateElement.bootstrap(doc);\n    }\n    return doc;\n  }\n} else {\n  // do nothing if using native imports\n  var importer = {};\n}\n\n// NOTE: We cannot polyfill document.currentScript because it's not possible\n// both to override and maintain the ability to capture the native value;\n// therefore we choose to expose _currentScript both when native imports\n// and the polyfill are in use.\nvar currentScriptDescriptor = {\n  get: function() {\n    return HTMLImports.currentScript || document.currentScript;\n  },\n  configurable: true\n};\n\nObject.defineProperty(document, '_currentScript', currentScriptDescriptor);\nObject.defineProperty(mainDoc, '_currentScript', currentScriptDescriptor);\n\n// Polyfill document.baseURI for browsers without it.\nif (!document.baseURI) {\n  var baseURIDescriptor = {\n    get: function() {\n      return window.location.href;\n    },\n    configurable: true\n  };\n\n  Object.defineProperty(document, 'baseURI', baseURIDescriptor);\n  Object.defineProperty(mainDoc, 'baseURI', baseURIDescriptor);\n}\n\n// call a callback when all HTMLImports in the document at call (or at least\n//  document ready) time have loaded.\n// 1. ensure the document is in a ready state (has dom), then \n// 2. watch for loading of imports and call callback when done\nfunction whenImportsReady(callback, doc) {\n  doc = doc || mainDoc;\n  // if document is loading, wait and try again\n  whenDocumentReady(function() {\n    watchImportsLoad(callback, doc);\n  }, doc);\n}\n\n// call the callback when the document is in a ready state (has dom)\nvar requiredReadyState = HTMLImports.isIE ? 'complete' : 'interactive';\nvar READY_EVENT = 'readystatechange';\nfunction isDocumentReady(doc) {\n  return (doc.readyState === 'complete' ||\n      doc.readyState === requiredReadyState);\n}\n\n// call <callback> when we ensure the document is in a ready state\nfunction whenDocumentReady(callback, doc) {\n  if (!isDocumentReady(doc)) {\n    var checkReady = function() {\n      if (doc.readyState === 'complete' || \n          doc.readyState === requiredReadyState) {\n        doc.removeEventListener(READY_EVENT, checkReady);\n        whenDocumentReady(callback, doc);\n      }\n    }\n    doc.addEventListener(READY_EVENT, checkReady);\n  } else if (callback) {\n    callback();\n  }\n}\n\n// call <callback> when we ensure all imports have loaded\nfunction watchImportsLoad(callback, doc) {\n  var imports = doc.querySelectorAll('link[rel=import]');\n  var loaded = 0, l = imports.length;\n  function checkDone(d) { \n    if (loaded == l) {\n      // go async to ensure parser isn't stuck on a script tag\n      requestAnimationFrame(callback);\n    }\n  }\n  function loadedImport(e) {\n    loaded++;\n    checkDone();\n  }\n  if (l) {\n    for (var i=0, imp; (i<l) && (imp=imports[i]); i++) {\n      if (isImportLoaded(imp)) {\n        loadedImport.call(imp);\n      } else {\n        imp.addEventListener('load', loadedImport);\n        imp.addEventListener('error', loadedImport);\n      }\n    }\n  } else {\n    checkDone();\n  }\n}\n\nfunction isImportLoaded(link) {\n  return useNative ? (link.import && (link.import.readyState !== 'loading')) :\n      link.__importParsed;\n}\n\n// exports\nscope.hasNative = hasNative;\nscope.useNative = useNative;\nscope.importer = importer;\nscope.whenImportsReady = whenImportsReady;\nscope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;\nscope.isImportLoaded = isImportLoaded;\nscope.importLoader = importLoader;\n\n})(window.HTMLImports);\n",
+    " /*\nCopyright 2013 The Polymer Authors. All rights reserved.\nUse of this source code is governed by a BSD-style\nlicense that can be found in the LICENSE file.\n*/\n\n(function(scope){\n\nvar IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;\nvar importSelector = 'link[rel=' + IMPORT_LINK_TYPE + ']';\nvar importer = scope.importer;\n\n// we track mutations for addedNodes, looking for imports\nfunction handler(mutations) {\n  for (var i=0, l=mutations.length, m; (i<l) && (m=mutations[i]); i++) {\n    if (m.type === 'childList' && m.addedNodes.length) {\n      addedNodes(m.addedNodes);\n    }\n  }\n}\n\n// find loadable elements and add them to the importer\nfunction addedNodes(nodes) {\n  for (var i=0, l=nodes.length, n; (i<l) && (n=nodes[i]); i++) {\n    if (shouldLoadNode(n)) {\n      importer.loadNode(n);\n    }\n    if (n.children && n.children.length) {\n      addedNodes(n.children);\n    }\n  }\n}\n\nfunction shouldLoadNode(node) {\n  return (node.nodeType === 1) && matches.call(node,\n      importer.loadSelectorsForNode(node));\n}\n\n// x-plat matches\nvar matches = HTMLElement.prototype.matches || \n    HTMLElement.prototype.matchesSelector || \n    HTMLElement.prototype.webkitMatchesSelector ||\n    HTMLElement.prototype.mozMatchesSelector ||\n    HTMLElement.prototype.msMatchesSelector;\n\nvar observer = new MutationObserver(handler);\n\n// observe the given root for loadable elements\nfunction observe(root) {\n  observer.observe(root, {childList: true, subtree: true});\n}\n\n// exports\n// TODO(sorvell): factor so can put on scope\nscope.observe = observe;\nimporter.observe = observe;\n\n})(HTMLImports);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function(){\n\n// bootstrap\n\n// IE shim for CustomEvent\nif (typeof window.CustomEvent !== 'function') {\n  window.CustomEvent = function(inType, dictionary) {\n     var e = document.createEvent('HTMLEvents');\n     e.initEvent(inType,\n        dictionary.bubbles === false ? false : true,\n        dictionary.cancelable === false ? false : true,\n        dictionary.detail);\n     return e;\n  };\n}\n\n// TODO(sorvell): SD polyfill intrusion\nvar doc = window.ShadowDOMPolyfill ? \n    window.ShadowDOMPolyfill.wrapIfNeeded(document) : document;\n\n// Fire the 'HTMLImportsLoaded' event when imports in document at load time \n// have loaded. This event is required to simulate the script blocking \n// behavior of native imports. A main document script that needs to be sure\n// imports have loaded should wait for this event.\nHTMLImports.whenImportsReady(function() {\n  HTMLImports.ready = true;\n  HTMLImports.readyTime = new Date().getTime();\n  doc.dispatchEvent(\n    new CustomEvent('HTMLImportsLoaded', {bubbles: true})\n  );\n});\n\n\n// no need to bootstrap the polyfill when native imports is available.\nif (!HTMLImports.useNative) {\n  function bootstrap() {\n    HTMLImports.importer.bootDocument(doc);\n  }\n    \n  // TODO(sorvell): SD polyfill does *not* generate mutations for nodes added\n  // by the parser. For this reason, we must wait until the dom exists to \n  // bootstrap.\n  if (document.readyState === 'complete' ||\n      (document.readyState === 'interactive' && !window.attachEvent)) {\n    bootstrap();\n  } else {\n    document.addEventListener('DOMContentLoaded', bootstrap);\n  }\n}\n\n})();\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\nwindow.CustomElements = window.CustomElements || {flags:{}};",
+    " /*\r\nCopyright 2013 The Polymer Authors. All rights reserved.\r\nUse of this source code is governed by a BSD-style\r\nlicense that can be found in the LICENSE file.\r\n*/\r\n\r\n(function(scope){\r\n\r\nvar logFlags = window.logFlags || {};\r\nvar IMPORT_LINK_TYPE = window.HTMLImports ? HTMLImports.IMPORT_LINK_TYPE : 'none';\r\n\r\n// walk the subtree rooted at node, applying 'find(element, data)' function\r\n// to each element\r\n// if 'find' returns true for 'element', do not search element's subtree\r\nfunction findAll(node, find, data) {\r\n  var e = node.firstElementChild;\r\n  if (!e) {\r\n    e = node.firstChild;\r\n    while (e && e.nodeType !== Node.ELEMENT_NODE) {\r\n      e = e.nextSibling;\r\n    }\r\n  }\r\n  while (e) {\r\n    if (find(e, data) !== true) {\r\n      findAll(e, find, data);\r\n    }\r\n    e = e.nextElementSibling;\r\n  }\r\n  return null;\r\n}\r\n\r\n// walk all shadowRoots on a given node.\r\nfunction forRoots(node, cb) {\r\n  var root = node.shadowRoot;\r\n  while(root) {\r\n    forSubtree(root, cb);\r\n    root = root.olderShadowRoot;\r\n  }\r\n}\r\n\r\n// walk the subtree rooted at node, including descent into shadow-roots,\r\n// applying 'cb' to each element\r\nfunction forSubtree(node, cb) {\r\n  //logFlags.dom && node.childNodes && node.childNodes.length && console.group('subTree: ', node);\r\n  findAll(node, function(e) {\r\n    if (cb(e)) {\r\n      return true;\r\n    }\r\n    forRoots(e, cb);\r\n  });\r\n  forRoots(node, cb);\r\n  //logFlags.dom && node.childNodes && node.childNodes.length && console.groupEnd();\r\n}\r\n\r\n// manage lifecycle on added node\r\nfunction added(node) {\r\n  if (upgrade(node)) {\r\n    insertedNode(node);\r\n    return true;\r\n  }\r\n  inserted(node);\r\n}\r\n\r\n// manage lifecycle on added node's subtree only\r\nfunction addedSubtree(node) {\r\n  forSubtree(node, function(e) {\r\n    if (added(e)) {\r\n      return true;\r\n    }\r\n  });\r\n}\r\n\r\n// manage lifecycle on added node and it's subtree\r\nfunction addedNode(node) {\r\n  return added(node) || addedSubtree(node);\r\n}\r\n\r\n// upgrade custom elements at node, if applicable\r\nfunction upgrade(node) {\r\n  if (!node.__upgraded__ && node.nodeType === Node.ELEMENT_NODE) {\r\n    var type = node.getAttribute('is') || node.localName;\r\n    var definition = scope.registry[type];\r\n    if (definition) {\r\n      logFlags.dom && console.group('upgrade:', node.localName);\r\n      scope.upgrade(node);\r\n      logFlags.dom && console.groupEnd();\r\n      return true;\r\n    }\r\n  }\r\n}\r\n\r\nfunction insertedNode(node) {\r\n  inserted(node);\r\n  if (inDocument(node)) {\r\n    forSubtree(node, function(e) {\r\n      inserted(e);\r\n    });\r\n  }\r\n}\r\n\r\n// TODO(sorvell): on platforms without MutationObserver, mutations may not be\r\n// reliable and therefore attached/detached are not reliable.\r\n// To make these callbacks less likely to fail, we defer all inserts and removes\r\n// to give a chance for elements to be inserted into dom.\r\n// This ensures attachedCallback fires for elements that are created and\r\n// immediately added to dom.\r\nvar hasPolyfillMutations = (!window.MutationObserver ||\r\n    (window.MutationObserver === window.JsMutationObserver));\r\nscope.hasPolyfillMutations = hasPolyfillMutations;\r\n\r\nvar isPendingMutations = false;\r\nvar pendingMutations = [];\r\nfunction deferMutation(fn) {\r\n  pendingMutations.push(fn);\r\n  if (!isPendingMutations) {\r\n    isPendingMutations = true;\r\n    var async = (window.Platform && window.Platform.endOfMicrotask) ||\r\n        setTimeout;\r\n    async(takeMutations);\r\n  }\r\n}\r\n\r\nfunction takeMutations() {\r\n  isPendingMutations = false;\r\n  var $p = pendingMutations;\r\n  for (var i=0, l=$p.length, p; (i<l) && (p=$p[i]); i++) {\r\n    p();\r\n  }\r\n  pendingMutations = [];\r\n}\r\n\r\nfunction inserted(element) {\r\n  if (hasPolyfillMutations) {\r\n    deferMutation(function() {\r\n      _inserted(element);\r\n    });\r\n  } else {\r\n    _inserted(element);\r\n  }\r\n}\r\n\r\n// TODO(sjmiles): if there are descents into trees that can never have inDocument(*) true, fix this\r\nfunction _inserted(element) {\r\n  // TODO(sjmiles): it's possible we were inserted and removed in the space\r\n  // of one microtask, in which case we won't be 'inDocument' here\r\n  // But there are other cases where we are testing for inserted without\r\n  // specific knowledge of mutations, and must test 'inDocument' to determine\r\n  // whether to call inserted\r\n  // If we can factor these cases into separate code paths we can have\r\n  // better diagnostics.\r\n  // TODO(sjmiles): when logging, do work on all custom elements so we can\r\n  // track behavior even when callbacks not defined\r\n  //console.log('inserted: ', element.localName);\r\n  if (element.attachedCallback || element.detachedCallback || (element.__upgraded__ && logFlags.dom)) {\r\n    logFlags.dom && console.group('inserted:', element.localName);\r\n    if (inDocument(element)) {\r\n      element.__inserted = (element.__inserted || 0) + 1;\r\n      // if we are in a 'removed' state, bluntly adjust to an 'inserted' state\r\n      if (element.__inserted < 1) {\r\n        element.__inserted = 1;\r\n      }\r\n      // if we are 'over inserted', squelch the callback\r\n      if (element.__inserted > 1) {\r\n        logFlags.dom && console.warn('inserted:', element.localName,\r\n          'insert/remove count:', element.__inserted)\r\n      } else if (element.attachedCallback) {\r\n        logFlags.dom && console.log('inserted:', element.localName);\r\n        element.attachedCallback();\r\n      }\r\n    }\r\n    logFlags.dom && console.groupEnd();\r\n  }\r\n}\r\n\r\nfunction removedNode(node) {\r\n  removed(node);\r\n  forSubtree(node, function(e) {\r\n    removed(e);\r\n  });\r\n}\r\n\r\nfunction removed(element) {\r\n  if (hasPolyfillMutations) {\r\n    deferMutation(function() {\r\n      _removed(element);\r\n    });\r\n  } else {\r\n    _removed(element);\r\n  }\r\n}\r\n\r\nfunction _removed(element) {\r\n  // TODO(sjmiles): temporary: do work on all custom elements so we can track\r\n  // behavior even when callbacks not defined\r\n  if (element.attachedCallback || element.detachedCallback || (element.__upgraded__ && logFlags.dom)) {\r\n    logFlags.dom && console.group('removed:', element.localName);\r\n    if (!inDocument(element)) {\r\n      element.__inserted = (element.__inserted || 0) - 1;\r\n      // if we are in a 'inserted' state, bluntly adjust to an 'removed' state\r\n      if (element.__inserted > 0) {\r\n        element.__inserted = 0;\r\n      }\r\n      // if we are 'over removed', squelch the callback\r\n      if (element.__inserted < 0) {\r\n        logFlags.dom && console.warn('removed:', element.localName,\r\n            'insert/remove count:', element.__inserted)\r\n      } else if (element.detachedCallback) {\r\n        element.detachedCallback();\r\n      }\r\n    }\r\n    logFlags.dom && console.groupEnd();\r\n  }\r\n}\r\n\r\n// SD polyfill intrustion due mainly to the fact that 'document'\r\n// is not entirely wrapped\r\nfunction wrapIfNeeded(node) {\r\n  return window.ShadowDOMPolyfill ? ShadowDOMPolyfill.wrapIfNeeded(node)\r\n      : node;\r\n}\r\n\r\nfunction inDocument(element) {\r\n  var p = element;\r\n  var doc = wrapIfNeeded(document);\r\n  while (p) {\r\n    if (p == doc) {\r\n      return true;\r\n    }\r\n    p = p.parentNode || p.host;\r\n  }\r\n}\r\n\r\nfunction watchShadow(node) {\r\n  if (node.shadowRoot && !node.shadowRoot.__watched) {\r\n    logFlags.dom && console.log('watching shadow-root for: ', node.localName);\r\n    // watch all unwatched roots...\r\n    var root = node.shadowRoot;\r\n    while (root) {\r\n      watchRoot(root);\r\n      root = root.olderShadowRoot;\r\n    }\r\n  }\r\n}\r\n\r\nfunction watchRoot(root) {\r\n  if (!root.__watched) {\r\n    observe(root);\r\n    root.__watched = true;\r\n  }\r\n}\r\n\r\nfunction handler(mutations) {\r\n  //\r\n  if (logFlags.dom) {\r\n    var mx = mutations[0];\r\n    if (mx && mx.type === 'childList' && mx.addedNodes) {\r\n        if (mx.addedNodes) {\r\n          var d = mx.addedNodes[0];\r\n          while (d && d !== document && !d.host) {\r\n            d = d.parentNode;\r\n          }\r\n          var u = d && (d.URL || d._URL || (d.host && d.host.localName)) || '';\r\n          u = u.split('/?').shift().split('/').pop();\r\n        }\r\n    }\r\n    console.group('mutations (%d) [%s]', mutations.length, u || '');\r\n  }\r\n  //\r\n  mutations.forEach(function(mx) {\r\n    //logFlags.dom && console.group('mutation');\r\n    if (mx.type === 'childList') {\r\n      forEach(mx.addedNodes, function(n) {\r\n        //logFlags.dom && console.log(n.localName);\r\n        if (!n.localName) {\r\n          return;\r\n        }\r\n        // nodes added may need lifecycle management\r\n        addedNode(n);\r\n      });\r\n      // removed nodes may need lifecycle management\r\n      forEach(mx.removedNodes, function(n) {\r\n        //logFlags.dom && console.log(n.localName);\r\n        if (!n.localName) {\r\n          return;\r\n        }\r\n        removedNode(n);\r\n      });\r\n    }\r\n    //logFlags.dom && console.groupEnd();\r\n  });\r\n  logFlags.dom && console.groupEnd();\r\n};\r\n\r\nvar observer = new MutationObserver(handler);\r\n\r\nfunction takeRecords() {\r\n  // TODO(sjmiles): ask Raf why we have to call handler ourselves\r\n  handler(observer.takeRecords());\r\n  takeMutations();\r\n}\r\n\r\nvar forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);\r\n\r\nfunction observe(inRoot) {\r\n  observer.observe(inRoot, {childList: true, subtree: true});\r\n}\r\n\r\nfunction observeDocument(doc) {\r\n  observe(doc);\r\n}\r\n\r\nfunction upgradeDocument(doc) {\r\n  logFlags.dom && console.group('upgradeDocument: ', (doc.baseURI).split('/').pop());\r\n  addedNode(doc);\r\n  logFlags.dom && console.groupEnd();\r\n}\r\n\r\nfunction upgradeDocumentTree(doc) {\r\n  doc = wrapIfNeeded(doc);\r\n  upgradeDocument(doc);\r\n  //console.log('upgradeDocumentTree: ', (doc.baseURI).split('/').pop());\r\n  // upgrade contained imported documents\r\n  var imports = doc.querySelectorAll('link[rel=' + IMPORT_LINK_TYPE + ']');\r\n  for (var i=0, l=imports.length, n; (i<l) && (n=imports[i]); i++) {\r\n    if (n.import && n.import.__parsed) {\r\n      upgradeDocumentTree(n.import);\r\n    }\r\n  }\r\n}\r\n\r\n// exports\r\nscope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;\r\nscope.watchShadow = watchShadow;\r\nscope.upgradeDocumentTree = upgradeDocumentTree;\r\nscope.upgradeAll = addedNode;\r\nscope.upgradeSubtree = addedSubtree;\r\nscope.insertedNode = insertedNode;\r\n\r\nscope.observeDocument = observeDocument;\r\nscope.upgradeDocument = upgradeDocument;\r\n\r\nscope.takeRecords = takeRecords;\r\n\r\n})(window.CustomElements);\r\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * Implements `document.register`\n * @module CustomElements\n*/\n\n/**\n * Polyfilled extensions to the `document` object.\n * @class Document\n*/\n\n(function(scope) {\n\n// imports\n\nif (!scope) {\n  scope = window.CustomElements = {flags:{}};\n}\nvar flags = scope.flags;\n\n// native document.registerElement?\n\nvar hasNative = Boolean(document.registerElement);\n// TODO(sorvell): See https://github.com/Polymer/polymer/issues/399\n// we'll address this by defaulting to CE polyfill in the presence of the SD\n// polyfill. This will avoid spamming excess attached/detached callbacks.\n// If there is a compelling need to run CE native with SD polyfill,\n// we'll need to fix this issue.\nvar useNative = !flags.register && hasNative && !window.ShadowDOMPolyfill;\n\nif (useNative) {\n\n  // stub\n  var nop = function() {};\n\n  // exports\n  scope.registry = {};\n  scope.upgradeElement = nop;\n\n  scope.watchShadow = nop;\n  scope.upgrade = nop;\n  scope.upgradeAll = nop;\n  scope.upgradeSubtree = nop;\n  scope.observeDocument = nop;\n  scope.upgradeDocument = nop;\n  scope.upgradeDocumentTree = nop;\n  scope.takeRecords = nop;\n\n} else {\n\n  /**\n   * Registers a custom tag name with the document.\n   *\n   * When a registered element is created, a `readyCallback` method is called\n   * in the scope of the element. The `readyCallback` method can be specified on\n   * either `options.prototype` or `options.lifecycle` with the latter taking\n   * precedence.\n   *\n   * @method register\n   * @param {String} name The tag name to register. Must include a dash ('-'),\n   *    for example 'x-component'.\n   * @param {Object} options\n   *    @param {String} [options.extends]\n   *      (_off spec_) Tag name of an element to extend (or blank for a new\n   *      element). This parameter is not part of the specification, but instead\n   *      is a hint for the polyfill because the extendee is difficult to infer.\n   *      Remember that the input prototype must chain to the extended element's\n   *      prototype (or HTMLElement.prototype) regardless of the value of\n   *      `extends`.\n   *    @param {Object} options.prototype The prototype to use for the new\n   *      element. The prototype must inherit from HTMLElement.\n   *    @param {Object} [options.lifecycle]\n   *      Callbacks that fire at important phases in the life of the custom\n   *      element.\n   *\n   * @example\n   *      FancyButton = document.registerElement(\"fancy-button\", {\n   *        extends: 'button',\n   *        prototype: Object.create(HTMLButtonElement.prototype, {\n   *          readyCallback: {\n   *            value: function() {\n   *              console.log(\"a fancy-button was created\",\n   *            }\n   *          }\n   *        })\n   *      });\n   * @return {Function} Constructor for the newly registered type.\n   */\n  function register(name, options) {\n    //console.warn('document.registerElement(\"' + name + '\", ', options, ')');\n    // construct a defintion out of options\n    // TODO(sjmiles): probably should clone options instead of mutating it\n    var definition = options || {};\n    if (!name) {\n      // TODO(sjmiles): replace with more appropriate error (EricB can probably\n      // offer guidance)\n      throw new Error('document.registerElement: first argument `name` must not be empty');\n    }\n    if (name.indexOf('-') < 0) {\n      // TODO(sjmiles): replace with more appropriate error (EricB can probably\n      // offer guidance)\n      throw new Error('document.registerElement: first argument (\\'name\\') must contain a dash (\\'-\\'). Argument provided was \\'' + String(name) + '\\'.');\n    }\n    // elements may only be registered once\n    if (getRegisteredDefinition(name)) {\n      throw new Error('DuplicateDefinitionError: a type with name \\'' + String(name) + '\\' is already registered');\n    }\n    // must have a prototype, default to an extension of HTMLElement\n    // TODO(sjmiles): probably should throw if no prototype, check spec\n    if (!definition.prototype) {\n      // TODO(sjmiles): replace with more appropriate error (EricB can probably\n      // offer guidance)\n      throw new Error('Options missing required prototype property');\n    }\n    // record name\n    definition.__name = name.toLowerCase();\n    // ensure a lifecycle object so we don't have to null test it\n    definition.lifecycle = definition.lifecycle || {};\n    // build a list of ancestral custom elements (for native base detection)\n    // TODO(sjmiles): we used to need to store this, but current code only\n    // uses it in 'resolveTagName': it should probably be inlined\n    definition.ancestry = ancestry(definition.extends);\n    // extensions of native specializations of HTMLElement require localName\n    // to remain native, and use secondary 'is' specifier for extension type\n    resolveTagName(definition);\n    // some platforms require modifications to the user-supplied prototype\n    // chain\n    resolvePrototypeChain(definition);\n    // overrides to implement attributeChanged callback\n    overrideAttributeApi(definition.prototype);\n    // 7.1.5: Register the DEFINITION with DOCUMENT\n    registerDefinition(definition.__name, definition);\n    // 7.1.7. Run custom element constructor generation algorithm with PROTOTYPE\n    // 7.1.8. Return the output of the previous step.\n    definition.ctor = generateConstructor(definition);\n    definition.ctor.prototype = definition.prototype;\n    // force our .constructor to be our actual constructor\n    definition.prototype.constructor = definition.ctor;\n    // if initial parsing is complete\n    if (scope.ready) {\n      // upgrade any pre-existing nodes of this type\n      scope.upgradeDocumentTree(document);\n    }\n    return definition.ctor;\n  }\n\n  function ancestry(extnds) {\n    var extendee = getRegisteredDefinition(extnds);\n    if (extendee) {\n      return ancestry(extendee.extends).concat([extendee]);\n    }\n    return [];\n  }\n\n  function resolveTagName(definition) {\n    // if we are explicitly extending something, that thing is our\n    // baseTag, unless it represents a custom component\n    var baseTag = definition.extends;\n    // if our ancestry includes custom components, we only have a\n    // baseTag if one of them does\n    for (var i=0, a; (a=definition.ancestry[i]); i++) {\n      baseTag = a.is && a.tag;\n    }\n    // our tag is our baseTag, if it exists, and otherwise just our name\n    definition.tag = baseTag || definition.__name;\n    if (baseTag) {\n      // if there is a base tag, use secondary 'is' specifier\n      definition.is = definition.__name;\n    }\n  }\n\n  function resolvePrototypeChain(definition) {\n    // if we don't support __proto__ we need to locate the native level\n    // prototype for precise mixing in\n    if (!Object.__proto__) {\n      // default prototype\n      var nativePrototype = HTMLElement.prototype;\n      // work out prototype when using type-extension\n      if (definition.is) {\n        var inst = document.createElement(definition.tag);\n        nativePrototype = Object.getPrototypeOf(inst);\n      }\n      // ensure __proto__ reference is installed at each point on the prototype\n      // chain.\n      // NOTE: On platforms without __proto__, a mixin strategy is used instead\n      // of prototype swizzling. In this case, this generated __proto__ provides\n      // limited support for prototype traversal.\n      var proto = definition.prototype, ancestor;\n      while (proto && (proto !== nativePrototype)) {\n        var ancestor = Object.getPrototypeOf(proto);\n        proto.__proto__ = ancestor;\n        proto = ancestor;\n      }\n    }\n    // cache this in case of mixin\n    definition.native = nativePrototype;\n  }\n\n  // SECTION 4\n\n  function instantiate(definition) {\n    // 4.a.1. Create a new object that implements PROTOTYPE\n    // 4.a.2. Let ELEMENT by this new object\n    //\n    // the custom element instantiation algorithm must also ensure that the\n    // output is a valid DOM element with the proper wrapper in place.\n    //\n    return upgrade(domCreateElement(definition.tag), definition);\n  }\n\n  function upgrade(element, definition) {\n    // some definitions specify an 'is' attribute\n    if (definition.is) {\n      element.setAttribute('is', definition.is);\n    }\n    // remove 'unresolved' attr, which is a standin for :unresolved.\n    element.removeAttribute('unresolved');\n    // make 'element' implement definition.prototype\n    implement(element, definition);\n    // flag as upgraded\n    element.__upgraded__ = true;\n    // lifecycle management\n    created(element);\n    // attachedCallback fires in tree order, call before recursing\n    scope.insertedNode(element);\n    // there should never be a shadow root on element at this point\n    scope.upgradeSubtree(element);\n    // OUTPUT\n    return element;\n  }\n\n  function implement(element, definition) {\n    // prototype swizzling is best\n    if (Object.__proto__) {\n      element.__proto__ = definition.prototype;\n    } else {\n      // where above we can re-acquire inPrototype via\n      // getPrototypeOf(Element), we cannot do so when\n      // we use mixin, so we install a magic reference\n      customMixin(element, definition.prototype, definition.native);\n      element.__proto__ = definition.prototype;\n    }\n  }\n\n  function customMixin(inTarget, inSrc, inNative) {\n    // TODO(sjmiles): 'used' allows us to only copy the 'youngest' version of\n    // any property. This set should be precalculated. We also need to\n    // consider this for supporting 'super'.\n    var used = {};\n    // start with inSrc\n    var p = inSrc;\n    // sometimes the default is HTMLUnknownElement.prototype instead of\n    // HTMLElement.prototype, so we add a test\n    // the idea is to avoid mixing in native prototypes, so adding\n    // the second test is WLOG\n    while (p !== inNative && p !== HTMLUnknownElement.prototype) {\n      var keys = Object.getOwnPropertyNames(p);\n      for (var i=0, k; k=keys[i]; i++) {\n        if (!used[k]) {\n          Object.defineProperty(inTarget, k,\n              Object.getOwnPropertyDescriptor(p, k));\n          used[k] = 1;\n        }\n      }\n      p = Object.getPrototypeOf(p);\n    }\n  }\n\n  function created(element) {\n    // invoke createdCallback\n    if (element.createdCallback) {\n      element.createdCallback();\n    }\n  }\n\n  // attribute watching\n\n  function overrideAttributeApi(prototype) {\n    // overrides to implement callbacks\n    // TODO(sjmiles): should support access via .attributes NamedNodeMap\n    // TODO(sjmiles): preserves user defined overrides, if any\n    if (prototype.setAttribute._polyfilled) {\n      return;\n    }\n    var setAttribute = prototype.setAttribute;\n    prototype.setAttribute = function(name, value) {\n      changeAttribute.call(this, name, value, setAttribute);\n    }\n    var removeAttribute = prototype.removeAttribute;\n    prototype.removeAttribute = function(name) {\n      changeAttribute.call(this, name, null, removeAttribute);\n    }\n    prototype.setAttribute._polyfilled = true;\n  }\n\n  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/\n  // index.html#dfn-attribute-changed-callback\n  function changeAttribute(name, value, operation) {\n    var oldValue = this.getAttribute(name);\n    operation.apply(this, arguments);\n    var newValue = this.getAttribute(name);\n    if (this.attributeChangedCallback\n        && (newValue !== oldValue)) {\n      this.attributeChangedCallback(name, oldValue, newValue);\n    }\n  }\n\n  // element registry (maps tag names to definitions)\n\n  var registry = {};\n\n  function getRegisteredDefinition(name) {\n    if (name) {\n      return registry[name.toLowerCase()];\n    }\n  }\n\n  function registerDefinition(name, definition) {\n    registry[name] = definition;\n  }\n\n  function generateConstructor(definition) {\n    return function() {\n      return instantiate(definition);\n    };\n  }\n\n  function createElement(tag, typeExtension) {\n    // TODO(sjmiles): ignore 'tag' when using 'typeExtension', we could\n    // error check it, or perhaps there should only ever be one argument\n    var definition = getRegisteredDefinition(typeExtension || tag);\n    if (definition) {\n      if (tag == definition.tag && typeExtension == definition.is) {\n        return new definition.ctor();\n      }\n      // Handle empty string for type extension.\n      if (!typeExtension && !definition.is) {\n        return new definition.ctor();\n      }\n    }\n\n    if (typeExtension) {\n      var element = createElement(tag);\n      element.setAttribute('is', typeExtension);\n      return element;\n    }\n    var element = domCreateElement(tag);\n    // Custom tags should be HTMLElements even if not upgraded.\n    if (tag.indexOf('-') >= 0) {\n      implement(element, HTMLElement);\n    }\n    return element;\n  }\n\n  function upgradeElement(element) {\n    if (!element.__upgraded__ && (element.nodeType === Node.ELEMENT_NODE)) {\n      var is = element.getAttribute('is');\n      var definition = getRegisteredDefinition(is || element.localName);\n      if (definition) {\n        if (is && definition.tag == element.localName) {\n          return upgrade(element, definition);\n        } else if (!is && !definition.extends) {\n          return upgrade(element, definition);\n        }\n      }\n    }\n  }\n\n  function cloneNode(deep) {\n    // call original clone\n    var n = domCloneNode.call(this, deep);\n    // upgrade the element and subtree\n    scope.upgradeAll(n);\n    // return the clone\n    return n;\n  }\n  // capture native createElement before we override it\n\n  var domCreateElement = document.createElement.bind(document);\n\n  // capture native cloneNode before we override it\n\n  var domCloneNode = Node.prototype.cloneNode;\n\n  // exports\n\n  document.registerElement = register;\n  document.createElement = createElement; // override\n  Node.prototype.cloneNode = cloneNode; // override\n\n  scope.registry = registry;\n\n  /**\n   * Upgrade an element to a custom element. Upgrading an element\n   * causes the custom prototype to be applied, an `is` attribute\n   * to be attached (as needed), and invocation of the `readyCallback`.\n   * `upgrade` does nothing if the element is already upgraded, or\n   * if it matches no registered custom tag name.\n   *\n   * @method ugprade\n   * @param {Element} element The element to upgrade.\n   * @return {Element} The upgraded element.\n   */\n  scope.upgrade = upgradeElement;\n}\n\n// bc\ndocument.register = document.registerElement;\n\nscope.hasNative = hasNative;\nscope.useNative = useNative;\n\n})(window.CustomElements);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n\n// import\n\nvar IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;\n\n// highlander object for parsing a document tree\n\nvar parser = {\n  selectors: [\n    'link[rel=' + IMPORT_LINK_TYPE + ']'\n  ],\n  map: {\n    link: 'parseLink'\n  },\n  parse: function(inDocument) {\n    if (!inDocument.__parsed) {\n      // only parse once\n      inDocument.__parsed = true;\n      // all parsable elements in inDocument (depth-first pre-order traversal)\n      var elts = inDocument.querySelectorAll(parser.selectors);\n      // for each parsable node type, call the mapped parsing method\n      forEach(elts, function(e) {\n        parser[parser.map[e.localName]](e);\n      });\n      // upgrade all upgradeable static elements, anything dynamically\n      // created should be caught by observer\n      CustomElements.upgradeDocument(inDocument);\n      // observe document for dom changes\n      CustomElements.observeDocument(inDocument);\n    }\n  },\n  parseLink: function(linkElt) {\n    // imports\n    if (isDocumentLink(linkElt)) {\n      this.parseImport(linkElt);\n    }\n  },\n  parseImport: function(linkElt) {\n    if (linkElt.import) {\n      parser.parse(linkElt.import);\n    }\n  }\n};\n\nfunction isDocumentLink(inElt) {\n  return (inElt.localName === 'link'\n      && inElt.getAttribute('rel') === IMPORT_LINK_TYPE);\n}\n\nvar forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);\n\n// exports\n\nscope.parser = parser;\nscope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;\n\n})(window.CustomElements);",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function(scope){\n\n// bootstrap parsing\nfunction bootstrap() {\n  // parse document\n  CustomElements.parser.parse(document);\n  // one more pass before register is 'live'\n  CustomElements.upgradeDocument(document);\n  // choose async\n  var async = window.Platform && Platform.endOfMicrotask ? \n    Platform.endOfMicrotask :\n    setTimeout;\n  async(function() {\n    // set internal 'ready' flag, now document.registerElement will trigger \n    // synchronous upgrades\n    CustomElements.ready = true;\n    // capture blunt profiling data\n    CustomElements.readyTime = Date.now();\n    if (window.HTMLImports) {\n      CustomElements.elapsed = CustomElements.readyTime - HTMLImports.readyTime;\n    }\n    // notify the system that we are bootstrapped\n    document.dispatchEvent(\n      new CustomEvent('WebComponentsReady', {bubbles: true})\n    );\n\n    // install upgrade hook if HTMLImports are available\n    if (window.HTMLImports) {\n      HTMLImports.__importsParsingHook = function(elt) {\n        CustomElements.parser.parse(elt.import);\n      }\n    }\n  });\n}\n\n// CustomEvent shim for IE\nif (typeof window.CustomEvent !== 'function') {\n  window.CustomEvent = function(inType) {\n    var e = document.createEvent('HTMLEvents');\n    e.initEvent(inType, true, true);\n    return e;\n  };\n}\n\n// When loading at readyState complete time (or via flag), boot custom elements\n// immediately.\n// If relevant, HTMLImports must already be loaded.\nif (document.readyState === 'complete' || scope.flags.eager) {\n  bootstrap();\n// When loading at readyState interactive time, bootstrap only if HTMLImports\n// are not pending. Also avoid IE as the semantics of this state are unreliable.\n} else if (document.readyState === 'interactive' && !window.attachEvent &&\n    (!window.HTMLImports || window.HTMLImports.ready)) {\n  bootstrap();\n// When loading at other readyStates, wait for the appropriate DOM event to \n// bootstrap.\n} else {\n  var loadEvent = window.HTMLImports && !HTMLImports.ready ?\n      'HTMLImportsLoaded' : 'DOMContentLoaded';\n  window.addEventListener(loadEvent, bootstrap);\n}\n\n})(window.CustomElements);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function() {\n\n// inject style sheet\nvar style = document.createElement('style');\nstyle.textContent = 'element {display: none !important;} /* injected by platform.js */';\nvar head = document.querySelector('head');\nhead.insertBefore(style, head.firstChild);\n\nif (window.ShadowDOMPolyfill) {\n\n  // ensure wrapped inputs for these functions\n  var fns = ['upgradeAll', 'upgradeSubtree', 'observeDocument',\n      'upgradeDocument'];\n\n  // cache originals\n  var original = {};\n  fns.forEach(function(fn) {\n    original[fn] = CustomElements[fn];\n  });\n\n  // override\n  fns.forEach(function(fn) {\n    CustomElements[fn] = function(inNode) {\n      return original[fn](wrap(inNode));\n    };\n  });\n\n}\n\n})();\n",
+    "/*\n * Copyright 2014 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function(scope) {\n\nvar STYLE_SELECTOR = 'style';\n\nvar urlResolver = scope.urlResolver;\n\nvar loader = {\n  cacheStyles: function(styles, callback) {\n    var css = [];\n    for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) {\n      css.push(s.textContent);\n    }\n    cacheCssText(css.join('\\n'), callback);\n  },\n  xhrStyles: function(styles, callback) {\n    var loaded=0, l = styles.length;\n    // called in the context of the style\n    function loadedStyle(style) {\n      //console.log(style.textContent);\n      loaded++;\n      if (loaded === l && callback) {\n        callback();\n      }\n    }\n    for (var i=0, s; (i<l) && (s=styles[i]); i++) {\n      xhrLoadStyle(s, loadedStyle);\n    }\n  }\n};\n\n// use the platform to preload styles\nvar preloadElement = document.createElement('preloader');\npreloadElement.style.display = 'none';\nvar preloadRoot = preloadElement.createShadowRoot();\ndocument.head.appendChild(preloadElement);\n\nfunction cacheCssText(cssText, callback) {\n  var style = createStyleElement(cssText);\n  if (callback) {\n    style.addEventListener('load', callback);\n    style.addEventListener('error', callback);\n  }\n  preloadRoot.appendChild(style);\n}\n\nfunction createStyleElement(cssText, scope) {\n  scope = scope || document;\n  scope = scope.createElement ? scope : scope.ownerDocument;\n  var style = scope.createElement('style');\n  style.textContent = cssText;\n  return style;\n}\n\n// TODO(sorvell): use a common loader shared with HTMLImports polyfill\n// currently, this just loads the first @import per style element \n// and does not recurse into loaded elements; we'll address this with a \n// generalized loader that's built out of the one in the HTMLImports polyfill.\n// polyfill the loading of a style element's @import via xhr\nfunction xhrLoadStyle(style, callback) {\n  HTMLImports.xhr.load(atImportUrlFromStyle(style), function (err, resource,\n      url) {\n    replaceAtImportWithCssText(this, url, resource);\n    this.textContent = urlResolver.resolveCssText(this.textContent, url);\n    callback && callback(this);\n  }, style);\n}\n\nvar atImportRe = /@import\\s[(]?['\"]?([^\\s'\";)]*)/;\n\n// get the first @import rule from a style\nfunction atImportUrlFromStyle(style) {\n  var matches = style.textContent.match(atImportRe);\n  return matches && matches[1];\n}\n\nfunction replaceAtImportWithCssText(style, url, cssText) {\n  var re = new RegExp('@import[^;]*' + url + '[^;]*;', 'i');\n  style.textContent = style.textContent.replace(re, cssText);\n}\n\n// exports\nscope.loader = loader;\n\n})(window.Platform);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n  scope = scope || {};\n  scope.external = scope.external || {};\n  var target = {\n    shadow: function(inEl) {\n      if (inEl) {\n        return inEl.shadowRoot || inEl.webkitShadowRoot;\n      }\n    },\n    canTarget: function(shadow) {\n      return shadow && Boolean(shadow.elementFromPoint);\n    },\n    targetingShadow: function(inEl) {\n      var s = this.shadow(inEl);\n      if (this.canTarget(s)) {\n        return s;\n      }\n    },\n    olderShadow: function(shadow) {\n      var os = shadow.olderShadowRoot;\n      if (!os) {\n        var se = shadow.querySelector('shadow');\n        if (se) {\n          os = se.olderShadowRoot;\n        }\n      }\n      return os;\n    },\n    allShadows: function(element) {\n      var shadows = [], s = this.shadow(element);\n      while(s) {\n        shadows.push(s);\n        s = this.olderShadow(s);\n      }\n      return shadows;\n    },\n    searchRoot: function(inRoot, x, y) {\n      if (inRoot) {\n        var t = inRoot.elementFromPoint(x, y);\n        var st, sr, os;\n        // is element a shadow host?\n        sr = this.targetingShadow(t);\n        while (sr) {\n          // find the the element inside the shadow root\n          st = sr.elementFromPoint(x, y);\n          if (!st) {\n            // check for older shadows\n            sr = this.olderShadow(sr);\n          } else {\n            // shadowed element may contain a shadow root\n            var ssr = this.targetingShadow(st);\n            return this.searchRoot(ssr, x, y) || st;\n          }\n        }\n        // light dom element is the target\n        return t;\n      }\n    },\n    owner: function(element) {\n      var s = element;\n      // walk up until you hit the shadow root or document\n      while (s.parentNode) {\n        s = s.parentNode;\n      }\n      // the owner element is expected to be a Document or ShadowRoot\n      if (s.nodeType != Node.DOCUMENT_NODE && s.nodeType != Node.DOCUMENT_FRAGMENT_NODE) {\n        s = document;\n      }\n      return s;\n    },\n    findTarget: function(inEvent) {\n      var x = inEvent.clientX, y = inEvent.clientY;\n      // if the listener is in the shadow root, it is much faster to start there\n      var s = this.owner(inEvent.target);\n      // if x, y is not in this root, fall back to document search\n      if (!s.elementFromPoint(x, y)) {\n        s = document;\n      }\n      return this.searchRoot(s, x, y);\n    }\n  };\n  scope.targetFinding = target;\n  scope.findTarget = target.findTarget.bind(target);\n\n  window.PointerEventsPolyfill = scope;\n})(window.PointerEventsPolyfill);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function() {\n  function shadowSelector(v) {\n    return 'body ^^ ' + selector(v);\n  }\n  function selector(v) {\n    return '[touch-action=\"' + v + '\"]';\n  }\n  function rule(v) {\n    return '{ -ms-touch-action: ' + v + '; touch-action: ' + v + '; touch-action-delay: none; }';\n  }\n  var attrib2css = [\n    'none',\n    'auto',\n    'pan-x',\n    'pan-y',\n    {\n      rule: 'pan-x pan-y',\n      selectors: [\n        'pan-x pan-y',\n        'pan-y pan-x'\n      ]\n    }\n  ];\n  var styles = '';\n  attrib2css.forEach(function(r) {\n    if (String(r) === r) {\n      styles += selector(r) + rule(r) + '\\n';\n      styles += shadowSelector(r) + rule(r) + '\\n';\n    } else {\n      styles += r.selectors.map(selector) + rule(r.rule) + '\\n';\n      styles += r.selectors.map(shadowSelector) + rule(r.rule) + '\\n';\n    }\n  });\n  var el = document.createElement('style');\n  el.textContent = styles;\n  document.head.appendChild(el);\n})();\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This is the constructor for new PointerEvents.\n *\n * New Pointer Events must be given a type, and an optional dictionary of\n * initialization properties.\n *\n * Due to certain platform requirements, events returned from the constructor\n * identify as MouseEvents.\n *\n * @constructor\n * @param {String} inType The type of the event to create.\n * @param {Object} [inDict] An optional dictionary of initial event properties.\n * @return {Event} A new PointerEvent of type `inType` and initialized with properties from `inDict`.\n */\n(function(scope) {\n  // test for DOM Level 4 Events\n  var NEW_MOUSE_EVENT = false;\n  var HAS_BUTTONS = false;\n  try {\n    var ev = new MouseEvent('click', {buttons: 1});\n    NEW_MOUSE_EVENT = true;\n    HAS_BUTTONS = ev.buttons === 1;\n  } catch(e) {\n  }\n\n  var MOUSE_PROPS = [\n    'bubbles',\n    'cancelable',\n    'view',\n    'detail',\n    'screenX',\n    'screenY',\n    'clientX',\n    'clientY',\n    'ctrlKey',\n    'altKey',\n    'shiftKey',\n    'metaKey',\n    'button',\n    'relatedTarget',\n  ];\n\n  var MOUSE_DEFAULTS = [\n    false,\n    false,\n    null,\n    null,\n    0,\n    0,\n    0,\n    0,\n    false,\n    false,\n    false,\n    false,\n    0,\n    null\n  ];\n\n  function PointerEvent(inType, inDict) {\n    inDict = inDict || {};\n    // According to the w3c spec,\n    // http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-button\n    // MouseEvent.button == 0 can mean either no mouse button depressed, or the\n    // left mouse button depressed.\n    //\n    // As of now, the only way to distinguish between the two states of\n    // MouseEvent.button is by using the deprecated MouseEvent.which property, as\n    // this maps mouse buttons to positive integers > 0, and uses 0 to mean that\n    // no mouse button is held.\n    //\n    // MouseEvent.which is derived from MouseEvent.button at MouseEvent creation,\n    // but initMouseEvent does not expose an argument with which to set\n    // MouseEvent.which. Calling initMouseEvent with a buttonArg of 0 will set\n    // MouseEvent.button == 0 and MouseEvent.which == 1, breaking the expectations\n    // of app developers.\n    //\n    // The only way to propagate the correct state of MouseEvent.which and\n    // MouseEvent.button to a new MouseEvent.button == 0 and MouseEvent.which == 0\n    // is to call initMouseEvent with a buttonArg value of -1.\n    //\n    // This is fixed with DOM Level 4's use of buttons\n    var buttons;\n    if (inDict.buttons || HAS_BUTTONS) {\n      buttons = inDict.buttons;\n    } else {\n      switch (inDict.which) {\n        case 1: buttons = 1; break;\n        case 2: buttons = 4; break;\n        case 3: buttons = 2; break;\n        default: buttons = 0;\n      }\n    }\n\n    var e;\n    if (NEW_MOUSE_EVENT) {\n      e = new MouseEvent(inType, inDict);\n    } else {\n      e = document.createEvent('MouseEvent');\n\n      // import values from the given dictionary\n      var props = {}, p;\n      for(var i = 0; i < MOUSE_PROPS.length; i++) {\n        p = MOUSE_PROPS[i];\n        props[p] = inDict[p] || MOUSE_DEFAULTS[i];\n      }\n\n      // define the properties inherited from MouseEvent\n      e.initMouseEvent(\n        inType, props.bubbles, props.cancelable, props.view, props.detail,\n        props.screenX, props.screenY, props.clientX, props.clientY, props.ctrlKey,\n        props.altKey, props.shiftKey, props.metaKey, props.button, props.relatedTarget\n      );\n    }\n\n    // make the event pass instanceof checks\n    e.__proto__ = PointerEvent.prototype;\n\n    // define the buttons property according to DOM Level 3 spec\n    if (!HAS_BUTTONS) {\n      // IE 10 has buttons on MouseEvent.prototype as a getter w/o any setting\n      // mechanism\n      Object.defineProperty(e, 'buttons', {get: function(){ return buttons; }, enumerable: true});\n    }\n\n    // Spec requires that pointers without pressure specified use 0.5 for down\n    // state and 0 for up state.\n    var pressure = 0;\n    if (inDict.pressure) {\n      pressure = inDict.pressure;\n    } else {\n      pressure = buttons ? 0.5 : 0;\n    }\n\n    // define the properties of the PointerEvent interface\n    Object.defineProperties(e, {\n      pointerId: { value: inDict.pointerId || 0, enumerable: true },\n      width: { value: inDict.width || 0, enumerable: true },\n      height: { value: inDict.height || 0, enumerable: true },\n      pressure: { value: pressure, enumerable: true },\n      tiltX: { value: inDict.tiltX || 0, enumerable: true },\n      tiltY: { value: inDict.tiltY || 0, enumerable: true },\n      pointerType: { value: inDict.pointerType || '', enumerable: true },\n      hwTimestamp: { value: inDict.hwTimestamp || 0, enumerable: true },\n      isPrimary: { value: inDict.isPrimary || false, enumerable: true }\n    });\n    return e;\n  }\n\n  // PointerEvent extends MouseEvent\n  PointerEvent.prototype = Object.create(MouseEvent.prototype);\n\n  // attach to window\n  if (!scope.PointerEvent) {\n    scope.PointerEvent = PointerEvent;\n  }\n})(window);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This module implements an map of pointer states\n */\n(function(scope) {\n  var USE_MAP = window.Map && window.Map.prototype.forEach;\n  var POINTERS_FN = function(){ return this.size; };\n  function PointerMap() {\n    if (USE_MAP) {\n      var m = new Map();\n      m.pointers = POINTERS_FN;\n      return m;\n    } else {\n      this.keys = [];\n      this.values = [];\n    }\n  }\n\n  PointerMap.prototype = {\n    set: function(inId, inEvent) {\n      var i = this.keys.indexOf(inId);\n      if (i > -1) {\n        this.values[i] = inEvent;\n      } else {\n        this.keys.push(inId);\n        this.values.push(inEvent);\n      }\n    },\n    has: function(inId) {\n      return this.keys.indexOf(inId) > -1;\n    },\n    'delete': function(inId) {\n      var i = this.keys.indexOf(inId);\n      if (i > -1) {\n        this.keys.splice(i, 1);\n        this.values.splice(i, 1);\n      }\n    },\n    get: function(inId) {\n      var i = this.keys.indexOf(inId);\n      return this.values[i];\n    },\n    clear: function() {\n      this.keys.length = 0;\n      this.values.length = 0;\n    },\n    // return value, key, map\n    forEach: function(callback, thisArg) {\n      this.values.forEach(function(v, i) {\n        callback.call(thisArg, v, this.keys[i], this);\n      }, this);\n    },\n    pointers: function() {\n      return this.keys.length;\n    }\n  };\n\n  scope.PointerMap = PointerMap;\n})(window.PointerEventsPolyfill);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n  var CLONE_PROPS = [\n    // MouseEvent\n    'bubbles',\n    'cancelable',\n    'view',\n    'detail',\n    'screenX',\n    'screenY',\n    'clientX',\n    'clientY',\n    'ctrlKey',\n    'altKey',\n    'shiftKey',\n    'metaKey',\n    'button',\n    'relatedTarget',\n    // DOM Level 3\n    'buttons',\n    // PointerEvent\n    'pointerId',\n    'width',\n    'height',\n    'pressure',\n    'tiltX',\n    'tiltY',\n    'pointerType',\n    'hwTimestamp',\n    'isPrimary',\n    // event instance\n    'type',\n    'target',\n    'currentTarget',\n    'which'\n  ];\n\n  var CLONE_DEFAULTS = [\n    // MouseEvent\n    false,\n    false,\n    null,\n    null,\n    0,\n    0,\n    0,\n    0,\n    false,\n    false,\n    false,\n    false,\n    0,\n    null,\n    // DOM Level 3\n    0,\n    // PointerEvent\n    0,\n    0,\n    0,\n    0,\n    0,\n    0,\n    '',\n    0,\n    false,\n    // event instance\n    '',\n    null,\n    null,\n    0\n  ];\n\n  var HAS_SVG_INSTANCE = (typeof SVGElementInstance !== 'undefined');\n\n  /**\n   * This module is for normalizing events. Mouse and Touch events will be\n   * collected here, and fire PointerEvents that have the same semantics, no\n   * matter the source.\n   * Events fired:\n   *   - pointerdown: a pointing is added\n   *   - pointerup: a pointer is removed\n   *   - pointermove: a pointer is moved\n   *   - pointerover: a pointer crosses into an element\n   *   - pointerout: a pointer leaves an element\n   *   - pointercancel: a pointer will no longer generate events\n   */\n  var dispatcher = {\n    targets: new WeakMap(),\n    handledEvents: new WeakMap(),\n    pointermap: new scope.PointerMap(),\n    eventMap: {},\n    // Scope objects for native events.\n    // This exists for ease of testing.\n    eventSources: {},\n    eventSourceList: [],\n    /**\n     * Add a new event source that will generate pointer events.\n     *\n     * `inSource` must contain an array of event names named `events`, and\n     * functions with the names specified in the `events` array.\n     * @param {string} name A name for the event source\n     * @param {Object} source A new source of platform events.\n     */\n    registerSource: function(name, source) {\n      var s = source;\n      var newEvents = s.events;\n      if (newEvents) {\n        newEvents.forEach(function(e) {\n          if (s[e]) {\n            this.eventMap[e] = s[e].bind(s);\n          }\n        }, this);\n        this.eventSources[name] = s;\n        this.eventSourceList.push(s);\n      }\n    },\n    register: function(element) {\n      var l = this.eventSourceList.length;\n      for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) {\n        // call eventsource register\n        es.register.call(es, element);\n      }\n    },\n    unregister: function(element) {\n      var l = this.eventSourceList.length;\n      for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) {\n        // call eventsource register\n        es.unregister.call(es, element);\n      }\n    },\n    contains: scope.external.contains || function(container, contained) {\n      return container.contains(contained);\n    },\n    // EVENTS\n    down: function(inEvent) {\n      this.fireEvent('pointerdown', inEvent);\n    },\n    move: function(inEvent) {\n      this.fireEvent('pointermove', inEvent);\n    },\n    up: function(inEvent) {\n      this.fireEvent('pointerup', inEvent);\n    },\n    enter: function(inEvent) {\n      inEvent.bubbles = false;\n      this.fireEvent('pointerenter', inEvent);\n    },\n    leave: function(inEvent) {\n      inEvent.bubbles = false;\n      this.fireEvent('pointerleave', inEvent);\n    },\n    over: function(inEvent) {\n      inEvent.bubbles = true;\n      this.fireEvent('pointerover', inEvent);\n    },\n    out: function(inEvent) {\n      inEvent.bubbles = true;\n      this.fireEvent('pointerout', inEvent);\n    },\n    cancel: function(inEvent) {\n      this.fireEvent('pointercancel', inEvent);\n    },\n    leaveOut: function(event) {\n      this.out(event);\n      if (!this.contains(event.target, event.relatedTarget)) {\n        this.leave(event);\n      }\n    },\n    enterOver: function(event) {\n      this.over(event);\n      if (!this.contains(event.target, event.relatedTarget)) {\n        this.enter(event);\n      }\n    },\n    // LISTENER LOGIC\n    eventHandler: function(inEvent) {\n      // This is used to prevent multiple dispatch of pointerevents from\n      // platform events. This can happen when two elements in different scopes\n      // are set up to create pointer events, which is relevant to Shadow DOM.\n      if (this.handledEvents.get(inEvent)) {\n        return;\n      }\n      var type = inEvent.type;\n      var fn = this.eventMap && this.eventMap[type];\n      if (fn) {\n        fn(inEvent);\n      }\n      this.handledEvents.set(inEvent, true);\n    },\n    // set up event listeners\n    listen: function(target, events) {\n      events.forEach(function(e) {\n        this.addEvent(target, e);\n      }, this);\n    },\n    // remove event listeners\n    unlisten: function(target, events) {\n      events.forEach(function(e) {\n        this.removeEvent(target, e);\n      }, this);\n    },\n    addEvent: scope.external.addEvent || function(target, eventName) {\n      target.addEventListener(eventName, this.boundHandler);\n    },\n    removeEvent: scope.external.removeEvent || function(target, eventName) {\n      target.removeEventListener(eventName, this.boundHandler);\n    },\n    // EVENT CREATION AND TRACKING\n    /**\n     * Creates a new Event of type `inType`, based on the information in\n     * `inEvent`.\n     *\n     * @param {string} inType A string representing the type of event to create\n     * @param {Event} inEvent A platform event with a target\n     * @return {Event} A PointerEvent of type `inType`\n     */\n    makeEvent: function(inType, inEvent) {\n      // relatedTarget must be null if pointer is captured\n      if (this.captureInfo) {\n        inEvent.relatedTarget = null;\n      }\n      var e = new PointerEvent(inType, inEvent);\n      if (inEvent.preventDefault) {\n        e.preventDefault = inEvent.preventDefault;\n      }\n      this.targets.set(e, this.targets.get(inEvent) || inEvent.target);\n      return e;\n    },\n    // make and dispatch an event in one call\n    fireEvent: function(inType, inEvent) {\n      var e = this.makeEvent(inType, inEvent);\n      return this.dispatchEvent(e);\n    },\n    /**\n     * Returns a snapshot of inEvent, with writable properties.\n     *\n     * @param {Event} inEvent An event that contains properties to copy.\n     * @return {Object} An object containing shallow copies of `inEvent`'s\n     *    properties.\n     */\n    cloneEvent: function(inEvent) {\n      var eventCopy = {}, p;\n      for (var i = 0; i < CLONE_PROPS.length; i++) {\n        p = CLONE_PROPS[i];\n        eventCopy[p] = inEvent[p] || CLONE_DEFAULTS[i];\n        // Work around SVGInstanceElement shadow tree\n        // Return the <use> element that is represented by the instance for Safari, Chrome, IE.\n        // This is the behavior implemented by Firefox.\n        if (HAS_SVG_INSTANCE && (p === 'target' || p === 'relatedTarget')) {\n          if (eventCopy[p] instanceof SVGElementInstance) {\n            eventCopy[p] = eventCopy[p].correspondingUseElement;\n          }\n        }\n      }\n      // keep the semantics of preventDefault\n      if (inEvent.preventDefault) {\n        eventCopy.preventDefault = function() {\n          inEvent.preventDefault();\n        };\n      }\n      return eventCopy;\n    },\n    getTarget: function(inEvent) {\n      // if pointer capture is set, route all events for the specified pointerId\n      // to the capture target\n      if (this.captureInfo) {\n        if (this.captureInfo.id === inEvent.pointerId) {\n          return this.captureInfo.target;\n        }\n      }\n      return this.targets.get(inEvent);\n    },\n    setCapture: function(inPointerId, inTarget) {\n      if (this.captureInfo) {\n        this.releaseCapture(this.captureInfo.id);\n      }\n      this.captureInfo = {id: inPointerId, target: inTarget};\n      var e = new PointerEvent('gotpointercapture', { bubbles: true });\n      this.implicitRelease = this.releaseCapture.bind(this, inPointerId);\n      document.addEventListener('pointerup', this.implicitRelease);\n      document.addEventListener('pointercancel', this.implicitRelease);\n      this.targets.set(e, inTarget);\n      this.asyncDispatchEvent(e);\n    },\n    releaseCapture: function(inPointerId) {\n      if (this.captureInfo && this.captureInfo.id === inPointerId) {\n        var e = new PointerEvent('lostpointercapture', { bubbles: true });\n        var t = this.captureInfo.target;\n        this.captureInfo = null;\n        document.removeEventListener('pointerup', this.implicitRelease);\n        document.removeEventListener('pointercancel', this.implicitRelease);\n        this.targets.set(e, t);\n        this.asyncDispatchEvent(e);\n      }\n    },\n    /**\n     * Dispatches the event to its target.\n     *\n     * @param {Event} inEvent The event to be dispatched.\n     * @return {Boolean} True if an event handler returns true, false otherwise.\n     */\n    dispatchEvent: scope.external.dispatchEvent || function(inEvent) {\n      var t = this.getTarget(inEvent);\n      if (t) {\n        return t.dispatchEvent(inEvent);\n      }\n    },\n    asyncDispatchEvent: function(inEvent) {\n      setTimeout(this.dispatchEvent.bind(this, inEvent), 0);\n    }\n  };\n  dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher);\n  scope.dispatcher = dispatcher;\n  scope.register = dispatcher.register.bind(dispatcher);\n  scope.unregister = dispatcher.unregister.bind(dispatcher);\n})(window.PointerEventsPolyfill);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This module uses Mutation Observers to dynamically adjust which nodes will\n * generate Pointer Events.\n *\n * All nodes that wish to generate Pointer Events must have the attribute\n * `touch-action` set to `none`.\n */\n(function(scope) {\n  var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);\n  var map = Array.prototype.map.call.bind(Array.prototype.map);\n  var toArray = Array.prototype.slice.call.bind(Array.prototype.slice);\n  var filter = Array.prototype.filter.call.bind(Array.prototype.filter);\n  var MO = window.MutationObserver || window.WebKitMutationObserver;\n  var SELECTOR = '[touch-action]';\n  var OBSERVER_INIT = {\n    subtree: true,\n    childList: true,\n    attributes: true,\n    attributeOldValue: true,\n    attributeFilter: ['touch-action']\n  };\n\n  function Installer(add, remove, changed, binder) {\n    this.addCallback = add.bind(binder);\n    this.removeCallback = remove.bind(binder);\n    this.changedCallback = changed.bind(binder);\n    if (MO) {\n      this.observer = new MO(this.mutationWatcher.bind(this));\n    }\n  }\n\n  Installer.prototype = {\n    watchSubtree: function(target) {\n      // Only watch scopes that can target find, as these are top-level.\n      // Otherwise we can see duplicate additions and removals that add noise.\n      //\n      // TODO(dfreedman): For some instances with ShadowDOMPolyfill, we can see\n      // a removal without an insertion when a node is redistributed among\n      // shadows. Since it all ends up correct in the document, watching only\n      // the document will yield the correct mutations to watch.\n      if (scope.targetFinding.canTarget(target)) {\n        this.observer.observe(target, OBSERVER_INIT);\n      }\n    },\n    enableOnSubtree: function(target) {\n      this.watchSubtree(target);\n      if (target === document && document.readyState !== 'complete') {\n        this.installOnLoad();\n      } else {\n        this.installNewSubtree(target);\n      }\n    },\n    installNewSubtree: function(target) {\n      forEach(this.findElements(target), this.addElement, this);\n    },\n    findElements: function(target) {\n      if (target.querySelectorAll) {\n        return target.querySelectorAll(SELECTOR);\n      }\n      return [];\n    },\n    removeElement: function(el) {\n      this.removeCallback(el);\n    },\n    addElement: function(el) {\n      this.addCallback(el);\n    },\n    elementChanged: function(el, oldValue) {\n      this.changedCallback(el, oldValue);\n    },\n    concatLists: function(accum, list) {\n      return accum.concat(toArray(list));\n    },\n    // register all touch-action = none nodes on document load\n    installOnLoad: function() {\n      document.addEventListener('DOMContentLoaded', this.installNewSubtree.bind(this, document));\n    },\n    isElement: function(n) {\n      return n.nodeType === Node.ELEMENT_NODE;\n    },\n    flattenMutationTree: function(inNodes) {\n      // find children with touch-action\n      var tree = map(inNodes, this.findElements, this);\n      // make sure the added nodes are accounted for\n      tree.push(filter(inNodes, this.isElement));\n      // flatten the list\n      return tree.reduce(this.concatLists, []);\n    },\n    mutationWatcher: function(mutations) {\n      mutations.forEach(this.mutationHandler, this);\n    },\n    mutationHandler: function(m) {\n      if (m.type === 'childList') {\n        var added = this.flattenMutationTree(m.addedNodes);\n        added.forEach(this.addElement, this);\n        var removed = this.flattenMutationTree(m.removedNodes);\n        removed.forEach(this.removeElement, this);\n      } else if (m.type === 'attributes') {\n        this.elementChanged(m.target, m.oldValue);\n      }\n    }\n  };\n\n  if (!MO) {\n    Installer.prototype.watchSubtree = function(){\n      console.warn('PointerEventsPolyfill: MutationObservers not found, touch-action will not be dynamically detected');\n    };\n  }\n\n  scope.Installer = Installer;\n})(window.PointerEventsPolyfill);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function (scope) {\n  var dispatcher = scope.dispatcher;\n  var pointermap = dispatcher.pointermap;\n  // radius around touchend that swallows mouse events\n  var DEDUP_DIST = 25;\n\n  // handler block for native mouse events\n  var mouseEvents = {\n    POINTER_ID: 1,\n    POINTER_TYPE: 'mouse',\n    events: [\n      'mousedown',\n      'mousemove',\n      'mouseup',\n      'mouseover',\n      'mouseout'\n    ],\n    register: function(target) {\n      dispatcher.listen(target, this.events);\n    },\n    unregister: function(target) {\n      dispatcher.unlisten(target, this.events);\n    },\n    lastTouches: [],\n    // collide with the global mouse listener\n    isEventSimulatedFromTouch: function(inEvent) {\n      var lts = this.lastTouches;\n      var x = inEvent.clientX, y = inEvent.clientY;\n      for (var i = 0, l = lts.length, t; i < l && (t = lts[i]); i++) {\n        // simulated mouse events will be swallowed near a primary touchend\n        var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y);\n        if (dx <= DEDUP_DIST && dy <= DEDUP_DIST) {\n          return true;\n        }\n      }\n    },\n    prepareEvent: function(inEvent) {\n      var e = dispatcher.cloneEvent(inEvent);\n      // forward mouse preventDefault\n      var pd = e.preventDefault;\n      e.preventDefault = function() {\n        inEvent.preventDefault();\n        pd();\n      };\n      e.pointerId = this.POINTER_ID;\n      e.isPrimary = true;\n      e.pointerType = this.POINTER_TYPE;\n      return e;\n    },\n    mousedown: function(inEvent) {\n      if (!this.isEventSimulatedFromTouch(inEvent)) {\n        var p = pointermap.has(this.POINTER_ID);\n        // TODO(dfreedman) workaround for some elements not sending mouseup\n        // http://crbug/149091\n        if (p) {\n          this.cancel(inEvent);\n        }\n        var e = this.prepareEvent(inEvent);\n        pointermap.set(this.POINTER_ID, inEvent);\n        dispatcher.down(e);\n      }\n    },\n    mousemove: function(inEvent) {\n      if (!this.isEventSimulatedFromTouch(inEvent)) {\n        var e = this.prepareEvent(inEvent);\n        dispatcher.move(e);\n      }\n    },\n    mouseup: function(inEvent) {\n      if (!this.isEventSimulatedFromTouch(inEvent)) {\n        var p = pointermap.get(this.POINTER_ID);\n        if (p && p.button === inEvent.button) {\n          var e = this.prepareEvent(inEvent);\n          dispatcher.up(e);\n          this.cleanupMouse();\n        }\n      }\n    },\n    mouseover: function(inEvent) {\n      if (!this.isEventSimulatedFromTouch(inEvent)) {\n        var e = this.prepareEvent(inEvent);\n        dispatcher.enterOver(e);\n      }\n    },\n    mouseout: function(inEvent) {\n      if (!this.isEventSimulatedFromTouch(inEvent)) {\n        var e = this.prepareEvent(inEvent);\n        dispatcher.leaveOut(e);\n      }\n    },\n    cancel: function(inEvent) {\n      var e = this.prepareEvent(inEvent);\n      dispatcher.cancel(e);\n      this.cleanupMouse();\n    },\n    cleanupMouse: function() {\n      pointermap['delete'](this.POINTER_ID);\n    }\n  };\n\n  scope.mouseEvents = mouseEvents;\n})(window.PointerEventsPolyfill);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n  var dispatcher = scope.dispatcher;\n  var findTarget = scope.findTarget;\n  var allShadows = scope.targetFinding.allShadows.bind(scope.targetFinding);\n  var pointermap = dispatcher.pointermap;\n  var touchMap = Array.prototype.map.call.bind(Array.prototype.map);\n  // This should be long enough to ignore compat mouse events made by touch\n  var DEDUP_TIMEOUT = 2500;\n  var CLICK_COUNT_TIMEOUT = 200;\n  var ATTRIB = 'touch-action';\n  var INSTALLER;\n  // The presence of touch event handlers blocks scrolling, and so we must be careful to\n  // avoid adding handlers unnecessarily.  Chrome plans to add a touch-action-delay property\n  // (crbug.com/329559) to address this, and once we have that we can opt-in to a simpler\n  // handler registration mechanism.  Rather than try to predict how exactly to opt-in to\n  // that we'll just leave this disabled until there is a build of Chrome to test.\n  var HAS_TOUCH_ACTION_DELAY = false;\n  \n  // handler block for native touch events\n  var touchEvents = {\n    scrollType: new WeakMap(),\n    events: [\n      'touchstart',\n      'touchmove',\n      'touchend',\n      'touchcancel'\n    ],\n    register: function(target) {\n      if (HAS_TOUCH_ACTION_DELAY) {\n        dispatcher.listen(target, this.events);\n      } else {\n        INSTALLER.enableOnSubtree(target);\n      }\n    },\n    unregister: function(target) {\n      if (HAS_TOUCH_ACTION_DELAY) {\n        dispatcher.unlisten(target, this.events);\n      } else {\n        // TODO(dfreedman): is it worth it to disconnect the MO?\n      }\n    },\n    elementAdded: function(el) {\n      var a = el.getAttribute(ATTRIB);\n      var st = this.touchActionToScrollType(a);\n      if (st) {\n        this.scrollType.set(el, st);\n        dispatcher.listen(el, this.events);\n        // set touch-action on shadows as well\n        allShadows(el).forEach(function(s) {\n          this.scrollType.set(s, st);\n          dispatcher.listen(s, this.events);\n        }, this);\n      }\n    },\n    elementRemoved: function(el) {\n      this.scrollType['delete'](el);\n      dispatcher.unlisten(el, this.events);\n      // remove touch-action from shadow\n      allShadows(el).forEach(function(s) {\n        this.scrollType['delete'](s);\n        dispatcher.unlisten(s, this.events);\n      }, this);\n    },\n    elementChanged: function(el, oldValue) {\n      var a = el.getAttribute(ATTRIB);\n      var st = this.touchActionToScrollType(a);\n      var oldSt = this.touchActionToScrollType(oldValue);\n      // simply update scrollType if listeners are already established\n      if (st && oldSt) {\n        this.scrollType.set(el, st);\n        allShadows(el).forEach(function(s) {\n          this.scrollType.set(s, st);\n        }, this);\n      } else if (oldSt) {\n        this.elementRemoved(el);\n      } else if (st) {\n        this.elementAdded(el);\n      }\n    },\n    scrollTypes: {\n      EMITTER: 'none',\n      XSCROLLER: 'pan-x',\n      YSCROLLER: 'pan-y',\n      SCROLLER: /^(?:pan-x pan-y)|(?:pan-y pan-x)|auto$/\n    },\n    touchActionToScrollType: function(touchAction) {\n      var t = touchAction;\n      var st = this.scrollTypes;\n      if (t === 'none') {\n        return 'none';\n      } else if (t === st.XSCROLLER) {\n        return 'X';\n      } else if (t === st.YSCROLLER) {\n        return 'Y';\n      } else if (st.SCROLLER.exec(t)) {\n        return 'XY';\n      }\n    },\n    POINTER_TYPE: 'touch',\n    firstTouch: null,\n    isPrimaryTouch: function(inTouch) {\n      return this.firstTouch === inTouch.identifier;\n    },\n    setPrimaryTouch: function(inTouch) {\n      // set primary touch if there no pointers, or the only pointer is the mouse\n      if (pointermap.pointers() === 0 || (pointermap.pointers() === 1 && pointermap.has(1))) {\n        this.firstTouch = inTouch.identifier;\n        this.firstXY = {X: inTouch.clientX, Y: inTouch.clientY};\n        this.scrolling = false;\n        this.cancelResetClickCount();\n      }\n    },\n    removePrimaryPointer: function(inPointer) {\n      if (inPointer.isPrimary) {\n        this.firstTouch = null;\n        this.firstXY = null;\n        this.resetClickCount();\n      }\n    },\n    clickCount: 0,\n    resetId: null,\n    resetClickCount: function() {\n      var fn = function() {\n        this.clickCount = 0;\n        this.resetId = null;\n      }.bind(this);\n      this.resetId = setTimeout(fn, CLICK_COUNT_TIMEOUT);\n    },\n    cancelResetClickCount: function() {\n      if (this.resetId) {\n        clearTimeout(this.resetId);\n      }\n    },\n    touchToPointer: function(inTouch) {\n      var e = dispatcher.cloneEvent(inTouch);\n      // Spec specifies that pointerId 1 is reserved for Mouse.\n      // Touch identifiers can start at 0.\n      // Add 2 to the touch identifier for compatibility.\n      e.pointerId = inTouch.identifier + 2;\n      e.target = findTarget(e);\n      e.bubbles = true;\n      e.cancelable = true;\n      e.detail = this.clickCount;\n      e.button = 0;\n      e.buttons = 1;\n      e.width = inTouch.webkitRadiusX || inTouch.radiusX || 0;\n      e.height = inTouch.webkitRadiusY || inTouch.radiusY || 0;\n      e.pressure = inTouch.webkitForce || inTouch.force || 0.5;\n      e.isPrimary = this.isPrimaryTouch(inTouch);\n      e.pointerType = this.POINTER_TYPE;\n      return e;\n    },\n    processTouches: function(inEvent, inFunction) {\n      var tl = inEvent.changedTouches;\n      var pointers = touchMap(tl, this.touchToPointer, this);\n      // forward touch preventDefaults\n      pointers.forEach(function(p) {\n        p.preventDefault = function() {\n          this.scrolling = false;\n          this.firstXY = null;\n          inEvent.preventDefault();\n        };\n      }, this);\n      pointers.forEach(inFunction, this);\n    },\n    // For single axis scrollers, determines whether the element should emit\n    // pointer events or behave as a scroller\n    shouldScroll: function(inEvent) {\n      if (this.firstXY) {\n        var ret;\n        var scrollAxis = this.scrollType.get(inEvent.currentTarget);\n        if (scrollAxis === 'none') {\n          // this element is a touch-action: none, should never scroll\n          ret = false;\n        } else if (scrollAxis === 'XY') {\n          // this element should always scroll\n          ret = true;\n        } else {\n          var t = inEvent.changedTouches[0];\n          // check the intended scroll axis, and other axis\n          var a = scrollAxis;\n          var oa = scrollAxis === 'Y' ? 'X' : 'Y';\n          var da = Math.abs(t['client' + a] - this.firstXY[a]);\n          var doa = Math.abs(t['client' + oa] - this.firstXY[oa]);\n          // if delta in the scroll axis > delta other axis, scroll instead of\n          // making events\n          ret = da >= doa;\n        }\n        this.firstXY = null;\n        return ret;\n      }\n    },\n    findTouch: function(inTL, inId) {\n      for (var i = 0, l = inTL.length, t; i < l && (t = inTL[i]); i++) {\n        if (t.identifier === inId) {\n          return true;\n        }\n      }\n    },\n    // In some instances, a touchstart can happen without a touchend. This\n    // leaves the pointermap in a broken state.\n    // Therefore, on every touchstart, we remove the touches that did not fire a\n    // touchend event.\n    // To keep state globally consistent, we fire a\n    // pointercancel for this \"abandoned\" touch\n    vacuumTouches: function(inEvent) {\n      var tl = inEvent.touches;\n      // pointermap.pointers() should be < tl.length here, as the touchstart has not\n      // been processed yet.\n      if (pointermap.pointers() >= tl.length) {\n        var d = [];\n        pointermap.forEach(function(value, key) {\n          // Never remove pointerId == 1, which is mouse.\n          // Touch identifiers are 2 smaller than their pointerId, which is the\n          // index in pointermap.\n          if (key !== 1 && !this.findTouch(tl, key - 2)) {\n            var p = value.out;\n            d.push(this.touchToPointer(p));\n          }\n        }, this);\n        d.forEach(this.cancelOut, this);\n      }\n    },\n    touchstart: function(inEvent) {\n      this.vacuumTouches(inEvent);\n      this.setPrimaryTouch(inEvent.changedTouches[0]);\n      this.dedupSynthMouse(inEvent);\n      if (!this.scrolling) {\n        this.clickCount++;\n        this.processTouches(inEvent, this.overDown);\n      }\n    },\n    overDown: function(inPointer) {\n      var p = pointermap.set(inPointer.pointerId, {\n        target: inPointer.target,\n        out: inPointer,\n        outTarget: inPointer.target\n      });\n      dispatcher.over(inPointer);\n      dispatcher.enter(inPointer);\n      dispatcher.down(inPointer);\n    },\n    touchmove: function(inEvent) {\n      if (!this.scrolling) {\n        if (this.shouldScroll(inEvent)) {\n          this.scrolling = true;\n          this.touchcancel(inEvent);\n        } else {\n          inEvent.preventDefault();\n          this.processTouches(inEvent, this.moveOverOut);\n        }\n      }\n    },\n    moveOverOut: function(inPointer) {\n      var event = inPointer;\n      var pointer = pointermap.get(event.pointerId);\n      // a finger drifted off the screen, ignore it\n      if (!pointer) {\n        return;\n      }\n      var outEvent = pointer.out;\n      var outTarget = pointer.outTarget;\n      dispatcher.move(event);\n      if (outEvent && outTarget !== event.target) {\n        outEvent.relatedTarget = event.target;\n        event.relatedTarget = outTarget;\n        // recover from retargeting by shadow\n        outEvent.target = outTarget;\n        if (event.target) {\n          dispatcher.leaveOut(outEvent);\n          dispatcher.enterOver(event);\n        } else {\n          // clean up case when finger leaves the screen\n          event.target = outTarget;\n          event.relatedTarget = null;\n          this.cancelOut(event);\n        }\n      }\n      pointer.out = event;\n      pointer.outTarget = event.target;\n    },\n    touchend: function(inEvent) {\n      this.dedupSynthMouse(inEvent);\n      this.processTouches(inEvent, this.upOut);\n    },\n    upOut: function(inPointer) {\n      if (!this.scrolling) {\n        dispatcher.up(inPointer);\n        dispatcher.out(inPointer);\n        dispatcher.leave(inPointer);\n      }\n      this.cleanUpPointer(inPointer);\n    },\n    touchcancel: function(inEvent) {\n      this.processTouches(inEvent, this.cancelOut);\n    },\n    cancelOut: function(inPointer) {\n      dispatcher.cancel(inPointer);\n      dispatcher.out(inPointer);\n      dispatcher.leave(inPointer);\n      this.cleanUpPointer(inPointer);\n    },\n    cleanUpPointer: function(inPointer) {\n      pointermap['delete'](inPointer.pointerId);\n      this.removePrimaryPointer(inPointer);\n    },\n    // prevent synth mouse events from creating pointer events\n    dedupSynthMouse: function(inEvent) {\n      var lts = scope.mouseEvents.lastTouches;\n      var t = inEvent.changedTouches[0];\n      // only the primary finger will synth mouse events\n      if (this.isPrimaryTouch(t)) {\n        // remember x/y of last touch\n        var lt = {x: t.clientX, y: t.clientY};\n        lts.push(lt);\n        var fn = (function(lts, lt){\n          var i = lts.indexOf(lt);\n          if (i > -1) {\n            lts.splice(i, 1);\n          }\n        }).bind(null, lts, lt);\n        setTimeout(fn, DEDUP_TIMEOUT);\n      }\n    }\n  };\n\n  if (!HAS_TOUCH_ACTION_DELAY) {\n    INSTALLER = new scope.Installer(touchEvents.elementAdded, touchEvents.elementRemoved, touchEvents.elementChanged, touchEvents);\n  }\n\n  scope.touchEvents = touchEvents;\n})(window.PointerEventsPolyfill);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n  var dispatcher = scope.dispatcher;\n  var pointermap = dispatcher.pointermap;\n  var HAS_BITMAP_TYPE = window.MSPointerEvent && typeof window.MSPointerEvent.MSPOINTER_TYPE_MOUSE === 'number';\n  var msEvents = {\n    events: [\n      'MSPointerDown',\n      'MSPointerMove',\n      'MSPointerUp',\n      'MSPointerOut',\n      'MSPointerOver',\n      'MSPointerCancel',\n      'MSGotPointerCapture',\n      'MSLostPointerCapture'\n    ],\n    register: function(target) {\n      dispatcher.listen(target, this.events);\n    },\n    unregister: function(target) {\n      dispatcher.unlisten(target, this.events);\n    },\n    POINTER_TYPES: [\n      '',\n      'unavailable',\n      'touch',\n      'pen',\n      'mouse'\n    ],\n    prepareEvent: function(inEvent) {\n      var e = inEvent;\n      if (HAS_BITMAP_TYPE) {\n        e = dispatcher.cloneEvent(inEvent);\n        e.pointerType = this.POINTER_TYPES[inEvent.pointerType];\n      }\n      return e;\n    },\n    cleanup: function(id) {\n      pointermap['delete'](id);\n    },\n    MSPointerDown: function(inEvent) {\n      pointermap.set(inEvent.pointerId, inEvent);\n      var e = this.prepareEvent(inEvent);\n      dispatcher.down(e);\n    },\n    MSPointerMove: function(inEvent) {\n      var e = this.prepareEvent(inEvent);\n      dispatcher.move(e);\n    },\n    MSPointerUp: function(inEvent) {\n      var e = this.prepareEvent(inEvent);\n      dispatcher.up(e);\n      this.cleanup(inEvent.pointerId);\n    },\n    MSPointerOut: function(inEvent) {\n      var e = this.prepareEvent(inEvent);\n      dispatcher.leaveOut(e);\n    },\n    MSPointerOver: function(inEvent) {\n      var e = this.prepareEvent(inEvent);\n      dispatcher.enterOver(e);\n    },\n    MSPointerCancel: function(inEvent) {\n      var e = this.prepareEvent(inEvent);\n      dispatcher.cancel(e);\n      this.cleanup(inEvent.pointerId);\n    },\n    MSLostPointerCapture: function(inEvent) {\n      var e = dispatcher.makeEvent('lostpointercapture', inEvent);\n      dispatcher.dispatchEvent(e);\n    },\n    MSGotPointerCapture: function(inEvent) {\n      var e = dispatcher.makeEvent('gotpointercapture', inEvent);\n      dispatcher.dispatchEvent(e);\n    }\n  };\n\n  scope.msEvents = msEvents;\n})(window.PointerEventsPolyfill);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This module contains the handlers for native platform events.\n * From here, the dispatcher is called to create unified pointer events.\n * Included are touch events (v1), mouse events, and MSPointerEvents.\n */\n(function(scope) {\n  var dispatcher = scope.dispatcher;\n\n  // only activate if this platform does not have pointer events\n  if (window.navigator.pointerEnabled === undefined) {\n    Object.defineProperty(window.navigator, 'pointerEnabled', {value: true, enumerable: true});\n\n    if (window.navigator.msPointerEnabled) {\n      var tp = window.navigator.msMaxTouchPoints;\n      Object.defineProperty(window.navigator, 'maxTouchPoints', {\n        value: tp,\n        enumerable: true\n      });\n      dispatcher.registerSource('ms', scope.msEvents);\n    } else {\n      dispatcher.registerSource('mouse', scope.mouseEvents);\n      if (window.ontouchstart !== undefined) {\n        dispatcher.registerSource('touch', scope.touchEvents);\n      }\n    }\n\n    dispatcher.register(document);\n  }\n})(window.PointerEventsPolyfill);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n  var dispatcher = scope.dispatcher;\n  var n = window.navigator;\n  var s, r;\n  function assertDown(id) {\n    if (!dispatcher.pointermap.has(id)) {\n      throw new Error('InvalidPointerId');\n    }\n  }\n  if (n.msPointerEnabled) {\n    s = function(pointerId) {\n      assertDown(pointerId);\n      this.msSetPointerCapture(pointerId);\n    };\n    r = function(pointerId) {\n      assertDown(pointerId);\n      this.msReleasePointerCapture(pointerId);\n    };\n  } else {\n    s = function setPointerCapture(pointerId) {\n      assertDown(pointerId);\n      dispatcher.setCapture(pointerId, this);\n    };\n    r = function releasePointerCapture(pointerId) {\n      assertDown(pointerId);\n      dispatcher.releaseCapture(pointerId, this);\n    };\n  }\n  if (window.Element && !Element.prototype.setPointerCapture) {\n    Object.defineProperties(Element.prototype, {\n      'setPointerCapture': {\n        value: s\n      },\n      'releasePointerCapture': {\n        value: r\n      }\n    });\n  }\n})(window.PointerEventsPolyfill);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * PointerGestureEvent is the constructor for all PointerGesture events.\n *\n * @module PointerGestures\n * @class PointerGestureEvent\n * @extends UIEvent\n * @constructor\n * @param {String} inType Event type\n * @param {Object} [inDict] Dictionary of properties to initialize on the event\n */\n\nfunction PointerGestureEvent(inType, inDict) {\n  var dict = inDict || {};\n  var e = document.createEvent('Event');\n  var props = {\n    bubbles: Boolean(dict.bubbles) === dict.bubbles || true,\n    cancelable: Boolean(dict.cancelable) === dict.cancelable || true\n  };\n\n  e.initEvent(inType, props.bubbles, props.cancelable);\n\n  var keys = Object.keys(dict), k;\n  for (var i = 0; i < keys.length; i++) {\n    k = keys[i];\n    e[k] = dict[k];\n  }\n\n  e.preventTap = this.preventTap;\n\n  return e;\n}\n\n/**\n * Allows for any gesture to prevent the tap gesture.\n *\n * @method preventTap\n */\nPointerGestureEvent.prototype.preventTap = function() {\n  this.tapPrevented = true;\n};\n\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n  /**\n   * This class contains the gesture recognizers that create the PointerGesture\n   * events.\n   *\n   * @class PointerGestures\n   * @static\n   */\n  scope = scope || {};\n  scope.utils = {\n    LCA: {\n      // Determines the lowest node in the ancestor chain of a and b\n      find: function(a, b) {\n        if (a === b) {\n          return a;\n        }\n        // fast case, a is a direct descendant of b or vice versa\n        if (a.contains) {\n          if (a.contains(b)) {\n            return a;\n          }\n          if (b.contains(a)) {\n            return b;\n          }\n        }\n        var adepth = this.depth(a);\n        var bdepth = this.depth(b);\n        var d = adepth - bdepth;\n        if (d > 0) {\n          a = this.walk(a, d);\n        } else {\n          b = this.walk(b, -d);\n        }\n        while(a && b && a !== b) {\n          a = this.walk(a, 1);\n          b = this.walk(b, 1);\n        }\n        return a;\n      },\n      walk: function(n, u) {\n        for (var i = 0; i < u; i++) {\n          n = n.parentNode;\n        }\n        return n;\n      },\n      depth: function(n) {\n        var d = 0;\n        while(n) {\n          d++;\n          n = n.parentNode;\n        }\n        return d;\n      }\n    }\n  };\n  scope.findLCA = function(a, b) {\n    return scope.utils.LCA.find(a, b);\n  }\n  window.PointerGestures = scope;\n})(window.PointerGestures);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This module implements an map of pointer states\n */\n(function(scope) {\n  var USE_MAP = window.Map && window.Map.prototype.forEach;\n  var POINTERS_FN = function(){ return this.size; };\n  function PointerMap() {\n    if (USE_MAP) {\n      var m = new Map();\n      m.pointers = POINTERS_FN;\n      return m;\n    } else {\n      this.keys = [];\n      this.values = [];\n    }\n  }\n\n  PointerMap.prototype = {\n    set: function(inId, inEvent) {\n      var i = this.keys.indexOf(inId);\n      if (i > -1) {\n        this.values[i] = inEvent;\n      } else {\n        this.keys.push(inId);\n        this.values.push(inEvent);\n      }\n    },\n    has: function(inId) {\n      return this.keys.indexOf(inId) > -1;\n    },\n    'delete': function(inId) {\n      var i = this.keys.indexOf(inId);\n      if (i > -1) {\n        this.keys.splice(i, 1);\n        this.values.splice(i, 1);\n      }\n    },\n    get: function(inId) {\n      var i = this.keys.indexOf(inId);\n      return this.values[i];\n    },\n    clear: function() {\n      this.keys.length = 0;\n      this.values.length = 0;\n    },\n    // return value, key, map\n    forEach: function(callback, thisArg) {\n      this.values.forEach(function(v, i) {\n        callback.call(thisArg, v, this.keys[i], this);\n      }, this);\n    },\n    pointers: function() {\n      return this.keys.length;\n    }\n  };\n\n  scope.PointerMap = PointerMap;\n})(window.PointerGestures);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n  var CLONE_PROPS = [\n    // MouseEvent\n    'bubbles',\n    'cancelable',\n    'view',\n    'detail',\n    'screenX',\n    'screenY',\n    'clientX',\n    'clientY',\n    'ctrlKey',\n    'altKey',\n    'shiftKey',\n    'metaKey',\n    'button',\n    'relatedTarget',\n    // DOM Level 3\n    'buttons',\n    // PointerEvent\n    'pointerId',\n    'width',\n    'height',\n    'pressure',\n    'tiltX',\n    'tiltY',\n    'pointerType',\n    'hwTimestamp',\n    'isPrimary',\n    // event instance\n    'type',\n    'target',\n    'currentTarget',\n    'screenX',\n    'screenY',\n    'pageX',\n    'pageY',\n    'tapPrevented'\n  ];\n\n  var CLONE_DEFAULTS = [\n    // MouseEvent\n    false,\n    false,\n    null,\n    null,\n    0,\n    0,\n    0,\n    0,\n    false,\n    false,\n    false,\n    false,\n    0,\n    null,\n    // DOM Level 3\n    0,\n    // PointerEvent\n    0,\n    0,\n    0,\n    0,\n    0,\n    0,\n    '',\n    0,\n    false,\n    // event instance\n    '',\n    null,\n    null,\n    0,\n    0,\n    0,\n    0\n  ];\n\n  var dispatcher = {\n    handledEvents: new WeakMap(),\n    targets: new WeakMap(),\n    handlers: {},\n    recognizers: {},\n    events: {},\n    // Add a new gesture recognizer to the event listeners.\n    // Recognizer needs an `events` property.\n    registerRecognizer: function(inName, inRecognizer) {\n      var r = inRecognizer;\n      this.recognizers[inName] = r;\n      r.events.forEach(function(e) {\n        if (r[e]) {\n          this.events[e] = true;\n          var f = r[e].bind(r);\n          this.addHandler(e, f);\n        }\n      }, this);\n    },\n    addHandler: function(inEvent, inFn) {\n      var e = inEvent;\n      if (!this.handlers[e]) {\n        this.handlers[e] = [];\n      }\n      this.handlers[e].push(inFn);\n    },\n    // add event listeners for inTarget\n    registerTarget: function(inTarget) {\n      this.listen(Object.keys(this.events), inTarget);\n    },\n    // remove event listeners for inTarget\n    unregisterTarget: function(inTarget) {\n      this.unlisten(Object.keys(this.events), inTarget);\n    },\n    // LISTENER LOGIC\n    eventHandler: function(inEvent) {\n      if (this.handledEvents.get(inEvent)) {\n        return;\n      }\n      var type = inEvent.type, fns = this.handlers[type];\n      if (fns) {\n        this.makeQueue(fns, inEvent);\n      }\n      this.handledEvents.set(inEvent, true);\n    },\n    // queue event for async dispatch\n    makeQueue: function(inHandlerFns, inEvent) {\n      // must clone events to keep the (possibly shadowed) target correct for\n      // async dispatching\n      var e = this.cloneEvent(inEvent);\n      setTimeout(this.runQueue.bind(this, inHandlerFns, e), 0);\n    },\n    // Dispatch the queued events\n    runQueue: function(inHandlers, inEvent) {\n      this.currentPointerId = inEvent.pointerId;\n      for (var i = 0, f, l = inHandlers.length; (i < l) && (f = inHandlers[i]); i++) {\n        f(inEvent);\n      }\n      this.currentPointerId = 0;\n    },\n    // set up event listeners\n    listen: function(inEvents, inTarget) {\n      inEvents.forEach(function(e) {\n        this.addEvent(e, this.boundHandler, false, inTarget);\n      }, this);\n    },\n    // remove event listeners\n    unlisten: function(inEvents) {\n      inEvents.forEach(function(e) {\n        this.removeEvent(e, this.boundHandler, false, inTarget);\n      }, this);\n    },\n    addEvent: function(inEventName, inEventHandler, inCapture, inTarget) {\n      inTarget.addEventListener(inEventName, inEventHandler, inCapture);\n    },\n    removeEvent: function(inEventName, inEventHandler, inCapture, inTarget) {\n      inTarget.removeEventListener(inEventName, inEventHandler, inCapture);\n    },\n    // EVENT CREATION AND TRACKING\n    // Creates a new Event of type `inType`, based on the information in\n    // `inEvent`.\n    makeEvent: function(inType, inDict) {\n      return new PointerGestureEvent(inType, inDict);\n    },\n    /*\n     * Returns a snapshot of inEvent, with writable properties.\n     *\n     * @method cloneEvent\n     * @param {Event} inEvent An event that contains properties to copy.\n     * @return {Object} An object containing shallow copies of `inEvent`'s\n     *    properties.\n     */\n    cloneEvent: function(inEvent) {\n      var eventCopy = {}, p;\n      for (var i = 0; i < CLONE_PROPS.length; i++) {\n        p = CLONE_PROPS[i];\n        eventCopy[p] = inEvent[p] || CLONE_DEFAULTS[i];\n      }\n      return eventCopy;\n    },\n    // Dispatches the event to its target.\n    dispatchEvent: function(inEvent, inTarget) {\n      var t = inTarget || this.targets.get(inEvent);\n      if (t) {\n        t.dispatchEvent(inEvent);\n        if (inEvent.tapPrevented) {\n          this.preventTap(this.currentPointerId);\n        }\n      }\n    },\n    asyncDispatchEvent: function(inEvent, inTarget) {\n      var fn = function() {\n        this.dispatchEvent(inEvent, inTarget);\n      }.bind(this);\n      setTimeout(fn, 0);\n    },\n    preventTap: function(inPointerId) {\n      var t = this.recognizers.tap;\n      if (t){\n        t.preventTap(inPointerId);\n      }\n    }\n  };\n  dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher);\n  scope.dispatcher = dispatcher;\n  var registerQueue = [];\n  var immediateRegister = false;\n  /**\n   * Enable gesture events for a given scope, typically\n   * [ShadowRoots](https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#shadow-root-object).\n   *\n   * @for PointerGestures\n   * @method register\n   * @param {ShadowRoot} scope A top level scope to enable gesture\n   * support on.\n   */\n  scope.register = function(inScope) {\n    if (immediateRegister) {\n      var pe = window.PointerEventsPolyfill;\n      if (pe) {\n        pe.register(inScope);\n      }\n      scope.dispatcher.registerTarget(inScope);\n    } else {\n      registerQueue.push(inScope);\n    }\n  };\n  // wait to register scopes until recognizers load\n  document.addEventListener('DOMContentLoaded', function() {\n    immediateRegister = true;\n    registerQueue.push(document);\n    registerQueue.forEach(scope.register);\n  });\n})(window.PointerGestures);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This event is fired when a pointer is held down for 200ms.\n *\n * @module PointerGestures\n * @submodule Events\n * @class hold\n */\n/**\n * Milliseconds pointer has been held down.\n * @type Number\n * @property holdTime\n */\n/**\n * Type of pointer that made the holding event.\n * @type String\n * @property pointerType\n */\n/**\n * This event is fired every 200ms while a pointer is held down.\n *\n * @class holdpulse\n * @extends hold\n */\n/**\n * This event is fired when a held pointer is released or moved.\n *\n * @class released\n */\n/**\n * Type of pointer that made the holding event.\n * @type String\n * @property pointerType\n */\n\n(function(scope) {\n  var dispatcher = scope.dispatcher;\n  var hold = {\n    // wait at least HOLD_DELAY ms between hold and pulse events\n    HOLD_DELAY: 200,\n    // pointer can move WIGGLE_THRESHOLD pixels before not counting as a hold\n    WIGGLE_THRESHOLD: 16,\n    events: [\n      'pointerdown',\n      'pointermove',\n      'pointerup',\n      'pointercancel'\n    ],\n    heldPointer: null,\n    holdJob: null,\n    pulse: function() {\n      var hold = Date.now() - this.heldPointer.timeStamp;\n      var type = this.held ? 'holdpulse' : 'hold';\n      this.fireHold(type, hold);\n      this.held = true;\n    },\n    cancel: function() {\n      clearInterval(this.holdJob);\n      if (this.held) {\n        this.fireHold('release');\n      }\n      this.held = false;\n      this.heldPointer = null;\n      this.target = null;\n      this.holdJob = null;\n    },\n    pointerdown: function(inEvent) {\n      if (inEvent.isPrimary && !this.heldPointer) {\n        this.heldPointer = inEvent;\n        this.target = inEvent.target;\n        this.holdJob = setInterval(this.pulse.bind(this), this.HOLD_DELAY);\n      }\n    },\n    pointerup: function(inEvent) {\n      if (this.heldPointer && this.heldPointer.pointerId === inEvent.pointerId) {\n        this.cancel();\n      }\n    },\n    pointercancel: function(inEvent) {\n      this.cancel();\n    },\n    pointermove: function(inEvent) {\n      if (this.heldPointer && this.heldPointer.pointerId === inEvent.pointerId) {\n        var x = inEvent.clientX - this.heldPointer.clientX;\n        var y = inEvent.clientY - this.heldPointer.clientY;\n        if ((x * x + y * y) > this.WIGGLE_THRESHOLD) {\n          this.cancel();\n        }\n      }\n    },\n    fireHold: function(inType, inHoldTime) {\n      var p = {\n        pointerType: this.heldPointer.pointerType\n      };\n      if (inHoldTime) {\n        p.holdTime = inHoldTime;\n      }\n      var e = dispatcher.makeEvent(inType, p);\n      dispatcher.dispatchEvent(e, this.target);\n      if (e.tapPrevented) {\n        dispatcher.preventTap(this.heldPointer.pointerId);\n      }\n    }\n  };\n  dispatcher.registerRecognizer('hold', hold);\n})(window.PointerGestures);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This event denotes the beginning of a series of tracking events.\n *\n * @module PointerGestures\n * @submodule Events\n * @class trackstart\n */\n/**\n * Pixels moved in the x direction since trackstart.\n * @type Number\n * @property dx\n */\n/**\n * Pixes moved in the y direction since trackstart.\n * @type Number\n * @property dy\n */\n/**\n * Pixels moved in the x direction since the last track.\n * @type Number\n * @property ddx\n */\n/**\n * Pixles moved in the y direction since the last track.\n * @type Number\n * @property ddy\n */\n/**\n * The clientX position of the track gesture.\n * @type Number\n * @property clientX\n */\n/**\n * The clientY position of the track gesture.\n * @type Number\n * @property clientY\n */\n/**\n * The pageX position of the track gesture.\n * @type Number\n * @property pageX\n */\n/**\n * The pageY position of the track gesture.\n * @type Number\n * @property pageY\n */\n/**\n * The screenX position of the track gesture.\n * @type Number\n * @property screenX\n */\n/**\n * The screenY position of the track gesture.\n * @type Number\n * @property screenY\n */\n/**\n * The last x axis direction of the pointer.\n * @type Number\n * @property xDirection\n */\n/**\n * The last y axis direction of the pointer.\n * @type Number\n * @property yDirection\n */\n/**\n * A shared object between all tracking events.\n * @type Object\n * @property trackInfo\n */\n/**\n * The element currently under the pointer.\n * @type Element\n * @property relatedTarget\n */\n/**\n * The type of pointer that make the track gesture.\n * @type String\n * @property pointerType\n */\n/**\n *\n * This event fires for all pointer movement being tracked.\n *\n * @class track\n * @extends trackstart\n */\n/**\n * This event fires when the pointer is no longer being tracked.\n *\n * @class trackend\n * @extends trackstart\n */\n\n (function(scope) {\n   var dispatcher = scope.dispatcher;\n   var pointermap = new scope.PointerMap();\n   var track = {\n     events: [\n       'pointerdown',\n       'pointermove',\n       'pointerup',\n       'pointercancel'\n     ],\n     WIGGLE_THRESHOLD: 4,\n     clampDir: function(inDelta) {\n       return inDelta > 0 ? 1 : -1;\n     },\n     calcPositionDelta: function(inA, inB) {\n       var x = 0, y = 0;\n       if (inA && inB) {\n         x = inB.pageX - inA.pageX;\n         y = inB.pageY - inA.pageY;\n       }\n       return {x: x, y: y};\n     },\n     fireTrack: function(inType, inEvent, inTrackingData) {\n       var t = inTrackingData;\n       var d = this.calcPositionDelta(t.downEvent, inEvent);\n       var dd = this.calcPositionDelta(t.lastMoveEvent, inEvent);\n       if (dd.x) {\n         t.xDirection = this.clampDir(dd.x);\n       }\n       if (dd.y) {\n         t.yDirection = this.clampDir(dd.y);\n       }\n       var trackData = {\n         dx: d.x,\n         dy: d.y,\n         ddx: dd.x,\n         ddy: dd.y,\n         clientX: inEvent.clientX,\n         clientY: inEvent.clientY,\n         pageX: inEvent.pageX,\n         pageY: inEvent.pageY,\n         screenX: inEvent.screenX,\n         screenY: inEvent.screenY,\n         xDirection: t.xDirection,\n         yDirection: t.yDirection,\n         trackInfo: t.trackInfo,\n         relatedTarget: inEvent.target,\n         pointerType: inEvent.pointerType\n       };\n       var e = dispatcher.makeEvent(inType, trackData);\n       t.lastMoveEvent = inEvent;\n       dispatcher.dispatchEvent(e, t.downTarget);\n     },\n     pointerdown: function(inEvent) {\n       if (inEvent.isPrimary && (inEvent.pointerType === 'mouse' ? inEvent.buttons === 1 : true)) {\n         var p = {\n           downEvent: inEvent,\n           downTarget: inEvent.target,\n           trackInfo: {},\n           lastMoveEvent: null,\n           xDirection: 0,\n           yDirection: 0,\n           tracking: false\n         };\n         pointermap.set(inEvent.pointerId, p);\n       }\n     },\n     pointermove: function(inEvent) {\n       var p = pointermap.get(inEvent.pointerId);\n       if (p) {\n         if (!p.tracking) {\n           var d = this.calcPositionDelta(p.downEvent, inEvent);\n           var move = d.x * d.x + d.y * d.y;\n           // start tracking only if finger moves more than WIGGLE_THRESHOLD\n           if (move > this.WIGGLE_THRESHOLD) {\n             p.tracking = true;\n             this.fireTrack('trackstart', p.downEvent, p);\n             this.fireTrack('track', inEvent, p);\n           }\n         } else {\n           this.fireTrack('track', inEvent, p);\n         }\n       }\n     },\n     pointerup: function(inEvent) {\n       var p = pointermap.get(inEvent.pointerId);\n       if (p) {\n         if (p.tracking) {\n           this.fireTrack('trackend', inEvent, p);\n         }\n         pointermap.delete(inEvent.pointerId);\n       }\n     },\n     pointercancel: function(inEvent) {\n       this.pointerup(inEvent);\n     }\n   };\n   dispatcher.registerRecognizer('track', track);\n })(window.PointerGestures);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This event denotes a rapid down/move/up sequence from a pointer.\n *\n * The event is sent to the first element the pointer went down on.\n *\n * @module PointerGestures\n * @submodule Events\n * @class flick\n */\n/**\n * Signed velocity of the flick in the x direction.\n * @property xVelocity\n * @type Number\n */\n/**\n * Signed velocity of the flick in the y direction.\n * @type Number\n * @property yVelocity\n */\n/**\n * Unsigned total velocity of the flick.\n * @type Number\n * @property velocity\n */\n/**\n * Angle of the flick in degrees, with 0 along the\n * positive x axis.\n * @type Number\n * @property angle\n */\n/**\n * Axis with the greatest absolute velocity. Denoted\n * with 'x' or 'y'.\n * @type String\n * @property majorAxis\n */\n/**\n * Type of the pointer that made the flick.\n * @type String\n * @property pointerType\n */\n\n(function(scope) {\n  var dispatcher = scope.dispatcher;\n  var flick = {\n    // TODO(dfreedman): value should be low enough for low speed flicks, but\n    // high enough to remove accidental flicks\n    MIN_VELOCITY: 0.5 /* px/ms */,\n    MAX_QUEUE: 4,\n    moveQueue: [],\n    target: null,\n    pointerId: null,\n    events: [\n      'pointerdown',\n      'pointermove',\n      'pointerup',\n      'pointercancel'\n    ],\n    pointerdown: function(inEvent) {\n      if (inEvent.isPrimary && !this.pointerId) {\n        this.pointerId = inEvent.pointerId;\n        this.target = inEvent.target;\n        this.addMove(inEvent);\n      }\n    },\n    pointermove: function(inEvent) {\n      if (inEvent.pointerId === this.pointerId) {\n        this.addMove(inEvent);\n      }\n    },\n    pointerup: function(inEvent) {\n      if (inEvent.pointerId === this.pointerId) {\n        this.fireFlick(inEvent);\n      }\n      this.cleanup();\n    },\n    pointercancel: function(inEvent) {\n      this.cleanup();\n    },\n    cleanup: function() {\n      this.moveQueue = [];\n      this.target = null;\n      this.pointerId = null;\n    },\n    addMove: function(inEvent) {\n      if (this.moveQueue.length >= this.MAX_QUEUE) {\n        this.moveQueue.shift();\n      }\n      this.moveQueue.push(inEvent);\n    },\n    fireFlick: function(inEvent) {\n      var e = inEvent;\n      var l = this.moveQueue.length;\n      var dt, dx, dy, tx, ty, tv, x = 0, y = 0, v = 0;\n      // flick based off the fastest segment of movement\n      for (var i = 0, m; i < l && (m = this.moveQueue[i]); i++) {\n        dt = e.timeStamp - m.timeStamp;\n        dx = e.clientX - m.clientX, dy = e.clientY - m.clientY;\n        tx = dx / dt, ty = dy / dt, tv = Math.sqrt(tx * tx + ty * ty);\n        if (tv > v) {\n          x = tx, y = ty, v = tv;\n        }\n      }\n      var ma = Math.abs(x) > Math.abs(y) ? 'x' : 'y';\n      var a = this.calcAngle(x, y);\n      if (Math.abs(v) >= this.MIN_VELOCITY) {\n        var ev = dispatcher.makeEvent('flick', {\n          xVelocity: x,\n          yVelocity: y,\n          velocity: v,\n          angle: a,\n          majorAxis: ma,\n          pointerType: inEvent.pointerType\n        });\n        dispatcher.dispatchEvent(ev, this.target);\n      }\n    },\n    calcAngle: function(inX, inY) {\n      return (Math.atan2(inY, inX) * 180 / Math.PI);\n    }\n  };\n  dispatcher.registerRecognizer('flick', flick);\n})(window.PointerGestures);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/*\n * Basic strategy: find the farthest apart points, use as diameter of circle\n * react to size change and rotation of the chord\n */\n\n/**\n * @module PointerGestures\n * @submodule Events\n * @class pinch\n */\n/**\n * Scale of the pinch zoom gesture\n * @property scale\n * @type Number\n */\n/**\n * Center X position of pointers causing pinch\n * @property centerX\n * @type Number\n */\n/**\n * Center Y position of pointers causing pinch\n * @property centerY\n * @type Number\n */\n\n/**\n * @module PointerGestures\n * @submodule Events\n * @class rotate\n */\n/**\n * Angle (in degrees) of rotation. Measured from starting positions of pointers.\n * @property angle\n * @type Number\n */\n/**\n * Center X position of pointers causing rotation\n * @property centerX\n * @type Number\n */\n/**\n * Center Y position of pointers causing rotation\n * @property centerY\n * @type Number\n */\n(function(scope) {\n  var dispatcher = scope.dispatcher;\n  var pointermap = new scope.PointerMap();\n  var RAD_TO_DEG = 180 / Math.PI;\n  var pinch = {\n    events: [\n      'pointerdown',\n      'pointermove',\n      'pointerup',\n      'pointercancel'\n    ],\n    reference: {},\n    pointerdown: function(ev) {\n      pointermap.set(ev.pointerId, ev);\n      if (pointermap.pointers() == 2) {\n        var points = this.calcChord();\n        var angle = this.calcAngle(points);\n        this.reference = {\n          angle: angle,\n          diameter: points.diameter,\n          target: scope.findLCA(points.a.target, points.b.target)\n        };\n      }\n    },\n    pointerup: function(ev) {\n      pointermap.delete(ev.pointerId);\n    },\n    pointermove: function(ev) {\n      if (pointermap.has(ev.pointerId)) {\n        pointermap.set(ev.pointerId, ev);\n        if (pointermap.pointers() > 1) {\n          this.calcPinchRotate();\n        }\n      }\n    },\n    pointercancel: function(ev) {\n      this.pointerup(ev);\n    },\n    dispatchPinch: function(diameter, points) {\n      var zoom = diameter / this.reference.diameter;\n      var ev = dispatcher.makeEvent('pinch', {\n        scale: zoom,\n        centerX: points.center.x,\n        centerY: points.center.y\n      });\n      dispatcher.dispatchEvent(ev, this.reference.target);\n    },\n    dispatchRotate: function(angle, points) {\n      var diff = Math.round((angle - this.reference.angle) % 360);\n      var ev = dispatcher.makeEvent('rotate', {\n        angle: diff,\n        centerX: points.center.x,\n        centerY: points.center.y\n      });\n      dispatcher.dispatchEvent(ev, this.reference.target);\n    },\n    calcPinchRotate: function() {\n      var points = this.calcChord();\n      var diameter = points.diameter;\n      var angle = this.calcAngle(points);\n      if (diameter != this.reference.diameter) {\n        this.dispatchPinch(diameter, points);\n      }\n      if (angle != this.reference.angle) {\n        this.dispatchRotate(angle, points);\n      }\n    },\n    calcChord: function() {\n      var pointers = [];\n      pointermap.forEach(function(p) {\n        pointers.push(p);\n      });\n      var dist = 0;\n      var points = {};\n      var x, y, d;\n      for (var i = 0; i < pointers.length; i++) {\n        var a = pointers[i];\n        for (var j = i + 1; j < pointers.length; j++) {\n          var b = pointers[j];\n          x = Math.abs(a.clientX - b.clientX);\n          y = Math.abs(a.clientY - b.clientY);\n          d = x + y;\n          if (d > dist) {\n            dist = d;\n            points = {a: a, b: b};\n          }\n        }\n      }\n      x = Math.abs(points.a.clientX + points.b.clientX) / 2;\n      y = Math.abs(points.a.clientY + points.b.clientY) / 2;\n      points.center = { x: x, y: y };\n      points.diameter = dist;\n      return points;\n    },\n    calcAngle: function(points) {\n      var x = points.a.clientX - points.b.clientX;\n      var y = points.a.clientY - points.b.clientY;\n      return (360 + Math.atan2(y, x) * RAD_TO_DEG) % 360;\n    },\n  };\n  dispatcher.registerRecognizer('pinch', pinch);\n})(window.PointerGestures);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This event is fired when a pointer quickly goes down and up, and is used to\n * denote activation.\n *\n * Any gesture event can prevent the tap event from being created by calling\n * `event.preventTap`.\n *\n * Any pointer event can prevent the tap by setting the `tapPrevented` property\n * on itself.\n *\n * @module PointerGestures\n * @submodule Events\n * @class tap\n */\n/**\n * X axis position of the tap.\n * @property x\n * @type Number\n */\n/**\n * Y axis position of the tap.\n * @property y\n * @type Number\n */\n/**\n * Type of the pointer that made the tap.\n * @property pointerType\n * @type String\n */\n(function(scope) {\n  var dispatcher = scope.dispatcher;\n  var pointermap = new scope.PointerMap();\n  var tap = {\n    events: [\n      'pointerdown',\n      'pointermove',\n      'pointerup',\n      'pointercancel',\n      'keyup'\n    ],\n    pointerdown: function(inEvent) {\n      if (inEvent.isPrimary && !inEvent.tapPrevented) {\n        pointermap.set(inEvent.pointerId, {\n          target: inEvent.target,\n          x: inEvent.clientX,\n          y: inEvent.clientY\n        });\n      }\n    },\n    pointermove: function(inEvent) {\n      if (inEvent.isPrimary) {\n        var start = pointermap.get(inEvent.pointerId);\n        if (start) {\n          if (inEvent.tapPrevented) {\n            pointermap.delete(inEvent.pointerId);\n          }\n        }\n      }\n    },\n    pointerup: function(inEvent) {\n      var start = pointermap.get(inEvent.pointerId);\n      if (start && !inEvent.tapPrevented) {\n        var t = scope.findLCA(start.target, inEvent.target);\n        if (t) {\n          var e = dispatcher.makeEvent('tap', {\n            x: inEvent.clientX,\n            y: inEvent.clientY,\n            detail: inEvent.detail,\n            pointerType: inEvent.pointerType\n          });\n          dispatcher.dispatchEvent(e, t);\n        }\n      }\n      pointermap.delete(inEvent.pointerId);\n    },\n    pointercancel: function(inEvent) {\n      pointermap.delete(inEvent.pointerId);\n    },\n    keyup: function(inEvent) {\n      var code = inEvent.keyCode;\n      // 32 == spacebar\n      if (code === 32) {\n        var t = inEvent.target;\n        if (!(t instanceof HTMLInputElement || t instanceof HTMLTextAreaElement)) {\n          dispatcher.dispatchEvent(dispatcher.makeEvent('tap', {\n            x: 0,\n            y: 0,\n            detail: 0,\n            pointerType: 'unavailable'\n          }), t);\n        }\n      }\n    },\n    preventTap: function(inPointerId) {\n      pointermap.delete(inPointerId);\n    }\n  };\n  dispatcher.registerRecognizer('tap', tap);\n})(window.PointerGestures);\n",
+    "// Copyright 2011 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n(function(global) {\n  'use strict';\n\n  var filter = Array.prototype.filter.call.bind(Array.prototype.filter);\n\n  function getTreeScope(node) {\n    while (node.parentNode) {\n      node = node.parentNode;\n    }\n\n    return typeof node.getElementById === 'function' ? node : null;\n  }\n\n  // JScript does not have __proto__. We wrap all object literals with\n  // createObject which uses Object.create, Object.defineProperty and\n  // Object.getOwnPropertyDescriptor to create a new object that does the exact\n  // same thing. The main downside to this solution is that we have to extract\n  // all those property descriptors for IE.\n  var createObject = ('__proto__' in {}) ?\n      function(obj) { return obj; } :\n      function(obj) {\n        var proto = obj.__proto__;\n        if (!proto)\n          return obj;\n        var newObject = Object.create(proto);\n        Object.getOwnPropertyNames(obj).forEach(function(name) {\n          Object.defineProperty(newObject, name,\n                               Object.getOwnPropertyDescriptor(obj, name));\n        });\n        return newObject;\n      };\n\n  // IE does not support have Document.prototype.contains.\n  if (typeof document.contains != 'function') {\n    Document.prototype.contains = function(node) {\n      if (node === this || node.parentNode === this)\n        return true;\n      return this.documentElement.contains(node);\n    }\n  }\n\n  Node.prototype.bind = function(name, observable) {\n    console.error('Unhandled binding to Node: ', this, name, observable);\n  };\n\n  function unbind(node, name) {\n    var bindings = node.bindings;\n    if (!bindings) {\n      node.bindings = {};\n      return;\n    }\n\n    var binding = bindings[name];\n    if (!binding)\n      return;\n\n    binding.close();\n    bindings[name] = undefined;\n  }\n\n  Node.prototype.unbind = function(name) {\n    unbind(this, name);\n  };\n\n  Node.prototype.unbindAll = function() {\n    if (!this.bindings)\n      return;\n    var names = Object.keys(this.bindings);\n    for (var i = 0; i < names.length; i++) {\n      var binding = this.bindings[names[i]];\n      if (binding)\n        binding.close();\n    }\n\n    this.bindings = {};\n  };\n\n  function sanitizeValue(value) {\n    return value == null ? '' : value;\n  }\n\n  function updateText(node, value) {\n    node.data = sanitizeValue(value);\n  }\n\n  function textBinding(node) {\n    return function(value) {\n      return updateText(node, value);\n    };\n  }\n\n  Text.prototype.bind = function(name, value, oneTime) {\n    if (name !== 'textContent')\n      return Node.prototype.bind.call(this, name, value, oneTime);\n\n    if (oneTime)\n      return updateText(this, value);\n\n    unbind(this, 'textContent');\n    updateText(this, value.open(textBinding(this)));\n    return this.bindings.textContent = value;\n  }\n\n  function updateAttribute(el, name, conditional, value) {\n    if (conditional) {\n      if (value)\n        el.setAttribute(name, '');\n      else\n        el.removeAttribute(name);\n      return;\n    }\n\n    el.setAttribute(name, sanitizeValue(value));\n  }\n\n  function attributeBinding(el, name, conditional) {\n    return function(value) {\n      updateAttribute(el, name, conditional, value);\n    };\n  }\n\n  Element.prototype.bind = function(name, value, oneTime) {\n    var conditional = name[name.length - 1] == '?';\n    if (conditional) {\n      this.removeAttribute(name);\n      name = name.slice(0, -1);\n    }\n\n    if (oneTime)\n      return updateAttribute(this, name, conditional, value);\n\n    unbind(this, name);\n    updateAttribute(this, name, conditional,\n        value.open(attributeBinding(this, name, conditional)));\n\n    return this.bindings[name] = value;\n  };\n\n  var checkboxEventType;\n  (function() {\n    // Attempt to feature-detect which event (change or click) is fired first\n    // for checkboxes.\n    var div = document.createElement('div');\n    var checkbox = div.appendChild(document.createElement('input'));\n    checkbox.setAttribute('type', 'checkbox');\n    var first;\n    var count = 0;\n    checkbox.addEventListener('click', function(e) {\n      count++;\n      first = first || 'click';\n    });\n    checkbox.addEventListener('change', function() {\n      count++;\n      first = first || 'change';\n    });\n\n    var event = document.createEvent('MouseEvent');\n    event.initMouseEvent(\"click\", true, true, window, 0, 0, 0, 0, 0, false,\n        false, false, false, 0, null);\n    checkbox.dispatchEvent(event);\n    // WebKit/Blink don't fire the change event if the element is outside the\n    // document, so assume 'change' for that case.\n    checkboxEventType = count == 1 ? 'change' : first;\n  })();\n\n  function getEventForInputType(element) {\n    switch (element.type) {\n      case 'checkbox':\n        return checkboxEventType;\n      case 'radio':\n      case 'select-multiple':\n      case 'select-one':\n        return 'change';\n      default:\n        return 'input';\n    }\n  }\n\n  function updateInput(input, property, value, santizeFn) {\n    input[property] = (santizeFn || sanitizeValue)(value);\n  }\n\n  function inputBinding(input, property, santizeFn) {\n    return function(value) {\n      return updateInput(input, property, value, santizeFn);\n    }\n  }\n\n  function noop() {}\n\n  function bindInputEvent(input, property, observable, postEventFn) {\n    var eventType = getEventForInputType(input);\n\n    function eventHandler() {\n      observable.setValue(input[property]);\n      observable.discardChanges();\n      (postEventFn || noop)(input);\n      Platform.performMicrotaskCheckpoint();\n    }\n    input.addEventListener(eventType, eventHandler);\n\n    var capturedClose = observable.close;\n    observable.close = function() {\n      if (!capturedClose)\n        return;\n      input.removeEventListener(eventType, eventHandler);\n\n      observable.close = capturedClose;\n      observable.close();\n      capturedClose = undefined;\n    }\n  }\n\n  function booleanSanitize(value) {\n    return Boolean(value);\n  }\n\n  // |element| is assumed to be an HTMLInputElement with |type| == 'radio'.\n  // Returns an array containing all radio buttons other than |element| that\n  // have the same |name|, either in the form that |element| belongs to or,\n  // if no form, in the document tree to which |element| belongs.\n  //\n  // This implementation is based upon the HTML spec definition of a\n  // \"radio button group\":\n  //   http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state.html#radio-button-group\n  //\n  function getAssociatedRadioButtons(element) {\n    if (element.form) {\n      return filter(element.form.elements, function(el) {\n        return el != element &&\n            el.tagName == 'INPUT' &&\n            el.type == 'radio' &&\n            el.name == element.name;\n      });\n    } else {\n      var treeScope = getTreeScope(element);\n      if (!treeScope)\n        return [];\n      var radios = treeScope.querySelectorAll(\n          'input[type=\"radio\"][name=\"' + element.name + '\"]');\n      return filter(radios, function(el) {\n        return el != element && !el.form;\n      });\n    }\n  }\n\n  function checkedPostEvent(input) {\n    // Only the radio button that is getting checked gets an event. We\n    // therefore find all the associated radio buttons and update their\n    // check binding manually.\n    if (input.tagName === 'INPUT' &&\n        input.type === 'radio') {\n      getAssociatedRadioButtons(input).forEach(function(radio) {\n        var checkedBinding = radio.bindings.checked;\n        if (checkedBinding) {\n          // Set the value directly to avoid an infinite call stack.\n          checkedBinding.setValue(false);\n        }\n      });\n    }\n  }\n\n  HTMLInputElement.prototype.bind = function(name, value, oneTime) {\n    if (name !== 'value' && name !== 'checked')\n      return HTMLElement.prototype.bind.call(this, name, value, oneTime);\n\n\n    this.removeAttribute(name);\n    var sanitizeFn = name == 'checked' ? booleanSanitize : sanitizeValue;\n    var postEventFn = name == 'checked' ? checkedPostEvent : noop;\n\n    if (oneTime)\n      return updateInput(this, name, value, sanitizeFn);\n\n    unbind(this, name);\n    bindInputEvent(this, name, value, postEventFn);\n    updateInput(this, name,\n                value.open(inputBinding(this, name, sanitizeFn)),\n                sanitizeFn);\n\n    return this.bindings[name] = value;\n  }\n\n  HTMLTextAreaElement.prototype.bind = function(name, value, oneTime) {\n    if (name !== 'value')\n      return HTMLElement.prototype.bind.call(this, name, value, oneTime);\n\n    this.removeAttribute('value');\n\n    if (oneTime)\n      return updateInput(this, 'value', value);\n\n    unbind(this, 'value');\n    bindInputEvent(this, 'value', value);\n    updateInput(this, 'value',\n                value.open(inputBinding(this, 'value', sanitizeValue)));\n\n    return this.bindings.value = value;\n  }\n\n  function updateOption(option, value) {\n    var parentNode = option.parentNode;;\n    var select;\n    var selectBinding;\n    var oldValue;\n    if (parentNode instanceof HTMLSelectElement &&\n        parentNode.bindings &&\n        parentNode.bindings.value) {\n      select = parentNode;\n      selectBinding = select.bindings.value;\n      oldValue = select.value;\n    }\n\n    option.value = sanitizeValue(value);\n\n    if (select && select.value != oldValue) {\n      selectBinding.setValue(select.value);\n      selectBinding.discardChanges();\n      Platform.performMicrotaskCheckpoint();\n    }\n  }\n\n  function optionBinding(option) {\n    return function(value) {\n      updateOption(option, value);\n    }\n  }\n\n  HTMLOptionElement.prototype.bind = function(name, value, oneTime) {\n    if (name !== 'value')\n      return HTMLElement.prototype.bind.call(this, name, value, oneTime);\n\n    this.removeAttribute('value');\n\n    if (oneTime)\n      return updateOption(this, value);\n\n    unbind(this, 'value');\n    bindInputEvent(this, 'value', value);\n    updateOption(this, value.open(optionBinding(this)));\n    return this.bindings.value = value;\n  }\n\n  HTMLSelectElement.prototype.bind = function(name, value, oneTime) {\n    if (name === 'selectedindex')\n      name = 'selectedIndex';\n\n    if (name !== 'selectedIndex' && name !== 'value')\n      return HTMLElement.prototype.bind.call(this, name, value, oneTime);\n\n    this.removeAttribute(name);\n\n    if (oneTime)\n      return updateInput(this, name, value);\n\n    unbind(this, name);\n    bindInputEvent(this, name, value);\n    updateInput(this, name,\n                value.open(inputBinding(this, name)));\n    return this.bindings[name] = value;\n  }\n})(this);\n",
+    "// Copyright 2011 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n(function(global) {\n  'use strict';\n\n  function assert(v) {\n    if (!v)\n      throw new Error('Assertion failed');\n  }\n\n  var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);\n\n  function getFragmentRoot(node) {\n    var p;\n    while (p = node.parentNode) {\n      node = p;\n    }\n\n    return node;\n  }\n\n  function searchRefId(node, id) {\n    if (!id)\n      return;\n\n    var ref;\n    var selector = '#' + id;\n    while (!ref) {\n      node = getFragmentRoot(node);\n\n      if (node.protoContent_)\n        ref = node.protoContent_.querySelector(selector);\n      else if (node.getElementById)\n        ref = node.getElementById(id);\n\n      if (ref || !node.templateCreator_)\n        break\n\n      node = node.templateCreator_;\n    }\n\n    return ref;\n  }\n\n  function getInstanceRoot(node) {\n    while (node.parentNode) {\n      node = node.parentNode;\n    }\n    return node.templateCreator_ ? node : null;\n  }\n\n  var Map;\n  if (global.Map && typeof global.Map.prototype.forEach === 'function') {\n    Map = global.Map;\n  } else {\n    Map = function() {\n      this.keys = [];\n      this.values = [];\n    };\n\n    Map.prototype = {\n      set: function(key, value) {\n        var index = this.keys.indexOf(key);\n        if (index < 0) {\n          this.keys.push(key);\n          this.values.push(value);\n        } else {\n          this.values[index] = value;\n        }\n      },\n\n      get: function(key) {\n        var index = this.keys.indexOf(key);\n        if (index < 0)\n          return;\n\n        return this.values[index];\n      },\n\n      delete: function(key, value) {\n        var index = this.keys.indexOf(key);\n        if (index < 0)\n          return false;\n\n        this.keys.splice(index, 1);\n        this.values.splice(index, 1);\n        return true;\n      },\n\n      forEach: function(f, opt_this) {\n        for (var i = 0; i < this.keys.length; i++)\n          f.call(opt_this || this, this.values[i], this.keys[i], this);\n      }\n    };\n  }\n\n  // JScript does not have __proto__. We wrap all object literals with\n  // createObject which uses Object.create, Object.defineProperty and\n  // Object.getOwnPropertyDescriptor to create a new object that does the exact\n  // same thing. The main downside to this solution is that we have to extract\n  // all those property descriptors for IE.\n  var createObject = ('__proto__' in {}) ?\n      function(obj) { return obj; } :\n      function(obj) {\n        var proto = obj.__proto__;\n        if (!proto)\n          return obj;\n        var newObject = Object.create(proto);\n        Object.getOwnPropertyNames(obj).forEach(function(name) {\n          Object.defineProperty(newObject, name,\n                               Object.getOwnPropertyDescriptor(obj, name));\n        });\n        return newObject;\n      };\n\n  // IE does not support have Document.prototype.contains.\n  if (typeof document.contains != 'function') {\n    Document.prototype.contains = function(node) {\n      if (node === this || node.parentNode === this)\n        return true;\n      return this.documentElement.contains(node);\n    }\n  }\n\n  var BIND = 'bind';\n  var REPEAT = 'repeat';\n  var IF = 'if';\n\n  var templateAttributeDirectives = {\n    'template': true,\n    'repeat': true,\n    'bind': true,\n    'ref': true\n  };\n\n  var semanticTemplateElements = {\n    'THEAD': true,\n    'TBODY': true,\n    'TFOOT': true,\n    'TH': true,\n    'TR': true,\n    'TD': true,\n    'COLGROUP': true,\n    'COL': true,\n    'CAPTION': true,\n    'OPTION': true,\n    'OPTGROUP': true\n  };\n\n  var hasTemplateElement = typeof HTMLTemplateElement !== 'undefined';\n\n  var allTemplatesSelectors = 'template, ' +\n      Object.keys(semanticTemplateElements).map(function(tagName) {\n        return tagName.toLowerCase() + '[template]';\n      }).join(', ');\n\n  function isSVGTemplate(el) {\n    return el.tagName == 'template' &&\n           el.namespaceURI == 'http://www.w3.org/2000/svg';\n  }\n\n  function isHTMLTemplate(el) {\n    return el.tagName == 'TEMPLATE' &&\n           el.namespaceURI == 'http://www.w3.org/1999/xhtml';\n  }\n\n  function isAttributeTemplate(el) {\n    return Boolean(semanticTemplateElements[el.tagName] &&\n                   el.hasAttribute('template'));\n  }\n\n  function isTemplate(el) {\n    if (el.isTemplate_ === undefined)\n      el.isTemplate_ = el.tagName == 'TEMPLATE' || isAttributeTemplate(el);\n\n    return el.isTemplate_;\n  }\n\n  // FIXME: Observe templates being added/removed from documents\n  // FIXME: Expose imperative API to decorate and observe templates in\n  // \"disconnected tress\" (e.g. ShadowRoot)\n  document.addEventListener('DOMContentLoaded', function(e) {\n    bootstrapTemplatesRecursivelyFrom(document);\n    // FIXME: Is this needed? Seems like it shouldn't be.\n    Platform.performMicrotaskCheckpoint();\n  }, false);\n\n  function forAllTemplatesFrom(node, fn) {\n    var subTemplates = node.querySelectorAll(allTemplatesSelectors);\n\n    if (isTemplate(node))\n      fn(node)\n    forEach(subTemplates, fn);\n  }\n\n  function bootstrapTemplatesRecursivelyFrom(node) {\n    function bootstrap(template) {\n      if (!HTMLTemplateElement.decorate(template))\n        bootstrapTemplatesRecursivelyFrom(template.content);\n    }\n\n    forAllTemplatesFrom(node, bootstrap);\n  }\n\n  if (!hasTemplateElement) {\n    /**\n     * This represents a <template> element.\n     * @constructor\n     * @extends {HTMLElement}\n     */\n    global.HTMLTemplateElement = function() {\n      throw TypeError('Illegal constructor');\n    };\n  }\n\n  var hasProto = '__proto__' in {};\n\n  function mixin(to, from) {\n    Object.getOwnPropertyNames(from).forEach(function(name) {\n      Object.defineProperty(to, name,\n                            Object.getOwnPropertyDescriptor(from, name));\n    });\n  }\n\n  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner\n  function getOrCreateTemplateContentsOwner(template) {\n    var doc = template.ownerDocument\n    if (!doc.defaultView)\n      return doc;\n    var d = doc.templateContentsOwner_;\n    if (!d) {\n      // TODO(arv): This should either be a Document or HTMLDocument depending\n      // on doc.\n      d = doc.implementation.createHTMLDocument('');\n      while (d.lastChild) {\n        d.removeChild(d.lastChild);\n      }\n      doc.templateContentsOwner_ = d;\n    }\n    return d;\n  }\n\n  function getTemplateStagingDocument(template) {\n    if (!template.stagingDocument_) {\n      var owner = template.ownerDocument;\n      if (!owner.stagingDocument_) {\n        owner.stagingDocument_ = owner.implementation.createHTMLDocument('');\n        owner.stagingDocument_.stagingDocument_ = owner.stagingDocument_;\n      }\n\n      template.stagingDocument_ = owner.stagingDocument_;\n    }\n\n    return template.stagingDocument_;\n  }\n\n  // For non-template browsers, the parser will disallow <template> in certain\n  // locations, so we allow \"attribute templates\" which combine the template\n  // element with the top-level container node of the content, e.g.\n  //\n  //   <tr template repeat=\"{{ foo }}\"\" class=\"bar\"><td>Bar</td></tr>\n  //\n  // becomes\n  //\n  //   <template repeat=\"{{ foo }}\">\n  //   + #document-fragment\n  //     + <tr class=\"bar\">\n  //       + <td>Bar</td>\n  //\n  function extractTemplateFromAttributeTemplate(el) {\n    var template = el.ownerDocument.createElement('template');\n    el.parentNode.insertBefore(template, el);\n\n    var attribs = el.attributes;\n    var count = attribs.length;\n    while (count-- > 0) {\n      var attrib = attribs[count];\n      if (templateAttributeDirectives[attrib.name]) {\n        if (attrib.name !== 'template')\n          template.setAttribute(attrib.name, attrib.value);\n        el.removeAttribute(attrib.name);\n      }\n    }\n\n    return template;\n  }\n\n  function extractTemplateFromSVGTemplate(el) {\n    var template = el.ownerDocument.createElement('template');\n    el.parentNode.insertBefore(template, el);\n\n    var attribs = el.attributes;\n    var count = attribs.length;\n    while (count-- > 0) {\n      var attrib = attribs[count];\n      template.setAttribute(attrib.name, attrib.value);\n      el.removeAttribute(attrib.name);\n    }\n\n    el.parentNode.removeChild(el);\n    return template;\n  }\n\n  function liftNonNativeTemplateChildrenIntoContent(template, el, useRoot) {\n    var content = template.content;\n    if (useRoot) {\n      content.appendChild(el);\n      return;\n    }\n\n    var child;\n    while (child = el.firstChild) {\n      content.appendChild(child);\n    }\n  }\n\n  var templateObserver;\n  if (typeof MutationObserver == 'function') {\n    templateObserver = new MutationObserver(function(records) {\n      for (var i = 0; i < records.length; i++) {\n        records[i].target.refChanged_();\n      }\n    });\n  }\n\n  /**\n   * Ensures proper API and content model for template elements.\n   * @param {HTMLTemplateElement} opt_instanceRef The template element which\n   *     |el| template element will return as the value of its ref(), and whose\n   *     content will be used as source when createInstance() is invoked.\n   */\n  HTMLTemplateElement.decorate = function(el, opt_instanceRef) {\n    if (el.templateIsDecorated_)\n      return false;\n\n    var templateElement = el;\n    templateElement.templateIsDecorated_ = true;\n\n    var isNativeHTMLTemplate = isHTMLTemplate(templateElement) &&\n                               hasTemplateElement;\n    var bootstrapContents = isNativeHTMLTemplate;\n    var liftContents = !isNativeHTMLTemplate;\n    var liftRoot = false;\n\n    if (!isNativeHTMLTemplate) {\n      if (isAttributeTemplate(templateElement)) {\n        assert(!opt_instanceRef);\n        templateElement = extractTemplateFromAttributeTemplate(el);\n        templateElement.templateIsDecorated_ = true;\n        isNativeHTMLTemplate = hasTemplateElement;\n        liftRoot = true;\n      } else if (isSVGTemplate(templateElement)) {\n        templateElement = extractTemplateFromSVGTemplate(el);\n        templateElement.templateIsDecorated_ = true;\n        isNativeHTMLTemplate = hasTemplateElement;\n      }\n    }\n\n    if (!isNativeHTMLTemplate) {\n      fixTemplateElementPrototype(templateElement);\n      var doc = getOrCreateTemplateContentsOwner(templateElement);\n      templateElement.content_ = doc.createDocumentFragment();\n    }\n\n    if (opt_instanceRef) {\n      // template is contained within an instance, its direct content must be\n      // empty\n      templateElement.instanceRef_ = opt_instanceRef;\n    } else if (liftContents) {\n      liftNonNativeTemplateChildrenIntoContent(templateElement,\n                                               el,\n                                               liftRoot);\n    } else if (bootstrapContents) {\n      bootstrapTemplatesRecursivelyFrom(templateElement.content);\n    }\n\n    return true;\n  };\n\n  // TODO(rafaelw): This used to decorate recursively all templates from a given\n  // node. This happens by default on 'DOMContentLoaded', but may be needed\n  // in subtrees not descendent from document (e.g. ShadowRoot).\n  // Review whether this is the right public API.\n  HTMLTemplateElement.bootstrap = bootstrapTemplatesRecursivelyFrom;\n\n  var htmlElement = global.HTMLUnknownElement || HTMLElement;\n\n  var contentDescriptor = {\n    get: function() {\n      return this.content_;\n    },\n    enumerable: true,\n    configurable: true\n  };\n\n  if (!hasTemplateElement) {\n    // Gecko is more picky with the prototype than WebKit. Make sure to use the\n    // same prototype as created in the constructor.\n    HTMLTemplateElement.prototype = Object.create(htmlElement.prototype);\n\n    Object.defineProperty(HTMLTemplateElement.prototype, 'content',\n                          contentDescriptor);\n  }\n\n  function fixTemplateElementPrototype(el) {\n    if (hasProto)\n      el.__proto__ = HTMLTemplateElement.prototype;\n    else\n      mixin(el, HTMLTemplateElement.prototype);\n  }\n\n  function ensureSetModelScheduled(template) {\n    if (!template.setModelFn_) {\n      template.setModelFn_ = function() {\n        template.setModelFnScheduled_ = false;\n        var map = getBindings(template,\n            template.delegate_ && template.delegate_.prepareBinding);\n        processBindings(template, map, template.model_);\n      };\n    }\n\n    if (!template.setModelFnScheduled_) {\n      template.setModelFnScheduled_ = true;\n      Observer.runEOM_(template.setModelFn_);\n    }\n  }\n\n  mixin(HTMLTemplateElement.prototype, {\n    bind: function(name, value, oneTime) {\n      if (name != 'ref')\n        return Element.prototype.bind.call(this, name, value, oneTime);\n\n      var self = this;\n      var ref = oneTime ? value : value.open(function(ref) {\n        self.setAttribute('ref', ref);\n        self.refChanged_();\n      });\n\n      this.setAttribute('ref', ref);\n      this.refChanged_();\n      if (oneTime)\n        return;\n\n      this.unbind('ref');\n      return this.bindings.ref = value;\n    },\n\n    processBindingDirectives_: function(directives) {\n      if (this.iterator_)\n        this.iterator_.closeDeps();\n\n      if (!directives.if && !directives.bind && !directives.repeat) {\n        if (this.iterator_) {\n          this.iterator_.close();\n          this.iterator_ = undefined;\n          this.bindings.iterator = undefined;\n        }\n\n        return;\n      }\n\n      if (!this.iterator_) {\n        this.iterator_ = new TemplateIterator(this);\n        this.bindings = this.bindings || {};\n        this.bindings.iterator = this.iterator_;\n      }\n\n      this.iterator_.updateDependencies(directives, this.model_);\n\n      if (templateObserver) {\n        templateObserver.observe(this, { attributes: true,\n                                         attributeFilter: ['ref'] });\n      }\n\n      return this.iterator_;\n    },\n\n    createInstance: function(model, bindingDelegate, delegate_,\n                             instanceBindings_) {\n      if (bindingDelegate)\n        delegate_ = this.newDelegate_(bindingDelegate);\n\n      if (!this.refContent_)\n        this.refContent_ = this.ref_.content;\n      var content = this.refContent_;\n      var map = this.bindingMap_;\n      if (!map || map.content !== content) {\n        // TODO(rafaelw): Setup a MutationObserver on content to detect\n        // when the instanceMap is invalid.\n        map = createInstanceBindingMap(content,\n            delegate_ && delegate_.prepareBinding) || [];\n        map.content = content;\n        this.bindingMap_ = map;\n      }\n\n      var stagingDocument = getTemplateStagingDocument(this);\n      var instance = stagingDocument.createDocumentFragment();\n      instance.templateCreator_ = this;\n      instance.protoContent_ = content;\n\n      var instanceRecord = {\n        firstNode: null,\n        lastNode: null,\n        model: model\n      };\n\n      var i = 0;\n      for (var child = content.firstChild; child; child = child.nextSibling) {\n        var clone = cloneAndBindInstance(child, instance, stagingDocument,\n                                         map.children[i++],\n                                         model,\n                                         delegate_,\n                                         instanceBindings_);\n        clone.templateInstance_ = instanceRecord;\n      }\n\n      instanceRecord.firstNode = instance.firstChild;\n      instanceRecord.lastNode = instance.lastChild;\n      instance.templateCreator_ = undefined;\n      instance.protoContent_ = undefined;\n      return instance;\n    },\n\n    get model() {\n      return this.model_;\n    },\n\n    set model(model) {\n      this.model_ = model;\n      ensureSetModelScheduled(this);\n    },\n\n    get bindingDelegate() {\n      return this.delegate_ && this.delegate_.raw;\n    },\n\n    refChanged_: function() {\n      if (!this.iterator_ || this.refContent_ === this.ref_.content)\n        return;\n\n      this.refContent_ = undefined;\n      this.iterator_.valueChanged();\n      this.iterator_.updateIteratedValue();\n    },\n\n    clear: function() {\n      this.model_ = undefined;\n      this.delegate_ = undefined;\n      this.bindings_ = undefined;\n      this.refContent_ = undefined;\n      if (!this.iterator_)\n        return;\n      this.iterator_.valueChanged();\n      this.iterator_.close()\n      this.iterator_ = undefined;\n    },\n\n    setDelegate_: function(delegate) {\n      this.delegate_ = delegate;\n      this.bindingMap_ = undefined;\n      if (this.iterator_) {\n        this.iterator_.instancePositionChangedFn_ = undefined;\n        this.iterator_.instanceModelFn_ = undefined;\n      }\n    },\n\n    newDelegate_: function(bindingDelegate) {\n      if (!bindingDelegate)\n        return {};\n\n      function delegateFn(name) {\n        var fn = bindingDelegate && bindingDelegate[name];\n        if (typeof fn != 'function')\n          return;\n\n        return function() {\n          return fn.apply(bindingDelegate, arguments);\n        };\n      }\n\n      return {\n        raw: bindingDelegate,\n        prepareBinding: delegateFn('prepareBinding'),\n        prepareInstanceModel: delegateFn('prepareInstanceModel'),\n        prepareInstancePositionChanged:\n            delegateFn('prepareInstancePositionChanged')\n      };\n    },\n\n    // TODO(rafaelw): Assigning .bindingDelegate always succeeds. It may\n    // make sense to issue a warning or even throw if the template is already\n    // \"activated\", since this would be a strange thing to do.\n    set bindingDelegate(bindingDelegate) {\n      if (this.delegate_) {\n        throw Error('Template must be cleared before a new bindingDelegate ' +\n                    'can be assigned');\n      }\n\n      this.setDelegate_(this.newDelegate_(bindingDelegate));\n    },\n\n    get ref_() {\n      var ref = searchRefId(this, this.getAttribute('ref'));\n      if (!ref)\n        ref = this.instanceRef_;\n\n      if (!ref)\n        return this;\n\n      var nextRef = ref.ref_;\n      return nextRef ? nextRef : ref;\n    }\n  });\n\n  // Returns\n  //   a) undefined if there are no mustaches.\n  //   b) [TEXT, (ONE_TIME?, PATH, DELEGATE_FN, TEXT)+] if there is at least one mustache.\n  function parseMustaches(s, name, node, prepareBindingFn) {\n    if (!s || !s.length)\n      return;\n\n    var tokens;\n    var length = s.length;\n    var startIndex = 0, lastIndex = 0, endIndex = 0;\n    var onlyOneTime = true;\n    while (lastIndex < length) {\n      var startIndex = s.indexOf('{{', lastIndex);\n      var oneTimeStart = s.indexOf('[[', lastIndex);\n      var oneTime = false;\n      var terminator = '}}';\n\n      if (oneTimeStart >= 0 &&\n          (startIndex < 0 || oneTimeStart < startIndex)) {\n        startIndex = oneTimeStart;\n        oneTime = true;\n        terminator = ']]';\n      }\n\n      endIndex = startIndex < 0 ? -1 : s.indexOf(terminator, startIndex + 2);\n\n      if (endIndex < 0) {\n        if (!tokens)\n          return;\n\n        tokens.push(s.slice(lastIndex)); // TEXT\n        break;\n      }\n\n      tokens = tokens || [];\n      tokens.push(s.slice(lastIndex, startIndex)); // TEXT\n      var pathString = s.slice(startIndex + 2, endIndex).trim();\n      tokens.push(oneTime); // ONE_TIME?\n      onlyOneTime = onlyOneTime && oneTime;\n      tokens.push(Path.get(pathString)); // PATH\n      var delegateFn = prepareBindingFn &&\n                       prepareBindingFn(pathString, name, node);\n      tokens.push(delegateFn); // DELEGATE_FN\n      lastIndex = endIndex + 2;\n    }\n\n    if (lastIndex === length)\n      tokens.push(''); // TEXT\n\n    tokens.hasOnePath = tokens.length === 5;\n    tokens.isSimplePath = tokens.hasOnePath &&\n                          tokens[0] == '' &&\n                          tokens[4] == '';\n    tokens.onlyOneTime = onlyOneTime;\n\n    tokens.combinator = function(values) {\n      var newValue = tokens[0];\n\n      for (var i = 1; i < tokens.length; i += 4) {\n        var value = tokens.hasOnePath ? values : values[(i - 1) / 4];\n        if (value !== undefined)\n          newValue += value;\n        newValue += tokens[i + 3];\n      }\n\n      return newValue;\n    }\n\n    return tokens;\n  };\n\n  function processOneTimeBinding(name, tokens, node, model) {\n    if (tokens.hasOnePath) {\n      var delegateFn = tokens[3];\n      var value = delegateFn ? delegateFn(model, node, true) :\n                               tokens[2].getValueFrom(model);\n      return tokens.isSimplePath ? value : tokens.combinator(value);\n    }\n\n    var values = [];\n    for (var i = 1; i < tokens.length; i += 4) {\n      var delegateFn = tokens[i + 2];\n      values[(i - 1) / 4] = delegateFn ? delegateFn(model, node) :\n          tokens[i + 1].getValueFrom(model);\n    }\n\n    return tokens.combinator(values);\n  }\n\n  function processSinglePathBinding(name, tokens, node, model) {\n    var delegateFn = tokens[3];\n    var observer = delegateFn ? delegateFn(model, node, false) :\n        new PathObserver(model, tokens[2]);\n\n    return tokens.isSimplePath ? observer :\n        new ObserverTransform(observer, tokens.combinator);\n  }\n\n  function processBinding(name, tokens, node, model) {\n    if (tokens.onlyOneTime)\n      return processOneTimeBinding(name, tokens, node, model);\n\n    if (tokens.hasOnePath)\n      return processSinglePathBinding(name, tokens, node, model);\n\n    var observer = new CompoundObserver();\n\n    for (var i = 1; i < tokens.length; i += 4) {\n      var oneTime = tokens[i];\n      var delegateFn = tokens[i + 2];\n\n      if (delegateFn) {\n        var value = delegateFn(model, node, oneTime);\n        if (oneTime)\n          observer.addPath(value)\n        else\n          observer.addObserver(value);\n        continue;\n      }\n\n      var path = tokens[i + 1];\n      if (oneTime)\n        observer.addPath(path.getValueFrom(model))\n      else\n        observer.addPath(model, path);\n    }\n\n    return new ObserverTransform(observer, tokens.combinator);\n  }\n\n  function processBindings(node, bindings, model, instanceBindings) {\n    for (var i = 0; i < bindings.length; i += 2) {\n      var name = bindings[i]\n      var tokens = bindings[i + 1];\n      var value = processBinding(name, tokens, node, model);\n      var binding = node.bind(name, value, tokens.onlyOneTime);\n      if (binding && instanceBindings)\n        instanceBindings.push(binding);\n    }\n\n    if (!bindings.isTemplate)\n      return;\n\n    node.model_ = model;\n    var iter = node.processBindingDirectives_(bindings);\n    if (instanceBindings && iter)\n      instanceBindings.push(iter);\n  }\n\n  function parseWithDefault(el, name, prepareBindingFn) {\n    var v = el.getAttribute(name);\n    return parseMustaches(v == '' ? '{{}}' : v, name, el, prepareBindingFn);\n  }\n\n  function parseAttributeBindings(element, prepareBindingFn) {\n    assert(element);\n\n    var bindings = [];\n    var ifFound = false;\n    var bindFound = false;\n\n    for (var i = 0; i < element.attributes.length; i++) {\n      var attr = element.attributes[i];\n      var name = attr.name;\n      var value = attr.value;\n\n      // Allow bindings expressed in attributes to be prefixed with underbars.\n      // We do this to allow correct semantics for browsers that don't implement\n      // <template> where certain attributes might trigger side-effects -- and\n      // for IE which sanitizes certain attributes, disallowing mustache\n      // replacements in their text.\n      while (name[0] === '_') {\n        name = name.substring(1);\n      }\n\n      if (isTemplate(element) &&\n          (name === IF || name === BIND || name === REPEAT)) {\n        continue;\n      }\n\n      var tokens = parseMustaches(value, name, element,\n                                  prepareBindingFn);\n      if (!tokens)\n        continue;\n\n      bindings.push(name, tokens);\n    }\n\n    if (isTemplate(element)) {\n      bindings.isTemplate = true;\n      bindings.if = parseWithDefault(element, IF, prepareBindingFn);\n      bindings.bind = parseWithDefault(element, BIND, prepareBindingFn);\n      bindings.repeat = parseWithDefault(element, REPEAT, prepareBindingFn);\n\n      if (bindings.if && !bindings.bind && !bindings.repeat)\n        bindings.bind = parseMustaches('{{}}', BIND, element, prepareBindingFn);\n    }\n\n    return bindings;\n  }\n\n  function getBindings(node, prepareBindingFn) {\n    if (node.nodeType === Node.ELEMENT_NODE)\n      return parseAttributeBindings(node, prepareBindingFn);\n\n    if (node.nodeType === Node.TEXT_NODE) {\n      var tokens = parseMustaches(node.data, 'textContent', node,\n                                  prepareBindingFn);\n      if (tokens)\n        return ['textContent', tokens];\n    }\n\n    return [];\n  }\n\n  function cloneAndBindInstance(node, parent, stagingDocument, bindings, model,\n                                delegate,\n                                instanceBindings,\n                                instanceRecord) {\n    var clone = parent.appendChild(stagingDocument.importNode(node, false));\n\n    var i = 0;\n    for (var child = node.firstChild; child; child = child.nextSibling) {\n      cloneAndBindInstance(child, clone, stagingDocument,\n                            bindings.children[i++],\n                            model,\n                            delegate,\n                            instanceBindings);\n    }\n\n    if (bindings.isTemplate) {\n      HTMLTemplateElement.decorate(clone, node);\n      if (delegate)\n        clone.setDelegate_(delegate);\n    }\n\n    processBindings(clone, bindings, model, instanceBindings);\n    return clone;\n  }\n\n  function createInstanceBindingMap(node, prepareBindingFn) {\n    var map = getBindings(node, prepareBindingFn);\n    map.children = {};\n    var index = 0;\n    for (var child = node.firstChild; child; child = child.nextSibling) {\n      map.children[index++] = createInstanceBindingMap(child, prepareBindingFn);\n    }\n\n    return map;\n  }\n\n  Object.defineProperty(Node.prototype, 'templateInstance', {\n    get: function() {\n      var instance = this.templateInstance_;\n      return instance ? instance :\n          (this.parentNode ? this.parentNode.templateInstance : undefined);\n    }\n  });\n\n  function TemplateIterator(templateElement) {\n    this.closed = false;\n    this.templateElement_ = templateElement;\n\n    // Flattened array of tuples:\n    //   <instanceTerminatorNode, [bindingsSetupByInstance]>\n    this.terminators = [];\n\n    this.deps = undefined;\n    this.iteratedValue = [];\n    this.presentValue = undefined;\n    this.arrayObserver = undefined;\n  }\n\n  TemplateIterator.prototype = {\n    closeDeps: function() {\n      var deps = this.deps;\n      if (deps) {\n        if (deps.ifOneTime === false)\n          deps.ifValue.close();\n        if (deps.oneTime === false)\n          deps.value.close();\n      }\n    },\n\n    updateDependencies: function(directives, model) {\n      this.closeDeps();\n\n      var deps = this.deps = {};\n      var template = this.templateElement_;\n\n      if (directives.if) {\n        deps.hasIf = true;\n        deps.ifOneTime = directives.if.onlyOneTime;\n        deps.ifValue = processBinding(IF, directives.if, template, model);\n\n        // oneTime if & predicate is false. nothing else to do.\n        if (deps.ifOneTime && !deps.ifValue) {\n          this.updateIteratedValue();\n          return;\n        }\n\n        if (!deps.ifOneTime)\n          deps.ifValue.open(this.updateIteratedValue, this);\n      }\n\n      if (directives.repeat) {\n        deps.repeat = true;\n        deps.oneTime = directives.repeat.onlyOneTime;\n        deps.value = processBinding(REPEAT, directives.repeat, template, model);\n      } else {\n        deps.repeat = false;\n        deps.oneTime = directives.bind.onlyOneTime;\n        deps.value = processBinding(BIND, directives.bind, template, model);\n      }\n\n      if (!deps.oneTime)\n        deps.value.open(this.updateIteratedValue, this);\n\n      this.updateIteratedValue();\n    },\n\n    updateIteratedValue: function() {\n      if (this.deps.hasIf) {\n        var ifValue = this.deps.ifValue;\n        if (!this.deps.ifOneTime)\n          ifValue = ifValue.discardChanges();\n        if (!ifValue) {\n          this.valueChanged();\n          return;\n        }\n      }\n\n      var value = this.deps.value;\n      if (!this.deps.oneTime)\n        value = value.discardChanges();\n      if (!this.deps.repeat)\n        value = [value];\n      var observe = this.deps.repeat &&\n                    !this.deps.oneTime &&\n                    Array.isArray(value);\n      this.valueChanged(value, observe);\n    },\n\n    valueChanged: function(value, observeValue) {\n      if (!Array.isArray(value))\n        value = [];\n\n      if (value === this.iteratedValue)\n        return;\n\n      this.unobserve();\n      this.presentValue = value;\n      if (observeValue) {\n        this.arrayObserver = new ArrayObserver(this.presentValue);\n        this.arrayObserver.open(this.handleSplices, this);\n      }\n\n      this.handleSplices(ArrayObserver.calculateSplices(this.presentValue,\n                                                        this.iteratedValue));\n    },\n\n    getTerminatorAt: function(index) {\n      if (index == -1)\n        return this.templateElement_;\n      var terminator = this.terminators[index*2];\n      if (terminator.nodeType !== Node.ELEMENT_NODE ||\n          this.templateElement_ === terminator) {\n        return terminator;\n      }\n\n      var subIterator = terminator.iterator_;\n      if (!subIterator)\n        return terminator;\n\n      return subIterator.getTerminatorAt(subIterator.terminators.length/2 - 1);\n    },\n\n    // TODO(rafaelw): If we inserting sequences of instances we can probably\n    // avoid lots of calls to getTerminatorAt(), or cache its result.\n    insertInstanceAt: function(index, fragment, instanceNodes,\n                               instanceBindings) {\n      var previousTerminator = this.getTerminatorAt(index - 1);\n      var terminator = previousTerminator;\n      if (fragment)\n        terminator = fragment.lastChild || terminator;\n      else if (instanceNodes)\n        terminator = instanceNodes[instanceNodes.length - 1] || terminator;\n\n      this.terminators.splice(index*2, 0, terminator, instanceBindings);\n      var parent = this.templateElement_.parentNode;\n      var insertBeforeNode = previousTerminator.nextSibling;\n\n      if (fragment) {\n        parent.insertBefore(fragment, insertBeforeNode);\n      } else if (instanceNodes) {\n        for (var i = 0; i < instanceNodes.length; i++)\n          parent.insertBefore(instanceNodes[i], insertBeforeNode);\n      }\n    },\n\n    extractInstanceAt: function(index) {\n      var instanceNodes = [];\n      var previousTerminator = this.getTerminatorAt(index - 1);\n      var terminator = this.getTerminatorAt(index);\n      instanceNodes.instanceBindings = this.terminators[index*2 + 1];\n      this.terminators.splice(index*2, 2);\n\n      var parent = this.templateElement_.parentNode;\n      while (terminator !== previousTerminator) {\n        var node = previousTerminator.nextSibling;\n        if (node == terminator)\n          terminator = previousTerminator;\n\n        parent.removeChild(node);\n        instanceNodes.push(node);\n      }\n\n      return instanceNodes;\n    },\n\n    getDelegateFn: function(fn) {\n      fn = fn && fn(this.templateElement_);\n      return typeof fn === 'function' ? fn : null;\n    },\n\n    handleSplices: function(splices) {\n      if (this.closed || !splices.length)\n        return;\n\n      var template = this.templateElement_;\n\n      if (!template.parentNode) {\n        this.close();\n        return;\n      }\n\n      ArrayObserver.applySplices(this.iteratedValue, this.presentValue,\n                                 splices);\n\n      var delegate = template.delegate_;\n      if (this.instanceModelFn_ === undefined) {\n        this.instanceModelFn_ =\n            this.getDelegateFn(delegate && delegate.prepareInstanceModel);\n      }\n\n      if (this.instancePositionChangedFn_ === undefined) {\n        this.instancePositionChangedFn_ =\n            this.getDelegateFn(delegate &&\n                               delegate.prepareInstancePositionChanged);\n      }\n\n      var instanceCache = new Map;\n      var removeDelta = 0;\n      splices.forEach(function(splice) {\n        splice.removed.forEach(function(model) {\n          var instanceNodes =\n              this.extractInstanceAt(splice.index + removeDelta);\n          instanceCache.set(model, instanceNodes);\n        }, this);\n\n        removeDelta -= splice.addedCount;\n      }, this);\n\n      splices.forEach(function(splice) {\n        var addIndex = splice.index;\n        for (; addIndex < splice.index + splice.addedCount; addIndex++) {\n          var model = this.iteratedValue[addIndex];\n          var fragment = undefined;\n          var instanceNodes = instanceCache.get(model);\n          var instanceBindings;\n          if (instanceNodes) {\n            instanceCache.delete(model);\n            instanceBindings = instanceNodes.instanceBindings;\n          } else {\n            instanceBindings = [];\n            if (this.instanceModelFn_)\n              model = this.instanceModelFn_(model);\n\n            if (model !== undefined) {\n              fragment = template.createInstance(model, undefined, delegate,\n                                                 instanceBindings);\n            }\n          }\n\n          this.insertInstanceAt(addIndex, fragment, instanceNodes,\n                                instanceBindings);\n        }\n      }, this);\n\n      instanceCache.forEach(function(instanceNodes) {\n        this.closeInstanceBindings(instanceNodes.instanceBindings);\n      }, this);\n\n      if (this.instancePositionChangedFn_)\n        this.reportInstancesMoved(splices);\n    },\n\n    reportInstanceMoved: function(index) {\n      var previousTerminator = this.getTerminatorAt(index - 1);\n      var terminator = this.getTerminatorAt(index);\n      if (previousTerminator === terminator)\n        return; // instance has zero nodes.\n\n      // We must use the first node of the instance, because any subsequent\n      // nodes may have been generated by sub-templates.\n      // TODO(rafaelw): This is brittle WRT instance mutation -- e.g. if the\n      // first node was removed by script.\n      var templateInstance = previousTerminator.nextSibling.templateInstance;\n      this.instancePositionChangedFn_(templateInstance, index);\n    },\n\n    reportInstancesMoved: function(splices) {\n      var index = 0;\n      var offset = 0;\n      for (var i = 0; i < splices.length; i++) {\n        var splice = splices[i];\n        if (offset != 0) {\n          while (index < splice.index) {\n            this.reportInstanceMoved(index);\n            index++;\n          }\n        } else {\n          index = splice.index;\n        }\n\n        while (index < splice.index + splice.addedCount) {\n          this.reportInstanceMoved(index);\n          index++;\n        }\n\n        offset += splice.addedCount - splice.removed.length;\n      }\n\n      if (offset == 0)\n        return;\n\n      var length = this.terminators.length / 2;\n      while (index < length) {\n        this.reportInstanceMoved(index);\n        index++;\n      }\n    },\n\n    closeInstanceBindings: function(instanceBindings) {\n      for (var i = 0; i < instanceBindings.length; i++) {\n        instanceBindings[i].close();\n      }\n    },\n\n    unobserve: function() {\n      if (!this.arrayObserver)\n        return;\n\n      this.arrayObserver.close();\n      this.arrayObserver = undefined;\n    },\n\n    close: function() {\n      if (this.closed)\n        return;\n      this.unobserve();\n      for (var i = 1; i < this.terminators.length; i += 2) {\n        this.closeInstanceBindings(this.terminators[i]);\n      }\n\n      this.terminators.length = 0;\n      this.closeDeps();\n      this.templateElement_.iterator_ = undefined;\n      this.closed = true;\n    }\n  };\n\n  // Polyfill-specific API.\n  HTMLTemplateElement.forAllTemplatesFrom_ = forAllTemplatesFrom;\n})(this);\n",
+    "/*\n  Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com>\n  Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com>\n  Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>\n  Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>\n  Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>\n  Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>\n  Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>\n  Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>\n  Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n(function (global) {\n    'use strict';\n\n    var Token,\n        TokenName,\n        Syntax,\n        Messages,\n        source,\n        index,\n        length,\n        delegate,\n        lookahead,\n        state;\n\n    Token = {\n        BooleanLiteral: 1,\n        EOF: 2,\n        Identifier: 3,\n        Keyword: 4,\n        NullLiteral: 5,\n        NumericLiteral: 6,\n        Punctuator: 7,\n        StringLiteral: 8\n    };\n\n    TokenName = {};\n    TokenName[Token.BooleanLiteral] = 'Boolean';\n    TokenName[Token.EOF] = '<end>';\n    TokenName[Token.Identifier] = 'Identifier';\n    TokenName[Token.Keyword] = 'Keyword';\n    TokenName[Token.NullLiteral] = 'Null';\n    TokenName[Token.NumericLiteral] = 'Numeric';\n    TokenName[Token.Punctuator] = 'Punctuator';\n    TokenName[Token.StringLiteral] = 'String';\n\n    Syntax = {\n        ArrayExpression: 'ArrayExpression',\n        BinaryExpression: 'BinaryExpression',\n        CallExpression: 'CallExpression',\n        ConditionalExpression: 'ConditionalExpression',\n        EmptyStatement: 'EmptyStatement',\n        ExpressionStatement: 'ExpressionStatement',\n        Identifier: 'Identifier',\n        Literal: 'Literal',\n        LabeledStatement: 'LabeledStatement',\n        LogicalExpression: 'LogicalExpression',\n        MemberExpression: 'MemberExpression',\n        ObjectExpression: 'ObjectExpression',\n        Program: 'Program',\n        Property: 'Property',\n        ThisExpression: 'ThisExpression',\n        UnaryExpression: 'UnaryExpression'\n    };\n\n    // Error messages should be identical to V8.\n    Messages = {\n        UnexpectedToken:  'Unexpected token %0',\n        UnknownLabel: 'Undefined label \\'%0\\'',\n        Redeclaration: '%0 \\'%1\\' has already been declared'\n    };\n\n    // Ensure the condition is true, otherwise throw an error.\n    // This is only to have a better contract semantic, i.e. another safety net\n    // to catch a logic error. The condition shall be fulfilled in normal case.\n    // Do NOT use this to enforce a certain condition on any user input.\n\n    function assert(condition, message) {\n        if (!condition) {\n            throw new Error('ASSERT: ' + message);\n        }\n    }\n\n    function isDecimalDigit(ch) {\n        return (ch >= 48 && ch <= 57);   // 0..9\n    }\n\n\n    // 7.2 White Space\n\n    function isWhiteSpace(ch) {\n        return (ch === 32) ||  // space\n            (ch === 9) ||      // tab\n            (ch === 0xB) ||\n            (ch === 0xC) ||\n            (ch === 0xA0) ||\n            (ch >= 0x1680 && '\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\uFEFF'.indexOf(String.fromCharCode(ch)) > 0);\n    }\n\n    // 7.3 Line Terminators\n\n    function isLineTerminator(ch) {\n        return (ch === 10) || (ch === 13) || (ch === 0x2028) || (ch === 0x2029);\n    }\n\n    // 7.6 Identifier Names and Identifiers\n\n    function isIdentifierStart(ch) {\n        return (ch === 36) || (ch === 95) ||  // $ (dollar) and _ (underscore)\n            (ch >= 65 && ch <= 90) ||         // A..Z\n            (ch >= 97 && ch <= 122);          // a..z\n    }\n\n    function isIdentifierPart(ch) {\n        return (ch === 36) || (ch === 95) ||  // $ (dollar) and _ (underscore)\n            (ch >= 65 && ch <= 90) ||         // A..Z\n            (ch >= 97 && ch <= 122) ||        // a..z\n            (ch >= 48 && ch <= 57);           // 0..9\n    }\n\n    // 7.6.1.1 Keywords\n\n    function isKeyword(id) {\n        return (id === 'this')\n    }\n\n    // 7.4 Comments\n\n    function skipWhitespace() {\n        while (index < length && isWhiteSpace(source.charCodeAt(index))) {\n           ++index;\n        }\n    }\n\n    function getIdentifier() {\n        var start, ch;\n\n        start = index++;\n        while (index < length) {\n            ch = source.charCodeAt(index);\n            if (isIdentifierPart(ch)) {\n                ++index;\n            } else {\n                break;\n            }\n        }\n\n        return source.slice(start, index);\n    }\n\n    function scanIdentifier() {\n        var start, id, type;\n\n        start = index;\n\n        id = getIdentifier();\n\n        // There is no keyword or literal with only one character.\n        // Thus, it must be an identifier.\n        if (id.length === 1) {\n            type = Token.Identifier;\n        } else if (isKeyword(id)) {\n            type = Token.Keyword;\n        } else if (id === 'null') {\n            type = Token.NullLiteral;\n        } else if (id === 'true' || id === 'false') {\n            type = Token.BooleanLiteral;\n        } else {\n            type = Token.Identifier;\n        }\n\n        return {\n            type: type,\n            value: id,\n            range: [start, index]\n        };\n    }\n\n\n    // 7.7 Punctuators\n\n    function scanPunctuator() {\n        var start = index,\n            code = source.charCodeAt(index),\n            code2,\n            ch1 = source[index],\n            ch2;\n\n        switch (code) {\n\n        // Check for most common single-character punctuators.\n        case 46:   // . dot\n        case 40:   // ( open bracket\n        case 41:   // ) close bracket\n        case 59:   // ; semicolon\n        case 44:   // , comma\n        case 123:  // { open curly brace\n        case 125:  // } close curly brace\n        case 91:   // [\n        case 93:   // ]\n        case 58:   // :\n        case 63:   // ?\n            ++index;\n            return {\n                type: Token.Punctuator,\n                value: String.fromCharCode(code),\n                range: [start, index]\n            };\n\n        default:\n            code2 = source.charCodeAt(index + 1);\n\n            // '=' (char #61) marks an assignment or comparison operator.\n            if (code2 === 61) {\n                switch (code) {\n                case 37:  // %\n                case 38:  // &\n                case 42:  // *:\n                case 43:  // +\n                case 45:  // -\n                case 47:  // /\n                case 60:  // <\n                case 62:  // >\n                case 124: // |\n                    index += 2;\n                    return {\n                        type: Token.Punctuator,\n                        value: String.fromCharCode(code) + String.fromCharCode(code2),\n                        range: [start, index]\n                    };\n\n                case 33: // !\n                case 61: // =\n                    index += 2;\n\n                    // !== and ===\n                    if (source.charCodeAt(index) === 61) {\n                        ++index;\n                    }\n                    return {\n                        type: Token.Punctuator,\n                        value: source.slice(start, index),\n                        range: [start, index]\n                    };\n                default:\n                    break;\n                }\n            }\n            break;\n        }\n\n        // Peek more characters.\n\n        ch2 = source[index + 1];\n\n        // Other 2-character punctuators: && ||\n\n        if (ch1 === ch2 && ('&|'.indexOf(ch1) >= 0)) {\n            index += 2;\n            return {\n                type: Token.Punctuator,\n                value: ch1 + ch2,\n                range: [start, index]\n            };\n        }\n\n        if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {\n            ++index;\n            return {\n                type: Token.Punctuator,\n                value: ch1,\n                range: [start, index]\n            };\n        }\n\n        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n    }\n\n    // 7.8.3 Numeric Literals\n    function scanNumericLiteral() {\n        var number, start, ch;\n\n        ch = source[index];\n        assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'),\n            'Numeric literal must start with a decimal digit or a decimal point');\n\n        start = index;\n        number = '';\n        if (ch !== '.') {\n            number = source[index++];\n            ch = source[index];\n\n            // Hex number starts with '0x'.\n            // Octal number starts with '0'.\n            if (number === '0') {\n                // decimal number starts with '0' such as '09' is illegal.\n                if (ch && isDecimalDigit(ch.charCodeAt(0))) {\n                    throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n                }\n            }\n\n            while (isDecimalDigit(source.charCodeAt(index))) {\n                number += source[index++];\n            }\n            ch = source[index];\n        }\n\n        if (ch === '.') {\n            number += source[index++];\n            while (isDecimalDigit(source.charCodeAt(index))) {\n                number += source[index++];\n            }\n            ch = source[index];\n        }\n\n        if (ch === 'e' || ch === 'E') {\n            number += source[index++];\n\n            ch = source[index];\n            if (ch === '+' || ch === '-') {\n                number += source[index++];\n            }\n            if (isDecimalDigit(source.charCodeAt(index))) {\n                while (isDecimalDigit(source.charCodeAt(index))) {\n                    number += source[index++];\n                }\n            } else {\n                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n            }\n        }\n\n        if (isIdentifierStart(source.charCodeAt(index))) {\n            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n        }\n\n        return {\n            type: Token.NumericLiteral,\n            value: parseFloat(number),\n            range: [start, index]\n        };\n    }\n\n    // 7.8.4 String Literals\n\n    function scanStringLiteral() {\n        var str = '', quote, start, ch, octal = false;\n\n        quote = source[index];\n        assert((quote === '\\'' || quote === '\"'),\n            'String literal must starts with a quote');\n\n        start = index;\n        ++index;\n\n        while (index < length) {\n            ch = source[index++];\n\n            if (ch === quote) {\n                quote = '';\n                break;\n            } else if (ch === '\\\\') {\n                ch = source[index++];\n                if (!ch || !isLineTerminator(ch.charCodeAt(0))) {\n                    switch (ch) {\n                    case 'n':\n                        str += '\\n';\n                        break;\n                    case 'r':\n                        str += '\\r';\n                        break;\n                    case 't':\n                        str += '\\t';\n                        break;\n                    case 'b':\n                        str += '\\b';\n                        break;\n                    case 'f':\n                        str += '\\f';\n                        break;\n                    case 'v':\n                        str += '\\x0B';\n                        break;\n\n                    default:\n                        str += ch;\n                        break;\n                    }\n                } else {\n                    if (ch ===  '\\r' && source[index] === '\\n') {\n                        ++index;\n                    }\n                }\n            } else if (isLineTerminator(ch.charCodeAt(0))) {\n                break;\n            } else {\n                str += ch;\n            }\n        }\n\n        if (quote !== '') {\n            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n        }\n\n        return {\n            type: Token.StringLiteral,\n            value: str,\n            octal: octal,\n            range: [start, index]\n        };\n    }\n\n    function isIdentifierName(token) {\n        return token.type === Token.Identifier ||\n            token.type === Token.Keyword ||\n            token.type === Token.BooleanLiteral ||\n            token.type === Token.NullLiteral;\n    }\n\n    function advance() {\n        var ch;\n\n        skipWhitespace();\n\n        if (index >= length) {\n            return {\n                type: Token.EOF,\n                range: [index, index]\n            };\n        }\n\n        ch = source.charCodeAt(index);\n\n        // Very common: ( and ) and ;\n        if (ch === 40 || ch === 41 || ch === 58) {\n            return scanPunctuator();\n        }\n\n        // String literal starts with single quote (#39) or double quote (#34).\n        if (ch === 39 || ch === 34) {\n            return scanStringLiteral();\n        }\n\n        if (isIdentifierStart(ch)) {\n            return scanIdentifier();\n        }\n\n        // Dot (.) char #46 can also start a floating-point number, hence the need\n        // to check the next character.\n        if (ch === 46) {\n            if (isDecimalDigit(source.charCodeAt(index + 1))) {\n                return scanNumericLiteral();\n            }\n            return scanPunctuator();\n        }\n\n        if (isDecimalDigit(ch)) {\n            return scanNumericLiteral();\n        }\n\n        return scanPunctuator();\n    }\n\n    function lex() {\n        var token;\n\n        token = lookahead;\n        index = token.range[1];\n\n        lookahead = advance();\n\n        index = token.range[1];\n\n        return token;\n    }\n\n    function peek() {\n        var pos;\n\n        pos = index;\n        lookahead = advance();\n        index = pos;\n    }\n\n    // Throw an exception\n\n    function throwError(token, messageFormat) {\n        var error,\n            args = Array.prototype.slice.call(arguments, 2),\n            msg = messageFormat.replace(\n                /%(\\d)/g,\n                function (whole, index) {\n                    assert(index < args.length, 'Message reference must be in range');\n                    return args[index];\n                }\n            );\n\n        error = new Error(msg);\n        error.index = index;\n        error.description = msg;\n        throw error;\n    }\n\n    // Throw an exception because of the token.\n\n    function throwUnexpected(token) {\n        throwError(token, Messages.UnexpectedToken, token.value);\n    }\n\n    // Expect the next token to match the specified punctuator.\n    // If not, an exception will be thrown.\n\n    function expect(value) {\n        var token = lex();\n        if (token.type !== Token.Punctuator || token.value !== value) {\n            throwUnexpected(token);\n        }\n    }\n\n    // Return true if the next token matches the specified punctuator.\n\n    function match(value) {\n        return lookahead.type === Token.Punctuator && lookahead.value === value;\n    }\n\n    // Return true if the next token matches the specified keyword\n\n    function matchKeyword(keyword) {\n        return lookahead.type === Token.Keyword && lookahead.value === keyword;\n    }\n\n    function consumeSemicolon() {\n        // Catch the very common case first: immediately a semicolon (char #59).\n        if (source.charCodeAt(index) === 59) {\n            lex();\n            return;\n        }\n\n        skipWhitespace();\n\n        if (match(';')) {\n            lex();\n            return;\n        }\n\n        if (lookahead.type !== Token.EOF && !match('}')) {\n            throwUnexpected(lookahead);\n        }\n    }\n\n    // 11.1.4 Array Initialiser\n\n    function parseArrayInitialiser() {\n        var elements = [];\n\n        expect('[');\n\n        while (!match(']')) {\n            if (match(',')) {\n                lex();\n                elements.push(null);\n            } else {\n                elements.push(parseExpression());\n\n                if (!match(']')) {\n                    expect(',');\n                }\n            }\n        }\n\n        expect(']');\n\n        return delegate.createArrayExpression(elements);\n    }\n\n    // 11.1.5 Object Initialiser\n\n    function parseObjectPropertyKey() {\n        var token;\n\n        skipWhitespace();\n        token = lex();\n\n        // Note: This function is called only from parseObjectProperty(), where\n        // EOF and Punctuator tokens are already filtered out.\n        if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {\n            return delegate.createLiteral(token);\n        }\n\n        return delegate.createIdentifier(token.value);\n    }\n\n    function parseObjectProperty() {\n        var token, key;\n\n        token = lookahead;\n        skipWhitespace();\n\n        if (token.type === Token.EOF || token.type === Token.Punctuator) {\n            throwUnexpected(token);\n        }\n\n        key = parseObjectPropertyKey();\n        expect(':');\n        return delegate.createProperty('init', key, parseExpression());\n    }\n\n    function parseObjectInitialiser() {\n        var properties = [];\n\n        expect('{');\n\n        while (!match('}')) {\n            properties.push(parseObjectProperty());\n\n            if (!match('}')) {\n                expect(',');\n            }\n        }\n\n        expect('}');\n\n        return delegate.createObjectExpression(properties);\n    }\n\n    // 11.1.6 The Grouping Operator\n\n    function parseGroupExpression() {\n        var expr;\n\n        expect('(');\n\n        expr = parseExpression();\n\n        expect(')');\n\n        return expr;\n    }\n\n\n    // 11.1 Primary Expressions\n\n    function parsePrimaryExpression() {\n        var type, token, expr;\n\n        if (match('(')) {\n            return parseGroupExpression();\n        }\n\n        type = lookahead.type;\n\n        if (type === Token.Identifier) {\n            expr = delegate.createIdentifier(lex().value);\n        } else if (type === Token.StringLiteral || type === Token.NumericLiteral) {\n            expr = delegate.createLiteral(lex());\n        } else if (type === Token.Keyword) {\n            if (matchKeyword('this')) {\n                lex();\n                expr = delegate.createThisExpression();\n            }\n        } else if (type === Token.BooleanLiteral) {\n            token = lex();\n            token.value = (token.value === 'true');\n            expr = delegate.createLiteral(token);\n        } else if (type === Token.NullLiteral) {\n            token = lex();\n            token.value = null;\n            expr = delegate.createLiteral(token);\n        } else if (match('[')) {\n            expr = parseArrayInitialiser();\n        } else if (match('{')) {\n            expr = parseObjectInitialiser();\n        }\n\n        if (expr) {\n            return expr;\n        }\n\n        throwUnexpected(lex());\n    }\n\n    // 11.2 Left-Hand-Side Expressions\n\n    function parseArguments() {\n        var args = [];\n\n        expect('(');\n\n        if (!match(')')) {\n            while (index < length) {\n                args.push(parseExpression());\n                if (match(')')) {\n                    break;\n                }\n                expect(',');\n            }\n        }\n\n        expect(')');\n\n        return args;\n    }\n\n    function parseNonComputedProperty() {\n        var token;\n\n        token = lex();\n\n        if (!isIdentifierName(token)) {\n            throwUnexpected(token);\n        }\n\n        return delegate.createIdentifier(token.value);\n    }\n\n    function parseNonComputedMember() {\n        expect('.');\n\n        return parseNonComputedProperty();\n    }\n\n    function parseComputedMember() {\n        var expr;\n\n        expect('[');\n\n        expr = parseExpression();\n\n        expect(']');\n\n        return expr;\n    }\n\n    function parseLeftHandSideExpression() {\n        var expr, property;\n\n        expr = parsePrimaryExpression();\n\n        while (match('.') || match('[')) {\n            if (match('[')) {\n                property = parseComputedMember();\n                expr = delegate.createMemberExpression('[', expr, property);\n            } else {\n                property = parseNonComputedMember();\n                expr = delegate.createMemberExpression('.', expr, property);\n            }\n        }\n\n        return expr;\n    }\n\n    // 11.3 Postfix Expressions\n\n    var parsePostfixExpression = parseLeftHandSideExpression;\n\n    // 11.4 Unary Operators\n\n    function parseUnaryExpression() {\n        var token, expr;\n\n        if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) {\n            expr = parsePostfixExpression();\n        } else if (match('+') || match('-') || match('!')) {\n            token = lex();\n            expr = parseUnaryExpression();\n            expr = delegate.createUnaryExpression(token.value, expr);\n        } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {\n            throwError({}, Messages.UnexpectedToken);\n        } else {\n            expr = parsePostfixExpression();\n        }\n\n        return expr;\n    }\n\n    function binaryPrecedence(token) {\n        var prec = 0;\n\n        if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {\n            return 0;\n        }\n\n        switch (token.value) {\n        case '||':\n            prec = 1;\n            break;\n\n        case '&&':\n            prec = 2;\n            break;\n\n        case '==':\n        case '!=':\n        case '===':\n        case '!==':\n            prec = 6;\n            break;\n\n        case '<':\n        case '>':\n        case '<=':\n        case '>=':\n        case 'instanceof':\n            prec = 7;\n            break;\n\n        case 'in':\n            prec = 7;\n            break;\n\n        case '+':\n        case '-':\n            prec = 9;\n            break;\n\n        case '*':\n        case '/':\n        case '%':\n            prec = 11;\n            break;\n\n        default:\n            break;\n        }\n\n        return prec;\n    }\n\n    // 11.5 Multiplicative Operators\n    // 11.6 Additive Operators\n    // 11.7 Bitwise Shift Operators\n    // 11.8 Relational Operators\n    // 11.9 Equality Operators\n    // 11.10 Binary Bitwise Operators\n    // 11.11 Binary Logical Operators\n\n    function parseBinaryExpression() {\n        var expr, token, prec, stack, right, operator, left, i;\n\n        left = parseUnaryExpression();\n\n        token = lookahead;\n        prec = binaryPrecedence(token);\n        if (prec === 0) {\n            return left;\n        }\n        token.prec = prec;\n        lex();\n\n        right = parseUnaryExpression();\n\n        stack = [left, token, right];\n\n        while ((prec = binaryPrecedence(lookahead)) > 0) {\n\n            // Reduce: make a binary expression from the three topmost entries.\n            while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {\n                right = stack.pop();\n                operator = stack.pop().value;\n                left = stack.pop();\n                expr = delegate.createBinaryExpression(operator, left, right);\n                stack.push(expr);\n            }\n\n            // Shift.\n            token = lex();\n            token.prec = prec;\n            stack.push(token);\n            expr = parseUnaryExpression();\n            stack.push(expr);\n        }\n\n        // Final reduce to clean-up the stack.\n        i = stack.length - 1;\n        expr = stack[i];\n        while (i > 1) {\n            expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr);\n            i -= 2;\n        }\n\n        return expr;\n    }\n\n\n    // 11.12 Conditional Operator\n\n    function parseConditionalExpression() {\n        var expr, consequent, alternate;\n\n        expr = parseBinaryExpression();\n\n        if (match('?')) {\n            lex();\n            consequent = parseConditionalExpression();\n            expect(':');\n            alternate = parseConditionalExpression();\n\n            expr = delegate.createConditionalExpression(expr, consequent, alternate);\n        }\n\n        return expr;\n    }\n\n    // Simplification since we do not support AssignmentExpression.\n    var parseExpression = parseConditionalExpression;\n\n    // Polymer Syntax extensions\n\n    // Filter ::\n    //   Identifier\n    //   Identifier \"(\" \")\"\n    //   Identifier \"(\" FilterArguments \")\"\n\n    function parseFilter() {\n        var identifier, args;\n\n        identifier = lex();\n\n        if (identifier.type !== Token.Identifier) {\n            throwUnexpected(identifier);\n        }\n\n        args = match('(') ? parseArguments() : [];\n\n        return delegate.createFilter(identifier.value, args);\n    }\n\n    // Filters ::\n    //   \"|\" Filter\n    //   Filters \"|\" Filter\n\n    function parseFilters() {\n        while (match('|')) {\n            lex();\n            parseFilter();\n        }\n    }\n\n    // TopLevel ::\n    //   LabelledExpressions\n    //   AsExpression\n    //   InExpression\n    //   FilterExpression\n\n    // AsExpression ::\n    //   FilterExpression as Identifier\n\n    // InExpression ::\n    //   Identifier, Identifier in FilterExpression\n    //   Identifier in FilterExpression\n\n    // FilterExpression ::\n    //   Expression\n    //   Expression Filters\n\n    function parseTopLevel() {\n        skipWhitespace();\n        peek();\n\n        var expr = parseExpression();\n        if (expr) {\n            if (lookahead.value === ',' || lookahead.value == 'in' &&\n                       expr.type === Syntax.Identifier) {\n                parseInExpression(expr);\n            } else {\n                parseFilters();\n                if (lookahead.value === 'as') {\n                    parseAsExpression(expr);\n                } else {\n                    delegate.createTopLevel(expr);\n                }\n            }\n        }\n\n        if (lookahead.type !== Token.EOF) {\n            throwUnexpected(lookahead);\n        }\n    }\n\n    function parseAsExpression(expr) {\n        lex();  // as\n        var identifier = lex().value;\n        delegate.createAsExpression(expr, identifier);\n    }\n\n    function parseInExpression(identifier) {\n        var indexName;\n        if (lookahead.value === ',') {\n            lex();\n            if (lookahead.type !== Token.Identifier)\n                throwUnexpected(lookahead);\n            indexName = lex().value;\n        }\n\n        lex();  // in\n        var expr = parseExpression();\n        parseFilters();\n        delegate.createInExpression(identifier.name, indexName, expr);\n    }\n\n    function parse(code, inDelegate) {\n        delegate = inDelegate;\n        source = code;\n        index = 0;\n        length = source.length;\n        lookahead = null;\n        state = {\n            labelSet: {}\n        };\n\n        return parseTopLevel();\n    }\n\n    global.esprima = {\n        parse: parse\n    };\n})(this);\n",
+    "// Copyright 2013 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n(function (global) {\n  'use strict';\n\n  // JScript does not have __proto__. We wrap all object literals with\n  // createObject which uses Object.create, Object.defineProperty and\n  // Object.getOwnPropertyDescriptor to create a new object that does the exact\n  // same thing. The main downside to this solution is that we have to extract\n  // all those property descriptors for IE.\n  var createObject = ('__proto__' in {}) ?\n      function(obj) { return obj; } :\n      function(obj) {\n        var proto = obj.__proto__;\n        if (!proto)\n          return obj;\n        var newObject = Object.create(proto);\n        Object.getOwnPropertyNames(obj).forEach(function(name) {\n          Object.defineProperty(newObject, name,\n                               Object.getOwnPropertyDescriptor(obj, name));\n        });\n        return newObject;\n      };\n\n  function prepareBinding(expressionText, name, node, filterRegistry) {\n    var expression;\n    try {\n      expression = getExpression(expressionText);\n      if (expression.scopeIdent &&\n          (node.nodeType !== Node.ELEMENT_NODE ||\n           node.tagName !== 'TEMPLATE' ||\n           (name !== 'bind' && name !== 'repeat'))) {\n        throw Error('as and in can only be used within <template bind/repeat>');\n      }\n    } catch (ex) {\n      console.error('Invalid expression syntax: ' + expressionText, ex);\n      return;\n    }\n\n    return function(model, node, oneTime) {\n      var binding = expression.getBinding(model, filterRegistry, oneTime);\n      if (expression.scopeIdent && binding) {\n        node.polymerExpressionScopeIdent_ = expression.scopeIdent;\n        if (expression.indexIdent)\n          node.polymerExpressionIndexIdent_ = expression.indexIdent;\n      }\n\n      return binding;\n    }\n  }\n\n  // TODO(rafaelw): Implement simple LRU.\n  var expressionParseCache = Object.create(null);\n\n  function getExpression(expressionText) {\n    var expression = expressionParseCache[expressionText];\n    if (!expression) {\n      var delegate = new ASTDelegate();\n      esprima.parse(expressionText, delegate);\n      expression = new Expression(delegate);\n      expressionParseCache[expressionText] = expression;\n    }\n    return expression;\n  }\n\n  function Literal(value) {\n    this.value = value;\n    this.valueFn_ = undefined;\n  }\n\n  Literal.prototype = {\n    valueFn: function() {\n      if (!this.valueFn_) {\n        var value = this.value;\n        this.valueFn_ = function() {\n          return value;\n        }\n      }\n\n      return this.valueFn_;\n    }\n  }\n\n  function IdentPath(name) {\n    this.name = name;\n    this.path = Path.get(name);\n  }\n\n  IdentPath.prototype = {\n    valueFn: function() {\n      if (!this.valueFn_) {\n        var name = this.name;\n        var path = this.path;\n        this.valueFn_ = function(model, observer) {\n          if (observer)\n            observer.addPath(model, path);\n\n          return path.getValueFrom(model);\n        }\n      }\n\n      return this.valueFn_;\n    },\n\n    setValue: function(model, newValue) {\n      if (this.path.length == 1);\n        model = findScope(model, this.path[0]);\n\n      return this.path.setValueFrom(model, newValue);\n    }\n  };\n\n  function MemberExpression(object, property, accessor) {\n    // convert literal computed property access where literal value is a value\n    // path to ident dot-access.\n    if (accessor == '[' &&\n        property instanceof Literal &&\n        Path.get(property.value).valid) {\n      accessor = '.';\n      property = new IdentPath(property.value);\n    }\n\n    this.dynamicDeps = typeof object == 'function' || object.dynamic;\n\n    this.dynamic = typeof property == 'function' ||\n                   property.dynamic ||\n                   accessor == '[';\n\n    this.simplePath =\n        !this.dynamic &&\n        !this.dynamicDeps &&\n        property instanceof IdentPath &&\n        (object instanceof MemberExpression || object instanceof IdentPath);\n\n    this.object = this.simplePath ? object : getFn(object);\n    this.property = accessor == '.' ? property : getFn(property);\n  }\n\n  MemberExpression.prototype = {\n    get fullPath() {\n      if (!this.fullPath_) {\n        var last = this.object instanceof IdentPath ?\n            this.object.name : this.object.fullPath;\n        this.fullPath_ = Path.get(last + '.' + this.property.name);\n      }\n\n      return this.fullPath_;\n    },\n\n    valueFn: function() {\n      if (!this.valueFn_) {\n        var object = this.object;\n\n        if (this.simplePath) {\n          var path = this.fullPath;\n\n          this.valueFn_ = function(model, observer) {\n            if (observer)\n              observer.addPath(model, path);\n\n            return path.getValueFrom(model);\n          };\n        } else if (this.property instanceof IdentPath) {\n          var path = Path.get(this.property.name);\n\n          this.valueFn_ = function(model, observer) {\n            var context = object(model, observer);\n\n            if (observer)\n              observer.addPath(context, path);\n\n            return path.getValueFrom(context);\n          }\n        } else {\n          // Computed property.\n          var property = this.property;\n\n          this.valueFn_ = function(model, observer) {\n            var context = object(model, observer);\n            var propName = property(model, observer);\n            if (observer)\n              observer.addPath(context, propName);\n\n            return context ? context[propName] : undefined;\n          };\n        }\n      }\n      return this.valueFn_;\n    },\n\n    setValue: function(model, newValue) {\n      if (this.simplePath) {\n        this.fullPath.setValueFrom(model, newValue);\n        return newValue;\n      }\n\n      var object = this.object(model);\n      var propName = this.property instanceof IdentPath ? this.property.name :\n          this.property(model);\n      return object[propName] = newValue;\n    }\n  };\n\n  function Filter(name, args) {\n    this.name = name;\n    this.args = [];\n    for (var i = 0; i < args.length; i++) {\n      this.args[i] = getFn(args[i]);\n    }\n  }\n\n  Filter.prototype = {\n    transform: function(value, toModelDirection, filterRegistry, model,\n                        observer) {\n      var fn = filterRegistry[this.name];\n      var context = model;\n      if (fn) {\n        context = undefined;\n      } else {\n        fn = context[this.name];\n        if (!fn) {\n          console.error('Cannot find filter: ' + this.name);\n          return;\n        }\n      }\n\n      // If toModelDirection is falsey, then the \"normal\" (dom-bound) direction\n      // is used. Otherwise, it looks for a 'toModel' property function on the\n      // object.\n      if (toModelDirection) {\n        fn = fn.toModel;\n      } else if (typeof fn.toDOM == 'function') {\n        fn = fn.toDOM;\n      }\n\n      if (typeof fn != 'function') {\n        console.error('No ' + (toModelDirection ? 'toModel' : 'toDOM') +\n                      ' found on' + this.name);\n        return;\n      }\n\n      var args = [value];\n      for (var i = 0; i < this.args.length; i++) {\n        args[i + 1] = getFn(this.args[i])(model, observer);\n      }\n\n      return fn.apply(context, args);\n    }\n  };\n\n  function notImplemented() { throw Error('Not Implemented'); }\n\n  var unaryOperators = {\n    '+': function(v) { return +v; },\n    '-': function(v) { return -v; },\n    '!': function(v) { return !v; }\n  };\n\n  var binaryOperators = {\n    '+': function(l, r) { return l+r; },\n    '-': function(l, r) { return l-r; },\n    '*': function(l, r) { return l*r; },\n    '/': function(l, r) { return l/r; },\n    '%': function(l, r) { return l%r; },\n    '<': function(l, r) { return l<r; },\n    '>': function(l, r) { return l>r; },\n    '<=': function(l, r) { return l<=r; },\n    '>=': function(l, r) { return l>=r; },\n    '==': function(l, r) { return l==r; },\n    '!=': function(l, r) { return l!=r; },\n    '===': function(l, r) { return l===r; },\n    '!==': function(l, r) { return l!==r; },\n    '&&': function(l, r) { return l&&r; },\n    '||': function(l, r) { return l||r; },\n  };\n\n  function getFn(arg) {\n    return typeof arg == 'function' ? arg : arg.valueFn();\n  }\n\n  function ASTDelegate() {\n    this.expression = null;\n    this.filters = [];\n    this.deps = {};\n    this.currentPath = undefined;\n    this.scopeIdent = undefined;\n    this.indexIdent = undefined;\n    this.dynamicDeps = false;\n  }\n\n  ASTDelegate.prototype = {\n    createUnaryExpression: function(op, argument) {\n      if (!unaryOperators[op])\n        throw Error('Disallowed operator: ' + op);\n\n      argument = getFn(argument);\n\n      return function(model, observer) {\n        return unaryOperators[op](argument(model, observer));\n      };\n    },\n\n    createBinaryExpression: function(op, left, right) {\n      if (!binaryOperators[op])\n        throw Error('Disallowed operator: ' + op);\n\n      left = getFn(left);\n      right = getFn(right);\n\n      return function(model, observer) {\n        return binaryOperators[op](left(model, observer),\n                                   right(model, observer));\n      };\n    },\n\n    createConditionalExpression: function(test, consequent, alternate) {\n      test = getFn(test);\n      consequent = getFn(consequent);\n      alternate = getFn(alternate);\n\n      return function(model, observer) {\n        return test(model, observer) ?\n            consequent(model, observer) : alternate(model, observer);\n      }\n    },\n\n    createIdentifier: function(name) {\n      var ident = new IdentPath(name);\n      ident.type = 'Identifier';\n      return ident;\n    },\n\n    createMemberExpression: function(accessor, object, property) {\n      var ex = new MemberExpression(object, property, accessor);\n      if (ex.dynamicDeps)\n        this.dynamicDeps = true;\n      return ex;\n    },\n\n    createLiteral: function(token) {\n      return new Literal(token.value);\n    },\n\n    createArrayExpression: function(elements) {\n      for (var i = 0; i < elements.length; i++)\n        elements[i] = getFn(elements[i]);\n\n      return function(model, observer) {\n        var arr = []\n        for (var i = 0; i < elements.length; i++)\n          arr.push(elements[i](model, observer));\n        return arr;\n      }\n    },\n\n    createProperty: function(kind, key, value) {\n      return {\n        key: key instanceof IdentPath ? key.name : key.value,\n        value: value\n      };\n    },\n\n    createObjectExpression: function(properties) {\n      for (var i = 0; i < properties.length; i++)\n        properties[i].value = getFn(properties[i].value);\n\n      return function(model, observer) {\n        var obj = {};\n        for (var i = 0; i < properties.length; i++)\n          obj[properties[i].key] = properties[i].value(model, observer);\n        return obj;\n      }\n    },\n\n    createFilter: function(name, args) {\n      this.filters.push(new Filter(name, args));\n    },\n\n    createAsExpression: function(expression, scopeIdent) {\n      this.expression = expression;\n      this.scopeIdent = scopeIdent;\n    },\n\n    createInExpression: function(scopeIdent, indexIdent, expression) {\n      this.expression = expression;\n      this.scopeIdent = scopeIdent;\n      this.indexIdent = indexIdent;\n    },\n\n    createTopLevel: function(expression) {\n      this.expression = expression;\n    },\n\n    createThisExpression: notImplemented\n  }\n\n  function ConstantObservable(value) {\n    this.value_ = value;\n  }\n\n  ConstantObservable.prototype = {\n    open: function() { return this.value_; },\n    discardChanges: function() { return this.value_; },\n    deliver: function() {},\n    close: function() {},\n  }\n\n  function Expression(delegate) {\n    this.scopeIdent = delegate.scopeIdent;\n    this.indexIdent = delegate.indexIdent;\n\n    if (!delegate.expression)\n      throw Error('No expression found.');\n\n    this.expression = delegate.expression;\n    getFn(this.expression); // forces enumeration of path dependencies\n\n    this.filters = delegate.filters;\n    this.dynamicDeps = delegate.dynamicDeps;\n  }\n\n  Expression.prototype = {\n    getBinding: function(model, filterRegistry, oneTime) {\n      if (oneTime)\n        return this.getValue(model, undefined, filterRegistry);\n\n      var observer = new CompoundObserver();\n      this.getValue(model, observer, filterRegistry);  // captures deps.\n      var self = this;\n\n      function valueFn() {\n        if (self.dynamicDeps)\n          observer.startReset();\n\n        var value = self.getValue(model,\n                                  self.dynamicDeps ? observer : undefined,\n                                  filterRegistry);\n        if (self.dynamicDeps)\n          observer.finishReset();\n\n        return value;\n      }\n\n      function setValueFn(newValue) {\n        self.setValue(model, newValue, filterRegistry);\n        return newValue;\n      }\n\n      return new ObserverTransform(observer, valueFn, setValueFn, true);\n    },\n\n    getValue: function(model, observer, filterRegistry) {\n      var value = getFn(this.expression)(model, observer);\n      for (var i = 0; i < this.filters.length; i++) {\n        value = this.filters[i].transform(value, false, filterRegistry, model,\n                                          observer);\n      }\n\n      return value;\n    },\n\n    setValue: function(model, newValue, filterRegistry) {\n      var count = this.filters ? this.filters.length : 0;\n      while (count-- > 0) {\n        newValue = this.filters[count].transform(newValue, true, filterRegistry,\n                                                 model);\n      }\n\n      if (this.expression.setValue)\n        return this.expression.setValue(model, newValue);\n    }\n  }\n\n  /**\n   * Converts a style property name to a css property name. For example:\n   * \"WebkitUserSelect\" to \"-webkit-user-select\"\n   */\n  function convertStylePropertyName(name) {\n    return String(name).replace(/[A-Z]/g, function(c) {\n      return '-' + c.toLowerCase();\n    });\n  }\n\n  function isEventHandler(name) {\n    return name[0] === 'o' &&\n           name[1] === 'n' &&\n           name[2] === '-';\n  }\n\n  var mixedCaseEventTypes = {};\n  [\n    'webkitAnimationStart',\n    'webkitAnimationEnd',\n    'webkitTransitionEnd',\n    'DOMFocusOut',\n    'DOMFocusIn',\n    'DOMMouseScroll'\n  ].forEach(function(e) {\n    mixedCaseEventTypes[e.toLowerCase()] = e;\n  });\n\n  var parentScopeName = '@' + Math.random().toString(36).slice(2);\n\n  // Single ident paths must bind directly to the appropriate scope object.\n  // I.e. Pushed values in two-bindings need to be assigned to the actual model\n  // object.\n  function findScope(model, prop) {\n    while (model[parentScopeName] &&\n           !Object.prototype.hasOwnProperty.call(model, prop)) {\n      model = model[parentScopeName];\n    }\n\n    return model;\n  }\n\n  function resolveEventReceiver(model, path, node) {\n    if (path.length == 0)\n      return undefined;\n\n    if (path.length == 1)\n      return findScope(model, path[0]);\n\n    for (var i = 0; model != null && i < path.length - 1; i++) {\n      model = model[path[i]];\n    }\n\n    return model;\n  }\n\n  function prepareEventBinding(path, name, polymerExpressions) {\n    var eventType = name.substring(3);\n    eventType = mixedCaseEventTypes[eventType] || eventType;\n\n    return function(model, node, oneTime) {\n      var fn, receiver, handler;\n      if (typeof polymerExpressions.resolveEventHandler == 'function') {\n        handler = function(e) {\n          fn = fn || polymerExpressions.resolveEventHandler(model, path, node);\n          fn(e, e.detail, e.currentTarget);\n\n          if (Platform && typeof Platform.flush == 'function')\n            Platform.flush();\n        };\n      } else {\n        handler = function(e) {\n          fn = fn || path.getValueFrom(model);\n          receiver = receiver || resolveEventReceiver(model, path, node);\n\n          fn.apply(receiver, [e, e.detail, e.currentTarget]);\n\n          if (Platform && typeof Platform.flush == 'function')\n            Platform.flush();\n        };\n      }\n\n      node.addEventListener(eventType, handler);\n\n      if (oneTime)\n        return;\n\n      function bindingValue() {\n        return '{{ ' + path + ' }}';\n      }\n\n      return {\n        open: bindingValue,\n        discardChanges: bindingValue,\n        close: function() {\n          node.removeEventListener(eventType, handler);\n        }\n      };\n    }\n  }\n\n  function PolymerExpressions() {}\n\n  PolymerExpressions.prototype = {\n    // \"built-in\" filters\n    styleObject: function(value) {\n      var parts = [];\n      for (var key in value) {\n        parts.push(convertStylePropertyName(key) + ': ' + value[key]);\n      }\n      return parts.join('; ');\n    },\n\n    tokenList: function(value) {\n      var tokens = [];\n      for (var key in value) {\n        if (value[key])\n          tokens.push(key);\n      }\n      return tokens.join(' ');\n    },\n\n    // binding delegate API\n    prepareInstancePositionChanged: function(template) {\n      var indexIdent = template.polymerExpressionIndexIdent_;\n      if (!indexIdent)\n        return;\n\n      return function(templateInstance, index) {\n        templateInstance.model[indexIdent] = index;\n      };\n    },\n\n    prepareBinding: function(pathString, name, node) {\n      var path = Path.get(pathString);\n      if (isEventHandler(name)) {\n        if (!path.valid) {\n          console.error('on-* bindings must be simple path expressions');\n          return;\n        }\n\n        return prepareEventBinding(path, name, this);\n      }\n\n      if (path.valid) {\n        if (path.length == 1) {\n          return function(model, node, oneTime) {\n            if (oneTime)\n              return path.getValueFrom(model);\n\n            var scope = findScope(model, path[0]);\n            return new PathObserver(scope, path);\n          }\n        }\n\n        return; // bail out early if pathString is simple path.\n      }\n\n      return prepareBinding(pathString, name, node, this);\n    },\n\n    prepareInstanceModel: function(template) {\n      var scopeName = template.polymerExpressionScopeIdent_;\n      if (!scopeName)\n        return;\n\n      var parentScope = template.templateInstance ?\n          template.templateInstance.model :\n          template.model;\n\n      var indexName = template.polymerExpressionIndexIdent_;\n\n      return function(model) {\n        var scope = Object.create(parentScope);\n        scope[scopeName] = model;\n        scope[indexName] = undefined;\n        scope[parentScopeName] = parentScope;\n        return scope;\n      };\n    }\n  };\n\n  global.PolymerExpressions = PolymerExpressions;\n  if (global.exposeGetExpression)\n    global.getExpression_ = getExpression;\n\n  global.PolymerExpressions.prepareEventBinding = prepareEventBinding;\n})(this);\n",
+    "/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function(scope) {\n\n// inject style sheet\nvar style = document.createElement('style');\nstyle.textContent = 'template {display: none !important;} /* injected by platform.js */';\nvar head = document.querySelector('head');\nhead.insertBefore(style, head.firstChild);\n\n// flush (with logging)\nvar flushing;\nfunction flush() {\n  if (!flushing) {\n    flushing = true;\n    scope.endOfMicrotask(function() {\n      flushing = false;\n      logFlags.data && console.group('Platform.flush()');\n      scope.performMicrotaskCheckpoint();\n      logFlags.data && console.groupEnd();\n    });\n  }\n};\n\n// polling dirty checker\nvar FLUSH_POLL_INTERVAL = 125;\nwindow.addEventListener('WebComponentsReady', function() {\n  flush();\n  // flush periodically if platform does not have object observe.\n  if (!Observer.hasObjectObserve) {\n    scope.flushPoll = setInterval(flush, FLUSH_POLL_INTERVAL);\n  }\n});\n\nif (window.CustomElements && !CustomElements.useNative) {\n  var originalImportNode = Document.prototype.importNode;\n  Document.prototype.importNode = function(node, deep) {\n    var imported = originalImportNode.call(this, node, deep);\n    CustomElements.upgradeAll(imported);\n    return imported;\n  }\n}\n\n// exports\nscope.flush = flush;\n\n})(window.Platform);\n\n"
+  ]
+}
\ No newline at end of file
diff --git a/pkg/web_components/lib/platform.js b/pkg/web_components/lib/platform.js
new file mode 100644
index 0000000..e4add15
--- /dev/null
+++ b/pkg/web_components/lib/platform.js
@@ -0,0 +1,35 @@
+// Copyright (c) 2012 The Polymer Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// 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.
+// @version: 0.1.4-e263883
+function PointerGestureEvent(a,b){var c=b||{},d=document.createEvent("Event"),e={bubbles:Boolean(c.bubbles)===c.bubbles||!0,cancelable:Boolean(c.cancelable)===c.cancelable||!0};d.initEvent(a,e.bubbles,e.cancelable);for(var f,g=Object.keys(c),h=0;h<g.length;h++)f=g[h],d[f]=c[f];return d.preventTap=this.preventTap,d}"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}(),function(a){"use strict";function b(){function a(a){b=a}if("function"!=typeof Object.observe||"function"!=typeof Array.observe)return!1;var b=[],c={};if(Object.observe(c,a),c.id=1,c.id=2,delete c.id,Object.deliverChangeRecords(a),3!==b.length)return!1;if("new"==b[0].type&&"updated"==b[1].type&&"deleted"==b[2].type)L="new",M="updated",N="reconfigured",O="deleted";else if("add"!=b[0].type||"update"!=b[1].type||"delete"!=b[2].type)return console.error("Unexpected change record names for Object.observe. Using dirty-checking instead"),!1;return Object.unobserve(c,a),c=[0],Array.observe(c,a),c[1]=1,c.length=0,Object.deliverChangeRecords(a),2!=b.length?!1:b[0].type!=P||b[1].type!=P?!1:(Array.unobserve(c,a),!0)}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:S(a)&&S(b)?!0:a!==a&&b!==b}function h(a){return"string"!=typeof a?!1:(a=a.trim(),""==a?!0:"."==a[0]?!1:$.test(a))}function i(a,b){if(b!==_)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),void(R&&this.length&&(this.getValueFrom=this.compiledGetValueFromFn())))}function j(a){if(a instanceof i)return a;null==a&&(a=""),"string"!=typeof a&&(a=String(a));var b=ab[a];if(b)return b;if(!h(a))return bb;var b=new i(a,_);return ab[a]=b,b}function k(b){for(var c=0;db>c&&b.check_();)c++;return a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=c),c>0}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(){if(!eb.length)return!1;for(var a=0;a<eb.length;a++)eb[a]();return eb.length=0,!0}function p(){function a(a){b&&b.state_===kb&&!d&&b.check_(a)}var b,c,d=!1,e=!0;return{open:function(c){if(b)throw Error("ObservedObject in use");e||Object.deliverChangeRecords(a),b=c,e=!1},observe:function(b,d){c=b,d?Array.observe(c,a):Object.observe(c,a)},deliver:function(b){d=b,Object.deliverChangeRecords(a),d=!1},close:function(){b=void 0,Object.unobserve(c,a),gb.push(this)}}}function q(a,b,c){var d=gb.pop()||p();return d.open(a),d.observe(b,c),d}function r(){function a(b){if(f(b)){var c=i.indexOf(b);c>=0?(i[c]=void 0,h.push(b)):h.indexOf(b)<0&&(h.push(b),Object.observe(b,d)),a(Object.getPrototypeOf(b))}}function b(){if(k=!1,j){var b=i===hb?[]:i;i=h,h=b;var c;for(var f in e)c=e[f],c&&c.state_==kb&&c.iterateObjects_(a);for(var g=0;g<i.length;g++){var l=i[g];l&&Object.unobserve(l,d)}i.length=0}}function c(){k||(j=!0,k=!0,fb(b))}function d(){var a;for(var b in e)a=e[b],a&&a.state_==kb&&a.check_();c()}var e=[],g=0,h=[],i=hb,j=!1,k=!1,l={object:void 0,objects:h,open:function(b){e[b.id_]=b,g++,b.iterateObjects_(a)},close:function(a){if(e[a.id_]=void 0,g--,g)return void c();j=!1;for(var b=0;b<h.length;b++)Object.unobserve(h[b],d),t.unobservedCount++;e.length=0,h.length=0,ib.push(this)},reset:c};return l}function s(a,b){return cb&&cb.object===b||(cb=ib.pop()||r(),cb.object=b),cb.open(a),cb}function t(){this.state_=jb,this.callback_=void 0,this.target_=void 0,this.directObserver_=void 0,this.value_=void 0,this.id_=nb++}function u(a){t._allObserversCount++,pb&&ob.push(a)}function v(){t._allObserversCount--}function w(a){t.call(this),this.value_=a,this.oldObject_=void 0}function x(a){if(!Array.isArray(a))throw Error("Provided object is not an Array");w.call(this,a)}function y(a,b){t.call(this),this.object_=a,this.path_=b instanceof i?b:j(b),this.directObserver_=void 0}function z(){t.call(this),this.value_=[],this.directObserver_=void 0,this.observed_=[]}function A(a){return a}function B(a,b,c,d){this.callback_=void 0,this.target_=void 0,this.value_=void 0,this.observable_=a,this.getValueFn_=b||A,this.setValueFn_=c||A,this.dontPassThroughSet_=d}function C(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 D(a,b,c){for(var d={},e={},f=0;f<b.length;f++){var g=b[f];tb[g.type]?(g.name in c||(c[g.name]=g.oldValue),g.type!=M&&(g.type!=L?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 E(a,b,c){return{index:a,removed:b,addedCount:c}}function F(){}function G(a,b,c,d,e,f){return yb.calcSplices(a,b,c,d,e,f)}function H(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 I(a,b,c,d){for(var e=E(b,c,d),f=!1,g=0,h=0;h<a.length;h++){var i=a[h];if(i.index+=g,!f){var j=H(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 J(a,b){for(var c=[],f=0;f<b.length;f++){var g=b[f];switch(g.type){case P:I(c,g.index,g.removed.slice(),g.addedCount);break;case L:case M:case O:if(!d(g.name))continue;var h=e(g.name);if(0>h)continue;I(c,h,[g.oldValue],1);break;default:console.error("Unexpected record type: "+JSON.stringify(g))}}return c}function K(a,b){var c=[];return J(a,b).forEach(function(b){return 1==b.addedCount&&1==b.removed.length?void(b.removed[0]!==a[b.index]&&c.push(b)):void(c=c.concat(G(a,b.index,b.index+b.addedCount,b.removed,0,b.removed.length)))}),c}var L="add",M="update",N="reconfigure",O="delete",P="splice",Q=b(),R=c(),S=a.Number.isNaN||function(b){return"number"==typeof b&&a.isNaN(b)},T="__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},U="[$_a-zA-Z]",V="[$_a-zA-Z0-9]",W=U+"+"+V+"*",X="(?:[0-9]|[1-9]+[0-9]+)",Y="(?:"+W+"|"+X+")",Z="(?:"+Y+")(?:\\s*\\.\\s*"+Y+")*",$=new RegExp("^"+Z+"$"),_={},ab={};i.get=j,i.prototype=T({__proto__:[],valid:!0,toString:function(){return this.join(".")},getValueFrom:function(a){for(var b=0;b<this.length;b++){if(null==a)return;a=a[this[b]]}return a},iterateObjects:function(a,b){for(var c=0;c<this.length;c++){if(c&&(a=a[this[c-1]]),!a)return;b(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 bb=new i("",_);bb.valid=!1,bb.getValueFrom=bb.setValueFrom=function(){};var cb,db=1e3,eb=[],fb=Q?function(){var a={pingPong:!0},b=!1;return Object.observe(a,function(){o(),b=!1}),function(c){eb.push(c),b||(b=!0,a.pingPong=!a.pingPong)}}():function(){return function(a){eb.push(a)}}(),gb=[],hb=[],ib=[],jb=0,kb=1,lb=2,mb=3,nb=1;t.prototype={open:function(a,b){if(this.state_!=jb)throw Error("Observer has already been opened.");return u(this),this.callback_=a,this.target_=b,this.state_=kb,this.connect_(),this.value_},close:function(){this.state_==kb&&(v(this),this.state_=lb,this.disconnect_(),this.value_=void 0,this.callback_=void 0,this.target_=void 0)},deliver:function(){this.state_==kb&&k(this)},report_:function(a){try{this.callback_.apply(this.target_,a)}catch(b){t._errorThrownDuringCallback=!0,console.error("Exception caught during observer callback: "+(b.stack||b))}},discardChanges:function(){return this.check_(void 0,!0),this.value_}};var ob,pb=!Q;t._allObserversCount=0,pb&&(ob=[]);var qb=!1,rb="function"==typeof Object.deliverAllChangeRecords;a.Platform=a.Platform||{},a.Platform.performMicrotaskCheckpoint=function(){if(!qb){if(rb)return void Object.deliverAllChangeRecords();if(pb){qb=!0;var b,c,d=0;do{d++,c=ob,ob=[],b=!1;for(var e=0;e<c.length;e++){var f=c[e];f.state_==kb&&(f.check_()&&(b=!0),ob.push(f))}o()&&(b=!0)}while(db>d&&b);a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=d),qb=!1}}},pb&&(a.Platform.clearObservers=function(){ob=[]}),w.prototype=T({__proto__:t.prototype,arrayObserve:!1,connect_:function(){Q?this.directObserver_=q(this,this.value_,this.arrayObserve):this.oldObject_=this.copyObject(this.value_)},copyObject:function(a){var b=Array.isArray(a)?[]:{};for(var c in a)b[c]=a[c];return Array.isArray(a)&&(b.length=a.length),b},check_:function(a){var b,c;if(Q){if(!a)return!1;c={},b=D(this.value_,a,c)}else c=this.oldObject_,b=n(this.value_,this.oldObject_);return m(b)?!1:(Q||(this.oldObject_=this.copyObject(this.value_)),this.report_([b.added||{},b.removed||{},b.changed||{},function(a){return c[a]}]),!0)},disconnect_:function(){Q?(this.directObserver_.close(),this.directObserver_=void 0):this.oldObject_=void 0},deliver:function(){this.state_==kb&&(Q?this.directObserver_.deliver(!1):k(this))},discardChanges:function(){return this.directObserver_?this.directObserver_.deliver(!0):this.oldObject_=this.copyObject(this.value_),this.value_}}),x.prototype=T({__proto__:w.prototype,arrayObserve:!0,copyObject:function(a){return a.slice()},check_:function(a){var b;if(Q){if(!a)return!1;b=K(this.value_,a)}else b=G(this.value_,0,this.value_.length,this.oldObject_,0,this.oldObject_.length);return b&&b.length?(Q||(this.oldObject_=this.copyObject(this.value_)),this.report_([b]),!0):!1}}),x.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)})},y.prototype=T({__proto__:t.prototype,connect_:function(){Q&&(this.directObserver_=s(this,this.object_)),this.check_(void 0,!0)},disconnect_:function(){this.value_=void 0,this.directObserver_&&(this.directObserver_.close(this),this.directObserver_=void 0)},iterateObjects_:function(a){this.path_.iterateObjects(this.object_,a)},check_:function(a,b){var c=this.value_;return this.value_=this.path_.getValueFrom(this.object_),b||g(this.value_,c)?!1:(this.report_([this.value_,c]),!0)},setValue:function(a){this.path_&&this.path_.setValueFrom(this.object_,a)}});var sb={};z.prototype=T({__proto__:t.prototype,connect_:function(){if(this.check_(void 0,!0),Q){for(var a,b=!1,c=0;c<this.observed_.length;c+=2)if(a=this.observed_[c],a!==sb){b=!0;break}return this.directObserver_?b?void this.directObserver_.reset():(this.directObserver_.close(),void(this.directObserver_=void 0)):void(b&&(this.directObserver_=s(this,a)))}},closeObservers_:function(){for(var a=0;a<this.observed_.length;a+=2)this.observed_[a]===sb&&this.observed_[a+1].close();this.observed_.length=0},disconnect_:function(){this.value_=void 0,this.directObserver_&&(this.directObserver_.close(this),this.directObserver_=void 0),this.closeObservers_()},addPath:function(a,b){if(this.state_!=jb&&this.state_!=mb)throw Error("Cannot add paths once started.");this.observed_.push(a,b instanceof i?b:j(b))},addObserver:function(a){if(this.state_!=jb&&this.state_!=mb)throw Error("Cannot add observers once started.");a.open(this.deliver,this),this.observed_.push(sb,a)},startReset:function(){if(this.state_!=kb)throw Error("Can only reset while open");this.state_=mb,this.closeObservers_()},finishReset:function(){if(this.state_!=mb)throw Error("Can only finishReset after startReset");return this.state_=kb,this.connect_(),this.value_},iterateObjects_:function(a){for(var b,c=0;c<this.observed_.length;c+=2)b=this.observed_[c],b!==sb&&this.observed_[c+1].iterateObjects(b,a)},check_:function(a,b){for(var c,d=0;d<this.observed_.length;d+=2){var e=this.observed_[d+1],f=this.observed_[d],h=f===sb?e.discardChanges():e.getValueFrom(f);b?this.value_[d/2]=h:g(h,this.value_[d/2])||(c=c||[],c[d/2]=this.value_[d/2],this.value_[d/2]=h)}return c?(this.report_([this.value_,c,this.observed_]),!0):!1}}),B.prototype={open:function(a,b){return this.callback_=a,this.target_=b,this.value_=this.getValueFn_(this.observable_.open(this.observedCallback_,this)),this.value_},observedCallback_:function(a){if(a=this.getValueFn_(a),!g(a,this.value_)){var b=this.value_;this.value_=a,this.callback_.call(this.target_,this.value_,b)}},discardChanges:function(){return this.value_=this.getValueFn_(this.observable_.discardChanges()),this.value_},deliver:function(){return this.observable_.deliver()},setValue:function(a){return a=this.setValueFn_(a),!this.dontPassThroughSet_&&this.observable_.setValue?this.observable_.setValue(a):void 0},close:function(){this.observable_&&this.observable_.close(),this.callback_=void 0,this.target_=void 0,this.observable_=void 0,this.value_=void 0,this.getValueFn_=void 0,this.setValueFn_=void 0}};var tb={};tb[L]=!0,tb[M]=!0,tb[O]=!0,t.defineComputedProperty=function(a,b,c){var d=C(a,b),e=c.open(function(a,b){e=a,d&&d(M,b)});return Object.defineProperty(a,b,{get:function(){return c.deliver(),e},set:function(a){return c.setValue(a),a},configurable:!0}),{close:function(){c.close(),Object.defineProperty(a,b,{value:e,writable:!0,configurable:!0})}}};var ub=0,vb=1,wb=2,xb=3;F.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(ub):(e.push(vb),d=g),b--,c--):f==h?(e.push(xb),b--,d=h):(e.push(wb),c--,d=i)}else e.push(xb),b--;else e.push(wb),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,c-b==0&&f-e==0)return[];if(b==c){for(var j=E(b,[],0);f>e;)j.removed.push(d[e++]);return[j]}if(e==f)return[E(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 ub:j&&(l.push(j),j=void 0),m++,n++;break;case vb:j||(j=E(m,[],0)),j.addedCount++,m++,j.removed.push(d[n]),n++;break;case wb:j||(j=E(m,[],0)),j.addedCount++,m++;break;case xb:j||(j=E(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 yb=new F;a.Observer=t,a.Observer.runEOM_=fb,a.Observer.hasObjectObserve=Q,a.ArrayObserver=x,a.ArrayObserver.calculateSplices=function(a,b){return yb.calculateSplices(a,b)},a.ArraySplice=F,a.ObjectObserver=w,a.PathObserver=y,a.CompoundObserver=z,a.Path=i,a.ObserverTransform=B,a.Observer.changeRecordTypes={add:L,update:M,reconfigure:N,"delete":O,splice:P}}("undefined"!=typeof global&&global&&"undefined"!=typeof module&&module?global:this||window),window.Platform=window.Platform||{},window.logFlags=window.logFlags||{},function(a){var b=a.flags||{};location.search.slice(1).split("&").forEach(function(a){a=a.split("="),a[0]&&(b[a[0]]=a[1]||!0)});var c=document.currentScript||document.querySelector('script[src*="platform.js"]');if(c)for(var d,e=c.attributes,f=0;f<e.length;f++)d=e[f],"src"!==d.name&&(b[d.name]=d.value||!0);b.log&&b.log.split(",").forEach(function(a){window.logFlags[a]=!0}),b.shadow=b.shadow||b.shadowdom||b.polyfill,b.shadow="native"===b.shadow?!1:b.shadow||!HTMLElement.prototype.createShadowRoot,b.register&&(window.CustomElements=window.CustomElements||{flags:{}},window.CustomElements.flags.register=b.register),b.imports&&(window.HTMLImports=window.HTMLImports||{flags:{}},window.HTMLImports.flags.imports=b.imports),a.flags=b}(Platform),Platform.flags.shadow?(window.ShadowDOMPolyfill={},function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a,b){return L(b).forEach(function(c){K(a,c,M(b,c))}),a}function d(a,b){return L(b).forEach(function(c){switch(c){case"arguments":case"caller":case"length":case"name":case"prototype":case"toString":return}K(a,c,M(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=E.get(b);if(c)return c;var d=f(b),e=t(d);return q(b,e,a),e}function g(a,b){o(a,b,!0)}function h(a,b){o(b,a,!1)}function i(a){return/^on[a-z]+$/.test(a)}function j(a){return/^\w[a-zA-Z_0-9]*$/.test(a)}function k(a){return H&&j(a)?new Function("return this.impl."+a):function(){return this.impl[a]}}function l(a){return H&&j(a)?new Function("v","this.impl."+a+" = v"):function(b){this.impl[a]=b}}function m(a){return H&&j(a)?new Function("return this.impl."+a+".apply(this.impl, arguments)"):function(){return this.impl[a].apply(this.impl,arguments)}}function n(a,b){try{return Object.getOwnPropertyDescriptor(a,b)}catch(c){return O}}function o(b,c,d){for(var e=L(b),f=0;f<e.length;f++){var g=e[f];if("polymerBlackList_"!==g&&!(g in c||b.polymerBlackList_&&b.polymerBlackList_[g])){N&&b.__lookupGetter__(g);var h,j,o=n(b,g);if(d&&"function"==typeof o.value)c[g]=m(g);else{var p=i(g);h=p?a.getEventHandlerGetter(g):k(g),(o.writable||o.set)&&(j=p?a.getEventHandlerSetter(g):l(g)),K(c,g,{get:h,set:j,configurable:o.configurable,enumerable:o.enumerable})}}}}function p(a,b,c){var e=a.prototype;q(e,b,c),d(b,a)}function q(a,c,d){var e=c.prototype;b(void 0===E.get(a)),E.set(a,c),F.set(e,a),g(a,e),d&&h(e,d),K(e,"constructor",{value:c,configurable:!0,enumerable:!1,writable:!0})}function r(a,b){return E.get(b.prototype)===a}function s(a){var b=Object.getPrototypeOf(a),c=f(b),d=t(c);return q(b,d,a),d}function t(a){function b(b){a.call(this,b)}return b.prototype=Object.create(a.prototype),b.prototype.constructor=b,b}function u(a){return a instanceof G.EventTarget||a instanceof G.Event||a instanceof G.Range||a instanceof G.DOMImplementation||a instanceof G.CanvasRenderingContext2D||G.WebGLRenderingContext&&a instanceof G.WebGLRenderingContext}function v(a){return Q&&a instanceof Q||a instanceof S||a instanceof R||a instanceof T||a instanceof U||a instanceof P||a instanceof V||W&&a instanceof W||X&&a instanceof X}function w(a){return null===a?null:(b(v(a)),a.polymerWrapper_||(a.polymerWrapper_=new(f(a))(a)))}function x(a){return null===a?null:(b(u(a)),a.impl)}function y(a){return a&&u(a)?x(a):a}function z(a){return a&&!u(a)?w(a):a}function A(a,c){null!==c&&(b(v(a)),b(void 0===c||u(c)),a.polymerWrapper_=c)}function B(a,b,c){K(a.prototype,b,{get:c,configurable:!0,enumerable:!0})}function C(a,b){B(a,b,function(){return w(this.impl[b])})}function D(a,b){a.forEach(function(a){b.forEach(function(b){a.prototype[b]=function(){var a=z(this);return a[b].apply(a,arguments)}})})}var E=new WeakMap,F=new WeakMap,G=Object.create(null),H=!("securityPolicy"in document)||document.securityPolicy.allowsEval;if(H)try{var I=new Function("","return true;");H=I()}catch(J){H=!1}var K=Object.defineProperty,L=Object.getOwnPropertyNames,M=Object.getOwnPropertyDescriptor;L(window);var N=/Firefox/.test(navigator.userAgent),O={get:function(){},set:function(){},configurable:!0,enumerable:!0},P=window.DOMImplementation,Q=window.EventTarget,R=window.Event,S=window.Node,T=window.Window,U=window.Range,V=window.CanvasRenderingContext2D,W=window.WebGLRenderingContext,X=window.SVGElementInstance;a.assert=b,a.constructorTable=E,a.defineGetter=B,a.defineWrapGetter=C,a.forwardMethodsToWrapper=D,a.isWrapper=u,a.isWrapperFor=r,a.mixin=c,a.nativePrototypeTable=F,a.oneOf=e,a.registerObject=s,a.registerWrapper=p,a.rewrap=A,a.unwrap=x,a.unwrapIfNeeded=y,a.wrap=w,a.wrapIfNeeded=z,a.wrappers=G}(window.ShadowDOMPolyfill),function(a){"use strict";function b(){g=!1;var a=f.slice(0);f=[];for(var b=0;b<a.length;b++)a[b]()}function c(a){f.push(a),g||(g=!0,d(b,0))}var d,e=window.MutationObserver,f=[],g=!1;if(e){var h=1,i=new e(b),j=document.createTextNode(h);i.observe(j,{characterData:!0}),d=function(){h=(h+1)%2,j.data=h}}else d=window.setImmediate||window.setTimeout;a.setEndOfMicrotask=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(){p||(k(c),p=!0)}function c(){p=!1;do for(var a=o.slice(),b=!1,c=0;c<a.length;c++){var d=a[c],e=d.takeRecords();f(d),e.length&&(d.callback_(e,d),b=!0)}while(b)}function d(a,b){this.type=a,this.target=b,this.addedNodes=new m.NodeList,this.removedNodes=new m.NodeList,this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function e(a,b){for(;a;a=a.parentNode){var c=n.get(a);if(c)for(var d=0;d<c.length;d++){var e=c[d];e.options.subtree&&e.addTransientObserver(b)}}}function f(a){for(var b=0;b<a.nodes_.length;b++){var c=a.nodes_[b],d=n.get(c);if(!d)return;for(var e=0;e<d.length;e++){var f=d[e];f.observer===a&&f.removeTransientObservers()}}}function g(a,c,e){for(var f=Object.create(null),g=Object.create(null),h=a;h;h=h.parentNode){var i=n.get(h);if(i)for(var j=0;j<i.length;j++){var k=i[j],l=k.options;if((h===a||l.subtree)&&!("attributes"===c&&!l.attributes||"attributes"===c&&l.attributeFilter&&(null!==e.namespace||-1===l.attributeFilter.indexOf(e.name))||"characterData"===c&&!l.characterData||"childList"===c&&!l.childList)){var m=k.observer;f[m.uid_]=m,("attributes"===c&&l.attributeOldValue||"characterData"===c&&l.characterDataOldValue)&&(g[m.uid_]=e.oldValue)}}}var o=!1;for(var p in f){var m=f[p],q=new d(c,a);"name"in e&&"namespace"in e&&(q.attributeName=e.name,q.attributeNamespace=e.namespace),e.addedNodes&&(q.addedNodes=e.addedNodes),e.removedNodes&&(q.removedNodes=e.removedNodes),e.previousSibling&&(q.previousSibling=e.previousSibling),e.nextSibling&&(q.nextSibling=e.nextSibling),void 0!==g[p]&&(q.oldValue=g[p]),m.records_.push(q),o=!0}o&&b()}function h(a){if(this.childList=!!a.childList,this.subtree=!!a.subtree,this.attributes="attributes"in a||!("attributeOldValue"in a||"attributeFilter"in a)?!!a.attributes:!0,this.characterData="characterDataOldValue"in a&&!("characterData"in a)?!0:!!a.characterData,!this.attributes&&(a.attributeOldValue||"attributeFilter"in a)||!this.characterData&&a.characterDataOldValue)throw new TypeError;if(this.characterData=!!a.characterData,this.attributeOldValue=!!a.attributeOldValue,this.characterDataOldValue=!!a.characterDataOldValue,"attributeFilter"in a){if(null==a.attributeFilter||"object"!=typeof a.attributeFilter)throw new TypeError;this.attributeFilter=q.call(a.attributeFilter)}else this.attributeFilter=null}function i(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++r,o.push(this)}function j(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var k=a.setEndOfMicrotask,l=a.wrapIfNeeded,m=a.wrappers,n=new WeakMap,o=[],p=!1,q=Array.prototype.slice,r=0;i.prototype={observe:function(a,b){a=l(a);var c,d=new h(b),e=n.get(a);e||n.set(a,e=[]);for(var f=0;f<e.length;f++)e[f].observer===this&&(c=e[f],c.removeTransientObservers(),c.options=d);c||(c=new j(this,a,d),e.push(c),this.nodes_.push(a))},disconnect:function(){this.nodes_.forEach(function(a){for(var b=n.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}},j.prototype={addTransientObserver:function(a){if(a!==this.target){this.transientObservedNodes.push(a);var b=n.get(a);b||n.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[];for(var b=0;b<a.length;b++)for(var c=a[b],d=n.get(c),e=0;e<d.length;e++)if(d[e]===this){d.splice(e,1);break}}},a.enqueueMutation=g,a.registerTransientObservers=e,a.wrappers.MutationObserver=i,a.wrappers.MutationRecord=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a instanceof Q.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)&&P(b)||null}function f(f,g,h){if(h.length)return h.shift();if(b(f))return j(f)||f.host;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(a,d){for(var e=[];a;){for(var g=[],i=d,j=void 0;i;){var l=null;if(g.length){if(c(i)&&(l=h(g),k(j))){var n=g[g.length-1];g.push(n)}}else g.push(i);if(m(i,a))return g[g.length-1];b(i)&&g.pop(),j=i,i=f(i,l,e)}a=b(a)?a.host:a.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(a,b){return a===b?!0:a instanceof Q.ShadowRoot?n(l(a.host),b):!1}function o(a){return S.get(a)?void 0:(S.set(a,!0),p(P(a),P(a.target)))}function p(b,c){if(T.get(b))throw new Error("InvalidStateError");T.set(b,!0),a.renderAllPending();var d=g(c);return"load"===b.type&&2===d.length&&d[0].target instanceof Q.Document&&d.shift(),_.set(b,d),q(b,d)&&r(b,d)&&s(b,d),X.set(b,v.NONE),V.delete(b,null),T.delete(b),b.defaultPrevented}function q(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=v.CAPTURING_PHASE,!t(b[d],a,c)))return!1}return!0}function r(a,b){var c=v.AT_TARGET;return t(b[0],a,c)}function s(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=v.AT_TARGET;else{if(!d||Z.get(a))continue;c=v.BUBBLING_PHASE}if(!t(b[e],a,c))return}}function t(a,b,c){var d=a.target,e=a.currentTarget,f=R.get(e);if(!f)return!0;if("relatedTarget"in b){var g=O(b);if(g.relatedTarget){var h=P(g.relatedTarget),j=i(e,h);if(j===d)return!0;W.set(b,j)}}X.set(b,c);var k=b.type,l=!1;U.set(b,d),V.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===v.CAPTURING_PHASE||n.capture&&c===v.BUBBLING_PHASE))try{if("function"==typeof n.handler?n.handler.call(e,b):n.handler.handleEvent(b),Z.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!Y.get(b)}function u(a,b,c){this.type=a,this.handler=b,this.capture=Boolean(c)}function v(a,b){return a instanceof ab?void(this.impl=a):P(z(ab,"Event",a,b))}function w(a){return a&&a.relatedTarget?Object.create(a,{relatedTarget:{value:O(a.relatedTarget)}}):a}function x(a,b,c){var d=window[a],e=function(b,c){return b instanceof d?void(this.impl=b):P(z(d,a,b,c))};if(e.prototype=Object.create(b.prototype),c&&M(e.prototype,c),d)try{N(d,e,new d("temp"))}catch(f){N(d,e,document.createEvent(a))}return e}function y(a,b){return function(){arguments[b]=O(arguments[b]);var c=O(this);c[a].apply(c,arguments)}}function z(a,b,c,d){if(jb)return new a(c,w(d));var e=O(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=O(b)),g.push(b)}),e["init"+b].apply(e,g),e}function A(){v.call(this)}function B(a){return"function"==typeof a?!0:a&&a.handleEvent}function C(a){switch(a){case"DOMAttrModified":case"DOMAttributeNameChanged":case"DOMCharacterDataModified":case"DOMElementNameChanged":case"DOMNodeInserted":case"DOMNodeInsertedIntoDocument":case"DOMNodeRemoved":case"DOMNodeRemovedFromDocument":case"DOMSubtreeModified":return!0}return!1}function D(a){this.impl=a}function E(a){return a instanceof Q.ShadowRoot&&(a=a.host),O(a)}function F(a,b){var c=R.get(a);if(c)for(var d=0;d<c.length;d++)if(!c[d].removed&&c[d].type===b)return!0;return!1}function G(a,b){for(var c=O(a);c;c=c.parentNode)if(F(P(c),b))return!0;return!1}function H(a){L(a,mb)}function I(b,c,d,e){a.renderAllPending();for(var f=P(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 J(a){return function(){var b=$.get(this);return b&&b[a]&&b[a].value||null}}function K(a){var b=a.slice(2);return function(c){var d=$.get(this);d||(d=Object.create(null),$.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 L=a.forwardMethodsToWrapper,M=a.mixin,N=a.registerWrapper,O=a.unwrap,P=a.wrap,Q=a.wrappers,R=(new WeakMap,new WeakMap),S=new WeakMap,T=new WeakMap,U=new WeakMap,V=new WeakMap,W=new WeakMap,X=new WeakMap,Y=new WeakMap,Z=new WeakMap,$=new WeakMap,_=new WeakMap;u.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 ab=window.Event;ab.prototype.polymerBlackList_={returnValue:!0,keyLocation:!0},v.prototype={get target(){return U.get(this)},get currentTarget(){return V.get(this)},get eventPhase(){return X.get(this)},get path(){var a=new Q.NodeList,b=_.get(this);if(b){for(var c=0,d=b.length-1,e=l(V.get(this)),f=0;d>=f;f++){var g=b[f].currentTarget,h=l(g);n(e,h)&&(f!==d||g instanceof Q.Node)&&(a[c++]=g)}a.length=c}return a},stopPropagation:function(){Y.set(this,!0)},stopImmediatePropagation:function(){Y.set(this,!0),Z.set(this,!0)}},N(ab,v,document.createEvent("Event"));var bb=x("UIEvent",v),cb=x("CustomEvent",v),db={get relatedTarget(){return W.get(this)||P(O(this).relatedTarget)}},eb=M({initMouseEvent:y("initMouseEvent",14)},db),fb=M({initFocusEvent:y("initFocusEvent",5)},db),gb=x("MouseEvent",bb,eb),hb=x("FocusEvent",bb,fb),ib=Object.create(null),jb=function(){try{new window.FocusEvent("focus")}catch(a){return!1}return!0}();if(!jb){var kb=function(a,b,c){if(c){var d=ib[c];b=M(M({},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")}A.prototype=Object.create(v.prototype),M(A.prototype,{get returnValue(){return this.impl.returnValue},set returnValue(a){this.impl.returnValue=a}});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(B(b)&&!C(a)){var d=new u(a,b,c),e=R.get(this);if(e){for(var f=0;f<e.length;f++)if(d.equals(e[f]))return}else e=[],R.set(this,e);e.push(d);var g=E(this);g.addEventListener_(a,o,!0)}},removeEventListener:function(a,b,c){c=Boolean(c);var d=R.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,o,!0)}}},dispatchEvent:function(b){var c=O(b),d=c.type;S.set(c,!1),a.renderAllPending();var e;G(this,d)||(e=function(){},this.addEventListener(d,e,!0));try{return O(this).dispatchEvent_(c)}finally{e&&this.removeEventListener(d,e,!0)}}},lb&&N(lb,D);var nb=document.elementFromPoint;a.adjustRelatedTarget=i,a.elementFromPoint=I,a.getEventHandlerGetter=J,a.getEventHandlerSetter=K,a.wrapEventTargetMethods=H,a.wrappers.BeforeUnloadEvent=A,a.wrappers.CustomEvent=cb,a.wrappers.Event=v,a.wrappers.EventTarget=D,a.wrappers.FocusEvent=hb,a.wrappers.MouseEvent=gb,a.wrappers.UIEvent=bb}(window.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}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){y(a instanceof v)}function c(a){var b=new x;return b[0]=a,b.length=1,b}function d(a,b,c){A(b,"childList",{removedNodes:c,previousSibling:a.previousSibling,nextSibling:a.nextSibling})}function e(a,b){A(a,"childList",{removedNodes:b})}function f(a,b,d,e){if(a instanceof DocumentFragment){var f=h(a);J=!0;for(var g=f.length-1;g>=0;g--)a.removeChild(f[g]),f[g].parentNode_=b;J=!1;for(var g=0;g<f.length;g++)f[g].previousSibling_=f[g-1]||d,f[g].nextSibling_=f[g+1]||e;return d&&(d.nextSibling_=f[0]),e&&(e.previousSibling_=f[f.length-1]),f}var f=c(a),i=a.parentNode;return i&&i.removeChild(a),a.parentNode_=b,a.previousSibling_=d,a.nextSibling_=e,d&&(d.nextSibling_=a),e&&(e.previousSibling_=a),f}function g(a){if(a instanceof DocumentFragment)return h(a);var b=c(a),e=a.parentNode;return e&&d(a,e,b),b}function h(a){for(var b=new x,c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b.length=c,e(a,b),b}function i(a){return a}function j(a){a.nodeIsInserted_()}function k(a){for(var b=0;b<a.length;b++)j(a[b])}function l(){}function m(){}function n(a,b){var c=a.nodeType===v.DOCUMENT_NODE?a:a.ownerDocument;c!==b.ownerDocument&&c.adoptNode(b)}function o(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 p(a,b){o(a,b);var c=b.length;if(1===c)return F(b[0]);for(var d=F(a.ownerDocument.createDocumentFragment()),e=0;c>e;e++)d.appendChild(F(b[e]));return d}function q(a){if(void 0!==a.firstChild_)for(var b=a.firstChild_;b;){var c=b;b=b.nextSibling_,c.parentNode_=c.previousSibling_=c.nextSibling_=void 0}a.firstChild_=a.lastChild_=void 0}function r(a){if(a.invalidateShadowRenderer()){for(var b=a.firstChild;b;){y(b.parentNode===a);var c=b.nextSibling,d=F(b),e=d.parentNode;e&&Q.call(e,d),b.previousSibling_=b.nextSibling_=b.parentNode_=null,b=c}a.firstChild_=a.lastChild_=null}else for(var c,f=F(a),g=f.firstChild;g;)c=g.nextSibling,Q.call(f,g),g=c}function s(a){var b=a.parentNode;return b&&b.invalidateShadowRenderer()}function t(a){for(var b,c=0;c<a.length;c++)b=a[c],b.parentNode.removeChild(b)}function u(a,b,c){var d;if(d=G(c?K.call(c,a.impl,!1):L.call(a.impl,!1)),b){for(var e=a.firstChild;e;e=e.nextSibling)d.appendChild(u(e,!0,c));if(a instanceof I.HTMLTemplateElement)for(var f=d.content,e=a.content.firstChild;e;e=e.nextSibling)f.appendChild(u(e,!0,c))}return d}function v(a){y(a instanceof M),w.call(this,a),this.parentNode_=void 0,this.firstChild_=void 0,this.lastChild_=void 0,this.nextSibling_=void 0,this.previousSibling_=void 0}var w=a.wrappers.EventTarget,x=a.wrappers.NodeList,y=a.assert,z=a.defineWrapGetter,A=a.enqueueMutation,B=a.isWrapper,C=a.mixin,D=a.registerTransientObservers,E=a.registerWrapper,F=a.unwrap,G=a.wrap,H=a.wrapIfNeeded,I=a.wrappers,J=!1,K=document.importNode,L=window.Node.prototype.cloneNode,M=window.Node,N=window.DocumentFragment,O=(M.prototype.appendChild,M.prototype.compareDocumentPosition),P=M.prototype.insertBefore,Q=M.prototype.removeChild,R=M.prototype.replaceChild,S=/Trident/.test(navigator.userAgent),T=S?function(a,b){try{Q.call(a,b)}catch(c){if(!(a instanceof N))throw c}}:function(a,b){Q.call(a,b)};v.prototype=Object.create(w.prototype),C(v.prototype,{appendChild:function(a){return this.insertBefore(a,null)},insertBefore:function(a,c){b(a);var d;c?B(c)?d=F(c):(d=c,c=G(d)):(c=null,d=null),c&&y(c.parentNode===this);var e,h=c?c.previousSibling:this.lastChild,i=!this.invalidateShadowRenderer()&&!s(a);if(e=i?g(a):f(a,this,h,c),i)n(this,a),q(this),P.call(this.impl,F(a),d);else{h||(this.firstChild_=e[0]),c||(this.lastChild_=e[e.length-1]);var j=d?d.parentNode:this.impl;j?P.call(j,p(this,e),d):o(this,e)}return A(this,"childList",{addedNodes:e,nextSibling:c,previousSibling:h}),k(e),a},removeChild:function(a){if(b(a),a.parentNode!==this){for(var d=!1,e=(this.childNodes,this.firstChild);e;e=e.nextSibling)if(e===a){d=!0;break}if(!d)throw new Error("NotFoundError")}var f=F(a),g=a.nextSibling,h=a.previousSibling;if(this.invalidateShadowRenderer()){var i=this.firstChild,j=this.lastChild,k=f.parentNode;k&&T(k,f),i===a&&(this.firstChild_=g),j===a&&(this.lastChild_=h),h&&(h.nextSibling_=g),g&&(g.previousSibling_=h),a.previousSibling_=a.nextSibling_=a.parentNode_=void 0}else q(this),T(this.impl,f);return J||A(this,"childList",{removedNodes:c(a),nextSibling:g,previousSibling:h}),D(this,a),a},replaceChild:function(a,d){b(a);var e;if(B(d)?e=F(d):(e=d,d=G(e)),d.parentNode!==this)throw new Error("NotFoundError");var h,i=d.nextSibling,j=d.previousSibling,m=!this.invalidateShadowRenderer()&&!s(a);return m?h=g(a):(i===a&&(i=a.nextSibling),h=f(a,this,j,i)),m?(n(this,a),q(this),R.call(this.impl,F(a),e)):(this.firstChild===d&&(this.firstChild_=h[0]),this.lastChild===d&&(this.lastChild_=h[h.length-1]),d.previousSibling_=d.nextSibling_=d.parentNode_=void 0,e.parentNode&&R.call(e.parentNode,p(this,h),e)),A(this,"childList",{addedNodes:h,removedNodes:c(d),nextSibling:i,previousSibling:j}),l(d),k(h),d},nodeIsInserted_:function(){for(var a=this.firstChild;a;a=a.nextSibling)a.nodeIsInserted_()},hasChildNodes:function(){return null!==this.firstChild},get parentNode(){return void 0!==this.parentNode_?this.parentNode_:G(this.impl.parentNode)},get firstChild(){return void 0!==this.firstChild_?this.firstChild_:G(this.impl.firstChild)},get lastChild(){return void 0!==this.lastChild_?this.lastChild_:G(this.impl.lastChild)},get nextSibling(){return void 0!==this.nextSibling_?this.nextSibling_:G(this.impl.nextSibling)},get previousSibling(){return void 0!==this.previousSibling_?this.previousSibling_:G(this.impl.previousSibling)},get parentElement(){for(var a=this.parentNode;a&&a.nodeType!==v.ELEMENT_NODE;)a=a.parentNode;return a},get textContent(){for(var a="",b=this.firstChild;b;b=b.nextSibling)b.nodeType!=v.COMMENT_NODE&&(a+=b.textContent);return a},set textContent(a){var b=i(this.childNodes);if(this.invalidateShadowRenderer()){if(r(this),""!==a){var c=this.impl.ownerDocument.createTextNode(a);this.appendChild(c)}}else q(this),this.impl.textContent=a;var d=i(this.childNodes);A(this,"childList",{addedNodes:d,removedNodes:b}),m(b),k(d)},get childNodes(){for(var a=new x,b=0,c=this.firstChild;c;c=c.nextSibling)a[b++]=c;return a.length=b,a},cloneNode:function(a){return u(this,a)},contains:function(a){if(!a)return!1;if(a=H(a),a===this)return!0;var b=a.parentNode;return b?this.contains(b):!1},compareDocumentPosition:function(a){return O.call(this.impl,F(a))},normalize:function(){for(var a,b,c=i(this.childNodes),d=[],e="",f=0;f<c.length;f++)b=c[f],b.nodeType===v.TEXT_NODE?a||b.data.length?a?(e+=b.data,d.push(b)):a=b:this.removeNode(b):(a&&d.length&&(a.data+=e,cleanUpNodes(d)),d=[],e="",a=null,b.childNodes.length&&b.normalize());a&&d.length&&(a.data+=e,t(d))}}),z(v,"ownerDocument"),E(M,v,document.createDocumentFragment()),delete v.prototype.querySelector,delete v.prototype.querySelectorAll,v.prototype=C(Object.create(w.prototype),v.prototype),a.nodeWasAdded=j,a.nodeWasRemoved=l,a.nodesWereAdded=k,a.nodesWereRemoved=m,a.snapshotNodeList=i,a.wrappers.Node=v,a.cloneNode=u}(window.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}(window.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}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}var c=a.ChildNodeInterface,d=a.wrappers.Node,e=a.enqueueMutation,f=a.mixin,g=a.registerWrapper,h=window.CharacterData;b.prototype=Object.create(d.prototype),f(b.prototype,{get textContent(){return this.data},set textContent(a){this.data=a},get data(){return this.impl.data},set data(a){var b=this.impl.data;e(this,"characterData",{oldValue:b}),this.impl.data=a}}),f(b.prototype,c),g(h,b,document.createTextNode("")),a.wrappers.CharacterData=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a>>>0}function c(a){d.call(this,a)}var d=a.wrappers.CharacterData,e=(a.enqueueMutation,a.mixin),f=a.registerWrapper,g=window.Text;c.prototype=Object.create(d.prototype),e(c.prototype,{splitText:function(a){a=b(a);var c=this.data;if(a>c.length)throw new Error("IndexSizeError");var d=c.slice(0,a),e=c.slice(a);this.data=d;var f=this.ownerDocument.createTextNode(e);return this.parentNode&&this.parentNode.insertBefore(f,this.nextSibling),f}}),f(g,c,document.createTextNode("")),a.wrappers.Text=c}(window.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,b,c){k(a,"attributes",{name:b,namespace:null,oldValue:c})}function d(a){h.call(this,a)}function e(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 f=a.ChildNodeInterface,g=a.GetElementsByInterface,h=a.wrappers.Node,i=a.ParentNodeInterface,j=a.SelectorsInterface,k=(a.addWrapNodeListMethod,a.enqueueMutation),l=a.mixin,m=(a.oneOf,a.registerWrapper),n=a.wrappers,o=window.Element,p=["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"].filter(function(a){return o.prototype[a]}),q=p[0],r=o.prototype[q];d.prototype=Object.create(h.prototype),l(d.prototype,{createShadowRoot:function(){var b=new n.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,d){var e=this.impl.getAttribute(a);this.impl.setAttribute(a,d),c(this,a,e),b(this,a)},removeAttribute:function(a){var d=this.impl.getAttribute(a);this.impl.removeAttribute(a),c(this,a,d),b(this,a)},matches:function(a){return r.call(this.impl,a)}}),p.forEach(function(a){"matches"!==a&&(d.prototype[a]=function(a){return this.matches(a)})}),o.prototype.webkitCreateShadowRoot&&(d.prototype.webkitCreateShadowRoot=d.prototype.createShadowRoot),e(d.prototype,"id"),e(d.prototype,"className","class"),l(d.prototype,f),l(d.prototype,g),l(d.prototype,i),l(d.prototype,j),m(o,d,document.createElementNS(null,"x")),a.matchesNames=p,a.wrappers.Element=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a){case"&":return"&amp;";case"<":return"&lt;";case">":return"&gt;";case'"':return"&quot;";case" ":return"&nbsp;"}}function c(a){return a.replace(z,b)}function d(a){return a.replace(A,b)}function e(a){for(var b={},c=0;c<a.length;c++)b[a[c]]=!0;return b}function f(a,b){switch(a.nodeType){case Node.ELEMENT_NODE:for(var e,f=a.tagName.toLowerCase(),h="<"+f,i=a.attributes,j=0;e=i[j];j++)h+=" "+e.name+'="'+c(e.value)+'"';return h+=">",B[f]?h:h+g(a)+"</"+f+">";case Node.TEXT_NODE:var k=a.data;return b&&C[b.localName]?k:d(k);case Node.COMMENT_NODE:return"<!--"+a.data+"-->";default:throw console.error(a),new Error("not implemented")}}function g(a){a instanceof y.HTMLTemplateElement&&(a=a.content);for(var b="",c=a.firstChild;c;c=c.nextSibling)b+=f(c,a);return b}function h(a,b,c){var d=c||"div";a.textContent="";var e=w(a.ownerDocument.createElement(d));e.innerHTML=b;for(var f;f=e.firstChild;)a.appendChild(x(f))}function i(a){o.call(this,a)}function j(a,b){var c=w(a.cloneNode(!1));c.innerHTML=b;for(var d,e=w(document.createDocumentFragment());d=c.firstChild;)e.appendChild(d);return x(e)}function k(b){return function(){return a.renderAllPending(),this.impl[b]}}function l(a){p(i,a,k(a))}function m(b){Object.defineProperty(i.prototype,b,{get:k(b),set:function(c){a.renderAllPending(),this.impl[b]=c},configurable:!0,enumerable:!0})}function n(b){Object.defineProperty(i.prototype,b,{value:function(){return a.renderAllPending(),this.impl[b].apply(this.impl,arguments)},configurable:!0,enumerable:!0})}var o=a.wrappers.Element,p=a.defineGetter,q=a.enqueueMutation,r=a.mixin,s=a.nodesWereAdded,t=a.nodesWereRemoved,u=a.registerWrapper,v=a.snapshotNodeList,w=a.unwrap,x=a.wrap,y=a.wrappers,z=/[&\u00A0"]/g,A=/[&\u00A0<>]/g,B=e(["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"]),C=e(["style","script","xmp","iframe","noembed","noframes","plaintext","noscript"]),D=/MSIE/.test(navigator.userAgent),E=window.HTMLElement,F=window.HTMLTemplateElement;i.prototype=Object.create(o.prototype),r(i.prototype,{get innerHTML(){return g(this)},set innerHTML(a){if(D&&C[this.localName])return void(this.textContent=a);var b=v(this.childNodes);this.invalidateShadowRenderer()?this instanceof y.HTMLTemplateElement?h(this.content,a):h(this,a,this.tagName):!F&&this instanceof y.HTMLTemplateElement?h(this.content,a):this.impl.innerHTML=a;var c=v(this.childNodes);q(this,"childList",{addedNodes:c,removedNodes:b}),t(b),s(c)},get outerHTML(){return f(this,this.parentNode)},set outerHTML(a){var b=this.parentNode;if(b){b.invalidateShadowRenderer();var c=j(b,a);b.replaceChild(c,this)}},insertAdjacentHTML:function(a,b){var c,d;switch(String(a).toLowerCase()){case"beforebegin":c=this.parentNode,d=this;break;case"afterend":c=this.parentNode,d=this.nextSibling;break;case"afterbegin":c=this,d=this.firstChild;break;case"beforeend":c=this,d=null;break;default:return}var e=j(c,b);c.insertBefore(e,d)}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(l),["scrollLeft","scrollTop"].forEach(m),["getBoundingClientRect","getClientRects","scrollIntoView"].forEach(n),u(E,i,document.createElement("b")),a.wrappers.HTMLElement=i,a.getInnerHTML=g,a.setInnerHTML=h}(window.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,document.createElement("canvas")),a.wrappers.HTMLCanvasElement=b}(window.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}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a,b){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var e=f(document.createElement("img"));d.call(this,e),g(e,this),void 0!==a&&(e.width=a),void 0!==b&&(e.height=b)}var d=a.wrappers.HTMLElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLImageElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("img")),c.prototype=b.prototype,a.wrappers.HTMLImageElement=b,a.wrappers.Image=c}(window.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}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){if(!a.defaultView)return a;var b=k.get(a);if(!b){for(b=a.implementation.createHTMLDocument("");b.lastChild;)b.removeChild(b.lastChild);k.set(a,b)}return b}function c(a){for(var c,d=b(a.ownerDocument),e=h(d.createDocumentFragment());c=a.firstChild;)e.appendChild(c);return e}function d(a){if(e.call(this,a),!l){var b=c(a);j.set(this,i(b))}}var e=a.wrappers.HTMLElement,f=a.mixin,g=a.registerWrapper,h=a.unwrap,i=a.wrap,j=new WeakMap,k=new WeakMap,l=window.HTMLTemplateElement;d.prototype=Object.create(e.prototype),f(d.prototype,{get content(){return l?i(this.impl.content):j.get(this)}}),l&&g(l,d),a.wrappers.HTMLTemplateElement=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.registerWrapper,e=window.HTMLMediaElement;b.prototype=Object.create(c.prototype),d(e,b,document.createElement("audio")),a.wrappers.HTMLMediaElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var b=f(document.createElement("audio"));d.call(this,b),g(b,this),b.setAttribute("preload","auto"),void 0!==a&&b.setAttribute("src",a)}var d=a.wrappers.HTMLMediaElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLAudioElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("audio")),c.prototype=b.prototype,a.wrappers.HTMLAudioElement=b,a.wrappers.Audio=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a.replace(/\s+/g," ").trim()}function c(a){e.call(this,a)}function d(a,b,c,f){if(!(this instanceof d))throw new TypeError("DOM object constructor cannot be called as a function.");var g=i(document.createElement("option"));e.call(this,g),h(g,this),void 0!==a&&(g.text=a),void 0!==b&&g.setAttribute("value",b),c===!0&&g.setAttribute("selected",""),g.selected=f===!0}var e=a.wrappers.HTMLElement,f=a.mixin,g=a.registerWrapper,h=a.rewrap,i=a.unwrap,j=a.wrap,k=window.HTMLOptionElement;c.prototype=Object.create(e.prototype),f(c.prototype,{get text(){return b(this.textContent)},set text(a){this.textContent=b(String(a))},get form(){return j(i(this).form)}}),g(k,c,document.createElement("option")),d.prototype=c.prototype,a.wrappers.HTMLOptionElement=c,a.wrappers.Option=d}(window.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,g=(a.mixin,a.registerWrapper),h=window.HTMLUnknownElement;b.prototype=Object.create(d.prototype),g(h,b),a.wrappers.HTMLUnknownElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";var b=a.registerObject,c="http://www.w3.org/2000/svg",d=document.createElementNS(c,"title"),e=b(d),f=Object.getPrototypeOf(e.prototype).constructor;a.wrappers.SVGElement=f}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){m.call(this,a)}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.wrap,g=window.SVGUseElement,h="http://www.w3.org/2000/svg",i=f(document.createElementNS(h,"g")),j=document.createElementNS(h,"use"),k=i.constructor,l=Object.getPrototypeOf(k.prototype),m=l.constructor;b.prototype=Object.create(l),"instanceRoot"in j&&c(b.prototype,{get instanceRoot(){return f(e(this).instanceRoot)},get animatedInstanceRoot(){return f(e(this).animatedInstanceRoot)}}),d(g,b,j),a.wrappers.SVGUseElement=b}(window.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.wrap,g=window.SVGElementInstance;g&&(b.prototype=Object.create(c.prototype),d(b.prototype,{get correspondingElement(){return f(this.impl.correspondingElement)},get correspondingUseElement(){return f(this.impl.correspondingUseElement)},get parentNode(){return f(this.impl.parentNode)},get childNodes(){throw new Error("Not implemented")},get firstChild(){return f(this.impl.firstChild)},get lastChild(){return f(this.impl.lastChild)},get previousSibling(){return f(this.impl.previousSibling)},get nextSibling(){return f(this.impl.nextSibling)}}),e(g,b),a.wrappers.SVGElementInstance=b)}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.unwrapIfNeeded,g=a.wrap,h=window.CanvasRenderingContext2D;c(b.prototype,{get canvas(){return g(this.impl.canvas)},drawImage:function(){arguments[0]=f(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(h,b,document.createElement("canvas").getContext("2d")),a.wrappers.CanvasRenderingContext2D=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrapIfNeeded,f=a.wrap,g=window.WebGLRenderingContext;if(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)}});var h=/WebKit/.test(navigator.userAgent)?{drawingBufferHeight:null,drawingBufferWidth:null}:{};d(g,b,h),a.wrappers.WebGLRenderingContext=b}}(window.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))},toString:function(){return this.impl.toString()}},g.prototype.createContextualFragment&&(b.prototype.createContextualFragment=function(a){return f(this.impl.createContextualFragment(a))}),c(window.Range,b,document.createRange()),a.wrappers.Range=b}(window.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.createComment(""));a.wrappers.Comment=h,a.wrappers.DocumentFragment=g}(window.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,l=/[ \t\n\r\f]/;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},get host(){return j.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 l.test(a)?null:this.querySelector('[id="'+a+'"]')}}),a.wrappers.ShadowRoot=b}(window.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=F(a),g=F(c),h=e?F(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=G(f.lastChild);i&&(i.nextSibling_=i.nextSibling)}f.insertBefore(g,h)}function d(a){var c=F(a),d=c.parentNode;if(d){var e=G(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=I.get(a);c||I.set(a,c=[]),c.push(b)}function f(a){H.set(a,[])}function g(a){return H.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 z))return!1;if("*"===c||c===a.localName)return!0;if(!L.test(c))return!1;if(":"===c[0]&&!M.test(c))return!1;try{return a.matches(c)}catch(d){return!1}}function k(){for(var a=0;a<O.length;a++)O[a].render();O=[]}function l(){y=null,k()}function m(a){var b=K.get(a);return b||(b=new q(a),K.set(a,b)),b}function n(a){for(;a;a=a.parentNode)if(a instanceof D)return a;return null}function o(a){return m(a.host)}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 A}function s(a){return a instanceof A}function t(a){return a instanceof B}function u(a){return a instanceof B}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){J.set(a,b)}var y,z=a.wrappers.Element,A=a.wrappers.HTMLContentElement,B=a.wrappers.HTMLShadowElement,C=a.wrappers.Node,D=a.wrappers.ShadowRoot,E=(a.assert,a.mixin,a.oneOf),F=a.unwrap,G=a.wrap,H=new WeakMap,I=new WeakMap,J=new WeakMap,K=new WeakMap,L=/^[*.:#[a-zA-Z_|]/,M=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("|")+")"),N=E(window,["requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","setTimeout"]),O=[],P=new ArraySplice;P.equals=function(a,b){return F(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(F(b)),g=a||new WeakMap,i=P.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=G(f[k++]);g.get(q)||d(q)}for(var r=n.addedCount,s=f[k]&&G(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,O.push(this),y)return;y=window[N](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}},C.prototype.invalidateShadowRenderer=function(){var a=this.impl.polymerShadowRenderer_;return a?(a.invalidate(),!0):!1},A.prototype.getDistributedNodes=function(){return k(),g(this)},B.prototype.nodeIsInserted_=A.prototype.nodeIsInserted_=function(){this.invalidateShadowRenderer();var a,b=n(this);b&&(a=o(b)),this.impl.polymerShadowRenderer_=a,a&&a.invalidate()},a.eventParentsTable=I,a.getRendererForHost=m,a.getShadowTrees=w,a.insertionParentTable=J,a.renderAllPending=k,a.visual={insertBefore:c,remove:d}}(window.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","HTMLOutputElement","HTMLSelectElement","HTMLTextAreaElement"];i.forEach(b)}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}{var c=a.registerWrapper,d=a.unwrap,e=a.unwrapIfNeeded,f=a.wrap;window.Selection}b.prototype={get anchorNode(){return f(this.impl.anchorNode)},get focusNode(){return f(this.impl.focusNode)},addRange:function(a){this.impl.addRange(d(a))},collapse:function(a,b){this.impl.collapse(e(a),b)},containsNode:function(a,b){return this.impl.containsNode(e(a),b)},extend:function(a,b){this.impl.extend(e(a),b)},getRangeAt:function(a){return f(this.impl.getRangeAt(a))},removeRange:function(a){this.impl.removeRange(d(a))},selectAllChildren:function(a){this.impl.selectAllChildren(e(a))},toString:function(){return this.impl.toString()}},c(window.Selection,b,window.getSelection()),a.wrappers.Selection=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){k.call(this,a)}function c(a){var c=document[a];b.prototype[a]=function(){return z(c.apply(this.impl,arguments))}}function d(a,b){C.call(b.impl,y(a)),e(a,b)}function e(a,b){a.shadowRoot&&b.adoptNode(a.shadowRoot),a instanceof o&&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 z(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.wrappers.Selection,n=a.SelectorsInterface,o=a.wrappers.ShadowRoot,p=a.cloneNode,q=a.defineWrapGetter,r=a.elementFromPoint,s=a.forwardMethodsToWrapper,t=a.matchesNames,u=a.mixin,v=a.registerWrapper,w=a.renderAllPending,x=a.rewrap,y=a.unwrap,z=a.wrap,A=a.wrapEventTargetMethods,B=(a.wrapNodeList,new WeakMap);b.prototype=Object.create(k.prototype),q(b,"documentElement"),q(b,"body"),q(b,"head"),["createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","getElementById"].forEach(c);var C=document.adoptNode,D=document.getSelection;if(u(b.prototype,{adoptNode:function(a){return a.parentNode&&a.parentNode.removeChild(a),d(a,this),a},elementFromPoint:function(a,b){return r(this,this,a,b)},importNode:function(a,b){return p(a,b,this.impl)},getSelection:function(){return w(),new m(D.call(y(this)))}}),document.registerElement){var E=document.registerElement;b.prototype.registerElement=function(b,c){function d(a){return a?void(this.impl=a):c.extends?document.createElement(c.extends,b):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);["createdCallback","attachedCallback","detachedCallback","attributeChangedCallback"].forEach(function(a){var b=e[a];b&&(i[a]=function(){z(this)instanceof d||x(this),b.apply(z(this),arguments)})});var k={prototype:i};c.extends&&(k.extends=c.extends),d.prototype=e,d.prototype.constructor=d,a.constructorTable.set(i,d),a.nativePrototypeTable.set(e,i);E.call(y(this),b,k);return d},s([window.HTMLDocument||window.Document],["registerElement"])}s([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild"].concat(t)),s([window.HTMLDocument||window.Document],["adoptNode","importNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","elementFromPoint","getElementById","getSelection"]),u(b.prototype,j),u(b.prototype,l),u(b.prototype,n),u(b.prototype,{get implementation(){var a=B.get(this);return a?a:(a=new g(y(this).implementation),B.set(this,a),a)}}),v(window.Document,b,document.implementation.createHTMLDocument("")),window.HTMLDocument&&v(window.HTMLDocument,b),A([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]),h(g,"createDocumentType"),h(g,"createDocument"),h(g,"createHTMLDocument"),i(g,"hasFeature"),v(window.DOMImplementation,g),s([window.DOMImplementation],["createDocumentType","createDocument","createHTMLDocument","hasFeature"]),a.adoptNodeNoRemove=d,a.wrappers.DOMImplementation=g,a.wrappers.Document=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.EventTarget,d=a.wrappers.Selection,e=a.mixin,f=a.registerWrapper,g=a.renderAllPending,h=a.unwrap,i=a.unwrapIfNeeded,j=a.wrap,k=window.Window,l=window.getComputedStyle,m=window.getSelection;b.prototype=Object.create(c.prototype),k.prototype.getComputedStyle=function(a,b){return j(this||window).getComputedStyle(i(a),b)},k.prototype.getSelection=function(){return j(this||window).getSelection()},delete window.getComputedStyle,delete window.getSelection,["addEventListener","removeEventListener","dispatchEvent"].forEach(function(a){k.prototype[a]=function(){var b=j(this||window);return b[a].apply(b,arguments)},delete window[a]}),e(b.prototype,{getComputedStyle:function(a,b){return g(),l.call(h(this),i(a),b)},getSelection:function(){return g(),new d(m.call(h(this)))}}),f(k,b),a.wrappers.Window=b}(window.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}}var c=(a.isWrapperFor,{a:"HTMLAnchorElement",area:"HTMLAreaElement",br:"HTMLBRElement",base:"HTMLBaseElement",body:"HTMLBodyElement",button:"HTMLButtonElement",dl:"HTMLDListElement",datalist:"HTMLDataListElement",data:"HTMLDataElement",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",marquee:"HTMLMarqueeElement",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",time:"HTMLTimeElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",table:"HTMLTableElement",tr:"HTMLTableRowElement",thead:"HTMLTableSectionElement",tbody:"HTMLTableSectionElement",textarea:"HTMLTextAreaElement",track:"HTMLTrackElement",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}(window.ShadowDOMPolyfill),function(){window.wrap=ShadowDOMPolyfill.wrapIfNeeded,window.unwrap=ShadowDOMPolyfill.unwrapIfNeeded,Object.defineProperty(Element.prototype,"webkitShadowRoot",Object.getOwnPropertyDescriptor(Element.prototype,"shadowRoot"));var a=Element.prototype.createShadowRoot;Element.prototype.createShadowRoot=function(){var b=a.call(this);return CustomElements.watchShadow(this),b},Element.prototype.webkitCreateShadowRoot=Element.prototype.createShadowRoot}(),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(h,"")),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){a&&f().appendChild(document.createTextNode(a))}function f(){return o||(o=document.createElement("style"),o.setAttribute(q,""),o[q]=!0),o}var g={strictStyling:!1,registry:{},shimStyling:function(a,b,d){var f=this.isTypeExtension(d),g=this.registerDefinition(a,b,d);this.strictStyling&&this.applyScopeToContent(a,b);var h=this.stylesToShimmedCssText(g.rootStyles,g.scopeStyles,b,f);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);e(h)},stylesToShimmedCssText:function(a,b,c,d){c=c||"",this.insertPolyfillDirectives(a),this.insertPolyfillRules(a);var e=this.shimScoping(b,c,d);return e+=this.extractPolyfillUnscopedRules(a),e.trim()},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(i,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(j,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=k.exec(a);)c+=b[1].slice(0,-1)+"\n\n";return c},shimScoping:function(a,b,c){return a?this.convertScopedStyles(a,b,c):void 0},convertScopedStyles:function(a,c,e){var f=b(a);if(f=this.insertPolyfillHostInCssText(f),f=this.convertColonHost(f),f=this.convertColonAncestor(f),f=this.convertCombinators(f),c){var g=d(f);f=this.scopeRules(g,c,e)}return f},convertColonHost:function(a){return this.convertColonRule(a,cssColonHostRe,this.colonHostPartReplacer)},convertColonAncestor:function(a){return this.convertColonRule(a,cssColonAncestorRe,this.colonAncestorPartReplacer)},convertColonRule:function(a,b,c){return a.replace(b,function(a,b,d,e){if(b=polyfillHostNoCombinator,d){for(var f,g=d.split(","),h=[],i=0,j=g.length;j>i&&(f=g[i]);i++)f=f.trim(),h.push(c(b,f,e));return h.join(",")}return b+e})},colonAncestorPartReplacer:function(a,b,c){return b.match(l)?this.colonHostPartReplacer(a,b,c):a+b+c+", "+b+" "+a+c},colonHostPartReplacer:function(a,b,c){return a+b.replace(l,"")+c},convertCombinators:function(a){return a.replace(/\^\^/g," ").replace(/\^/g," ")},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,c),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&&!a.match(polyfillHostNoCombinator)?this.applyStrictSelectorScope(a,b):this.applySimpleSelectorScope(a,b,c)),e.push(a)},this),e.join(", ")},selectorNeedsScoping:function(a,b,c){var d=this.makeScopeMatcher(b,c);return!a.match(d)},makeScopeMatcher:function(a,b){var c=b?"\\[is=['\"]?"+a+"['\"]?\\]":a;return new RegExp("^("+c+")"+selectorReSuffix,"m")},applySimpleSelectorScope:function(a,b,c){var d=c?"[is="+b+"]":b;return a.match(polyfillHostRe)?(a=a.replace(polyfillHostNoCombinator,d),a.replace(polyfillHostRe,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(polyfillHostRe,"");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(hostRe,l).replace(colonHostRe,l).replace(colonAncestorRe,m)},propertiesFromRule:function(a){return a.style.content&&!a.style.content.match(/['"]+/)?a.style.cssText.replace(/content:[^;]*;/g,"content: '"+a.style.content+"';"):a.style.cssText}},h=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,i=/\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim,j=/\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,k=/\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,l="-shadowcsshost",m="-shadowcssancestor",n=")(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)";cssColonHostRe=new RegExp("("+l+n,"gim"),cssColonAncestorRe=new RegExp("("+m+n,"gim"),selectorReSuffix="([>\\s~+[.,{:][\\s\\S]*)?$",hostRe=/@host/gim,colonHostRe=/\:host/gim,colonAncestorRe=/\:ancestor/gim,polyfillHostNoCombinator=l+"-no-combinator",polyfillHostRe=new RegExp(l,"gim"),polyfillAncestorRe=new RegExp(m,"gim");var o,p="shim-shadowdom",q="shim-shadowdom-css";if(window.ShadowDOMPolyfill){e("style { display: none !important; }\n");var r=wrap(document),s=r.querySelector("head");s.insertBefore(f(),s.childNodes[0]),document.addEventListener("DOMContentLoaded",function(){var b=a.urlResolver;if(window.HTMLImports&&!HTMLImports.useNative){var c="link[rel=stylesheet]["+p+"]",d="style["+p+"]";HTMLImports.importer.documentPreloadSelectors+=","+c,HTMLImports.importer.importsPreloadSelectors+=","+c,HTMLImports.parser.documentSelectors=[HTMLImports.parser.documentSelectors,c,d].join(",");var e=HTMLImports.parser.parseGeneric;HTMLImports.parser.parseGeneric=function(a){if(!a[q]){var c=a.__importElement||a;if(!c.hasAttribute(p))return void e.call(this,a);a.__resource?(c=a.ownerDocument.createElement("style"),c.textContent=b.resolveCssText(a.__resource,a.href)):b.resolveStyle(c);var d=[c];c.textContent=g.stylesToShimmedCssText(d,d),c.removeAttribute(p,""),c.setAttribute(q,""),c[q]=!0,c.parentNode!==s&&(a.parentNode===s?s.replaceChild(c,a):s.appendChild(c)),c.__importParsed=!0,this.markParsingComplete(a)}};var f=HTMLImports.parser.hasResource;HTMLImports.parser.hasResource=function(a){return"link"===a.localName&&"stylesheet"===a.rel&&a.hasAttribute(p)?a.__resource:f.call(this,a)}}})}a.ShadowCSS=g}(window.Platform)):!function(){window.templateContent=window.templateContent||function(a){return a.content},window.wrap=window.unwrap=function(a){return a};var a=Element.prototype.webkitCreateShadowRoot;Element.prototype.webkitCreateShadowRoot=function(){var b=this.webkitShadowRoot,c=a.call(this);return c.olderShadowRoot=b,c.host=this,CustomElements.watchShadow(this),c},Object.defineProperties(Element.prototype,{shadowRoot:{get:function(){return this.webkitShadowRoot}},createShadowRoot:{value:function(){return this.webkitCreateShadowRoot()}}}),window.templateContent=function(a){if(window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(a),!a.content&&!a._content){for(var b=document.createDocumentFragment();a.firstChild;)b.appendChild(a.firstChild);a._content=b}return a.content||a._content}}(),function(a){"use strict";function b(a){return void 0!==m[a]}function c(){h.call(this),this._isInvalid=!0}function d(a){return""==a&&c.call(this),a.toLowerCase()}function e(a){var b=a.charCodeAt(0);return b>32&&127>b&&-1==[34,35,60,62,63,96].indexOf(b)?a:encodeURIComponent(a)}function f(a){var b=a.charCodeAt(0);return b>32&&127>b&&-1==[34,35,60,62,96].indexOf(b)?a:encodeURIComponent(a)}function g(a,g,h){function i(a){t.push(a)}var j=g||"scheme start",k=0,l="",r=!1,s=!1,t=[];a:for(;(a[k-1]!=o||0==k)&&!this._isInvalid;){var u=a[k];switch(j){case"scheme start":if(!u||!p.test(u)){if(g){i("Invalid scheme.");break a}l="",j="no scheme";continue}l+=u.toLowerCase(),j="scheme";break;case"scheme":if(u&&q.test(u))l+=u.toLowerCase();else{if(":"!=u){if(g){if(o==u)break a;i("Code point not allowed in scheme: "+u);break a}l="",k=0,j="no scheme";continue}if(this._scheme=l,l="",g)break a;b(this._scheme)&&(this._isRelative=!0),j="file"==this._scheme?"relative":this._isRelative&&h&&h._scheme==this._scheme?"relative or authority":this._isRelative?"authority first slash":"scheme data"}break;case"scheme data":"?"==u?(query="?",j="query"):"#"==u?(this._fragment="#",j="fragment"):o!=u&&"	"!=u&&"\n"!=u&&"\r"!=u&&(this._schemeData+=e(u));break;case"no scheme":if(h&&b(h._scheme)){j="relative";continue}i("Missing scheme."),c.call(this);break;case"relative or authority":if("/"!=u||"/"!=a[k+1]){i("Expected /, got: "+u),j="relative";continue}j="authority ignore slashes";break;case"relative":if(this._isRelative=!0,"file"!=this._scheme&&(this._scheme=h._scheme),o==u){this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._query=h._query;break a}if("/"==u||"\\"==u)"\\"==u&&i("\\ is an invalid code point."),j="relative slash";else if("?"==u)this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._query="?",j="query";else{if("#"!=u){var v=a[k+1],w=a[k+2];("file"!=this._scheme||!p.test(u)||":"!=v&&"|"!=v||o!=w&&"/"!=w&&"\\"!=w&&"?"!=w&&"#"!=w)&&(this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._path.pop()),j="relative path";continue}this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._query=h._query,this._fragment="#",j="fragment"}break;case"relative slash":if("/"!=u&&"\\"!=u){"file"!=this._scheme&&(this._host=h._host,this._port=h._port),j="relative path";continue}"\\"==u&&i("\\ is an invalid code point."),j="file"==this._scheme?"file host":"authority ignore slashes";break;case"authority first slash":if("/"!=u){i("Expected '/', got: "+u),j="authority ignore slashes";continue}j="authority second slash";break;case"authority second slash":if(j="authority ignore slashes","/"!=u){i("Expected '/', got: "+u);continue}break;case"authority ignore slashes":if("/"!=u&&"\\"!=u){j="authority";continue}i("Expected authority, got: "+u);break;case"authority":if("@"==u){r&&(i("@ already seen."),l+="%40"),r=!0;for(var x=0;x<l.length;x++){var y=l[x];if("	"!=y&&"\n"!=y&&"\r"!=y)if(":"!=y||null!==this._password){var z=e(y);null!==this._password?this._password+=z:this._username+=z}else this._password="";else i("Invalid whitespace in authority.")}l=""}else{if(o==u||"/"==u||"\\"==u||"?"==u||"#"==u){k-=l.length,l="",j="host";continue}l+=u}break;case"file host":if(o==u||"/"==u||"\\"==u||"?"==u||"#"==u){2!=l.length||!p.test(l[0])||":"!=l[1]&&"|"!=l[1]?0==l.length?j="relative path start":(this._host=d.call(this,l),l="",j="relative path start"):j="relative path";continue}"	"==u||"\n"==u||"\r"==u?i("Invalid whitespace in file host."):l+=u;break;case"host":case"hostname":if(":"!=u||s){if(o==u||"/"==u||"\\"==u||"?"==u||"#"==u){if(this._host=d.call(this,l),l="",j="relative path start",g)break a;continue}"	"!=u&&"\n"!=u&&"\r"!=u?("["==u?s=!0:"]"==u&&(s=!1),l+=u):i("Invalid code point in host/hostname: "+u)}else if(this._host=d.call(this,l),l="",j="port","hostname"==g)break a;break;case"port":if(/[0-9]/.test(u))l+=u;else{if(o==u||"/"==u||"\\"==u||"?"==u||"#"==u||g){if(""!=l){var A=parseInt(l,10);A!=m[this._scheme]&&(this._port=A+""),l=""}if(g)break a;j="relative path start";continue}"	"==u||"\n"==u||"\r"==u?i("Invalid code point in port: "+u):c.call(this)}break;case"relative path start":if("\\"==u&&i("'\\' not allowed in path."),j="relative path","/"!=u&&"\\"!=u)continue;break;case"relative path":if(o!=u&&"/"!=u&&"\\"!=u&&(g||"?"!=u&&"#"!=u))"	"!=u&&"\n"!=u&&"\r"!=u&&(l+=e(u));else{"\\"==u&&i("\\ not allowed in relative path.");var B;(B=n[l.toLowerCase()])&&(l=B),".."==l?(this._path.pop(),"/"!=u&&"\\"!=u&&this._path.push("")):"."==l&&"/"!=u&&"\\"!=u?this._path.push(""):"."!=l&&("file"==this._scheme&&0==this._path.length&&2==l.length&&p.test(l[0])&&"|"==l[1]&&(l=l[0]+":"),this._path.push(l)),l="","?"==u?(this._query="?",j="query"):"#"==u&&(this._fragment="#",j="fragment")}break;case"query":g||"#"!=u?o!=u&&"	"!=u&&"\n"!=u&&"\r"!=u&&(this._query+=f(u)):(this._fragment="#",j="fragment");break;case"fragment":o!=u&&"	"!=u&&"\n"!=u&&"\r"!=u&&(this._fragment+=u)}k++}}function h(){this._scheme="",this._schemeData="",this._username="",this._password=null,this._host="",this._port="",this._path=[],this._query="",this._fragment="",this._isInvalid=!1,this._isRelative=!1}function i(a,b){void 0===b||b instanceof i||(b=new i(String(b))),this._url=a,h.call(this);var c=a.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g,"");g.call(this,c,null,b)}var j=!1;if(!a.forceJURL)try{var k=new URL("b","http://a");j="http://a/b"===k.href}catch(l){}if(!j){var m=Object.create(null);m.ftp=21,m.file=0,m.gopher=70,m.http=80,m.https=443,m.ws=80,m.wss=443;var n=Object.create(null);n["%2e"]=".",n[".%2e"]="..",n["%2e."]="..",n["%2e%2e"]="..";var o=void 0,p=/[a-zA-Z]/,q=/[a-zA-Z0-9\+\-\.]/;i.prototype={get href(){if(this._isInvalid)return this._url;var a="";return(""!=this._username||null!=this._password)&&(a=this._username+(null!=this._password?":"+this._password:"")+"@"),this.protocol+(this._isRelative?"//"+a+this.host:"")+this.pathname+this._query+this._fragment},set href(a){h.call(this),g.call(this,a)},get protocol(){return this._scheme+":"},set protocol(a){this._isInvalid||g.call(this,a+":","scheme start")},get host(){return this._isInvalid?"":this._port?this._host+":"+this._port:this._host},set host(a){!this._isInvalid&&this._isRelative&&g.call(this,a,"host")},get hostname(){return this._host},set hostname(a){!this._isInvalid&&this._isRelative&&g.call(this,a,"hostname")},get port(){return this._port},set port(a){!this._isInvalid&&this._isRelative&&g.call(this,a,"port")},get pathname(){return this._isInvalid?"":this._isRelative?"/"+this._path.join("/"):this._schemeData},set pathname(a){!this._isInvalid&&this._isRelative&&(this._path=[],g.call(this,a,"relative path start"))},get search(){return this._isInvalid||!this._query||"?"==this._query?"":this._query},set search(a){!this._isInvalid&&this._isRelative&&(this._query="?","?"==a[0]&&(a=a.slice(1)),g.call(this,a,"query"))},get hash(){return this._isInvalid||!this._fragment||"#"==this._fragment?"":this._fragment},set hash(a){this._isInvalid||(this._fragment="#","#"==a[0]&&(a=a.slice(1)),g.call(this,a,"fragment"))}},a.URL=i}}(window),function(a){function b(a){for(var b=a||{},d=1;d<arguments.length;d++){var e=arguments[d];try{for(var f in e)c(f,e,b)}catch(g){}}return b}function c(a,b,c){var e=d(b,a);Object.defineProperty(c,a,e)}function d(a,b){if(a){var c=Object.getOwnPropertyDescriptor(a,b);return c||d(Object.getPrototypeOf(a),b)}}Function.prototype.bind||(Function.prototype.bind=function(a){var b=this,c=Array.prototype.slice.call(arguments,1);return function(){var d=c.slice();return d.push.apply(d,arguments),b.apply(a,d)}}),a.mixin=b}(window.Platform),function(a){"use strict";function b(a,b,c){var d="string"==typeof a?document.createElement(a):a.cloneNode(!0);if(d.innerHTML=b,c)for(var e in c)d.setAttribute(e,c[e]);return d}var c=DOMTokenList.prototype.add,d=DOMTokenList.prototype.remove;DOMTokenList.prototype.add=function(){for(var a=0;a<arguments.length;a++)c.call(this,arguments[a])},DOMTokenList.prototype.remove=function(){for(var a=0;a<arguments.length;a++)d.call(this,arguments[a])},DOMTokenList.prototype.toggle=function(a,b){1==arguments.length&&(b=!this.contains(a)),b?this.add(a):this.remove(a)},DOMTokenList.prototype.switch=function(a,b){a&&this.remove(a),b&&this.add(b)};var e=function(){return Array.prototype.slice.call(this)},f=window.NamedNodeMap||window.MozNamedAttrMap||{};if(NodeList.prototype.array=e,f.prototype.array=e,HTMLCollection.prototype.array=e,!window.performance){var g=Date.now();window.performance={now:function(){return Date.now()-g}}}window.requestAnimationFrame||(window.requestAnimationFrame=function(){var a=window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame;return a?function(b){return a(function(){b(performance.now())})}:function(a){return window.setTimeout(a,1e3/60)}}()),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(){return window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||function(a){clearTimeout(a)}}());var h=document.createElement("template"),i=document.createElement("base");i.href=document.baseURI,h.content.ownerDocument.appendChild(i);var j=[],k=function(){j.push(arguments)};window.Polymer=k,a.deliverDeclarations=function(){return a.deliverDeclarations=null,j},window.addEventListener("DOMContentLoaded",function(){window.Polymer===k&&(window.Polymer=function(){console.error('You tried to use polymer without loading it first. To load polymer, <link rel="import" href="components/polymer/polymer.html">')})}),a.createDOM=b}(window.Platform),window.templateContent=window.templateContent||function(a){return a.content},function(a){a=a||(window.Inspector={});var b;window.sinspect=function(a,d){b||(b=window.open("","ShadowDOM Inspector",null,!0),b.document.write(c),b.api={shadowize:shadowize}),f(a||wrap(document.body),d)};var c=["<!DOCTYPE html>","<html>","  <head>","    <title>ShadowDOM Inspector</title>","    <style>","      body {","      }","      pre {",'        font: 9pt "Courier New", monospace;',"        line-height: 1.5em;","      }","      tag {","        color: purple;","      }","      ul {","         margin: 0;","         padding: 0;","         list-style: none;","      }","      li {","         display: inline-block;","         background-color: #f1f1f1;","         padding: 4px 6px;","         border-radius: 4px;","         margin-right: 4px;","      }","    </style>","  </head>","  <body>",'    <ul id="crumbs">',"    </ul>",'    <div id="tree"></div>',"  </body>","</html>"].join("\n"),d=[],e=function(){var a=b.document,c=a.querySelector("#crumbs");c.textContent="";for(var e,g=0;e=d[g];g++){var h=a.createElement("a");h.href="#",h.textContent=e.localName,h.idx=g,h.onclick=function(a){for(var b;d.length>this.idx;)b=d.pop();f(b.shadow||b,b),a.preventDefault()},c.appendChild(a.createElement("li")).appendChild(h)}},f=function(a,c){var f=b.document;k=[];var g=c||a;d.push(g),e(),f.body.querySelector("#tree").innerHTML="<pre>"+j(a,a.childNodes)+"</pre>"},g=Array.prototype.forEach.call.bind(Array.prototype.forEach),h={STYLE:1,SCRIPT:1,"#comment":1,TEMPLATE:1},i=function(a){return h[a.nodeName]},j=function(a,b,c){if(i(a))return"";var d=c||"";if(a.localName||11==a.nodeType){var e=a.localName||"shadow-root",f=d+l(a);"content"==e&&(b=a.getDistributedNodes()),f+="<br/>";var h=d+"&nbsp;&nbsp;";g(b,function(a){f+=j(a,a.childNodes,h)}),f+=d,{br:1}[e]||(f+="<tag>&lt;/"+e+"&gt;</tag>",f+="<br/>")}else{var k=a.textContent.trim();f=k?d+'"'+k+'"<br/>':""}return f},k=[],l=function(a){var b="<tag>&lt;",c=a.localName||"shadow-root";return a.webkitShadowRoot||a.shadowRoot?(b+=' <button idx="'+k.length+'" onclick="api.shadowize.call(this)">'+c+"</button>",k.push(a)):b+=c||"shadow-root",a.attributes&&g(a.attributes,function(a){b+=" "+a.name+(a.value?'="'+a.value+'"':"")}),b+="&gt;</tag>"};shadowize=function(){var a=Number(this.attributes.idx.value),b=k[a];b?f(b.webkitShadowRoot||b.shadowRoot,b):(console.log("bad shadowize node"),console.dir(this))},a.output=j}(window.Inspector),function(){var a=document.createElement("style");a.textContent="body {transition: opacity ease-in 0.2s; } \nbody[unresolved] {opacity: 0; display: block; overflow: hidden; } \n";var b=document.querySelector("head");b.insertBefore(a,b.firstChild)}(Platform),function(a){function b(a,b){return b=b||[],b.map||(b=[b]),a.apply(this,b.map(d))}function c(a,c,d){var e;switch(arguments.length){case 0:return;case 1:e=null;break;case 2:e=c.apply(this);break;default:e=b(d,c)}f[a]=e}function d(a){return f[a]}function e(a,c){HTMLImports.whenImportsReady(function(){b(c,a)})}var f={};a.marshal=d,a.module=c,a.using=e}(window),function(a){function b(a){f.textContent=d++,e.push(a)}function c(){for(;e.length;)e.shift()()}var d=0,e=[],f=document.createTextNode("");new(window.MutationObserver||JsMutationObserver)(c).observe(f,{characterData:!0}),a.endOfMicrotask=b}(Platform),function(a){function b(a,b,d){return a.replace(d,function(a,d,e,f){var g=e.replace(/["']/g,"");return g=c(b,g),d+"'"+g+"'"+f})}function c(a,b){var c=new URL(b,a);return d(c.href)}function d(a){var b=document.baseURI,c=new URL(a,b);return c.host===b.host&&c.port===b.port&&c.protocol===b.protocol?e(b.pathname,c.pathname):a}function e(a,b){for(var c=a.split("/"),d=b.split("/");c.length&&c[0]===d[0];)c.shift(),d.shift();for(var e=0,f=c.length-1;f>e;e++)d.unshift("..");return d.join("/")}var f={resolveDom:function(a,b){b=b||a.ownerDocument.baseURI,this.resolveAttributes(a,b),this.resolveStyles(a,b);var c=a.querySelectorAll("template");if(c)for(var d,e=0,f=c.length;f>e&&(d=c[e]);e++)d.content&&this.resolveDom(d.content,b)},resolveStyles:function(a,b){var c=a.querySelectorAll("style");if(c)for(var d,e=0,f=c.length;f>e&&(d=c[e]);e++)this.resolveStyle(d,b)},resolveStyle:function(a,b){b=b||a.ownerDocument.baseURI,a.textContent=this.resolveCssText(a.textContent,b)},resolveCssText:function(a,c){return a=b(a,c,g),b(a,c,h)},resolveAttributes:function(a,b){a.hasAttributes&&a.hasAttributes()&&this.resolveElementAttributes(a,b);var c=a&&a.querySelectorAll(j);if(c)for(var d,e=0,f=c.length;f>e&&(d=c[e]);e++)this.resolveElementAttributes(d,b)},resolveElementAttributes:function(a,b){b=b||a.ownerDocument.baseURI,i.forEach(function(d){var e=a.attributes[d];if(e&&e.value&&e.value.search(k)<0){var f=c(b,e.value);e.value=f}})}},g=/(url\()([^)]*)(\))/g,h=/(@import[\s]+(?!url\())([^;]*)(;)/g,i=["href","src","action"],j="["+i.join("],[")+"]",k="{{.*}}";a.urlResolver=f}(Platform),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 WeakMap,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 void(c[d-1]=f)}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,a.MutationObserver||(a.MutationObserver=g)}(this),window.HTMLImports=window.HTMLImports||{flags:{}},function(a){var b=(a.path,a.xhr),c=a.flags,d=function(a,b){this.cache={},this.onload=a,this.oncomplete=b,this.inflight=0,this.pending={}};d.prototype={addNodes:function(a){this.inflight+=a.length;for(var b,c=0,d=a.length;d>c&&(b=a[c]);c++)this.require(b);this.checkDone()},addNode:function(a){this.inflight++,this.require(a),this.checkDone()},require:function(a){var b=a.src||a.href;a.__nodeUrl=b,this.dedupe(b,a)||this.fetch(b,a)},dedupe:function(a,b){if(this.pending[a])return this.pending[a].push(b),!0;return this.cache[a]?(this.onload(a,b,this.cache[a]),this.tail(),!0):(this.pending[a]=[b],!1)},fetch:function(a,d){c.load&&console.log("fetch",a,d);var e=function(b,c){this.receive(a,d,b,c)}.bind(this);b.load(a,e)},receive:function(a,b,c,d){this.cache[a]=d;for(var e,f=this.pending[a],g=0,h=f.length;h>g&&(e=f[g]);g++)this.onload(a,e,d),this.tail();this.pending[a]=null},tail:function(){--this.inflight,this.checkDone()},checkDone:function(){this.inflight||this.oncomplete()}},b=b||{async:!0,ok:function(a){return a.status>=200&&a.status<300||304===a.status||0===a.status},load:function(c,d,e){var f=new XMLHttpRequest;return(a.flags.debug||a.flags.bust)&&(c+="?"+Math.random()),f.open("GET",c,b.async),f.addEventListener("readystatechange",function(){4===f.readyState&&d.call(e,!b.ok(f)&&f,f.response||f.responseText,c)}),f.send(),f},loadDocument:function(a,b,c){this.load(a,b,c).responseType="document"}},a.xhr=b,a.Loader=d}(window.HTMLImports),function(a){function b(a){return"link"===a.localName&&a.rel===d}function c(a){var b=a.ownerDocument.createElement("style");return b.textContent=a.textContent,k.resolveUrlsInStyle(b),b}var d="import",e=a.flags,f=/Trident/.test(navigator.userAgent),g=window.ShadowDOMPolyfill?window.ShadowDOMPolyfill.wrapIfNeeded(document):document,h={documentSelectors:"link[rel="+d+"]",importsSelectors:["link[rel="+d+"]","link[rel=stylesheet]","style","script:not([type])",'script[type="text/javascript"]'].join(","),map:{link:"parseLink",script:"parseScript",style:"parseStyle"},parseNext:function(){var a=this.nextToParse();a&&this.parse(a)},parse:function(a){if(this.isParsed(a))return void(e.parse&&console.log("[%s] is already parsed",a.localName));var b=this[this.map[a.localName]];b&&(this.markParsing(a),b.call(this,a))},markParsing:function(a){e.parse&&console.log("parsing",a),this.parsingElement=a},markParsingComplete:function(a){a.__importParsed=!0,a.__importElement&&(a.__importElement.__importParsed=!0),this.parsingElement=null,e.parse&&console.log("completed",a),this.parseNext()},parseImport:function(a){if(a.import.__importParsed=!0,HTMLImports.__importsParsingHook&&HTMLImports.__importsParsingHook(a),a.dispatchEvent(a.__resource?new CustomEvent("load",{bubbles:!1}):new CustomEvent("error",{bubbles:!1})),a.__pending)for(var b;a.__pending.length;)b=a.__pending.shift(),b&&b({target:a});this.markParsingComplete(a)},parseLink:function(a){b(a)?this.parseImport(a):(a.href=a.href,this.parseGeneric(a))},parseStyle:function(a){var b=a;a=c(a),a.__importElement=b,this.parseGeneric(a)},parseGeneric:function(a){this.trackElement(a),document.head.appendChild(a)},trackElement:function(a){var b=this,c=function(){b.markParsingComplete(a)};if(a.addEventListener("load",c),a.addEventListener("error",c),f&&"style"===a.localName){var d=!1;if(-1==a.textContent.indexOf("@import"))d=!0;else if(a.sheet){d=!0;for(var e,g=a.sheet.cssRules,h=g?g.length:0,i=0;h>i&&(e=g[i]);i++)e.type===CSSRule.IMPORT_RULE&&(d=d&&Boolean(e.styleSheet))}d&&a.dispatchEvent(new CustomEvent("load",{bubbles:!1}))}},parseScript:function(b){var c=(b.__resource||b.textContent).trim();if(c){var d=b.__nodeUrl;if(!d){d=b.ownerDocument.baseURI;var e="["+Math.floor(1e3*(Math.random()+1))+"]",f=c.match(/Polymer\(['"]([^'"]*)/);e=f&&f[1]||e,d+="/"+e+".js"}c+="\n//# sourceURL="+d+"\n",a.currentScript=b,eval.call(window,c),a.currentScript=null}this.markParsingComplete(b)},nextToParse:function(){return!this.parsingElement&&this.nextToParseInDoc(g)},nextToParseInDoc:function(a,c){for(var d,e=a.querySelectorAll(this.parseSelectorsForNode(a)),f=0,g=e.length;g>f&&(d=e[f]);f++)if(!this.isParsed(d))return this.hasResource(d)?b(d)?this.nextToParseInDoc(d.import,d):d:void 0;return c},parseSelectorsForNode:function(a){var b=a.ownerDocument||a;return b===g?this.documentSelectors:this.importsSelectors},isParsed:function(a){return a.__importParsed},hasResource:function(a){return b(a)&&!a.import?!1:"script"===a.localName&&a.src&&!a.__resource?!1:!0}},i=/(url\()([^)]*)(\))/g,j=/(@import[\s]+(?!url\())([^;]*)(;)/g,k={resolveUrlsInStyle:function(a){var b=a.ownerDocument,c=b.createElement("a");return a.textContent=this.resolveUrlsInCssText(a.textContent,c),a},resolveUrlsInCssText:function(a,b){var c=this.replaceUrls(a,b,i);return c=this.replaceUrls(c,b,j)},replaceUrls:function(a,b,c){return a.replace(c,function(a,c,d,e){var f=d.replace(/["']/g,"");return b.href=f,f=b.href,c+"'"+f+"'"+e})}};a.parser=h,a.path=k,a.isIE=f}(HTMLImports),function(a){function b(a){return c(a,m)}function c(a,b){return"link"===a.localName&&a.getAttribute("rel")===b}function d(a,b){var c=a;c instanceof Document||(c=document.implementation.createHTMLDocument(m)),c._URL=b;var d=c.createElement("base");return d.setAttribute("href",b),c.baseURI||(c.baseURI=b),c.head.appendChild(d),a instanceof Document||(c.body.innerHTML=a),window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(c),c}function e(a,b){b=b||n,g(function(){h(a,b)},b)}function f(a){return"complete"===a.readyState||a.readyState===u}function g(a,b){if(f(b))a&&a();else{var c=function(){("complete"===b.readyState||b.readyState===u)&&(b.removeEventListener(v,c),g(a,b))};b.addEventListener(v,c)}}function h(a,b){function c(){f==g&&requestAnimationFrame(a)}function d(){f++,c()}var e=b.querySelectorAll("link[rel=import]"),f=0,g=e.length;if(g)for(var h,j=0;g>j&&(h=e[j]);j++)i(h)?d.call(h):(h.addEventListener("load",d),h.addEventListener("error",d));else c()}function i(a){return k?a.import&&"loading"!==a.import.readyState:a.__importParsed}var j="import"in document.createElement("link"),k=j,l=a.flags,m="import",n=window.ShadowDOMPolyfill?ShadowDOMPolyfill.wrapIfNeeded(document):document;if(k)var o={};else var p=(a.xhr,a.Loader),q=a.parser,o={documents:{},documentPreloadSelectors:"link[rel="+m+"]",importsPreloadSelectors:["link[rel="+m+"]","script[src]:not([type])",'script[src][type="text/javascript"]'].join(","),loadNode:function(a){r.addNode(a)},loadSubtree:function(a){var b=this.marshalNodes(a);r.addNodes(b)},marshalNodes:function(a){return a.querySelectorAll(this.loadSelectorsForNode(a))},loadSelectorsForNode:function(a){var b=a.ownerDocument||a;return b===n?this.documentPreloadSelectors:this.importsPreloadSelectors},loaded:function(a,c,e){if(l.load&&console.log("loaded",a,c),c.__resource=e,b(c)){var f=this.documents[a];f||(f=d(e,a),f.__importLink=c,this.bootDocument(f),this.documents[a]=f),c.import=f}q.parseNext()},bootDocument:function(a){this.loadSubtree(a),this.observe(a),q.parseNext()},loadedAll:function(){q.parseNext()}},r=new p(o.loaded.bind(o),o.loadedAll.bind(o));var s={get:function(){return HTMLImports.currentScript||document.currentScript},configurable:!0};if(Object.defineProperty(document,"_currentScript",s),Object.defineProperty(n,"_currentScript",s),!document.baseURI){var t={get:function(){return window.location.href},configurable:!0};Object.defineProperty(document,"baseURI",t),Object.defineProperty(n,"baseURI",t)}var u=HTMLImports.isIE?"complete":"interactive",v="readystatechange";a.hasNative=j,a.useNative=k,a.importer=o,a.whenImportsReady=e,a.IMPORT_LINK_TYPE=m,a.isImportLoaded=i,a.importLoader=r}(window.HTMLImports),function(a){function b(a){for(var b,d=0,e=a.length;e>d&&(b=a[d]);d++)"childList"===b.type&&b.addedNodes.length&&c(b.addedNodes)}function c(a){for(var b,e=0,g=a.length;g>e&&(b=a[e]);e++)d(b)&&f.loadNode(b),b.children&&b.children.length&&c(b.children)}function d(a){return 1===a.nodeType&&g.call(a,f.loadSelectorsForNode(a))}function e(a){h.observe(a,{childList:!0,subtree:!0})}var f=(a.IMPORT_LINK_TYPE,a.importer),g=HTMLElement.prototype.matches||HTMLElement.prototype.matchesSelector||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector,h=new MutationObserver(b);a.observe=e,f.observe=e}(HTMLImports),function(){function a(){HTMLImports.importer.bootDocument(b)}"function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a,b){var c=document.createEvent("HTMLEvents");return c.initEvent(a,b.bubbles===!1?!1:!0,b.cancelable===!1?!1:!0,b.detail),c});var b=window.ShadowDOMPolyfill?window.ShadowDOMPolyfill.wrapIfNeeded(document):document;HTMLImports.whenImportsReady(function(){HTMLImports.ready=!0,HTMLImports.readyTime=(new Date).getTime(),b.dispatchEvent(new CustomEvent("HTMLImportsLoaded",{bubbles:!0}))}),HTMLImports.useNative||("complete"===document.readyState||"interactive"===document.readyState&&!window.attachEvent?a():document.addEventListener("DOMContentLoaded",a))}(),window.CustomElements=window.CustomElements||{flags:{}},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:void c(a,d)}),c(a,d)}function e(a){return h(a)?(i(a),!0):void l(a)}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 A.dom&&console.group("upgrade:",b.localName),a.upgrade(b),A.dom&&console.groupEnd(),!0}}function i(a){l(a),r(a)&&d(a,function(a){l(a)})}function j(a){if(E.push(a),!D){D=!0;var b=window.Platform&&window.Platform.endOfMicrotask||setTimeout;b(k)}}function k(){D=!1;for(var a,b=E,c=0,d=b.length;d>c&&(a=b[c]);c++)a();E=[]}function l(a){C?j(function(){m(a)}):m(a)}function m(a){(a.attachedCallback||a.detachedCallback||a.__upgraded__&&A.dom)&&(A.dom&&console.group("inserted:",a.localName),r(a)&&(a.__inserted=(a.__inserted||0)+1,a.__inserted<1&&(a.__inserted=1),a.__inserted>1?A.dom&&console.warn("inserted:",a.localName,"insert/remove count:",a.__inserted):a.attachedCallback&&(A.dom&&console.log("inserted:",a.localName),a.attachedCallback())),A.dom&&console.groupEnd())}function n(a){o(a),d(a,function(a){o(a)})}function o(a){C?j(function(){p(a)}):p(a)}function p(a){(a.attachedCallback||a.detachedCallback||a.__upgraded__&&A.dom)&&(A.dom&&console.group("removed:",a.localName),r(a)||(a.__inserted=(a.__inserted||0)-1,a.__inserted>0&&(a.__inserted=0),a.__inserted<0?A.dom&&console.warn("removed:",a.localName,"insert/remove count:",a.__inserted):a.detachedCallback&&a.detachedCallback()),A.dom&&console.groupEnd())}function q(a){return window.ShadowDOMPolyfill?ShadowDOMPolyfill.wrapIfNeeded(a):a}function r(a){for(var b=a,c=q(document);b;){if(b==c)return!0;b=b.parentNode||b.host}}function s(a){if(a.shadowRoot&&!a.shadowRoot.__watched){A.dom&&console.log("watching shadow-root for: ",a.localName);for(var b=a.shadowRoot;b;)t(b),b=b.olderShadowRoot}}function t(a){a.__watched||(w(a),a.__watched=!0)}function u(a){if(A.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&&(G(a.addedNodes,function(a){a.localName&&g(a)}),G(a.removedNodes,function(a){a.localName&&n(a)}))}),A.dom&&console.groupEnd()}function v(){u(F.takeRecords()),k()}function w(a){F.observe(a,{childList:!0,subtree:!0})}function x(a){w(a)}function y(a){A.dom&&console.group("upgradeDocument: ",a.baseURI.split("/").pop()),g(a),A.dom&&console.groupEnd()}function z(a){a=q(a),y(a);for(var b,c=a.querySelectorAll("link[rel="+B+"]"),d=0,e=c.length;e>d&&(b=c[d]);d++)b.import&&b.import.__parsed&&z(b.import)}var A=window.logFlags||{},B=window.HTMLImports?HTMLImports.IMPORT_LINK_TYPE:"none",C=!window.MutationObserver||window.MutationObserver===window.JsMutationObserver;a.hasPolyfillMutations=C;var D=!1,E=[],F=new MutationObserver(u),G=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.IMPORT_LINK_TYPE=B,a.watchShadow=s,a.upgradeDocumentTree=z,a.upgradeAll=g,a.upgradeSubtree=f,a.insertedNode=i,a.observeDocument=x,a.upgradeDocument=y,a.takeRecords=v}(window.CustomElements),function(a){function b(b,f){var g=f||{};if(!b)throw new Error("document.registerElement: first argument `name` must not be empty");if(b.indexOf("-")<0)throw new Error("document.registerElement: first argument ('name') must contain a dash ('-'). Argument provided was '"+String(b)+"'.");if(m(b))throw new Error("DuplicateDefinitionError: a type with name '"+String(b)+"' is already registered");if(!g.prototype)throw new Error("Options missing required prototype property");return g.__name=b.toLowerCase(),g.lifecycle=g.lifecycle||{},g.ancestry=c(g.extends),d(g),e(g),k(g.prototype),n(g.__name,g),g.ctor=o(g),g.ctor.prototype=g.prototype,g.prototype.constructor=g.ctor,a.ready&&a.upgradeDocumentTree(document),g.ctor}function c(a){var b=m(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(x(a.tag),a)}function g(b,c){return c.is&&b.setAttribute("is",c.is),b.removeAttribute("unresolved"),h(b,c),b.__upgraded__=!0,j(b),a.insertedNode(b),a.upgradeSubtree(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){if(!a.setAttribute._polyfilled){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)},a.setAttribute._polyfilled=!0}}function l(a,b,c){var d=this.getAttribute(a);c.apply(this,arguments);var e=this.getAttribute(a);this.attributeChangedCallback&&e!==d&&this.attributeChangedCallback(a,d,e)}function m(a){return a?w[a.toLowerCase()]:void 0}function n(a,b){w[a]=b}function o(a){return function(){return f(a)}}function p(a,b){var c=m(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=p(a);return d.setAttribute("is",b),d}var d=x(a);return a.indexOf("-")>=0&&h(d,HTMLElement),d}function q(a){if(!a.__upgraded__&&a.nodeType===Node.ELEMENT_NODE){var b=a.getAttribute("is"),c=m(b||a.localName);if(c){if(b&&c.tag==a.localName)return g(a,c);if(!b&&!c.extends)return g(a,c)}}}function r(b){var c=y.call(this,b);return a.upgradeAll(c),c}a||(a=window.CustomElements={flags:{}});var s=a.flags,t=Boolean(document.registerElement),u=!s.register&&t&&!window.ShadowDOMPolyfill;if(u){var v=function(){};a.registry={},a.upgradeElement=v,a.watchShadow=v,a.upgrade=v,a.upgradeAll=v,a.upgradeSubtree=v,a.observeDocument=v,a.upgradeDocument=v,a.upgradeDocumentTree=v,a.takeRecords=v}else{var w={},x=document.createElement.bind(document),y=Node.prototype.cloneNode;document.registerElement=b,document.createElement=p,Node.prototype.cloneNode=r,a.registry=w,a.upgrade=q}document.register=document.registerElement,a.hasNative=t,a.useNative=u}(window.CustomElements),function(a){function b(a){return"link"===a.localName&&a.getAttribute("rel")===c}var c=a.IMPORT_LINK_TYPE,d={selectors:["link[rel="+c+"]"],map:{link:"parseLink"},parse:function(a){if(!a.__parsed){a.__parsed=!0;var b=a.querySelectorAll(d.selectors);e(b,function(a){d[d.map[a.localName]](a)}),CustomElements.upgradeDocument(a),CustomElements.observeDocument(a)}},parseLink:function(a){b(a)&&this.parseImport(a)},parseImport:function(a){a.import&&d.parse(a.import)}},e=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.parser=d,a.IMPORT_LINK_TYPE=c}(window.CustomElements),function(a){function b(){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.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0})),window.HTMLImports&&(HTMLImports.__importsParsingHook=function(a){CustomElements.parser.parse(a.import)})})}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.flags.eager)b();else if("interactive"!==document.readyState||window.attachEvent||window.HTMLImports&&!window.HTMLImports.ready){var c=window.HTMLImports&&!HTMLImports.ready?"HTMLImportsLoaded":"DOMContentLoaded";window.addEventListener(c,b)}else b()}(window.CustomElements),function(){var a=document.createElement("style");a.textContent="element {display: none !important;} /* injected by platform.js */";var b=document.querySelector("head");if(b.insertBefore(a,b.firstChild),window.ShadowDOMPolyfill){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](wrap(b))}})}}(),function(a){function b(a,b){var d=c(a);b&&(d.addEventListener("load",b),d.addEventListener("error",b)),j.appendChild(d)}function c(a,b){b=b||document,b=b.createElement?b:b.ownerDocument;var c=b.createElement("style");return c.textContent=a,c}function d(a,b){HTMLImports.xhr.load(e(a),function(a,c,d){f(this,d,c),this.textContent=g.resolveCssText(this.textContent,d),b&&b(this)},a)}function e(a){var b=a.textContent.match(k);return b&&b[1]}function f(a,b,c){var d=new RegExp("@import[^;]*"+b+"[^;]*;","i");a.textContent=a.textContent.replace(d,c)}var g=a.urlResolver,h={cacheStyles:function(a,c){for(var d,e=[],f=0,g=a.length;g>f&&(d=a[f]);f++)e.push(d.textContent);b(e.join("\n"),c)},xhrStyles:function(a,b){function c(){f++,f===g&&b&&b()}for(var e,f=0,g=a.length,h=0;g>h&&(e=a[h]);h++)d(e,c)}},i=document.createElement("preloader");i.style.display="none";var j=i.createShadowRoot();document.head.appendChild(i);var k=/@import\s[(]?['"]?([^\s'";)]*)/;a.loader=h}(window.Platform),function(a){a=a||{},a.external=a.external||{};var b={shadow:function(a){return a?a.shadowRoot||a.webkitShadowRoot:void 0},canTarget:function(a){return a&&Boolean(a.elementFromPoint)},targetingShadow:function(a){var b=this.shadow(a);return this.canTarget(b)?b:void 0},olderShadow:function(a){var b=a.olderShadowRoot;if(!b){var c=a.querySelector("shadow");c&&(b=c.olderShadowRoot)}return b},allShadows:function(a){for(var b=[],c=this.shadow(a);c;)b.push(c),c=this.olderShadow(c);return b},searchRoot:function(a,b,c){if(a){var d,e,f=a.elementFromPoint(b,c);for(e=this.targetingShadow(f);e;){if(d=e.elementFromPoint(b,c)){var g=this.targetingShadow(d);return this.searchRoot(g,b,c)||d}e=this.olderShadow(e)}return f}},owner:function(a){for(var b=a;b.parentNode;)b=b.parentNode;return b.nodeType!=Node.DOCUMENT_NODE&&b.nodeType!=Node.DOCUMENT_FRAGMENT_NODE&&(b=document),b},findTarget:function(a){var b=a.clientX,c=a.clientY,d=this.owner(a.target);return d.elementFromPoint(b,c)||(d=document),this.searchRoot(d,b,c)}};a.targetFinding=b,a.findTarget=b.findTarget.bind(b),window.PointerEventsPolyfill=a}(window.PointerEventsPolyfill),function(){function a(a){return"body ^^ "+b(a)}function b(a){return'[touch-action="'+a+'"]'}function c(a){return"{ -ms-touch-action: "+a+"; touch-action: "+a+"; touch-action-delay: none; }"}var d=["none","auto","pan-x","pan-y",{rule:"pan-x pan-y",selectors:["pan-x pan-y","pan-y pan-x"]}],e="";d.forEach(function(d){String(d)===d?(e+=b(d)+c(d)+"\n",e+=a(d)+c(d)+"\n"):(e+=d.selectors.map(b)+c(d.rule)+"\n",e+=d.selectors.map(a)+c(d.rule)+"\n")});var f=document.createElement("style");f.textContent=e,document.head.appendChild(f)}(),function(a){function b(a,e){e=e||{};var f;if(e.buttons||d)f=e.buttons;else switch(e.which){case 1:f=1;break;case 2:f=4;break;case 3:f=2;break;default:f=0}var i;if(c)i=new MouseEvent(a,e);else{i=document.createEvent("MouseEvent");for(var j,k={},l=0;l<g.length;l++)j=g[l],k[j]=e[j]||h[l];i.initMouseEvent(a,k.bubbles,k.cancelable,k.view,k.detail,k.screenX,k.screenY,k.clientX,k.clientY,k.ctrlKey,k.altKey,k.shiftKey,k.metaKey,k.button,k.relatedTarget)}i.__proto__=b.prototype,d||Object.defineProperty(i,"buttons",{get:function(){return f},enumerable:!0});var m=0;return m=e.pressure?e.pressure:f?.5:0,Object.defineProperties(i,{pointerId:{value:e.pointerId||0,enumerable:!0},width:{value:e.width||0,enumerable:!0},height:{value:e.height||0,enumerable:!0},pressure:{value:m,enumerable:!0},tiltX:{value:e.tiltX||0,enumerable:!0},tiltY:{value:e.tiltY||0,enumerable:!0},pointerType:{value:e.pointerType||"",enumerable:!0},hwTimestamp:{value:e.hwTimestamp||0,enumerable:!0},isPrimary:{value:e.isPrimary||!1,enumerable:!0}}),i}var c=!1,d=!1;try{var e=new MouseEvent("click",{buttons:1});c=!0,d=1===e.buttons}catch(f){}var g=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget"],h=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null];b.prototype=Object.create(MouseEvent.prototype),a.PointerEvent||(a.PointerEvent=b)}(window),function(a){function b(){if(c){var a=new Map;return a.pointers=d,a}this.keys=[],this.values=[]}var c=window.Map&&window.Map.prototype.forEach,d=function(){return this.size};b.prototype={set:function(a,b){var c=this.keys.indexOf(a);c>-1?this.values[c]=b:(this.keys.push(a),this.values.push(b))},has:function(a){return this.keys.indexOf(a)>-1},"delete":function(a){var b=this.keys.indexOf(a);b>-1&&(this.keys.splice(b,1),this.values.splice(b,1))},get:function(a){var b=this.keys.indexOf(a);return this.values[b]},clear:function(){this.keys.length=0,this.values.length=0},forEach:function(a,b){this.values.forEach(function(c,d){a.call(b,c,this.keys[d],this)},this)},pointers:function(){return this.keys.length}},a.PointerMap=b}(window.PointerEventsPolyfill),function(a){var b=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget","buttons","pointerId","width","height","pressure","tiltX","tiltY","pointerType","hwTimestamp","isPrimary","type","target","currentTarget","which"],c=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null,0,0,0,0,0,0,0,"",0,!1,"",null,null,0],d="undefined"!=typeof SVGElementInstance,e={targets:new WeakMap,handledEvents:new WeakMap,pointermap:new a.PointerMap,eventMap:{},eventSources:{},eventSourceList:[],registerSource:function(a,b){var c=b,d=c.events;d&&(d.forEach(function(a){c[a]&&(this.eventMap[a]=c[a].bind(c))},this),this.eventSources[a]=c,this.eventSourceList.push(c))},register:function(a){for(var b,c=this.eventSourceList.length,d=0;c>d&&(b=this.eventSourceList[d]);d++)b.register.call(b,a)},unregister:function(a){for(var b,c=this.eventSourceList.length,d=0;c>d&&(b=this.eventSourceList[d]);d++)b.unregister.call(b,a)},contains:a.external.contains||function(a,b){return a.contains(b)},down:function(a){this.fireEvent("pointerdown",a)},move:function(a){this.fireEvent("pointermove",a)},up:function(a){this.fireEvent("pointerup",a)},enter:function(a){a.bubbles=!1,this.fireEvent("pointerenter",a)},leave:function(a){a.bubbles=!1,this.fireEvent("pointerleave",a)},over:function(a){a.bubbles=!0,this.fireEvent("pointerover",a)},out:function(a){a.bubbles=!0,this.fireEvent("pointerout",a)},cancel:function(a){this.fireEvent("pointercancel",a)},leaveOut:function(a){this.out(a),this.contains(a.target,a.relatedTarget)||this.leave(a)},enterOver:function(a){this.over(a),this.contains(a.target,a.relatedTarget)||this.enter(a)},eventHandler:function(a){if(!this.handledEvents.get(a)){var b=a.type,c=this.eventMap&&this.eventMap[b];c&&c(a),this.handledEvents.set(a,!0)}},listen:function(a,b){b.forEach(function(b){this.addEvent(a,b)},this)},unlisten:function(a,b){b.forEach(function(b){this.removeEvent(a,b)},this)},addEvent:a.external.addEvent||function(a,b){a.addEventListener(b,this.boundHandler)},removeEvent:a.external.removeEvent||function(a,b){a.removeEventListener(b,this.boundHandler)},makeEvent:function(a,b){this.captureInfo&&(b.relatedTarget=null);var c=new PointerEvent(a,b);return b.preventDefault&&(c.preventDefault=b.preventDefault),this.targets.set(c,this.targets.get(b)||b.target),c},fireEvent:function(a,b){var c=this.makeEvent(a,b);return this.dispatchEvent(c)},cloneEvent:function(a){for(var e,f={},g=0;g<b.length;g++)e=b[g],f[e]=a[e]||c[g],!d||"target"!==e&&"relatedTarget"!==e||f[e]instanceof SVGElementInstance&&(f[e]=f[e].correspondingUseElement);return a.preventDefault&&(f.preventDefault=function(){a.preventDefault()}),f},getTarget:function(a){return this.captureInfo&&this.captureInfo.id===a.pointerId?this.captureInfo.target:this.targets.get(a)},setCapture:function(a,b){this.captureInfo&&this.releaseCapture(this.captureInfo.id),this.captureInfo={id:a,target:b};var c=new PointerEvent("gotpointercapture",{bubbles:!0});this.implicitRelease=this.releaseCapture.bind(this,a),document.addEventListener("pointerup",this.implicitRelease),document.addEventListener("pointercancel",this.implicitRelease),this.targets.set(c,b),this.asyncDispatchEvent(c)},releaseCapture:function(a){if(this.captureInfo&&this.captureInfo.id===a){var b=new PointerEvent("lostpointercapture",{bubbles:!0}),c=this.captureInfo.target;this.captureInfo=null,document.removeEventListener("pointerup",this.implicitRelease),document.removeEventListener("pointercancel",this.implicitRelease),this.targets.set(b,c),this.asyncDispatchEvent(b)}},dispatchEvent:a.external.dispatchEvent||function(a){var b=this.getTarget(a);return b?b.dispatchEvent(a):void 0},asyncDispatchEvent:function(a){setTimeout(this.dispatchEvent.bind(this,a),0)}};e.boundHandler=e.eventHandler.bind(e),a.dispatcher=e,a.register=e.register.bind(e),a.unregister=e.unregister.bind(e)}(window.PointerEventsPolyfill),function(a){function b(a,b,c,d){this.addCallback=a.bind(d),this.removeCallback=b.bind(d),this.changedCallback=c.bind(d),g&&(this.observer=new g(this.mutationWatcher.bind(this)))}var c=Array.prototype.forEach.call.bind(Array.prototype.forEach),d=Array.prototype.map.call.bind(Array.prototype.map),e=Array.prototype.slice.call.bind(Array.prototype.slice),f=Array.prototype.filter.call.bind(Array.prototype.filter),g=window.MutationObserver||window.WebKitMutationObserver,h="[touch-action]",i={subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0,attributeFilter:["touch-action"]};b.prototype={watchSubtree:function(b){a.targetFinding.canTarget(b)&&this.observer.observe(b,i)
+},enableOnSubtree:function(a){this.watchSubtree(a),a===document&&"complete"!==document.readyState?this.installOnLoad():this.installNewSubtree(a)},installNewSubtree:function(a){c(this.findElements(a),this.addElement,this)},findElements:function(a){return a.querySelectorAll?a.querySelectorAll(h):[]},removeElement:function(a){this.removeCallback(a)},addElement:function(a){this.addCallback(a)},elementChanged:function(a,b){this.changedCallback(a,b)},concatLists:function(a,b){return a.concat(e(b))},installOnLoad:function(){document.addEventListener("DOMContentLoaded",this.installNewSubtree.bind(this,document))},isElement:function(a){return a.nodeType===Node.ELEMENT_NODE},flattenMutationTree:function(a){var b=d(a,this.findElements,this);return b.push(f(a,this.isElement)),b.reduce(this.concatLists,[])},mutationWatcher:function(a){a.forEach(this.mutationHandler,this)},mutationHandler:function(a){if("childList"===a.type){var b=this.flattenMutationTree(a.addedNodes);b.forEach(this.addElement,this);var c=this.flattenMutationTree(a.removedNodes);c.forEach(this.removeElement,this)}else"attributes"===a.type&&this.elementChanged(a.target,a.oldValue)}},g||(b.prototype.watchSubtree=function(){console.warn("PointerEventsPolyfill: MutationObservers not found, touch-action will not be dynamically detected")}),a.Installer=b}(window.PointerEventsPolyfill),function(a){var b=a.dispatcher,c=b.pointermap,d=25,e={POINTER_ID:1,POINTER_TYPE:"mouse",events:["mousedown","mousemove","mouseup","mouseover","mouseout"],register:function(a){b.listen(a,this.events)},unregister:function(a){b.unlisten(a,this.events)},lastTouches:[],isEventSimulatedFromTouch:function(a){for(var b,c=this.lastTouches,e=a.clientX,f=a.clientY,g=0,h=c.length;h>g&&(b=c[g]);g++){var i=Math.abs(e-b.x),j=Math.abs(f-b.y);if(d>=i&&d>=j)return!0}},prepareEvent:function(a){var c=b.cloneEvent(a),d=c.preventDefault;return c.preventDefault=function(){a.preventDefault(),d()},c.pointerId=this.POINTER_ID,c.isPrimary=!0,c.pointerType=this.POINTER_TYPE,c},mousedown:function(a){if(!this.isEventSimulatedFromTouch(a)){var d=c.has(this.POINTER_ID);d&&this.cancel(a);var e=this.prepareEvent(a);c.set(this.POINTER_ID,a),b.down(e)}},mousemove:function(a){if(!this.isEventSimulatedFromTouch(a)){var c=this.prepareEvent(a);b.move(c)}},mouseup:function(a){if(!this.isEventSimulatedFromTouch(a)){var d=c.get(this.POINTER_ID);if(d&&d.button===a.button){var e=this.prepareEvent(a);b.up(e),this.cleanupMouse()}}},mouseover:function(a){if(!this.isEventSimulatedFromTouch(a)){var c=this.prepareEvent(a);b.enterOver(c)}},mouseout:function(a){if(!this.isEventSimulatedFromTouch(a)){var c=this.prepareEvent(a);b.leaveOut(c)}},cancel:function(a){var c=this.prepareEvent(a);b.cancel(c),this.cleanupMouse()},cleanupMouse:function(){c["delete"](this.POINTER_ID)}};a.mouseEvents=e}(window.PointerEventsPolyfill),function(a){var b,c=a.dispatcher,d=a.findTarget,e=a.targetFinding.allShadows.bind(a.targetFinding),f=c.pointermap,g=Array.prototype.map.call.bind(Array.prototype.map),h=2500,i=200,j="touch-action",k=!1,l={scrollType:new WeakMap,events:["touchstart","touchmove","touchend","touchcancel"],register:function(a){k?c.listen(a,this.events):b.enableOnSubtree(a)},unregister:function(a){k&&c.unlisten(a,this.events)},elementAdded:function(a){var b=a.getAttribute(j),d=this.touchActionToScrollType(b);d&&(this.scrollType.set(a,d),c.listen(a,this.events),e(a).forEach(function(a){this.scrollType.set(a,d),c.listen(a,this.events)},this))},elementRemoved:function(a){this.scrollType["delete"](a),c.unlisten(a,this.events),e(a).forEach(function(a){this.scrollType["delete"](a),c.unlisten(a,this.events)},this)},elementChanged:function(a,b){var c=a.getAttribute(j),d=this.touchActionToScrollType(c),f=this.touchActionToScrollType(b);d&&f?(this.scrollType.set(a,d),e(a).forEach(function(a){this.scrollType.set(a,d)},this)):f?this.elementRemoved(a):d&&this.elementAdded(a)},scrollTypes:{EMITTER:"none",XSCROLLER:"pan-x",YSCROLLER:"pan-y",SCROLLER:/^(?:pan-x pan-y)|(?:pan-y pan-x)|auto$/},touchActionToScrollType:function(a){var b=a,c=this.scrollTypes;return"none"===b?"none":b===c.XSCROLLER?"X":b===c.YSCROLLER?"Y":c.SCROLLER.exec(b)?"XY":void 0},POINTER_TYPE:"touch",firstTouch:null,isPrimaryTouch:function(a){return this.firstTouch===a.identifier},setPrimaryTouch:function(a){(0===f.pointers()||1===f.pointers()&&f.has(1))&&(this.firstTouch=a.identifier,this.firstXY={X:a.clientX,Y:a.clientY},this.scrolling=!1,this.cancelResetClickCount())},removePrimaryPointer:function(a){a.isPrimary&&(this.firstTouch=null,this.firstXY=null,this.resetClickCount())},clickCount:0,resetId:null,resetClickCount:function(){var a=function(){this.clickCount=0,this.resetId=null}.bind(this);this.resetId=setTimeout(a,i)},cancelResetClickCount:function(){this.resetId&&clearTimeout(this.resetId)},touchToPointer:function(a){var b=c.cloneEvent(a);return b.pointerId=a.identifier+2,b.target=d(b),b.bubbles=!0,b.cancelable=!0,b.detail=this.clickCount,b.button=0,b.buttons=1,b.width=a.webkitRadiusX||a.radiusX||0,b.height=a.webkitRadiusY||a.radiusY||0,b.pressure=a.webkitForce||a.force||.5,b.isPrimary=this.isPrimaryTouch(a),b.pointerType=this.POINTER_TYPE,b},processTouches:function(a,b){var c=a.changedTouches,d=g(c,this.touchToPointer,this);d.forEach(function(b){b.preventDefault=function(){this.scrolling=!1,this.firstXY=null,a.preventDefault()}},this),d.forEach(b,this)},shouldScroll:function(a){if(this.firstXY){var b,c=this.scrollType.get(a.currentTarget);if("none"===c)b=!1;else if("XY"===c)b=!0;else{var d=a.changedTouches[0],e=c,f="Y"===c?"X":"Y",g=Math.abs(d["client"+e]-this.firstXY[e]),h=Math.abs(d["client"+f]-this.firstXY[f]);b=g>=h}return this.firstXY=null,b}},findTouch:function(a,b){for(var c,d=0,e=a.length;e>d&&(c=a[d]);d++)if(c.identifier===b)return!0},vacuumTouches:function(a){var b=a.touches;if(f.pointers()>=b.length){var c=[];f.forEach(function(a,d){if(1!==d&&!this.findTouch(b,d-2)){var e=a.out;c.push(this.touchToPointer(e))}},this),c.forEach(this.cancelOut,this)}},touchstart:function(a){this.vacuumTouches(a),this.setPrimaryTouch(a.changedTouches[0]),this.dedupSynthMouse(a),this.scrolling||(this.clickCount++,this.processTouches(a,this.overDown))},overDown:function(a){f.set(a.pointerId,{target:a.target,out:a,outTarget:a.target});c.over(a),c.enter(a),c.down(a)},touchmove:function(a){this.scrolling||(this.shouldScroll(a)?(this.scrolling=!0,this.touchcancel(a)):(a.preventDefault(),this.processTouches(a,this.moveOverOut)))},moveOverOut:function(a){var b=a,d=f.get(b.pointerId);if(d){var e=d.out,g=d.outTarget;c.move(b),e&&g!==b.target&&(e.relatedTarget=b.target,b.relatedTarget=g,e.target=g,b.target?(c.leaveOut(e),c.enterOver(b)):(b.target=g,b.relatedTarget=null,this.cancelOut(b))),d.out=b,d.outTarget=b.target}},touchend:function(a){this.dedupSynthMouse(a),this.processTouches(a,this.upOut)},upOut:function(a){this.scrolling||(c.up(a),c.out(a),c.leave(a)),this.cleanUpPointer(a)},touchcancel:function(a){this.processTouches(a,this.cancelOut)},cancelOut:function(a){c.cancel(a),c.out(a),c.leave(a),this.cleanUpPointer(a)},cleanUpPointer:function(a){f["delete"](a.pointerId),this.removePrimaryPointer(a)},dedupSynthMouse:function(b){var c=a.mouseEvents.lastTouches,d=b.changedTouches[0];if(this.isPrimaryTouch(d)){var e={x:d.clientX,y:d.clientY};c.push(e);var f=function(a,b){var c=a.indexOf(b);c>-1&&a.splice(c,1)}.bind(null,c,e);setTimeout(f,h)}}};k||(b=new a.Installer(l.elementAdded,l.elementRemoved,l.elementChanged,l)),a.touchEvents=l}(window.PointerEventsPolyfill),function(a){var b=a.dispatcher,c=b.pointermap,d=window.MSPointerEvent&&"number"==typeof window.MSPointerEvent.MSPOINTER_TYPE_MOUSE,e={events:["MSPointerDown","MSPointerMove","MSPointerUp","MSPointerOut","MSPointerOver","MSPointerCancel","MSGotPointerCapture","MSLostPointerCapture"],register:function(a){b.listen(a,this.events)},unregister:function(a){b.unlisten(a,this.events)},POINTER_TYPES:["","unavailable","touch","pen","mouse"],prepareEvent:function(a){var c=a;return d&&(c=b.cloneEvent(a),c.pointerType=this.POINTER_TYPES[a.pointerType]),c},cleanup:function(a){c["delete"](a)},MSPointerDown:function(a){c.set(a.pointerId,a);var d=this.prepareEvent(a);b.down(d)},MSPointerMove:function(a){var c=this.prepareEvent(a);b.move(c)},MSPointerUp:function(a){var c=this.prepareEvent(a);b.up(c),this.cleanup(a.pointerId)},MSPointerOut:function(a){var c=this.prepareEvent(a);b.leaveOut(c)},MSPointerOver:function(a){var c=this.prepareEvent(a);b.enterOver(c)},MSPointerCancel:function(a){var c=this.prepareEvent(a);b.cancel(c),this.cleanup(a.pointerId)},MSLostPointerCapture:function(a){var c=b.makeEvent("lostpointercapture",a);b.dispatchEvent(c)},MSGotPointerCapture:function(a){var c=b.makeEvent("gotpointercapture",a);b.dispatchEvent(c)}};a.msEvents=e}(window.PointerEventsPolyfill),function(a){var b=a.dispatcher;if(void 0===window.navigator.pointerEnabled){if(Object.defineProperty(window.navigator,"pointerEnabled",{value:!0,enumerable:!0}),window.navigator.msPointerEnabled){var c=window.navigator.msMaxTouchPoints;Object.defineProperty(window.navigator,"maxTouchPoints",{value:c,enumerable:!0}),b.registerSource("ms",a.msEvents)}else b.registerSource("mouse",a.mouseEvents),void 0!==window.ontouchstart&&b.registerSource("touch",a.touchEvents);b.register(document)}}(window.PointerEventsPolyfill),function(a){function b(a){if(!e.pointermap.has(a))throw new Error("InvalidPointerId")}var c,d,e=a.dispatcher,f=window.navigator;f.msPointerEnabled?(c=function(a){b(a),this.msSetPointerCapture(a)},d=function(a){b(a),this.msReleasePointerCapture(a)}):(c=function(a){b(a),e.setCapture(a,this)},d=function(a){b(a),e.releaseCapture(a,this)}),window.Element&&!Element.prototype.setPointerCapture&&Object.defineProperties(Element.prototype,{setPointerCapture:{value:c},releasePointerCapture:{value:d}})}(window.PointerEventsPolyfill),PointerGestureEvent.prototype.preventTap=function(){this.tapPrevented=!0},function(a){a=a||{},a.utils={LCA:{find:function(a,b){if(a===b)return a;if(a.contains){if(a.contains(b))return a;if(b.contains(a))return b}var c=this.depth(a),d=this.depth(b),e=c-d;for(e>0?a=this.walk(a,e):b=this.walk(b,-e);a&&b&&a!==b;)a=this.walk(a,1),b=this.walk(b,1);return a},walk:function(a,b){for(var c=0;b>c;c++)a=a.parentNode;return a},depth:function(a){for(var b=0;a;)b++,a=a.parentNode;return b}}},a.findLCA=function(b,c){return a.utils.LCA.find(b,c)},window.PointerGestures=a}(window.PointerGestures),function(a){function b(){if(c){var a=new Map;return a.pointers=d,a}this.keys=[],this.values=[]}var c=window.Map&&window.Map.prototype.forEach,d=function(){return this.size};b.prototype={set:function(a,b){var c=this.keys.indexOf(a);c>-1?this.values[c]=b:(this.keys.push(a),this.values.push(b))},has:function(a){return this.keys.indexOf(a)>-1},"delete":function(a){var b=this.keys.indexOf(a);b>-1&&(this.keys.splice(b,1),this.values.splice(b,1))},get:function(a){var b=this.keys.indexOf(a);return this.values[b]},clear:function(){this.keys.length=0,this.values.length=0},forEach:function(a,b){this.values.forEach(function(c,d){a.call(b,c,this.keys[d],this)},this)},pointers:function(){return this.keys.length}},a.PointerMap=b}(window.PointerGestures),function(a){var b=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget","buttons","pointerId","width","height","pressure","tiltX","tiltY","pointerType","hwTimestamp","isPrimary","type","target","currentTarget","screenX","screenY","pageX","pageY","tapPrevented"],c=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null,0,0,0,0,0,0,0,"",0,!1,"",null,null,0,0,0,0],d={handledEvents:new WeakMap,targets:new WeakMap,handlers:{},recognizers:{},events:{},registerRecognizer:function(a,b){var c=b;this.recognizers[a]=c,c.events.forEach(function(a){if(c[a]){this.events[a]=!0;var b=c[a].bind(c);this.addHandler(a,b)}},this)},addHandler:function(a,b){var c=a;this.handlers[c]||(this.handlers[c]=[]),this.handlers[c].push(b)},registerTarget:function(a){this.listen(Object.keys(this.events),a)},unregisterTarget:function(a){this.unlisten(Object.keys(this.events),a)},eventHandler:function(a){if(!this.handledEvents.get(a)){var b=a.type,c=this.handlers[b];c&&this.makeQueue(c,a),this.handledEvents.set(a,!0)}},makeQueue:function(a,b){var c=this.cloneEvent(b);setTimeout(this.runQueue.bind(this,a,c),0)},runQueue:function(a,b){this.currentPointerId=b.pointerId;for(var c,d=0,e=a.length;e>d&&(c=a[d]);d++)c(b);this.currentPointerId=0},listen:function(a,b){a.forEach(function(a){this.addEvent(a,this.boundHandler,!1,b)},this)},unlisten:function(a){a.forEach(function(a){this.removeEvent(a,this.boundHandler,!1,inTarget)},this)},addEvent:function(a,b,c,d){d.addEventListener(a,b,c)},removeEvent:function(a,b,c,d){d.removeEventListener(a,b,c)},makeEvent:function(a,b){return new PointerGestureEvent(a,b)},cloneEvent:function(a){for(var d,e={},f=0;f<b.length;f++)d=b[f],e[d]=a[d]||c[f];return e},dispatchEvent:function(a,b){var c=b||this.targets.get(a);c&&(c.dispatchEvent(a),a.tapPrevented&&this.preventTap(this.currentPointerId))},asyncDispatchEvent:function(a,b){var c=function(){this.dispatchEvent(a,b)}.bind(this);setTimeout(c,0)},preventTap:function(a){var b=this.recognizers.tap;b&&b.preventTap(a)}};d.boundHandler=d.eventHandler.bind(d),a.dispatcher=d;var e=[],f=!1;a.register=function(b){if(f){var c=window.PointerEventsPolyfill;c&&c.register(b),a.dispatcher.registerTarget(b)}else e.push(b)},document.addEventListener("DOMContentLoaded",function(){f=!0,e.push(document),e.forEach(a.register)})}(window.PointerGestures),function(a){var b=a.dispatcher,c={HOLD_DELAY:200,WIGGLE_THRESHOLD:16,events:["pointerdown","pointermove","pointerup","pointercancel"],heldPointer:null,holdJob:null,pulse:function(){var a=Date.now()-this.heldPointer.timeStamp,b=this.held?"holdpulse":"hold";this.fireHold(b,a),this.held=!0},cancel:function(){clearInterval(this.holdJob),this.held&&this.fireHold("release"),this.held=!1,this.heldPointer=null,this.target=null,this.holdJob=null},pointerdown:function(a){a.isPrimary&&!this.heldPointer&&(this.heldPointer=a,this.target=a.target,this.holdJob=setInterval(this.pulse.bind(this),this.HOLD_DELAY))},pointerup:function(a){this.heldPointer&&this.heldPointer.pointerId===a.pointerId&&this.cancel()},pointercancel:function(){this.cancel()},pointermove:function(a){if(this.heldPointer&&this.heldPointer.pointerId===a.pointerId){var b=a.clientX-this.heldPointer.clientX,c=a.clientY-this.heldPointer.clientY;b*b+c*c>this.WIGGLE_THRESHOLD&&this.cancel()}},fireHold:function(a,c){var d={pointerType:this.heldPointer.pointerType};c&&(d.holdTime=c);var e=b.makeEvent(a,d);b.dispatchEvent(e,this.target),e.tapPrevented&&b.preventTap(this.heldPointer.pointerId)}};b.registerRecognizer("hold",c)}(window.PointerGestures),function(a){var b=a.dispatcher,c=new a.PointerMap,d={events:["pointerdown","pointermove","pointerup","pointercancel"],WIGGLE_THRESHOLD:4,clampDir:function(a){return a>0?1:-1},calcPositionDelta:function(a,b){var c=0,d=0;return a&&b&&(c=b.pageX-a.pageX,d=b.pageY-a.pageY),{x:c,y:d}},fireTrack:function(a,c,d){var e=d,f=this.calcPositionDelta(e.downEvent,c),g=this.calcPositionDelta(e.lastMoveEvent,c);g.x&&(e.xDirection=this.clampDir(g.x)),g.y&&(e.yDirection=this.clampDir(g.y));var h={dx:f.x,dy:f.y,ddx:g.x,ddy:g.y,clientX:c.clientX,clientY:c.clientY,pageX:c.pageX,pageY:c.pageY,screenX:c.screenX,screenY:c.screenY,xDirection:e.xDirection,yDirection:e.yDirection,trackInfo:e.trackInfo,relatedTarget:c.target,pointerType:c.pointerType},i=b.makeEvent(a,h);e.lastMoveEvent=c,b.dispatchEvent(i,e.downTarget)},pointerdown:function(a){if(a.isPrimary&&("mouse"===a.pointerType?1===a.buttons:!0)){var b={downEvent:a,downTarget:a.target,trackInfo:{},lastMoveEvent:null,xDirection:0,yDirection:0,tracking:!1};c.set(a.pointerId,b)}},pointermove:function(a){var b=c.get(a.pointerId);if(b)if(b.tracking)this.fireTrack("track",a,b);else{var d=this.calcPositionDelta(b.downEvent,a),e=d.x*d.x+d.y*d.y;e>this.WIGGLE_THRESHOLD&&(b.tracking=!0,this.fireTrack("trackstart",b.downEvent,b),this.fireTrack("track",a,b))}},pointerup:function(a){var b=c.get(a.pointerId);b&&(b.tracking&&this.fireTrack("trackend",a,b),c.delete(a.pointerId))},pointercancel:function(a){this.pointerup(a)}};b.registerRecognizer("track",d)}(window.PointerGestures),function(a){var b=a.dispatcher,c={MIN_VELOCITY:.5,MAX_QUEUE:4,moveQueue:[],target:null,pointerId:null,events:["pointerdown","pointermove","pointerup","pointercancel"],pointerdown:function(a){a.isPrimary&&!this.pointerId&&(this.pointerId=a.pointerId,this.target=a.target,this.addMove(a))},pointermove:function(a){a.pointerId===this.pointerId&&this.addMove(a)},pointerup:function(a){a.pointerId===this.pointerId&&this.fireFlick(a),this.cleanup()},pointercancel:function(){this.cleanup()},cleanup:function(){this.moveQueue=[],this.target=null,this.pointerId=null},addMove:function(a){this.moveQueue.length>=this.MAX_QUEUE&&this.moveQueue.shift(),this.moveQueue.push(a)},fireFlick:function(a){for(var c,d,e,f,g,h,i,j=a,k=this.moveQueue.length,l=0,m=0,n=0,o=0;k>o&&(i=this.moveQueue[o]);o++)c=j.timeStamp-i.timeStamp,d=j.clientX-i.clientX,e=j.clientY-i.clientY,f=d/c,g=e/c,h=Math.sqrt(f*f+g*g),h>n&&(l=f,m=g,n=h);var p=Math.abs(l)>Math.abs(m)?"x":"y",q=this.calcAngle(l,m);if(Math.abs(n)>=this.MIN_VELOCITY){var r=b.makeEvent("flick",{xVelocity:l,yVelocity:m,velocity:n,angle:q,majorAxis:p,pointerType:a.pointerType});b.dispatchEvent(r,this.target)}},calcAngle:function(a,b){return 180*Math.atan2(b,a)/Math.PI}};b.registerRecognizer("flick",c)}(window.PointerGestures),function(a){var b=a.dispatcher,c=new a.PointerMap,d=180/Math.PI,e={events:["pointerdown","pointermove","pointerup","pointercancel"],reference:{},pointerdown:function(b){if(c.set(b.pointerId,b),2==c.pointers()){var d=this.calcChord(),e=this.calcAngle(d);this.reference={angle:e,diameter:d.diameter,target:a.findLCA(d.a.target,d.b.target)}}},pointerup:function(a){c.delete(a.pointerId)},pointermove:function(a){c.has(a.pointerId)&&(c.set(a.pointerId,a),c.pointers()>1&&this.calcPinchRotate())},pointercancel:function(a){this.pointerup(a)},dispatchPinch:function(a,c){var d=a/this.reference.diameter,e=b.makeEvent("pinch",{scale:d,centerX:c.center.x,centerY:c.center.y});b.dispatchEvent(e,this.reference.target)},dispatchRotate:function(a,c){var d=Math.round((a-this.reference.angle)%360),e=b.makeEvent("rotate",{angle:d,centerX:c.center.x,centerY:c.center.y});b.dispatchEvent(e,this.reference.target)},calcPinchRotate:function(){var a=this.calcChord(),b=a.diameter,c=this.calcAngle(a);b!=this.reference.diameter&&this.dispatchPinch(b,a),c!=this.reference.angle&&this.dispatchRotate(c,a)},calcChord:function(){var a=[];c.forEach(function(b){a.push(b)});for(var b,d,e,f=0,g={},h=0;h<a.length;h++)for(var i=a[h],j=h+1;j<a.length;j++){var k=a[j];b=Math.abs(i.clientX-k.clientX),d=Math.abs(i.clientY-k.clientY),e=b+d,e>f&&(f=e,g={a:i,b:k})}return b=Math.abs(g.a.clientX+g.b.clientX)/2,d=Math.abs(g.a.clientY+g.b.clientY)/2,g.center={x:b,y:d},g.diameter=f,g},calcAngle:function(a){var b=a.a.clientX-a.b.clientX,c=a.a.clientY-a.b.clientY;return(360+Math.atan2(c,b)*d)%360}};b.registerRecognizer("pinch",e)}(window.PointerGestures),function(a){var b=a.dispatcher,c=new a.PointerMap,d={events:["pointerdown","pointermove","pointerup","pointercancel","keyup"],pointerdown:function(a){a.isPrimary&&!a.tapPrevented&&c.set(a.pointerId,{target:a.target,x:a.clientX,y:a.clientY})},pointermove:function(a){if(a.isPrimary){var b=c.get(a.pointerId);b&&a.tapPrevented&&c.delete(a.pointerId)}},pointerup:function(d){var e=c.get(d.pointerId);if(e&&!d.tapPrevented){var f=a.findLCA(e.target,d.target);if(f){var g=b.makeEvent("tap",{x:d.clientX,y:d.clientY,detail:d.detail,pointerType:d.pointerType});b.dispatchEvent(g,f)}}c.delete(d.pointerId)},pointercancel:function(a){c.delete(a.pointerId)},keyup:function(a){var c=a.keyCode;if(32===c){var d=a.target;d instanceof HTMLInputElement||d instanceof HTMLTextAreaElement||b.dispatchEvent(b.makeEvent("tap",{x:0,y:0,detail:0,pointerType:"unavailable"}),d)}},preventTap:function(a){c.delete(a)}};b.registerRecognizer("tap",d)}(window.PointerGestures),function(){"use strict";function a(a){for(;a.parentNode;)a=a.parentNode;return"function"==typeof a.getElementById?a:null}function b(a,b){var c=a.bindings;if(!c)return void(a.bindings={});var d=c[b];d&&(d.close(),c[b]=void 0)}function c(a){return null==a?"":a}function d(a,b){a.data=c(b)}function e(a){return function(b){return d(a,b)}}function f(a,b,d,e){return d?void(e?a.setAttribute(b,""):a.removeAttribute(b)):void a.setAttribute(b,c(e))}function g(a,b,c){return function(d){f(a,b,c,d)}}function h(a){switch(a.type){case"checkbox":return s;case"radio":case"select-multiple":case"select-one":return"change";default:return"input"}}function i(a,b,d,e){a[b]=(e||c)(d)}function j(a,b,c){return function(d){return i(a,b,d,c)}}function k(){}function l(a,b,c,d){function e(){c.setValue(a[b]),c.discardChanges(),(d||k)(a),Platform.performMicrotaskCheckpoint()}var f=h(a);a.addEventListener(f,e);var g=c.close;c.close=function(){g&&(a.removeEventListener(f,e),c.close=g,c.close(),g=void 0)}}function m(a){return Boolean(a)}function n(b){if(b.form)return r(b.form.elements,function(a){return a!=b&&"INPUT"==a.tagName&&"radio"==a.type&&a.name==b.name});var c=a(b);if(!c)return[];var d=c.querySelectorAll('input[type="radio"][name="'+b.name+'"]');return r(d,function(a){return a!=b&&!a.form})}function o(a){"INPUT"===a.tagName&&"radio"===a.type&&n(a).forEach(function(a){var b=a.bindings.checked;b&&b.setValue(!1)})}function p(a,b){var d,e,f,g=a.parentNode;g instanceof HTMLSelectElement&&g.bindings&&g.bindings.value&&(d=g,e=d.bindings.value,f=d.value),a.value=c(b),d&&d.value!=f&&(e.setValue(d.value),e.discardChanges(),Platform.performMicrotaskCheckpoint())}function q(a){return function(b){p(a,b)}}var r=Array.prototype.filter.call.bind(Array.prototype.filter);"function"!=typeof document.contains&&(Document.prototype.contains=function(a){return a===this||a.parentNode===this?!0:this.documentElement.contains(a)}),Node.prototype.bind=function(a,b){console.error("Unhandled binding to Node: ",this,a,b)},Node.prototype.unbind=function(a){b(this,a)},Node.prototype.unbindAll=function(){if(this.bindings){for(var a=Object.keys(this.bindings),b=0;b<a.length;b++){var c=this.bindings[a[b]];c&&c.close()}this.bindings={}}},Text.prototype.bind=function(a,c,f){return"textContent"!==a?Node.prototype.bind.call(this,a,c,f):f?d(this,c):(b(this,"textContent"),d(this,c.open(e(this))),this.bindings.textContent=c)},Element.prototype.bind=function(a,c,d){var e="?"==a[a.length-1];return e&&(this.removeAttribute(a),a=a.slice(0,-1)),d?f(this,a,e,c):(b(this,a),f(this,a,e,c.open(g(this,a,e))),this.bindings[a]=c)};var s;!function(){var a=document.createElement("div"),b=a.appendChild(document.createElement("input"));b.setAttribute("type","checkbox");var c,d=0;b.addEventListener("click",function(){d++,c=c||"click"}),b.addEventListener("change",function(){d++,c=c||"change"});var e=document.createEvent("MouseEvent");e.initMouseEvent("click",!0,!0,window,0,0,0,0,0,!1,!1,!1,!1,0,null),b.dispatchEvent(e),s=1==d?"change":c}(),HTMLInputElement.prototype.bind=function(a,d,e){if("value"!==a&&"checked"!==a)return HTMLElement.prototype.bind.call(this,a,d,e);this.removeAttribute(a);var f="checked"==a?m:c,g="checked"==a?o:k;return e?i(this,a,d,f):(b(this,a),l(this,a,d,g),i(this,a,d.open(j(this,a,f)),f),this.bindings[a]=d)},HTMLTextAreaElement.prototype.bind=function(a,d,e){return"value"!==a?HTMLElement.prototype.bind.call(this,a,d,e):(this.removeAttribute("value"),e?i(this,"value",d):(b(this,"value"),l(this,"value",d),i(this,"value",d.open(j(this,"value",c))),this.bindings.value=d))},HTMLOptionElement.prototype.bind=function(a,c,d){return"value"!==a?HTMLElement.prototype.bind.call(this,a,c,d):(this.removeAttribute("value"),d?p(this,c):(b(this,"value"),l(this,"value",c),p(this,c.open(q(this))),this.bindings.value=c))},HTMLSelectElement.prototype.bind=function(a,c,d){return"selectedindex"===a&&(a="selectedIndex"),"selectedIndex"!==a&&"value"!==a?HTMLElement.prototype.bind.call(this,a,c,d):(this.removeAttribute(a),d?i(this,a,c):(b(this,a),l(this,a,c),i(this,a,c.open(j(this,a))),this.bindings[a]=c))}}(this),function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a){for(var b;b=a.parentNode;)a=b;return a}function d(a,b){if(b){for(var d,e="#"+b;!d&&(a=c(a),a.protoContent_?d=a.protoContent_.querySelector(e):a.getElementById&&(d=a.getElementById(b)),!d&&a.templateCreator_);)a=a.templateCreator_;return d}}function e(a){return"template"==a.tagName&&"http://www.w3.org/2000/svg"==a.namespaceURI}function f(a){return"TEMPLATE"==a.tagName&&"http://www.w3.org/1999/xhtml"==a.namespaceURI}function g(a){return Boolean(J[a.tagName]&&a.hasAttribute("template"))}function h(a){return void 0===a.isTemplate_&&(a.isTemplate_="TEMPLATE"==a.tagName||g(a)),a.isTemplate_}function i(a,b){var c=a.querySelectorAll(L);h(a)&&b(a),E(c,b)}function j(a){function b(a){HTMLTemplateElement.decorate(a)||j(a.content)}i(a,b)}function k(a,b){Object.getOwnPropertyNames(b).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))})}function l(a){var b=a.ownerDocument;if(!b.defaultView)return b;var c=b.templateContentsOwner_;if(!c){for(c=b.implementation.createHTMLDocument("");c.lastChild;)c.removeChild(c.lastChild);b.templateContentsOwner_=c}return c}function m(a){if(!a.stagingDocument_){var b=a.ownerDocument;b.stagingDocument_||(b.stagingDocument_=b.implementation.createHTMLDocument(""),b.stagingDocument_.stagingDocument_=b.stagingDocument_),a.stagingDocument_=b.stagingDocument_}return a.stagingDocument_}function n(a){var b=a.ownerDocument.createElement("template");a.parentNode.insertBefore(b,a);for(var c=a.attributes,d=c.length;d-->0;){var e=c[d];I[e.name]&&("template"!==e.name&&b.setAttribute(e.name,e.value),a.removeAttribute(e.name))}return b}function o(a){var b=a.ownerDocument.createElement("template");a.parentNode.insertBefore(b,a);for(var c=a.attributes,d=c.length;d-->0;){var e=c[d];b.setAttribute(e.name,e.value),a.removeAttribute(e.name)}return a.parentNode.removeChild(a),b}function p(a,b,c){var d=a.content;if(c)return void d.appendChild(b);for(var e;e=b.firstChild;)d.appendChild(e)}function q(a){N?a.__proto__=HTMLTemplateElement.prototype:k(a,HTMLTemplateElement.prototype)}function r(a){a.setModelFn_||(a.setModelFn_=function(){a.setModelFnScheduled_=!1;var b=z(a,a.delegate_&&a.delegate_.prepareBinding);w(a,b,a.model_)}),a.setModelFnScheduled_||(a.setModelFnScheduled_=!0,Observer.runEOM_(a.setModelFn_))}function s(a,b,c,d){if(a&&a.length){for(var e,f=a.length,g=0,h=0,i=0,j=!0;f>h;){var g=a.indexOf("{{",h),k=a.indexOf("[[",h),l=!1,m="}}";if(k>=0&&(0>g||g>k)&&(g=k,l=!0,m="]]"),i=0>g?-1:a.indexOf(m,g+2),0>i){if(!e)return;e.push(a.slice(h));break}e=e||[],e.push(a.slice(h,g));var n=a.slice(g+2,i).trim();e.push(l),j=j&&l,e.push(Path.get(n));var o=d&&d(n,b,c);e.push(o),h=i+2}return h===f&&e.push(""),e.hasOnePath=5===e.length,e.isSimplePath=e.hasOnePath&&""==e[0]&&""==e[4],e.onlyOneTime=j,e.combinator=function(a){for(var b=e[0],c=1;c<e.length;c+=4){var d=e.hasOnePath?a:a[(c-1)/4];void 0!==d&&(b+=d),b+=e[c+3]}return b},e}}function t(a,b,c,d){if(b.hasOnePath){var e=b[3],f=e?e(d,c,!0):b[2].getValueFrom(d);return b.isSimplePath?f:b.combinator(f)}for(var g=[],h=1;h<b.length;h+=4){var e=b[h+2];g[(h-1)/4]=e?e(d,c):b[h+1].getValueFrom(d)}return b.combinator(g)}function u(a,b,c,d){var e=b[3],f=e?e(d,c,!1):new PathObserver(d,b[2]);return b.isSimplePath?f:new ObserverTransform(f,b.combinator)}function v(a,b,c,d){if(b.onlyOneTime)return t(a,b,c,d);if(b.hasOnePath)return u(a,b,c,d);for(var e=new CompoundObserver,f=1;f<b.length;f+=4){var g=b[f],h=b[f+2];if(h){var i=h(d,c,g);g?e.addPath(i):e.addObserver(i)}else{var j=b[f+1];g?e.addPath(j.getValueFrom(d)):e.addPath(d,j)}}return new ObserverTransform(e,b.combinator)}function w(a,b,c,d){for(var e=0;e<b.length;e+=2){var f=b[e],g=b[e+1],h=v(f,g,a,c),i=a.bind(f,h,g.onlyOneTime);i&&d&&d.push(i)}if(b.isTemplate){a.model_=c;var j=a.processBindingDirectives_(b);d&&j&&d.push(j)}}function x(a,b,c){var d=a.getAttribute(b);return s(""==d?"{{}}":d,b,a,c)}function y(a,c){b(a);for(var d=[],e=0;e<a.attributes.length;e++){for(var f=a.attributes[e],g=f.name,i=f.value;"_"===g[0];)g=g.substring(1);if(!h(a)||g!==H&&g!==F&&g!==G){var j=s(i,g,a,c);j&&d.push(g,j)}}return h(a)&&(d.isTemplate=!0,d.if=x(a,H,c),d.bind=x(a,F,c),d.repeat=x(a,G,c),!d.if||d.bind||d.repeat||(d.bind=s("{{}}",F,a,c))),d}function z(a,b){if(a.nodeType===Node.ELEMENT_NODE)return y(a,b);if(a.nodeType===Node.TEXT_NODE){var c=s(a.data,"textContent",a,b);if(c)return["textContent",c]}return[]}function A(a,b,c,d,e,f,g){for(var h=b.appendChild(c.importNode(a,!1)),i=0,j=a.firstChild;j;j=j.nextSibling)A(j,h,c,d.children[i++],e,f,g);return d.isTemplate&&(HTMLTemplateElement.decorate(h,a),f&&h.setDelegate_(f)),w(h,d,e,g),h}function B(a,b){var c=z(a,b);c.children={};for(var d=0,e=a.firstChild;e;e=e.nextSibling)c.children[d++]=B(e,b);return c}function C(a){this.closed=!1,this.templateElement_=a,this.terminators=[],this.deps=void 0,this.iteratedValue=[],this.presentValue=void 0,this.arrayObserver=void 0}var D,E=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.Map&&"function"==typeof a.Map.prototype.forEach?D=a.Map:(D=function(){this.keys=[],this.values=[]},D.prototype={set:function(a,b){var c=this.keys.indexOf(a);0>c?(this.keys.push(a),this.values.push(b)):this.values[c]=b},get:function(a){var b=this.keys.indexOf(a);if(!(0>b))return this.values[b]},"delete":function(a){var b=this.keys.indexOf(a);return 0>b?!1:(this.keys.splice(b,1),this.values.splice(b,1),!0)},forEach:function(a,b){for(var c=0;c<this.keys.length;c++)a.call(b||this,this.values[c],this.keys[c],this)}});"function"!=typeof document.contains&&(Document.prototype.contains=function(a){return a===this||a.parentNode===this?!0:this.documentElement.contains(a)});var F="bind",G="repeat",H="if",I={template:!0,repeat:!0,bind:!0,ref:!0},J={THEAD:!0,TBODY:!0,TFOOT:!0,TH:!0,TR:!0,TD:!0,COLGROUP:!0,COL:!0,CAPTION:!0,OPTION:!0,OPTGROUP:!0},K="undefined"!=typeof HTMLTemplateElement,L="template, "+Object.keys(J).map(function(a){return a.toLowerCase()+"[template]"}).join(", ");document.addEventListener("DOMContentLoaded",function(){j(document),Platform.performMicrotaskCheckpoint()},!1),K||(a.HTMLTemplateElement=function(){throw TypeError("Illegal constructor")});var M,N="__proto__"in{};"function"==typeof MutationObserver&&(M=new MutationObserver(function(a){for(var b=0;b<a.length;b++)a[b].target.refChanged_()})),HTMLTemplateElement.decorate=function(a,c){if(a.templateIsDecorated_)return!1;var d=a;d.templateIsDecorated_=!0;var h=f(d)&&K,i=h,k=!h,m=!1;if(h||(g(d)?(b(!c),d=n(a),d.templateIsDecorated_=!0,h=K,m=!0):e(d)&&(d=o(a),d.templateIsDecorated_=!0,h=K)),!h){q(d);var r=l(d);d.content_=r.createDocumentFragment()}return c?d.instanceRef_=c:k?p(d,a,m):i&&j(d.content),!0},HTMLTemplateElement.bootstrap=j;var O=a.HTMLUnknownElement||HTMLElement,P={get:function(){return this.content_},enumerable:!0,configurable:!0};K||(HTMLTemplateElement.prototype=Object.create(O.prototype),Object.defineProperty(HTMLTemplateElement.prototype,"content",P)),k(HTMLTemplateElement.prototype,{bind:function(a,b,c){if("ref"!=a)return Element.prototype.bind.call(this,a,b,c);var d=this,e=c?b:b.open(function(a){d.setAttribute("ref",a),d.refChanged_()});return this.setAttribute("ref",e),this.refChanged_(),c?void 0:(this.unbind("ref"),this.bindings.ref=b)},processBindingDirectives_:function(a){return this.iterator_&&this.iterator_.closeDeps(),a.if||a.bind||a.repeat?(this.iterator_||(this.iterator_=new C(this),this.bindings=this.bindings||{},this.bindings.iterator=this.iterator_),this.iterator_.updateDependencies(a,this.model_),M&&M.observe(this,{attributes:!0,attributeFilter:["ref"]}),this.iterator_):void(this.iterator_&&(this.iterator_.close(),this.iterator_=void 0,this.bindings.iterator=void 0))},createInstance:function(a,b,c,d){b&&(c=this.newDelegate_(b)),this.refContent_||(this.refContent_=this.ref_.content);
+var e=this.refContent_,f=this.bindingMap_;f&&f.content===e||(f=B(e,c&&c.prepareBinding)||[],f.content=e,this.bindingMap_=f);var g=m(this),h=g.createDocumentFragment();h.templateCreator_=this,h.protoContent_=e;for(var i={firstNode:null,lastNode:null,model:a},j=0,k=e.firstChild;k;k=k.nextSibling){var l=A(k,h,g,f.children[j++],a,c,d);l.templateInstance_=i}return i.firstNode=h.firstChild,i.lastNode=h.lastChild,h.templateCreator_=void 0,h.protoContent_=void 0,h},get model(){return this.model_},set model(a){this.model_=a,r(this)},get bindingDelegate(){return this.delegate_&&this.delegate_.raw},refChanged_:function(){this.iterator_&&this.refContent_!==this.ref_.content&&(this.refContent_=void 0,this.iterator_.valueChanged(),this.iterator_.updateIteratedValue())},clear:function(){this.model_=void 0,this.delegate_=void 0,this.bindings_=void 0,this.refContent_=void 0,this.iterator_&&(this.iterator_.valueChanged(),this.iterator_.close(),this.iterator_=void 0)},setDelegate_:function(a){this.delegate_=a,this.bindingMap_=void 0,this.iterator_&&(this.iterator_.instancePositionChangedFn_=void 0,this.iterator_.instanceModelFn_=void 0)},newDelegate_:function(a){function b(b){var c=a&&a[b];if("function"==typeof c)return function(){return c.apply(a,arguments)}}return a?{raw:a,prepareBinding:b("prepareBinding"),prepareInstanceModel:b("prepareInstanceModel"),prepareInstancePositionChanged:b("prepareInstancePositionChanged")}:{}},set bindingDelegate(a){if(this.delegate_)throw Error("Template must be cleared before a new bindingDelegate can be assigned");this.setDelegate_(this.newDelegate_(a))},get ref_(){var a=d(this,this.getAttribute("ref"));if(a||(a=this.instanceRef_),!a)return this;var b=a.ref_;return b?b:a}}),Object.defineProperty(Node.prototype,"templateInstance",{get:function(){var a=this.templateInstance_;return a?a:this.parentNode?this.parentNode.templateInstance:void 0}}),C.prototype={closeDeps:function(){var a=this.deps;a&&(a.ifOneTime===!1&&a.ifValue.close(),a.oneTime===!1&&a.value.close())},updateDependencies:function(a,b){this.closeDeps();var c=this.deps={},d=this.templateElement_;if(a.if){if(c.hasIf=!0,c.ifOneTime=a.if.onlyOneTime,c.ifValue=v(H,a.if,d,b),c.ifOneTime&&!c.ifValue)return void this.updateIteratedValue();c.ifOneTime||c.ifValue.open(this.updateIteratedValue,this)}a.repeat?(c.repeat=!0,c.oneTime=a.repeat.onlyOneTime,c.value=v(G,a.repeat,d,b)):(c.repeat=!1,c.oneTime=a.bind.onlyOneTime,c.value=v(F,a.bind,d,b)),c.oneTime||c.value.open(this.updateIteratedValue,this),this.updateIteratedValue()},updateIteratedValue:function(){if(this.deps.hasIf){var a=this.deps.ifValue;if(this.deps.ifOneTime||(a=a.discardChanges()),!a)return void this.valueChanged()}var b=this.deps.value;this.deps.oneTime||(b=b.discardChanges()),this.deps.repeat||(b=[b]);var c=this.deps.repeat&&!this.deps.oneTime&&Array.isArray(b);this.valueChanged(b,c)},valueChanged:function(a,b){Array.isArray(a)||(a=[]),a!==this.iteratedValue&&(this.unobserve(),this.presentValue=a,b&&(this.arrayObserver=new ArrayObserver(this.presentValue),this.arrayObserver.open(this.handleSplices,this)),this.handleSplices(ArrayObserver.calculateSplices(this.presentValue,this.iteratedValue)))},getTerminatorAt:function(a){if(-1==a)return this.templateElement_;var b=this.terminators[2*a];if(b.nodeType!==Node.ELEMENT_NODE||this.templateElement_===b)return b;var c=b.iterator_;return c?c.getTerminatorAt(c.terminators.length/2-1):b},insertInstanceAt:function(a,b,c,d){var e=this.getTerminatorAt(a-1),f=e;b?f=b.lastChild||f:c&&(f=c[c.length-1]||f),this.terminators.splice(2*a,0,f,d);var g=this.templateElement_.parentNode,h=e.nextSibling;if(b)g.insertBefore(b,h);else if(c)for(var i=0;i<c.length;i++)g.insertBefore(c[i],h)},extractInstanceAt:function(a){var b=[],c=this.getTerminatorAt(a-1),d=this.getTerminatorAt(a);b.instanceBindings=this.terminators[2*a+1],this.terminators.splice(2*a,2);for(var e=this.templateElement_.parentNode;d!==c;){var f=c.nextSibling;f==d&&(d=c),e.removeChild(f),b.push(f)}return b},getDelegateFn:function(a){return a=a&&a(this.templateElement_),"function"==typeof a?a:null},handleSplices:function(a){if(!this.closed&&a.length){var b=this.templateElement_;if(!b.parentNode)return void this.close();ArrayObserver.applySplices(this.iteratedValue,this.presentValue,a);var c=b.delegate_;void 0===this.instanceModelFn_&&(this.instanceModelFn_=this.getDelegateFn(c&&c.prepareInstanceModel)),void 0===this.instancePositionChangedFn_&&(this.instancePositionChangedFn_=this.getDelegateFn(c&&c.prepareInstancePositionChanged));var d=new D,e=0;a.forEach(function(a){a.removed.forEach(function(b){var c=this.extractInstanceAt(a.index+e);d.set(b,c)},this),e-=a.addedCount},this),a.forEach(function(a){for(var e=a.index;e<a.index+a.addedCount;e++){var f,g=this.iteratedValue[e],h=void 0,i=d.get(g);i?(d.delete(g),f=i.instanceBindings):(f=[],this.instanceModelFn_&&(g=this.instanceModelFn_(g)),void 0!==g&&(h=b.createInstance(g,void 0,c,f))),this.insertInstanceAt(e,h,i,f)}},this),d.forEach(function(a){this.closeInstanceBindings(a.instanceBindings)},this),this.instancePositionChangedFn_&&this.reportInstancesMoved(a)}},reportInstanceMoved:function(a){var b=this.getTerminatorAt(a-1),c=this.getTerminatorAt(a);if(b!==c){var d=b.nextSibling.templateInstance;this.instancePositionChangedFn_(d,a)}},reportInstancesMoved:function(a){for(var b=0,c=0,d=0;d<a.length;d++){var e=a[d];if(0!=c)for(;b<e.index;)this.reportInstanceMoved(b),b++;else b=e.index;for(;b<e.index+e.addedCount;)this.reportInstanceMoved(b),b++;c+=e.addedCount-e.removed.length}if(0!=c)for(var f=this.terminators.length/2;f>b;)this.reportInstanceMoved(b),b++},closeInstanceBindings:function(a){for(var b=0;b<a.length;b++)a[b].close()},unobserve:function(){this.arrayObserver&&(this.arrayObserver.close(),this.arrayObserver=void 0)},close:function(){if(!this.closed){this.unobserve();for(var a=1;a<this.terminators.length;a+=2)this.closeInstanceBindings(this.terminators[a]);this.terminators.length=0,this.closeDeps(),this.templateElement_.iterator_=void 0,this.closed=!0}}},HTMLTemplateElement.forAllTemplatesFrom_=i}(this),function(a){"use strict";function b(a,b){if(!a)throw new Error("ASSERT: "+b)}function c(a){return a>=48&&57>=a}function d(a){return 32===a||9===a||11===a||12===a||160===a||a>=5760&&" ᠎              ".indexOf(String.fromCharCode(a))>0}function e(a){return 10===a||13===a||8232===a||8233===a}function f(a){return 36===a||95===a||a>=65&&90>=a||a>=97&&122>=a}function g(a){return 36===a||95===a||a>=65&&90>=a||a>=97&&122>=a||a>=48&&57>=a}function h(a){return"this"===a}function i(){for(;Y>X&&d(W.charCodeAt(X));)++X}function j(){var a,b;for(a=X++;Y>X&&(b=W.charCodeAt(X),g(b));)++X;return W.slice(a,X)}function k(){var a,b,c;return a=X,b=j(),c=1===b.length?S.Identifier:h(b)?S.Keyword:"null"===b?S.NullLiteral:"true"===b||"false"===b?S.BooleanLiteral:S.Identifier,{type:c,value:b,range:[a,X]}}function l(){var a,b,c=X,d=W.charCodeAt(X),e=W[X];switch(d){case 46:case 40:case 41:case 59:case 44:case 123:case 125:case 91:case 93:case 58:case 63:return++X,{type:S.Punctuator,value:String.fromCharCode(d),range:[c,X]};default:if(a=W.charCodeAt(X+1),61===a)switch(d){case 37:case 38:case 42:case 43:case 45:case 47:case 60:case 62:case 124:return X+=2,{type:S.Punctuator,value:String.fromCharCode(d)+String.fromCharCode(a),range:[c,X]};case 33:case 61:return X+=2,61===W.charCodeAt(X)&&++X,{type:S.Punctuator,value:W.slice(c,X),range:[c,X]}}}return b=W[X+1],e===b&&"&|".indexOf(e)>=0?(X+=2,{type:S.Punctuator,value:e+b,range:[c,X]}):"<>=!+-*%&|^/".indexOf(e)>=0?(++X,{type:S.Punctuator,value:e,range:[c,X]}):void s({},V.UnexpectedToken,"ILLEGAL")}function m(){var a,d,e;if(e=W[X],b(c(e.charCodeAt(0))||"."===e,"Numeric literal must start with a decimal digit or a decimal point"),d=X,a="","."!==e){for(a=W[X++],e=W[X],"0"===a&&e&&c(e.charCodeAt(0))&&s({},V.UnexpectedToken,"ILLEGAL");c(W.charCodeAt(X));)a+=W[X++];e=W[X]}if("."===e){for(a+=W[X++];c(W.charCodeAt(X));)a+=W[X++];e=W[X]}if("e"===e||"E"===e)if(a+=W[X++],e=W[X],("+"===e||"-"===e)&&(a+=W[X++]),c(W.charCodeAt(X)))for(;c(W.charCodeAt(X));)a+=W[X++];else s({},V.UnexpectedToken,"ILLEGAL");return f(W.charCodeAt(X))&&s({},V.UnexpectedToken,"ILLEGAL"),{type:S.NumericLiteral,value:parseFloat(a),range:[d,X]}}function n(){var a,c,d,f="",g=!1;for(a=W[X],b("'"===a||'"'===a,"String literal must starts with a quote"),c=X,++X;Y>X;){if(d=W[X++],d===a){a="";break}if("\\"===d)if(d=W[X++],d&&e(d.charCodeAt(0)))"\r"===d&&"\n"===W[X]&&++X;else switch(d){case"n":f+="\n";break;case"r":f+="\r";break;case"t":f+="	";break;case"b":f+="\b";break;case"f":f+="\f";break;case"v":f+="";break;default:f+=d}else{if(e(d.charCodeAt(0)))break;f+=d}}return""!==a&&s({},V.UnexpectedToken,"ILLEGAL"),{type:S.StringLiteral,value:f,octal:g,range:[c,X]}}function o(a){return a.type===S.Identifier||a.type===S.Keyword||a.type===S.BooleanLiteral||a.type===S.NullLiteral}function p(){var a;return i(),X>=Y?{type:S.EOF,range:[X,X]}:(a=W.charCodeAt(X),40===a||41===a||58===a?l():39===a||34===a?n():f(a)?k():46===a?c(W.charCodeAt(X+1))?m():l():c(a)?m():l())}function q(){var a;return a=$,X=a.range[1],$=p(),X=a.range[1],a}function r(){var a;a=X,$=p(),X=a}function s(a,c){var d,e=Array.prototype.slice.call(arguments,2),f=c.replace(/%(\d)/g,function(a,c){return b(c<e.length,"Message reference must be in range"),e[c]});throw d=new Error(f),d.index=X,d.description=f,d}function t(a){s(a,V.UnexpectedToken,a.value)}function u(a){var b=q();(b.type!==S.Punctuator||b.value!==a)&&t(b)}function v(a){return $.type===S.Punctuator&&$.value===a}function w(a){return $.type===S.Keyword&&$.value===a}function x(){var a=[];for(u("[");!v("]");)v(",")?(q(),a.push(null)):(a.push(bb()),v("]")||u(","));return u("]"),Z.createArrayExpression(a)}function y(){var a;return i(),a=q(),a.type===S.StringLiteral||a.type===S.NumericLiteral?Z.createLiteral(a):Z.createIdentifier(a.value)}function z(){var a,b;return a=$,i(),(a.type===S.EOF||a.type===S.Punctuator)&&t(a),b=y(),u(":"),Z.createProperty("init",b,bb())}function A(){var a=[];for(u("{");!v("}");)a.push(z()),v("}")||u(",");return u("}"),Z.createObjectExpression(a)}function B(){var a;return u("("),a=bb(),u(")"),a}function C(){var a,b,c;return v("(")?B():(a=$.type,a===S.Identifier?c=Z.createIdentifier(q().value):a===S.StringLiteral||a===S.NumericLiteral?c=Z.createLiteral(q()):a===S.Keyword?w("this")&&(q(),c=Z.createThisExpression()):a===S.BooleanLiteral?(b=q(),b.value="true"===b.value,c=Z.createLiteral(b)):a===S.NullLiteral?(b=q(),b.value=null,c=Z.createLiteral(b)):v("[")?c=x():v("{")&&(c=A()),c?c:void t(q()))}function D(){var a=[];if(u("("),!v(")"))for(;Y>X&&(a.push(bb()),!v(")"));)u(",");return u(")"),a}function E(){var a;return a=q(),o(a)||t(a),Z.createIdentifier(a.value)}function F(){return u("."),E()}function G(){var a;return u("["),a=bb(),u("]"),a}function H(){var a,b;for(a=C();v(".")||v("[");)v("[")?(b=G(),a=Z.createMemberExpression("[",a,b)):(b=F(),a=Z.createMemberExpression(".",a,b));return a}function I(){var a,b;return $.type!==S.Punctuator&&$.type!==S.Keyword?b=ab():v("+")||v("-")||v("!")?(a=q(),b=I(),b=Z.createUnaryExpression(a.value,b)):w("delete")||w("void")||w("typeof")?s({},V.UnexpectedToken):b=ab(),b}function J(a){var b=0;if(a.type!==S.Punctuator&&a.type!==S.Keyword)return 0;switch(a.value){case"||":b=1;break;case"&&":b=2;break;case"==":case"!=":case"===":case"!==":b=6;break;case"<":case">":case"<=":case">=":case"instanceof":b=7;break;case"in":b=7;break;case"+":case"-":b=9;break;case"*":case"/":case"%":b=11}return b}function K(){var a,b,c,d,e,f,g,h;if(g=I(),b=$,c=J(b),0===c)return g;for(b.prec=c,q(),e=I(),d=[g,b,e];(c=J($))>0;){for(;d.length>2&&c<=d[d.length-2].prec;)e=d.pop(),f=d.pop().value,g=d.pop(),a=Z.createBinaryExpression(f,g,e),d.push(a);b=q(),b.prec=c,d.push(b),a=I(),d.push(a)}for(h=d.length-1,a=d[h];h>1;)a=Z.createBinaryExpression(d[h-1].value,d[h-2],a),h-=2;return a}function L(){var a,b,c;return a=K(),v("?")&&(q(),b=L(),u(":"),c=L(),a=Z.createConditionalExpression(a,b,c)),a}function M(){var a,b;return a=q(),a.type!==S.Identifier&&t(a),b=v("(")?D():[],Z.createFilter(a.value,b)}function N(){for(;v("|");)q(),M()}function O(){i(),r();var a=bb();a&&(","===$.value||"in"==$.value&&a.type===U.Identifier?Q(a):(N(),"as"===$.value?P(a):Z.createTopLevel(a))),$.type!==S.EOF&&t($)}function P(a){q();var b=q().value;Z.createAsExpression(a,b)}function Q(a){var b;","===$.value&&(q(),$.type!==S.Identifier&&t($),b=q().value),q();var c=bb();N(),Z.createInExpression(a.name,b,c)}function R(a,b){return Z=b,W=a,X=0,Y=W.length,$=null,_={labelSet:{}},O()}var S,T,U,V,W,X,Y,Z,$,_;S={BooleanLiteral:1,EOF:2,Identifier:3,Keyword:4,NullLiteral:5,NumericLiteral:6,Punctuator:7,StringLiteral:8},T={},T[S.BooleanLiteral]="Boolean",T[S.EOF]="<end>",T[S.Identifier]="Identifier",T[S.Keyword]="Keyword",T[S.NullLiteral]="Null",T[S.NumericLiteral]="Numeric",T[S.Punctuator]="Punctuator",T[S.StringLiteral]="String",U={ArrayExpression:"ArrayExpression",BinaryExpression:"BinaryExpression",CallExpression:"CallExpression",ConditionalExpression:"ConditionalExpression",EmptyStatement:"EmptyStatement",ExpressionStatement:"ExpressionStatement",Identifier:"Identifier",Literal:"Literal",LabeledStatement:"LabeledStatement",LogicalExpression:"LogicalExpression",MemberExpression:"MemberExpression",ObjectExpression:"ObjectExpression",Program:"Program",Property:"Property",ThisExpression:"ThisExpression",UnaryExpression:"UnaryExpression"},V={UnexpectedToken:"Unexpected token %0",UnknownLabel:"Undefined label '%0'",Redeclaration:"%0 '%1' has already been declared"};var ab=H,bb=L;a.esprima={parse:R}}(this),function(a){"use strict";function b(a,b,d,e){var f;try{if(f=c(a),f.scopeIdent&&(d.nodeType!==Node.ELEMENT_NODE||"TEMPLATE"!==d.tagName||"bind"!==b&&"repeat"!==b))throw Error("as and in can only be used within <template bind/repeat>")}catch(g){return void console.error("Invalid expression syntax: "+a,g)}return function(a,b,c){var d=f.getBinding(a,e,c);return f.scopeIdent&&d&&(b.polymerExpressionScopeIdent_=f.scopeIdent,f.indexIdent&&(b.polymerExpressionIndexIdent_=f.indexIdent)),d}}function c(a){var b=s[a];if(!b){var c=new j;esprima.parse(a,c),b=new l(c),s[a]=b}return b}function d(a){this.value=a,this.valueFn_=void 0}function e(a){this.name=a,this.path=Path.get(a)}function f(a,b,c){"["==c&&b instanceof d&&Path.get(b.value).valid&&(c=".",b=new e(b.value)),this.dynamicDeps="function"==typeof a||a.dynamic,this.dynamic="function"==typeof b||b.dynamic||"["==c,this.simplePath=!this.dynamic&&!this.dynamicDeps&&b instanceof e&&(a instanceof f||a instanceof e),this.object=this.simplePath?a:i(a),this.property="."==c?b:i(b)}function g(a,b){this.name=a,this.args=[];for(var c=0;c<b.length;c++)this.args[c]=i(b[c])}function h(){throw Error("Not Implemented")}function i(a){return"function"==typeof a?a:a.valueFn()}function j(){this.expression=null,this.filters=[],this.deps={},this.currentPath=void 0,this.scopeIdent=void 0,this.indexIdent=void 0,this.dynamicDeps=!1}function k(a){this.value_=a}function l(a){if(this.scopeIdent=a.scopeIdent,this.indexIdent=a.indexIdent,!a.expression)throw Error("No expression found.");this.expression=a.expression,i(this.expression),this.filters=a.filters,this.dynamicDeps=a.dynamicDeps}function m(a){return String(a).replace(/[A-Z]/g,function(a){return"-"+a.toLowerCase()})}function n(a){return"o"===a[0]&&"n"===a[1]&&"-"===a[2]}function o(a,b){for(;a[w]&&!Object.prototype.hasOwnProperty.call(a,b);)a=a[w];return a}function p(a,b){if(0==b.length)return void 0;if(1==b.length)return o(a,b[0]);for(var c=0;null!=a&&c<b.length-1;c++)a=a[b[c]];return a}function q(a,b,c){var d=b.substring(3);return d=v[d]||d,function(b,e,f){function g(){return"{{ "+a+" }}"}var h,i,j;return j="function"==typeof c.resolveEventHandler?function(d){h=h||c.resolveEventHandler(b,a,e),h(d,d.detail,d.currentTarget),Platform&&"function"==typeof Platform.flush&&Platform.flush()}:function(c){h=h||a.getValueFrom(b),i=i||p(b,a,e),h.apply(i,[c,c.detail,c.currentTarget]),Platform&&"function"==typeof Platform.flush&&Platform.flush()},e.addEventListener(d,j),f?void 0:{open:g,discardChanges:g,close:function(){e.removeEventListener(d,j)}}}}function r(){}var s=Object.create(null);d.prototype={valueFn:function(){if(!this.valueFn_){var a=this.value;this.valueFn_=function(){return a}}return this.valueFn_}},e.prototype={valueFn:function(){if(!this.valueFn_){var a=(this.name,this.path);this.valueFn_=function(b,c){return c&&c.addPath(b,a),a.getValueFrom(b)}}return this.valueFn_},setValue:function(a,b){return 1==this.path.length,a=o(a,this.path[0]),this.path.setValueFrom(a,b)}},f.prototype={get fullPath(){if(!this.fullPath_){var a=this.object instanceof e?this.object.name:this.object.fullPath;this.fullPath_=Path.get(a+"."+this.property.name)}return this.fullPath_},valueFn:function(){if(!this.valueFn_){var a=this.object;if(this.simplePath){var b=this.fullPath;this.valueFn_=function(a,c){return c&&c.addPath(a,b),b.getValueFrom(a)}}else if(this.property instanceof e){var b=Path.get(this.property.name);this.valueFn_=function(c,d){var e=a(c,d);return d&&d.addPath(e,b),b.getValueFrom(e)}}else{var c=this.property;this.valueFn_=function(b,d){var e=a(b,d),f=c(b,d);return d&&d.addPath(e,f),e?e[f]:void 0}}}return this.valueFn_},setValue:function(a,b){if(this.simplePath)return this.fullPath.setValueFrom(a,b),b;var c=this.object(a),d=this.property instanceof e?this.property.name:this.property(a);return c[d]=b}},g.prototype={transform:function(a,b,c,d,e){var f=c[this.name],g=d;if(f)g=void 0;else if(f=g[this.name],!f)return void console.error("Cannot find filter: "+this.name);if(b?f=f.toModel:"function"==typeof f.toDOM&&(f=f.toDOM),"function"!=typeof f)return void console.error("No "+(b?"toModel":"toDOM")+" found on"+this.name);for(var h=[a],j=0;j<this.args.length;j++)h[j+1]=i(this.args[j])(d,e);return f.apply(g,h)}};var t={"+":function(a){return+a},"-":function(a){return-a},"!":function(a){return!a}},u={"+":function(a,b){return a+b},"-":function(a,b){return a-b},"*":function(a,b){return a*b},"/":function(a,b){return a/b},"%":function(a,b){return a%b},"<":function(a,b){return b>a},">":function(a,b){return a>b},"<=":function(a,b){return b>=a},">=":function(a,b){return a>=b},"==":function(a,b){return a==b},"!=":function(a,b){return a!=b},"===":function(a,b){return a===b},"!==":function(a,b){return a!==b},"&&":function(a,b){return a&&b},"||":function(a,b){return a||b}};j.prototype={createUnaryExpression:function(a,b){if(!t[a])throw Error("Disallowed operator: "+a);return b=i(b),function(c,d){return t[a](b(c,d))}},createBinaryExpression:function(a,b,c){if(!u[a])throw Error("Disallowed operator: "+a);return b=i(b),c=i(c),function(d,e){return u[a](b(d,e),c(d,e))}},createConditionalExpression:function(a,b,c){return a=i(a),b=i(b),c=i(c),function(d,e){return a(d,e)?b(d,e):c(d,e)}},createIdentifier:function(a){var b=new e(a);return b.type="Identifier",b},createMemberExpression:function(a,b,c){var d=new f(b,c,a);return d.dynamicDeps&&(this.dynamicDeps=!0),d},createLiteral:function(a){return new d(a.value)},createArrayExpression:function(a){for(var b=0;b<a.length;b++)a[b]=i(a[b]);return function(b,c){for(var d=[],e=0;e<a.length;e++)d.push(a[e](b,c));return d}},createProperty:function(a,b,c){return{key:b instanceof e?b.name:b.value,value:c}},createObjectExpression:function(a){for(var b=0;b<a.length;b++)a[b].value=i(a[b].value);return function(b,c){for(var d={},e=0;e<a.length;e++)d[a[e].key]=a[e].value(b,c);return d}},createFilter:function(a,b){this.filters.push(new g(a,b))},createAsExpression:function(a,b){this.expression=a,this.scopeIdent=b},createInExpression:function(a,b,c){this.expression=c,this.scopeIdent=a,this.indexIdent=b},createTopLevel:function(a){this.expression=a},createThisExpression:h},k.prototype={open:function(){return this.value_},discardChanges:function(){return this.value_},deliver:function(){},close:function(){}},l.prototype={getBinding:function(a,b,c){function d(){g.dynamicDeps&&f.startReset();var c=g.getValue(a,g.dynamicDeps?f:void 0,b);return g.dynamicDeps&&f.finishReset(),c}function e(c){return g.setValue(a,c,b),c}if(c)return this.getValue(a,void 0,b);var f=new CompoundObserver;this.getValue(a,f,b);var g=this;return new ObserverTransform(f,d,e,!0)},getValue:function(a,b,c){for(var d=i(this.expression)(a,b),e=0;e<this.filters.length;e++)d=this.filters[e].transform(d,!1,c,a,b);return d},setValue:function(a,b,c){for(var d=this.filters?this.filters.length:0;d-->0;)b=this.filters[d].transform(b,!0,c,a);return this.expression.setValue?this.expression.setValue(a,b):void 0}};var v={};["webkitAnimationStart","webkitAnimationEnd","webkitTransitionEnd","DOMFocusOut","DOMFocusIn","DOMMouseScroll"].forEach(function(a){v[a.toLowerCase()]=a});var w="@"+Math.random().toString(36).slice(2);r.prototype={styleObject:function(a){var b=[];for(var c in a)b.push(m(c)+": "+a[c]);return b.join("; ")},tokenList:function(a){var b=[];for(var c in a)a[c]&&b.push(c);return b.join(" ")},prepareInstancePositionChanged:function(a){var b=a.polymerExpressionIndexIdent_;if(b)return function(a,c){a.model[b]=c}},prepareBinding:function(a,c,d){var e=Path.get(a);if(n(c))return e.valid?q(e,c,this):void console.error("on-* bindings must be simple path expressions");{if(!e.valid)return b(a,c,d,this);if(1==e.length)return function(a,b,c){if(c)return e.getValueFrom(a);var d=o(a,e[0]);return new PathObserver(d,e)}}},prepareInstanceModel:function(a){var b=a.polymerExpressionScopeIdent_;if(b){var c=a.templateInstance?a.templateInstance.model:a.model,d=a.polymerExpressionIndexIdent_;return function(a){var e=Object.create(c);return e[b]=a,e[d]=void 0,e[w]=c,e}}}},a.PolymerExpressions=r,a.exposeGetExpression&&(a.getExpression_=c),a.PolymerExpressions.prepareEventBinding=q}(this),function(a){function b(){e||(e=!0,a.endOfMicrotask(function(){e=!1,logFlags.data&&console.group("Platform.flush()"),a.performMicrotaskCheckpoint(),logFlags.data&&console.groupEnd()}))}var c=document.createElement("style");c.textContent="template {display: none !important;} /* injected by platform.js */";var d=document.querySelector("head");d.insertBefore(c,d.firstChild);var e,f=125;if(window.addEventListener("WebComponentsReady",function(){b(),Observer.hasObjectObserve||(a.flushPoll=setInterval(b,f))}),window.CustomElements&&!CustomElements.useNative){var g=Document.prototype.importNode;Document.prototype.importNode=function(a,b){var c=g.call(this,a,b);return CustomElements.upgradeAll(c),c}}a.flush=b}(window.Platform);
+//# sourceMappingURL=platform.js.map
\ No newline at end of file
diff --git a/pkg/web_components/lib/platform.js.map b/pkg/web_components/lib/platform.js.map
new file mode 100644
index 0000000..c8af66e
--- /dev/null
+++ b/pkg/web_components/lib/platform.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"platform.js","sources":["../PointerGestures/src/PointerGestureEvent.js","../WeakMap/weakmap.js","../observe-js/src/observe.js","build/if-poly.js","../ShadowDOM/src/wrappers.js","../ShadowDOM/src/microtask.js","../ShadowDOM/src/MutationObserver.js","../ShadowDOM/src/wrappers/events.js","../ShadowDOM/src/wrappers/NodeList.js","../ShadowDOM/src/wrappers/Node.js","../ShadowDOM/src/querySelector.js","../ShadowDOM/src/wrappers/node-interfaces.js","../ShadowDOM/src/wrappers/CharacterData.js","../ShadowDOM/src/wrappers/Text.js","../ShadowDOM/src/wrappers/Element.js","../ShadowDOM/src/wrappers/HTMLElement.js","../ShadowDOM/src/wrappers/HTMLCanvasElement.js","../ShadowDOM/src/wrappers/HTMLContentElement.js","../ShadowDOM/src/wrappers/HTMLImageElement.js","../ShadowDOM/src/wrappers/HTMLShadowElement.js","../ShadowDOM/src/wrappers/HTMLTemplateElement.js","../ShadowDOM/src/wrappers/HTMLMediaElement.js","../ShadowDOM/src/wrappers/HTMLAudioElement.js","../ShadowDOM/src/wrappers/HTMLOptionElement.js","../ShadowDOM/src/wrappers/HTMLUnknownElement.js","../ShadowDOM/src/wrappers/SVGElement.js","../ShadowDOM/src/wrappers/SVGUseElement.js","../ShadowDOM/src/wrappers/SVGElementInstance.js","../ShadowDOM/src/wrappers/CanvasRenderingContext2D.js","../ShadowDOM/src/wrappers/WebGLRenderingContext.js","../ShadowDOM/src/wrappers/Range.js","../ShadowDOM/src/wrappers/generic.js","../ShadowDOM/src/wrappers/ShadowRoot.js","../ShadowDOM/src/ShadowRenderer.js","../ShadowDOM/src/wrappers/elements-with-form-property.js","../ShadowDOM/src/wrappers/Selection.js","../ShadowDOM/src/wrappers/Document.js","../ShadowDOM/src/wrappers/Window.js","../ShadowDOM/src/wrappers/override-constructors.js","src/patches-shadowdom-polyfill.js","src/ShadowCSS.js","src/patches-shadowdom-native.js","../URL/url.js","src/lang.js","src/dom.js","src/template.js","src/inspector.js","src/unresolved.js","src/module.js","src/microtask.js","src/url.js","../MutationObservers/MutationObserver.js","../HTMLImports/src/scope.js","../HTMLImports/src/Loader.js","../HTMLImports/src/Parser.js","../HTMLImports/src/HTMLImports.js","../HTMLImports/src/Observer.js","../HTMLImports/src/boot.js","../CustomElements/src/scope.js","../CustomElements/src/Observer.js","../CustomElements/src/CustomElements.js","../CustomElements/src/Parser.js","../CustomElements/src/boot.js","src/patches-custom-elements.js","src/loader.js","../PointerEvents/src/boot.js","../PointerEvents/src/touch-action.js","../PointerEvents/src/PointerEvent.js","../PointerEvents/src/pointermap.js","../PointerEvents/src/dispatcher.js","../PointerEvents/src/installer.js","../PointerEvents/src/mouse.js","../PointerEvents/src/touch.js","../PointerEvents/src/ms.js","../PointerEvents/src/platform-events.js","../PointerEvents/src/capture.js","../PointerGestures/src/initialize.js","../PointerGestures/src/pointermap.js","../PointerGestures/src/dispatcher.js","../PointerGestures/src/hold.js","../PointerGestures/src/track.js","../PointerGestures/src/flick.js","../PointerGestures/src/pinch.js","../PointerGestures/src/tap.js","../NodeBind/src/NodeBind.js","../TemplateBinding/src/TemplateBinding.js","../polymer-expressions/third_party/esprima/esprima.js","../polymer-expressions/src/polymer-expressions.js","src/patches-mdv.js"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * PointerGestureEvent is the constructor for all PointerGesture events.\n *\n * @module PointerGestures\n * @class PointerGestureEvent\n * @extends UIEvent\n * @constructor\n * @param {String} inType Event type\n * @param {Object} [inDict] Dictionary of properties to initialize on the event\n */\n\nfunction PointerGestureEvent(inType, inDict) {\n  var dict = inDict || {};\n  var e = document.createEvent('Event');\n  var props = {\n    bubbles: Boolean(dict.bubbles) === dict.bubbles || true,\n    cancelable: Boolean(dict.cancelable) === dict.cancelable || true\n  };\n\n  e.initEvent(inType, props.bubbles, props.cancelable);\n\n  var keys = Object.keys(dict), k;\n  for (var i = 0; i < keys.length; i++) {\n    k = keys[i];\n    e[k] = dict[k];\n  }\n\n  e.preventTap = this.preventTap;\n\n  return e;\n}\n\n/**\n * Allows for any gesture to prevent the tap gesture.\n *\n * @method preventTap\n */\nPointerGestureEvent.prototype.preventTap = function() {\n  this.tapPrevented = true;\n};\n\n","/*\n * Copyright 2012 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nif (typeof WeakMap === 'undefined') {\n  (function() {\n    var defineProperty = Object.defineProperty;\n    var counter = Date.now() % 1e9;\n\n    var WeakMap = function() {\n      this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__');\n    };\n\n    WeakMap.prototype = {\n      set: function(key, value) {\n        var entry = key[this.name];\n        if (entry && entry[0] === key)\n          entry[1] = value;\n        else\n          defineProperty(key, this.name, {value: [key, value], writable: true});\n      },\n      get: function(key) {\n        var entry;\n        return (entry = key[this.name]) && entry[0] === key ?\n            entry[1] : undefined;\n      },\n      delete: function(key) {\n        this.set(key, undefined);\n      }\n    };\n\n    window.WeakMap = WeakMap;\n  })();\n}\n","// Copyright 2012 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n(function(global) {\n  'use strict';\n\n  var PROP_ADD_TYPE = 'add';\n  var PROP_UPDATE_TYPE = 'update';\n  var PROP_RECONFIGURE_TYPE = 'reconfigure';\n  var PROP_DELETE_TYPE = 'delete';\n  var ARRAY_SPLICE_TYPE = 'splice';\n\n  // Detect and do basic sanity checking on Object/Array.observe.\n  function detectObjectObserve() {\n    if (typeof Object.observe !== 'function' ||\n        typeof Array.observe !== 'function') {\n      return false;\n    }\n\n    var records = [];\n\n    function callback(recs) {\n      records = recs;\n    }\n\n    var test = {};\n    Object.observe(test, callback);\n    test.id = 1;\n    test.id = 2;\n    delete test.id;\n    Object.deliverChangeRecords(callback);\n    if (records.length !== 3)\n      return false;\n\n    // TODO(rafaelw): Remove this when new change record type names make it to\n    // chrome release.\n    if (records[0].type == 'new' &&\n        records[1].type == 'updated' &&\n        records[2].type == 'deleted') {\n      PROP_ADD_TYPE = 'new';\n      PROP_UPDATE_TYPE = 'updated';\n      PROP_RECONFIGURE_TYPE = 'reconfigured';\n      PROP_DELETE_TYPE = 'deleted';\n    } else if (records[0].type != 'add' ||\n               records[1].type != 'update' ||\n               records[2].type != 'delete') {\n      console.error('Unexpected change record names for Object.observe. ' +\n                    'Using dirty-checking instead');\n      return false;\n    }\n    Object.unobserve(test, callback);\n\n    test = [0];\n    Array.observe(test, callback);\n    test[1] = 1;\n    test.length = 0;\n    Object.deliverChangeRecords(callback);\n    if (records.length != 2)\n      return false;\n    if (records[0].type != ARRAY_SPLICE_TYPE ||\n        records[1].type != ARRAY_SPLICE_TYPE) {\n      return false;\n    }\n    Array.unobserve(test, callback);\n\n    return true;\n  }\n\n  var hasObserve = detectObjectObserve();\n\n  function detectEval() {\n    // don't test for eval if document has CSP securityPolicy object and we can see that\n    // eval is not supported. This avoids an error message in console even when the exception\n    // is caught\n    if (global.document &&\n        'securityPolicy' in global.document &&\n        !global.document.securityPolicy.allowsEval) {\n      return false;\n    }\n\n    try {\n      var f = new Function('', 'return true;');\n      return f();\n    } catch (ex) {\n      return false;\n    }\n  }\n\n  var hasEval = detectEval();\n\n  function isIndex(s) {\n    return +s === s >>> 0;\n  }\n\n  function toNumber(s) {\n    return +s;\n  }\n\n  function isObject(obj) {\n    return obj === Object(obj);\n  }\n\n  var numberIsNaN = global.Number.isNaN || function isNaN(value) {\n    return typeof value === 'number' && global.isNaN(value);\n  }\n\n  function areSameValue(left, right) {\n    if (left === right)\n      return left !== 0 || 1 / left === 1 / right;\n    if (numberIsNaN(left) && numberIsNaN(right))\n      return true;\n\n    return left !== left && right !== right;\n  }\n\n  var createObject = ('__proto__' in {}) ?\n    function(obj) { return obj; } :\n    function(obj) {\n      var proto = obj.__proto__;\n      if (!proto)\n        return obj;\n      var newObject = Object.create(proto);\n      Object.getOwnPropertyNames(obj).forEach(function(name) {\n        Object.defineProperty(newObject, name,\n                             Object.getOwnPropertyDescriptor(obj, name));\n      });\n      return newObject;\n    };\n\n  var identStart = '[\\$_a-zA-Z]';\n  var identPart = '[\\$_a-zA-Z0-9]';\n  var ident = identStart + '+' + identPart + '*';\n  var elementIndex = '(?:[0-9]|[1-9]+[0-9]+)';\n  var identOrElementIndex = '(?:' + ident + '|' + elementIndex + ')';\n  var path = '(?:' + identOrElementIndex + ')(?:\\\\s*\\\\.\\\\s*' + identOrElementIndex + ')*';\n  var pathRegExp = new RegExp('^' + path + '$');\n\n  function isPathValid(s) {\n    if (typeof s != 'string')\n      return false;\n    s = s.trim();\n\n    if (s == '')\n      return true;\n\n    if (s[0] == '.')\n      return false;\n\n    return pathRegExp.test(s);\n  }\n\n  var constructorIsPrivate = {};\n\n  function Path(s, privateToken) {\n    if (privateToken !== constructorIsPrivate)\n      throw Error('Use Path.get to retrieve path objects');\n\n    if (s.trim() == '')\n      return this;\n\n    if (isIndex(s)) {\n      this.push(s);\n      return this;\n    }\n\n    s.split(/\\s*\\.\\s*/).filter(function(part) {\n      return part;\n    }).forEach(function(part) {\n      this.push(part);\n    }, this);\n\n    if (hasEval && this.length) {\n      this.getValueFrom = this.compiledGetValueFromFn();\n    }\n  }\n\n  // TODO(rafaelw): Make simple LRU cache\n  var pathCache = {};\n\n  function getPath(pathString) {\n    if (pathString instanceof Path)\n      return pathString;\n\n    if (pathString == null)\n      pathString = '';\n\n    if (typeof pathString !== 'string')\n      pathString = String(pathString);\n\n    var path = pathCache[pathString];\n    if (path)\n      return path;\n    if (!isPathValid(pathString))\n      return invalidPath;\n    var path = new Path(pathString, constructorIsPrivate);\n    pathCache[pathString] = path;\n    return path;\n  }\n\n  Path.get = getPath;\n\n  Path.prototype = createObject({\n    __proto__: [],\n    valid: true,\n\n    toString: function() {\n      return this.join('.');\n    },\n\n    getValueFrom: function(obj, directObserver) {\n      for (var i = 0; i < this.length; i++) {\n        if (obj == null)\n          return;\n        obj = obj[this[i]];\n      }\n      return obj;\n    },\n\n    iterateObjects: function(obj, observe) {\n      for (var i = 0; i < this.length; i++) {\n        if (i)\n          obj = obj[this[i - 1]];\n        if (!obj)\n          return;\n        observe(obj);\n      }\n    },\n\n    compiledGetValueFromFn: function() {\n      var accessors = this.map(function(ident) {\n        return isIndex(ident) ? '[\"' + ident + '\"]' : '.' + ident;\n      });\n\n      var str = '';\n      var pathString = 'obj';\n      str += 'if (obj != null';\n      var i = 0;\n      for (; i < (this.length - 1); i++) {\n        var ident = this[i];\n        pathString += accessors[i];\n        str += ' &&\\n     ' + pathString + ' != null';\n      }\n      str += ')\\n';\n\n      pathString += accessors[i];\n\n      str += '  return ' + pathString + ';\\nelse\\n  return undefined;';\n      return new Function('obj', str);\n    },\n\n    setValueFrom: function(obj, value) {\n      if (!this.length)\n        return false;\n\n      for (var i = 0; i < this.length - 1; i++) {\n        if (!isObject(obj))\n          return false;\n        obj = obj[this[i]];\n      }\n\n      if (!isObject(obj))\n        return false;\n\n      obj[this[i]] = value;\n      return true;\n    }\n  });\n\n  var invalidPath = new Path('', constructorIsPrivate);\n  invalidPath.valid = false;\n  invalidPath.getValueFrom = invalidPath.setValueFrom = function() {};\n\n  var MAX_DIRTY_CHECK_CYCLES = 1000;\n\n  function dirtyCheck(observer) {\n    var cycles = 0;\n    while (cycles < MAX_DIRTY_CHECK_CYCLES && observer.check_()) {\n      cycles++;\n    }\n    if (global.testingExposeCycleCount)\n      global.dirtyCheckCycleCount = cycles;\n\n    return cycles > 0;\n  }\n\n  function objectIsEmpty(object) {\n    for (var prop in object)\n      return false;\n    return true;\n  }\n\n  function diffIsEmpty(diff) {\n    return objectIsEmpty(diff.added) &&\n           objectIsEmpty(diff.removed) &&\n           objectIsEmpty(diff.changed);\n  }\n\n  function diffObjectFromOldObject(object, oldObject) {\n    var added = {};\n    var removed = {};\n    var changed = {};\n\n    for (var prop in oldObject) {\n      var newValue = object[prop];\n\n      if (newValue !== undefined && newValue === oldObject[prop])\n        continue;\n\n      if (!(prop in object)) {\n        removed[prop] = undefined;\n        continue;\n      }\n\n      if (newValue !== oldObject[prop])\n        changed[prop] = newValue;\n    }\n\n    for (var prop in object) {\n      if (prop in oldObject)\n        continue;\n\n      added[prop] = object[prop];\n    }\n\n    if (Array.isArray(object) && object.length !== oldObject.length)\n      changed.length = object.length;\n\n    return {\n      added: added,\n      removed: removed,\n      changed: changed\n    };\n  }\n\n  var eomTasks = [];\n  function runEOMTasks() {\n    if (!eomTasks.length)\n      return false;\n\n    for (var i = 0; i < eomTasks.length; i++) {\n      eomTasks[i]();\n    }\n    eomTasks.length = 0;\n    return true;\n  }\n\n  var runEOM = hasObserve ? (function(){\n    var eomObj = { pingPong: true };\n    var eomRunScheduled = false;\n\n    Object.observe(eomObj, function() {\n      runEOMTasks();\n      eomRunScheduled = false;\n    });\n\n    return function(fn) {\n      eomTasks.push(fn);\n      if (!eomRunScheduled) {\n        eomRunScheduled = true;\n        eomObj.pingPong = !eomObj.pingPong;\n      }\n    };\n  })() :\n  (function() {\n    return function(fn) {\n      eomTasks.push(fn);\n    };\n  })();\n\n  var observedObjectCache = [];\n\n  function newObservedObject() {\n    var observer;\n    var object;\n    var discardRecords = false;\n    var first = true;\n\n    function callback(records) {\n      if (observer && observer.state_ === OPENED && !discardRecords)\n        observer.check_(records);\n    }\n\n    return {\n      open: function(obs) {\n        if (observer)\n          throw Error('ObservedObject in use');\n\n        if (!first)\n          Object.deliverChangeRecords(callback);\n\n        observer = obs;\n        first = false;\n      },\n      observe: function(obj, arrayObserve) {\n        object = obj;\n        if (arrayObserve)\n          Array.observe(object, callback);\n        else\n          Object.observe(object, callback);\n      },\n      deliver: function(discard) {\n        discardRecords = discard;\n        Object.deliverChangeRecords(callback);\n        discardRecords = false;\n      },\n      close: function() {\n        observer = undefined;\n        Object.unobserve(object, callback);\n        observedObjectCache.push(this);\n      }\n    };\n  }\n\n  function getObservedObject(observer, object, arrayObserve) {\n    var dir = observedObjectCache.pop() || newObservedObject();\n    dir.open(observer);\n    dir.observe(object, arrayObserve);\n    return dir;\n  }\n\n  var emptyArray = [];\n  var observedSetCache = [];\n\n  function newObservedSet() {\n    var observers = [];\n    var observerCount = 0;\n    var objects = [];\n    var toRemove = emptyArray;\n    var resetNeeded = false;\n    var resetScheduled = false;\n\n    function observe(obj) {\n      if (!isObject(obj))\n        return;\n\n      var index = toRemove.indexOf(obj);\n      if (index >= 0) {\n        toRemove[index] = undefined;\n        objects.push(obj);\n      } else if (objects.indexOf(obj) < 0) {\n        objects.push(obj);\n        Object.observe(obj, callback);\n      }\n\n      observe(Object.getPrototypeOf(obj));\n    }\n\n    function reset() {\n      resetScheduled = false;\n      if (!resetNeeded)\n        return;\n\n      var objs = toRemove === emptyArray ? [] : toRemove;\n      toRemove = objects;\n      objects = objs;\n\n      var observer;\n      for (var id in observers) {\n        observer = observers[id];\n        if (!observer || observer.state_ != OPENED)\n          continue;\n\n        observer.iterateObjects_(observe);\n      }\n\n      for (var i = 0; i < toRemove.length; i++) {\n        var obj = toRemove[i];\n        if (obj)\n          Object.unobserve(obj, callback);\n      }\n\n      toRemove.length = 0;\n    }\n\n    function scheduleReset() {\n      if (resetScheduled)\n        return;\n\n      resetNeeded = true;\n      resetScheduled = true;\n      runEOM(reset);\n    }\n\n    function callback() {\n      var observer;\n\n      for (var id in observers) {\n        observer = observers[id];\n        if (!observer || observer.state_ != OPENED)\n          continue;\n\n        observer.check_();\n      }\n\n      scheduleReset();\n    }\n\n    var record = {\n      object: undefined,\n      objects: objects,\n      open: function(obs) {\n        observers[obs.id_] = obs;\n        observerCount++;\n        obs.iterateObjects_(observe);\n      },\n      close: function(obs) {\n        var anyLeft = false;\n\n        observers[obs.id_] = undefined;\n        observerCount--;\n\n        if (observerCount) {\n          scheduleReset();\n          return;\n        }\n        resetNeeded = false;\n\n        for (var i = 0; i < objects.length; i++) {\n          Object.unobserve(objects[i], callback);\n          Observer.unobservedCount++;\n        }\n\n        observers.length = 0;\n        objects.length = 0;\n        observedSetCache.push(this);\n      },\n      reset: scheduleReset\n    };\n\n    return record;\n  }\n\n  var lastObservedSet;\n\n  function getObservedSet(observer, obj) {\n    if (!lastObservedSet || lastObservedSet.object !== obj) {\n      lastObservedSet = observedSetCache.pop() || newObservedSet();\n      lastObservedSet.object = obj;\n    }\n    lastObservedSet.open(observer);\n    return lastObservedSet;\n  }\n\n  var UNOPENED = 0;\n  var OPENED = 1;\n  var CLOSED = 2;\n  var RESETTING = 3;\n\n  var nextObserverId = 1;\n\n  function Observer() {\n    this.state_ = UNOPENED;\n    this.callback_ = undefined;\n    this.target_ = undefined; // TODO(rafaelw): Should be WeakRef\n    this.directObserver_ = undefined;\n    this.value_ = undefined;\n    this.id_ = nextObserverId++;\n  }\n\n  Observer.prototype = {\n    open: function(callback, target) {\n      if (this.state_ != UNOPENED)\n        throw Error('Observer has already been opened.');\n\n      addToAll(this);\n      this.callback_ = callback;\n      this.target_ = target;\n      this.state_ = OPENED;\n      this.connect_();\n      return this.value_;\n    },\n\n    close: function() {\n      if (this.state_ != OPENED)\n        return;\n\n      removeFromAll(this);\n      this.state_ = CLOSED;\n      this.disconnect_();\n      this.value_ = undefined;\n      this.callback_ = undefined;\n      this.target_ = undefined;\n    },\n\n    deliver: function() {\n      if (this.state_ != OPENED)\n        return;\n\n      dirtyCheck(this);\n    },\n\n    report_: function(changes) {\n      try {\n        this.callback_.apply(this.target_, changes);\n      } catch (ex) {\n        Observer._errorThrownDuringCallback = true;\n        console.error('Exception caught during observer callback: ' +\n                       (ex.stack || ex));\n      }\n    },\n\n    discardChanges: function() {\n      this.check_(undefined, true);\n      return this.value_;\n    }\n  }\n\n  var collectObservers = !hasObserve;\n  var allObservers;\n  Observer._allObserversCount = 0;\n\n  if (collectObservers) {\n    allObservers = [];\n  }\n\n  function addToAll(observer) {\n    Observer._allObserversCount++;\n    if (!collectObservers)\n      return;\n\n    allObservers.push(observer);\n  }\n\n  function removeFromAll(observer) {\n    Observer._allObserversCount--;\n  }\n\n  var runningMicrotaskCheckpoint = false;\n\n  var hasDebugForceFullDelivery = typeof Object.deliverAllChangeRecords == 'function';\n\n  global.Platform = global.Platform || {};\n\n  global.Platform.performMicrotaskCheckpoint = function() {\n    if (runningMicrotaskCheckpoint)\n      return;\n\n    if (hasDebugForceFullDelivery) {\n      Object.deliverAllChangeRecords();\n      return;\n    }\n\n    if (!collectObservers)\n      return;\n\n    runningMicrotaskCheckpoint = true;\n\n    var cycles = 0;\n    var anyChanged, toCheck;\n\n    do {\n      cycles++;\n      toCheck = allObservers;\n      allObservers = [];\n      anyChanged = false;\n\n      for (var i = 0; i < toCheck.length; i++) {\n        var observer = toCheck[i];\n        if (observer.state_ != OPENED)\n          continue;\n\n        if (observer.check_())\n          anyChanged = true;\n\n        allObservers.push(observer);\n      }\n      if (runEOMTasks())\n        anyChanged = true;\n    } while (cycles < MAX_DIRTY_CHECK_CYCLES && anyChanged);\n\n    if (global.testingExposeCycleCount)\n      global.dirtyCheckCycleCount = cycles;\n\n    runningMicrotaskCheckpoint = false;\n  };\n\n  if (collectObservers) {\n    global.Platform.clearObservers = function() {\n      allObservers = [];\n    };\n  }\n\n  function ObjectObserver(object) {\n    Observer.call(this);\n    this.value_ = object;\n    this.oldObject_ = undefined;\n  }\n\n  ObjectObserver.prototype = createObject({\n    __proto__: Observer.prototype,\n\n    arrayObserve: false,\n\n    connect_: function(callback, target) {\n      if (hasObserve) {\n        this.directObserver_ = getObservedObject(this, this.value_,\n                                                 this.arrayObserve);\n      } else {\n        this.oldObject_ = this.copyObject(this.value_);\n      }\n\n    },\n\n    copyObject: function(object) {\n      var copy = Array.isArray(object) ? [] : {};\n      for (var prop in object) {\n        copy[prop] = object[prop];\n      };\n      if (Array.isArray(object))\n        copy.length = object.length;\n      return copy;\n    },\n\n    check_: function(changeRecords, skipChanges) {\n      var diff;\n      var oldValues;\n      if (hasObserve) {\n        if (!changeRecords)\n          return false;\n\n        oldValues = {};\n        diff = diffObjectFromChangeRecords(this.value_, changeRecords,\n                                           oldValues);\n      } else {\n        oldValues = this.oldObject_;\n        diff = diffObjectFromOldObject(this.value_, this.oldObject_);\n      }\n\n      if (diffIsEmpty(diff))\n        return false;\n\n      if (!hasObserve)\n        this.oldObject_ = this.copyObject(this.value_);\n\n      this.report_([\n        diff.added || {},\n        diff.removed || {},\n        diff.changed || {},\n        function(property) {\n          return oldValues[property];\n        }\n      ]);\n\n      return true;\n    },\n\n    disconnect_: function() {\n      if (hasObserve) {\n        this.directObserver_.close();\n        this.directObserver_ = undefined;\n      } else {\n        this.oldObject_ = undefined;\n      }\n    },\n\n    deliver: function() {\n      if (this.state_ != OPENED)\n        return;\n\n      if (hasObserve)\n        this.directObserver_.deliver(false);\n      else\n        dirtyCheck(this);\n    },\n\n    discardChanges: function() {\n      if (this.directObserver_)\n        this.directObserver_.deliver(true);\n      else\n        this.oldObject_ = this.copyObject(this.value_);\n\n      return this.value_;\n    }\n  });\n\n  function ArrayObserver(array) {\n    if (!Array.isArray(array))\n      throw Error('Provided object is not an Array');\n    ObjectObserver.call(this, array);\n  }\n\n  ArrayObserver.prototype = createObject({\n\n    __proto__: ObjectObserver.prototype,\n\n    arrayObserve: true,\n\n    copyObject: function(arr) {\n      return arr.slice();\n    },\n\n    check_: function(changeRecords) {\n      var splices;\n      if (hasObserve) {\n        if (!changeRecords)\n          return false;\n        splices = projectArraySplices(this.value_, changeRecords);\n      } else {\n        splices = calcSplices(this.value_, 0, this.value_.length,\n                              this.oldObject_, 0, this.oldObject_.length);\n      }\n\n      if (!splices || !splices.length)\n        return false;\n\n      if (!hasObserve)\n        this.oldObject_ = this.copyObject(this.value_);\n\n      this.report_([splices]);\n      return true;\n    }\n  });\n\n  ArrayObserver.applySplices = function(previous, current, splices) {\n    splices.forEach(function(splice) {\n      var spliceArgs = [splice.index, splice.removed.length];\n      var addIndex = splice.index;\n      while (addIndex < splice.index + splice.addedCount) {\n        spliceArgs.push(current[addIndex]);\n        addIndex++;\n      }\n\n      Array.prototype.splice.apply(previous, spliceArgs);\n    });\n  };\n\n  function PathObserver(object, path) {\n    Observer.call(this);\n\n    this.object_ = object;\n    this.path_ = path instanceof Path ? path : getPath(path);\n    this.directObserver_ = undefined;\n  }\n\n  PathObserver.prototype = createObject({\n    __proto__: Observer.prototype,\n\n    connect_: function() {\n      if (hasObserve)\n        this.directObserver_ = getObservedSet(this, this.object_);\n\n      this.check_(undefined, true);\n    },\n\n    disconnect_: function() {\n      this.value_ = undefined;\n\n      if (this.directObserver_) {\n        this.directObserver_.close(this);\n        this.directObserver_ = undefined;\n      }\n    },\n\n    iterateObjects_: function(observe) {\n      this.path_.iterateObjects(this.object_, observe);\n    },\n\n    check_: function(changeRecords, skipChanges) {\n      var oldValue = this.value_;\n      this.value_ = this.path_.getValueFrom(this.object_);\n      if (skipChanges || areSameValue(this.value_, oldValue))\n        return false;\n\n      this.report_([this.value_, oldValue]);\n      return true;\n    },\n\n    setValue: function(newValue) {\n      if (this.path_)\n        this.path_.setValueFrom(this.object_, newValue);\n    }\n  });\n\n  function CompoundObserver() {\n    Observer.call(this);\n\n    this.value_ = [];\n    this.directObserver_ = undefined;\n    this.observed_ = [];\n  }\n\n  var observerSentinel = {};\n\n  CompoundObserver.prototype = createObject({\n    __proto__: Observer.prototype,\n\n    connect_: function() {\n      this.check_(undefined, true);\n\n      if (!hasObserve)\n        return;\n\n      var object;\n      var needsDirectObserver = false;\n      for (var i = 0; i < this.observed_.length; i += 2) {\n        object = this.observed_[i]\n        if (object !== observerSentinel) {\n          needsDirectObserver = true;\n          break;\n        }\n      }\n\n      if (this.directObserver_) {\n        if (needsDirectObserver) {\n          this.directObserver_.reset();\n          return;\n        }\n        this.directObserver_.close();\n        this.directObserver_ = undefined;\n        return;\n      }\n\n      if (needsDirectObserver)\n        this.directObserver_ = getObservedSet(this, object);\n    },\n\n    closeObservers_: function() {\n      for (var i = 0; i < this.observed_.length; i += 2) {\n        if (this.observed_[i] === observerSentinel)\n          this.observed_[i + 1].close();\n      }\n      this.observed_.length = 0;\n    },\n\n    disconnect_: function() {\n      this.value_ = undefined;\n\n      if (this.directObserver_) {\n        this.directObserver_.close(this);\n        this.directObserver_ = undefined;\n      }\n\n      this.closeObservers_();\n    },\n\n    addPath: function(object, path) {\n      if (this.state_ != UNOPENED && this.state_ != RESETTING)\n        throw Error('Cannot add paths once started.');\n\n      this.observed_.push(object, path instanceof Path ? path : getPath(path));\n    },\n\n    addObserver: function(observer) {\n      if (this.state_ != UNOPENED && this.state_ != RESETTING)\n        throw Error('Cannot add observers once started.');\n\n      observer.open(this.deliver, this);\n      this.observed_.push(observerSentinel, observer);\n    },\n\n    startReset: function() {\n      if (this.state_ != OPENED)\n        throw Error('Can only reset while open');\n\n      this.state_ = RESETTING;\n      this.closeObservers_();\n    },\n\n    finishReset: function() {\n      if (this.state_ != RESETTING)\n        throw Error('Can only finishReset after startReset');\n      this.state_ = OPENED;\n      this.connect_();\n\n      return this.value_;\n    },\n\n    iterateObjects_: function(observe) {\n      var object;\n      for (var i = 0; i < this.observed_.length; i += 2) {\n        object = this.observed_[i]\n        if (object !== observerSentinel)\n          this.observed_[i + 1].iterateObjects(object, observe)\n      }\n    },\n\n    check_: function(changeRecords, skipChanges) {\n      var oldValues;\n      for (var i = 0; i < this.observed_.length; i += 2) {\n        var pathOrObserver = this.observed_[i+1];\n        var object = this.observed_[i];\n        var value = object === observerSentinel ?\n            pathOrObserver.discardChanges() :\n            pathOrObserver.getValueFrom(object)\n\n        if (skipChanges) {\n          this.value_[i / 2] = value;\n          continue;\n        }\n\n        if (areSameValue(value, this.value_[i / 2]))\n          continue;\n\n        oldValues = oldValues || [];\n        oldValues[i / 2] = this.value_[i / 2];\n        this.value_[i / 2] = value;\n      }\n\n      if (!oldValues)\n        return false;\n\n      // TODO(rafaelw): Having observed_ as the third callback arg here is\n      // pretty lame API. Fix.\n      this.report_([this.value_, oldValues, this.observed_]);\n      return true;\n    }\n  });\n\n  function identFn(value) { return value; }\n\n  function ObserverTransform(observable, getValueFn, setValueFn,\n                             dontPassThroughSet) {\n    this.callback_ = undefined;\n    this.target_ = undefined;\n    this.value_ = undefined;\n    this.observable_ = observable;\n    this.getValueFn_ = getValueFn || identFn;\n    this.setValueFn_ = setValueFn || identFn;\n    // TODO(rafaelw): This is a temporary hack. PolymerExpressions needs this\n    // at the moment because of a bug in it's dependency tracking.\n    this.dontPassThroughSet_ = dontPassThroughSet;\n  }\n\n  ObserverTransform.prototype = {\n    open: function(callback, target) {\n      this.callback_ = callback;\n      this.target_ = target;\n      this.value_ =\n          this.getValueFn_(this.observable_.open(this.observedCallback_, this));\n      return this.value_;\n    },\n\n    observedCallback_: function(value) {\n      value = this.getValueFn_(value);\n      if (areSameValue(value, this.value_))\n        return;\n      var oldValue = this.value_;\n      this.value_ = value;\n      this.callback_.call(this.target_, this.value_, oldValue);\n    },\n\n    discardChanges: function() {\n      this.value_ = this.getValueFn_(this.observable_.discardChanges());\n      return this.value_;\n    },\n\n    deliver: function() {\n      return this.observable_.deliver();\n    },\n\n    setValue: function(value) {\n      value = this.setValueFn_(value);\n      if (!this.dontPassThroughSet_ && this.observable_.setValue)\n        return this.observable_.setValue(value);\n    },\n\n    close: function() {\n      if (this.observable_)\n        this.observable_.close();\n      this.callback_ = undefined;\n      this.target_ = undefined;\n      this.observable_ = undefined;\n      this.value_ = undefined;\n      this.getValueFn_ = undefined;\n      this.setValueFn_ = undefined;\n    }\n  }\n\n  var expectedRecordTypes = {};\n  expectedRecordTypes[PROP_ADD_TYPE] = true;\n  expectedRecordTypes[PROP_UPDATE_TYPE] = true;\n  expectedRecordTypes[PROP_DELETE_TYPE] = true;\n\n  function notifyFunction(object, name) {\n    if (typeof Object.observe !== 'function')\n      return;\n\n    var notifier = Object.getNotifier(object);\n    return function(type, oldValue) {\n      var changeRecord = {\n        object: object,\n        type: type,\n        name: name\n      };\n      if (arguments.length === 2)\n        changeRecord.oldValue = oldValue;\n      notifier.notify(changeRecord);\n    }\n  }\n\n  Observer.defineComputedProperty = function(target, name, observable) {\n    var notify = notifyFunction(target, name);\n    var value = observable.open(function(newValue, oldValue) {\n      value = newValue;\n      if (notify)\n        notify(PROP_UPDATE_TYPE, oldValue);\n    });\n\n    Object.defineProperty(target, name, {\n      get: function() {\n        observable.deliver();\n        return value;\n      },\n      set: function(newValue) {\n        observable.setValue(newValue);\n        return newValue;\n      },\n      configurable: true\n    });\n\n    return {\n      close: function() {\n        observable.close();\n        Object.defineProperty(target, name, {\n          value: value,\n          writable: true,\n          configurable: true\n        });\n      }\n    };\n  }\n\n  function diffObjectFromChangeRecords(object, changeRecords, oldValues) {\n    var added = {};\n    var removed = {};\n\n    for (var i = 0; i < changeRecords.length; i++) {\n      var record = changeRecords[i];\n      if (!expectedRecordTypes[record.type]) {\n        console.error('Unknown changeRecord type: ' + record.type);\n        console.error(record);\n        continue;\n      }\n\n      if (!(record.name in oldValues))\n        oldValues[record.name] = record.oldValue;\n\n      if (record.type == PROP_UPDATE_TYPE)\n        continue;\n\n      if (record.type == PROP_ADD_TYPE) {\n        if (record.name in removed)\n          delete removed[record.name];\n        else\n          added[record.name] = true;\n\n        continue;\n      }\n\n      // type = 'delete'\n      if (record.name in added) {\n        delete added[record.name];\n        delete oldValues[record.name];\n      } else {\n        removed[record.name] = true;\n      }\n    }\n\n    for (var prop in added)\n      added[prop] = object[prop];\n\n    for (var prop in removed)\n      removed[prop] = undefined;\n\n    var changed = {};\n    for (var prop in oldValues) {\n      if (prop in added || prop in removed)\n        continue;\n\n      var newValue = object[prop];\n      if (oldValues[prop] !== newValue)\n        changed[prop] = newValue;\n    }\n\n    return {\n      added: added,\n      removed: removed,\n      changed: changed\n    };\n  }\n\n  function newSplice(index, removed, addedCount) {\n    return {\n      index: index,\n      removed: removed,\n      addedCount: addedCount\n    };\n  }\n\n  var EDIT_LEAVE = 0;\n  var EDIT_UPDATE = 1;\n  var EDIT_ADD = 2;\n  var EDIT_DELETE = 3;\n\n  function ArraySplice() {}\n\n  ArraySplice.prototype = {\n\n    // Note: This function is *based* on the computation of the Levenshtein\n    // \"edit\" distance. The one change is that \"updates\" are treated as two\n    // edits - not one. With Array splices, an update is really a delete\n    // followed by an add. By retaining this, we optimize for \"keeping\" the\n    // maximum array items in the original array. For example:\n    //\n    //   'xxxx123' -> '123yyyy'\n    //\n    // With 1-edit updates, the shortest path would be just to update all seven\n    // characters. With 2-edit updates, we delete 4, leave 3, and add 4. This\n    // leaves the substring '123' intact.\n    calcEditDistances: function(current, currentStart, currentEnd,\n                                old, oldStart, oldEnd) {\n      // \"Deletion\" columns\n      var rowCount = oldEnd - oldStart + 1;\n      var columnCount = currentEnd - currentStart + 1;\n      var distances = new Array(rowCount);\n\n      // \"Addition\" rows. Initialize null column.\n      for (var i = 0; i < rowCount; i++) {\n        distances[i] = new Array(columnCount);\n        distances[i][0] = i;\n      }\n\n      // Initialize null row\n      for (var j = 0; j < columnCount; j++)\n        distances[0][j] = j;\n\n      for (var i = 1; i < rowCount; i++) {\n        for (var j = 1; j < columnCount; j++) {\n          if (this.equals(current[currentStart + j - 1], old[oldStart + i - 1]))\n            distances[i][j] = distances[i - 1][j - 1];\n          else {\n            var north = distances[i - 1][j] + 1;\n            var west = distances[i][j - 1] + 1;\n            distances[i][j] = north < west ? north : west;\n          }\n        }\n      }\n\n      return distances;\n    },\n\n    // This starts at the final weight, and walks \"backward\" by finding\n    // the minimum previous weight recursively until the origin of the weight\n    // matrix.\n    spliceOperationsFromEditDistances: function(distances) {\n      var i = distances.length - 1;\n      var j = distances[0].length - 1;\n      var current = distances[i][j];\n      var edits = [];\n      while (i > 0 || j > 0) {\n        if (i == 0) {\n          edits.push(EDIT_ADD);\n          j--;\n          continue;\n        }\n        if (j == 0) {\n          edits.push(EDIT_DELETE);\n          i--;\n          continue;\n        }\n        var northWest = distances[i - 1][j - 1];\n        var west = distances[i - 1][j];\n        var north = distances[i][j - 1];\n\n        var min;\n        if (west < north)\n          min = west < northWest ? west : northWest;\n        else\n          min = north < northWest ? north : northWest;\n\n        if (min == northWest) {\n          if (northWest == current) {\n            edits.push(EDIT_LEAVE);\n          } else {\n            edits.push(EDIT_UPDATE);\n            current = northWest;\n          }\n          i--;\n          j--;\n        } else if (min == west) {\n          edits.push(EDIT_DELETE);\n          i--;\n          current = west;\n        } else {\n          edits.push(EDIT_ADD);\n          j--;\n          current = north;\n        }\n      }\n\n      edits.reverse();\n      return edits;\n    },\n\n    /**\n     * Splice Projection functions:\n     *\n     * A splice map is a representation of how a previous array of items\n     * was transformed into a new array of items. Conceptually it is a list of\n     * tuples of\n     *\n     *   <index, removed, addedCount>\n     *\n     * which are kept in ascending index order of. The tuple represents that at\n     * the |index|, |removed| sequence of items were removed, and counting forward\n     * from |index|, |addedCount| items were added.\n     */\n\n    /**\n     * Lacking individual splice mutation information, the minimal set of\n     * splices can be synthesized given the previous state and final state of an\n     * array. The basic approach is to calculate the edit distance matrix and\n     * choose the shortest path through it.\n     *\n     * Complexity: O(l * p)\n     *   l: The length of the current array\n     *   p: The length of the old array\n     */\n    calcSplices: function(current, currentStart, currentEnd,\n                          old, oldStart, oldEnd) {\n      var prefixCount = 0;\n      var suffixCount = 0;\n\n      var minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart);\n      if (currentStart == 0 && oldStart == 0)\n        prefixCount = this.sharedPrefix(current, old, minLength);\n\n      if (currentEnd == current.length && oldEnd == old.length)\n        suffixCount = this.sharedSuffix(current, old, minLength - prefixCount);\n\n      currentStart += prefixCount;\n      oldStart += prefixCount;\n      currentEnd -= suffixCount;\n      oldEnd -= suffixCount;\n\n      if (currentEnd - currentStart == 0 && oldEnd - oldStart == 0)\n        return [];\n\n      if (currentStart == currentEnd) {\n        var splice = newSplice(currentStart, [], 0);\n        while (oldStart < oldEnd)\n          splice.removed.push(old[oldStart++]);\n\n        return [ splice ];\n      } else if (oldStart == oldEnd)\n        return [ newSplice(currentStart, [], currentEnd - currentStart) ];\n\n      var ops = this.spliceOperationsFromEditDistances(\n          this.calcEditDistances(current, currentStart, currentEnd,\n                                 old, oldStart, oldEnd));\n\n      var splice = undefined;\n      var splices = [];\n      var index = currentStart;\n      var oldIndex = oldStart;\n      for (var i = 0; i < ops.length; i++) {\n        switch(ops[i]) {\n          case EDIT_LEAVE:\n            if (splice) {\n              splices.push(splice);\n              splice = undefined;\n            }\n\n            index++;\n            oldIndex++;\n            break;\n          case EDIT_UPDATE:\n            if (!splice)\n              splice = newSplice(index, [], 0);\n\n            splice.addedCount++;\n            index++;\n\n            splice.removed.push(old[oldIndex]);\n            oldIndex++;\n            break;\n          case EDIT_ADD:\n            if (!splice)\n              splice = newSplice(index, [], 0);\n\n            splice.addedCount++;\n            index++;\n            break;\n          case EDIT_DELETE:\n            if (!splice)\n              splice = newSplice(index, [], 0);\n\n            splice.removed.push(old[oldIndex]);\n            oldIndex++;\n            break;\n        }\n      }\n\n      if (splice) {\n        splices.push(splice);\n      }\n      return splices;\n    },\n\n    sharedPrefix: function(current, old, searchLength) {\n      for (var i = 0; i < searchLength; i++)\n        if (!this.equals(current[i], old[i]))\n          return i;\n      return searchLength;\n    },\n\n    sharedSuffix: function(current, old, searchLength) {\n      var index1 = current.length;\n      var index2 = old.length;\n      var count = 0;\n      while (count < searchLength && this.equals(current[--index1], old[--index2]))\n        count++;\n\n      return count;\n    },\n\n    calculateSplices: function(current, previous) {\n      return this.calcSplices(current, 0, current.length, previous, 0,\n                              previous.length);\n    },\n\n    equals: function(currentValue, previousValue) {\n      return currentValue === previousValue;\n    }\n  };\n\n  var arraySplice = new ArraySplice();\n\n  function calcSplices(current, currentStart, currentEnd,\n                       old, oldStart, oldEnd) {\n    return arraySplice.calcSplices(current, currentStart, currentEnd,\n                                   old, oldStart, oldEnd);\n  }\n\n  function intersect(start1, end1, start2, end2) {\n    // Disjoint\n    if (end1 < start2 || end2 < start1)\n      return -1;\n\n    // Adjacent\n    if (end1 == start2 || end2 == start1)\n      return 0;\n\n    // Non-zero intersect, span1 first\n    if (start1 < start2) {\n      if (end1 < end2)\n        return end1 - start2; // Overlap\n      else\n        return end2 - start2; // Contained\n    } else {\n      // Non-zero intersect, span2 first\n      if (end2 < end1)\n        return end2 - start1; // Overlap\n      else\n        return end1 - start1; // Contained\n    }\n  }\n\n  function mergeSplice(splices, index, removed, addedCount) {\n\n    var splice = newSplice(index, removed, addedCount);\n\n    var inserted = false;\n    var insertionOffset = 0;\n\n    for (var i = 0; i < splices.length; i++) {\n      var current = splices[i];\n      current.index += insertionOffset;\n\n      if (inserted)\n        continue;\n\n      var intersectCount = intersect(splice.index,\n                                     splice.index + splice.removed.length,\n                                     current.index,\n                                     current.index + current.addedCount);\n\n      if (intersectCount >= 0) {\n        // Merge the two splices\n\n        splices.splice(i, 1);\n        i--;\n\n        insertionOffset -= current.addedCount - current.removed.length;\n\n        splice.addedCount += current.addedCount - intersectCount;\n        var deleteCount = splice.removed.length +\n                          current.removed.length - intersectCount;\n\n        if (!splice.addedCount && !deleteCount) {\n          // merged splice is a noop. discard.\n          inserted = true;\n        } else {\n          var removed = current.removed;\n\n          if (splice.index < current.index) {\n            // some prefix of splice.removed is prepended to current.removed.\n            var prepend = splice.removed.slice(0, current.index - splice.index);\n            Array.prototype.push.apply(prepend, removed);\n            removed = prepend;\n          }\n\n          if (splice.index + splice.removed.length > current.index + current.addedCount) {\n            // some suffix of splice.removed is appended to current.removed.\n            var append = splice.removed.slice(current.index + current.addedCount - splice.index);\n            Array.prototype.push.apply(removed, append);\n          }\n\n          splice.removed = removed;\n          if (current.index < splice.index) {\n            splice.index = current.index;\n          }\n        }\n      } else if (splice.index < current.index) {\n        // Insert splice here.\n\n        inserted = true;\n\n        splices.splice(i, 0, splice);\n        i++;\n\n        var offset = splice.addedCount - splice.removed.length\n        current.index += offset;\n        insertionOffset += offset;\n      }\n    }\n\n    if (!inserted)\n      splices.push(splice);\n  }\n\n  function createInitialSplices(array, changeRecords) {\n    var splices = [];\n\n    for (var i = 0; i < changeRecords.length; i++) {\n      var record = changeRecords[i];\n      switch(record.type) {\n        case ARRAY_SPLICE_TYPE:\n          mergeSplice(splices, record.index, record.removed.slice(), record.addedCount);\n          break;\n        case PROP_ADD_TYPE:\n        case PROP_UPDATE_TYPE:\n        case PROP_DELETE_TYPE:\n          if (!isIndex(record.name))\n            continue;\n          var index = toNumber(record.name);\n          if (index < 0)\n            continue;\n          mergeSplice(splices, index, [record.oldValue], 1);\n          break;\n        default:\n          console.error('Unexpected record type: ' + JSON.stringify(record));\n          break;\n      }\n    }\n\n    return splices;\n  }\n\n  function projectArraySplices(array, changeRecords) {\n    var splices = [];\n\n    createInitialSplices(array, changeRecords).forEach(function(splice) {\n      if (splice.addedCount == 1 && splice.removed.length == 1) {\n        if (splice.removed[0] !== array[splice.index])\n          splices.push(splice);\n\n        return\n      };\n\n      splices = splices.concat(calcSplices(array, splice.index, splice.index + splice.addedCount,\n                                           splice.removed, 0, splice.removed.length));\n    });\n\n    return splices;\n  }\n\n  global.Observer = Observer;\n  global.Observer.runEOM_ = runEOM;\n  global.Observer.hasObjectObserve = hasObserve;\n  global.ArrayObserver = ArrayObserver;\n  global.ArrayObserver.calculateSplices = function(current, previous) {\n    return arraySplice.calculateSplices(current, previous);\n  };\n\n  global.ArraySplice = ArraySplice;\n  global.ObjectObserver = ObjectObserver;\n  global.PathObserver = PathObserver;\n  global.CompoundObserver = CompoundObserver;\n  global.Path = Path;\n  global.ObserverTransform = ObserverTransform;\n\n  // TODO(rafaelw): Only needed for testing until new change record names\n  // make it to release.\n  global.Observer.changeRecordTypes = {\n    add: PROP_ADD_TYPE,\n    update: PROP_UPDATE_TYPE,\n    reconfigure: PROP_RECONFIGURE_TYPE,\n    'delete': PROP_DELETE_TYPE,\n    splice: ARRAY_SPLICE_TYPE\n  };\n})(typeof global !== 'undefined' && global && typeof module !== 'undefined' && module ? global : this || window);\n","// prepoulate window.Platform.flags for default controls\r\nwindow.Platform = window.Platform || {};\r\n// prepopulate window.logFlags if necessary\r\nwindow.logFlags = window.logFlags || {};\r\n// process flags\r\n(function(scope){\r\n  // import\r\n  var flags = scope.flags || {};\r\n  // populate flags from location\r\n  location.search.slice(1).split('&').forEach(function(o) {\r\n    o = o.split('=');\r\n    o[0] && (flags[o[0]] = o[1] || true);\r\n  });\r\n  var entryPoint = document.currentScript || document.querySelector('script[src*=\"platform.js\"]');\r\n  if (entryPoint) {\r\n    var a = entryPoint.attributes;\r\n    for (var i = 0, n; i < a.length; i++) {\r\n      n = a[i];\r\n      if (n.name !== 'src') {\r\n        flags[n.name] = n.value || true;\r\n      }\r\n    }\r\n  }\r\n  if (flags.log) {\r\n    flags.log.split(',').forEach(function(f) {\r\n      window.logFlags[f] = true;\r\n    });\r\n  }\r\n  // If any of these flags match 'native', then force native ShadowDOM; any\r\n  // other truthy value, or failure to detect native\r\n  // ShadowDOM, results in polyfill\r\n  flags.shadow = (flags.shadow || flags.shadowdom || flags.polyfill);\r\n  if (flags.shadow === 'native') {\r\n    flags.shadow = false;\r\n  } else {\r\n    flags.shadow = flags.shadow || !HTMLElement.prototype.createShadowRoot;\r\n  }\r\n\r\n  // CustomElements polyfill flag\r\n  if (flags.register) {\r\n    window.CustomElements = window.CustomElements || {flags: {}};\r\n    window.CustomElements.flags.register = flags.register;\r\n  }\r\n\r\n  if (flags.imports) {\r\n    window.HTMLImports = window.HTMLImports || {flags: {}};\r\n    window.HTMLImports.flags.imports = flags.imports;\r\n  }\r\n\r\n  // export\r\n  scope.flags = flags;\r\n})(Platform);\r\n\r\n// select ShadowDOM impl\r\nif (Platform.flags.shadow) {\r\n","// Copyright 2012 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\nwindow.ShadowDOMPolyfill = {};\n\n(function(scope) {\n  'use strict';\n\n  var constructorTable = new WeakMap();\n  var nativePrototypeTable = new WeakMap();\n  var wrappers = Object.create(null);\n\n  // Don't test for eval if document has CSP securityPolicy object and we can\n  // see that eval is not supported. This avoids an error message in console\n  // even when the exception is caught\n  var hasEval = !('securityPolicy' in document) ||\n      document.securityPolicy.allowsEval;\n  if (hasEval) {\n    try {\n      var f = new Function('', 'return true;');\n      hasEval = f();\n    } catch (ex) {\n      hasEval = false;\n    }\n  }\n\n  function assert(b) {\n    if (!b)\n      throw new Error('Assertion failed');\n  };\n\n  var defineProperty = Object.defineProperty;\n  var getOwnPropertyNames = Object.getOwnPropertyNames;\n  var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n\n  function mixin(to, from) {\n    getOwnPropertyNames(from).forEach(function(name) {\n      defineProperty(to, name, getOwnPropertyDescriptor(from, name));\n    });\n    return to;\n  };\n\n  function mixinStatics(to, from) {\n    getOwnPropertyNames(from).forEach(function(name) {\n      switch (name) {\n        case 'arguments':\n        case 'caller':\n        case 'length':\n        case 'name':\n        case 'prototype':\n        case 'toString':\n          return;\n      }\n      defineProperty(to, name, getOwnPropertyDescriptor(from, name));\n    });\n    return to;\n  };\n\n  function oneOf(object, propertyNames) {\n    for (var i = 0; i < propertyNames.length; i++) {\n      if (propertyNames[i] in object)\n        return propertyNames[i];\n    }\n  }\n\n  // Mozilla's old DOM bindings are bretty busted:\n  // https://bugzilla.mozilla.org/show_bug.cgi?id=855844\n  // Make sure they are create before we start modifying things.\n  getOwnPropertyNames(window);\n\n  function getWrapperConstructor(node) {\n    var nativePrototype = node.__proto__ || Object.getPrototypeOf(node);\n    var wrapperConstructor = constructorTable.get(nativePrototype);\n    if (wrapperConstructor)\n      return wrapperConstructor;\n\n    var parentWrapperConstructor = getWrapperConstructor(nativePrototype);\n\n    var GeneratedWrapper = createWrapperConstructor(parentWrapperConstructor);\n    registerInternal(nativePrototype, GeneratedWrapper, node);\n\n    return GeneratedWrapper;\n  }\n\n  function addForwardingProperties(nativePrototype, wrapperPrototype) {\n    installProperty(nativePrototype, wrapperPrototype, true);\n  }\n\n  function registerInstanceProperties(wrapperPrototype, instanceObject) {\n    installProperty(instanceObject, wrapperPrototype, false);\n  }\n\n  var isFirefox = /Firefox/.test(navigator.userAgent);\n\n  // This is used as a fallback when getting the descriptor fails in\n  // installProperty.\n  var dummyDescriptor = {\n    get: function() {},\n    set: function(v) {},\n    configurable: true,\n    enumerable: true\n  };\n\n  function isEventHandlerName(name) {\n    return /^on[a-z]+$/.test(name);\n  }\n\n  function isIdentifierName(name) {\n    return /^\\w[a-zA-Z_0-9]*$/.test(name);\n  }\n\n  function getGetter(name) {\n    return hasEval && isIdentifierName(name) ?\n        new Function('return this.impl.' + name) :\n        function() { return this.impl[name]; };\n  }\n\n  function getSetter(name) {\n    return hasEval && isIdentifierName(name) ?\n        new Function('v', 'this.impl.' + name + ' = v') :\n        function(v) { this.impl[name] = v; };\n  }\n\n  function getMethod(name) {\n    return hasEval && isIdentifierName(name) ?\n        new Function('return this.impl.' + name +\n                     '.apply(this.impl, arguments)') :\n        function() { return this.impl[name].apply(this.impl, arguments); };\n  }\n\n  function getDescriptor(source, name) {\n    try {\n      return Object.getOwnPropertyDescriptor(source, name);\n    } catch (ex) {\n      // JSC and V8 both use data properties instead of accessors which can\n      // cause getting the property desciptor to throw an exception.\n      // https://bugs.webkit.org/show_bug.cgi?id=49739\n      return dummyDescriptor;\n    }\n  }\n\n  function installProperty(source, target, allowMethod, opt_blacklist) {\n    var names = getOwnPropertyNames(source);\n    for (var i = 0; i < names.length; i++) {\n      var name = names[i];\n      if (name === 'polymerBlackList_')\n        continue;\n\n      if (name in target)\n        continue;\n\n      if (source.polymerBlackList_ && source.polymerBlackList_[name])\n        continue;\n\n      if (isFirefox) {\n        // Tickle Firefox's old bindings.\n        source.__lookupGetter__(name);\n      }\n      var descriptor = getDescriptor(source, name);\n      var getter, setter;\n      if (allowMethod && typeof descriptor.value === 'function') {\n        target[name] = getMethod(name);\n        continue;\n      }\n\n      var isEvent = isEventHandlerName(name);\n      if (isEvent)\n        getter = scope.getEventHandlerGetter(name);\n      else\n        getter = getGetter(name);\n\n      if (descriptor.writable || descriptor.set) {\n        if (isEvent)\n          setter = scope.getEventHandlerSetter(name);\n        else\n          setter = getSetter(name);\n      }\n\n      defineProperty(target, name, {\n        get: getter,\n        set: setter,\n        configurable: descriptor.configurable,\n        enumerable: descriptor.enumerable\n      });\n    }\n  }\n\n  /**\n   * @param {Function} nativeConstructor\n   * @param {Function} wrapperConstructor\n   * @param {Object=} opt_instance If present, this is used to extract\n   *     properties from an instance object.\n   */\n  function register(nativeConstructor, wrapperConstructor, opt_instance) {\n    var nativePrototype = nativeConstructor.prototype;\n    registerInternal(nativePrototype, wrapperConstructor, opt_instance);\n    mixinStatics(wrapperConstructor, nativeConstructor);\n  }\n\n  function registerInternal(nativePrototype, wrapperConstructor, opt_instance) {\n    var wrapperPrototype = wrapperConstructor.prototype;\n    assert(constructorTable.get(nativePrototype) === undefined);\n\n    constructorTable.set(nativePrototype, wrapperConstructor);\n    nativePrototypeTable.set(wrapperPrototype, nativePrototype);\n\n    addForwardingProperties(nativePrototype, wrapperPrototype);\n    if (opt_instance)\n      registerInstanceProperties(wrapperPrototype, opt_instance);\n    defineProperty(wrapperPrototype, 'constructor', {\n      value: wrapperConstructor,\n      configurable: true,\n      enumerable: false,\n      writable: true\n    });\n  }\n\n  function isWrapperFor(wrapperConstructor, nativeConstructor) {\n    return constructorTable.get(nativeConstructor.prototype) ===\n        wrapperConstructor;\n  }\n\n  /**\n   * Creates a generic wrapper constructor based on |object| and its\n   * constructor.\n   * @param {Node} object\n   * @return {Function} The generated constructor.\n   */\n  function registerObject(object) {\n    var nativePrototype = Object.getPrototypeOf(object);\n\n    var superWrapperConstructor = getWrapperConstructor(nativePrototype);\n    var GeneratedWrapper = createWrapperConstructor(superWrapperConstructor);\n    registerInternal(nativePrototype, GeneratedWrapper, object);\n\n    return GeneratedWrapper;\n  }\n\n  function createWrapperConstructor(superWrapperConstructor) {\n    function GeneratedWrapper(node) {\n      superWrapperConstructor.call(this, node);\n    }\n    GeneratedWrapper.prototype =\n        Object.create(superWrapperConstructor.prototype);\n    GeneratedWrapper.prototype.constructor = GeneratedWrapper;\n\n    return GeneratedWrapper;\n  }\n\n  var OriginalDOMImplementation = window.DOMImplementation;\n  var OriginalEventTarget = window.EventTarget;\n  var OriginalEvent = window.Event;\n  var OriginalNode = window.Node;\n  var OriginalWindow = window.Window;\n  var OriginalRange = window.Range;\n  var OriginalCanvasRenderingContext2D = window.CanvasRenderingContext2D;\n  var OriginalWebGLRenderingContext = window.WebGLRenderingContext;\n  var OriginalSVGElementInstance = window.SVGElementInstance;\n\n  function isWrapper(object) {\n    return object instanceof wrappers.EventTarget ||\n           object instanceof wrappers.Event ||\n           object instanceof wrappers.Range ||\n           object instanceof wrappers.DOMImplementation ||\n           object instanceof wrappers.CanvasRenderingContext2D ||\n           wrappers.WebGLRenderingContext &&\n               object instanceof wrappers.WebGLRenderingContext;\n  }\n\n  function isNative(object) {\n    return OriginalEventTarget && object instanceof OriginalEventTarget ||\n           object instanceof OriginalNode ||\n           object instanceof OriginalEvent ||\n           object instanceof OriginalWindow ||\n           object instanceof OriginalRange ||\n           object instanceof OriginalDOMImplementation ||\n           object instanceof OriginalCanvasRenderingContext2D ||\n           OriginalWebGLRenderingContext &&\n               object instanceof OriginalWebGLRenderingContext ||\n           OriginalSVGElementInstance &&\n               object instanceof OriginalSVGElementInstance;\n  }\n\n  /**\n   * Wraps a node in a WrapperNode. If there already exists a wrapper for the\n   * |node| that wrapper is returned instead.\n   * @param {Node} node\n   * @return {WrapperNode}\n   */\n  function wrap(impl) {\n    if (impl === null)\n      return null;\n\n    assert(isNative(impl));\n    return impl.polymerWrapper_ ||\n        (impl.polymerWrapper_ = new (getWrapperConstructor(impl))(impl));\n  }\n\n  /**\n   * Unwraps a wrapper and returns the node it is wrapping.\n   * @param {WrapperNode} wrapper\n   * @return {Node}\n   */\n  function unwrap(wrapper) {\n    if (wrapper === null)\n      return null;\n    assert(isWrapper(wrapper));\n    return wrapper.impl;\n  }\n\n  /**\n   * Unwraps object if it is a wrapper.\n   * @param {Object} object\n   * @return {Object} The native implementation object.\n   */\n  function unwrapIfNeeded(object) {\n    return object && isWrapper(object) ? unwrap(object) : object;\n  }\n\n  /**\n   * Wraps object if it is not a wrapper.\n   * @param {Object} object\n   * @return {Object} The wrapper for object.\n   */\n  function wrapIfNeeded(object) {\n    return object && !isWrapper(object) ? wrap(object) : object;\n  }\n\n  /**\n   * Overrides the current wrapper (if any) for node.\n   * @param {Node} node\n   * @param {WrapperNode=} wrapper If left out the wrapper will be created as\n   *     needed next time someone wraps the node.\n   */\n  function rewrap(node, wrapper) {\n    if (wrapper === null)\n      return;\n    assert(isNative(node));\n    assert(wrapper === undefined || isWrapper(wrapper));\n    node.polymerWrapper_ = wrapper;\n  }\n\n  function defineGetter(constructor, name, getter) {\n    defineProperty(constructor.prototype, name, {\n      get: getter,\n      configurable: true,\n      enumerable: true\n    });\n  }\n\n  function defineWrapGetter(constructor, name) {\n    defineGetter(constructor, name, function() {\n      return wrap(this.impl[name]);\n    });\n  }\n\n  /**\n   * Forwards existing methods on the native object to the wrapper methods.\n   * This does not wrap any of the arguments or the return value since the\n   * wrapper implementation already takes care of that.\n   * @param {Array.<Function>} constructors\n   * @parem {Array.<string>} names\n   */\n  function forwardMethodsToWrapper(constructors, names) {\n    constructors.forEach(function(constructor) {\n      names.forEach(function(name) {\n        constructor.prototype[name] = function() {\n          var w = wrapIfNeeded(this);\n          return w[name].apply(w, arguments);\n        };\n      });\n    });\n  }\n\n  scope.assert = assert;\n  scope.constructorTable = constructorTable;\n  scope.defineGetter = defineGetter;\n  scope.defineWrapGetter = defineWrapGetter;\n  scope.forwardMethodsToWrapper = forwardMethodsToWrapper;\n  scope.isWrapper = isWrapper;\n  scope.isWrapperFor = isWrapperFor;\n  scope.mixin = mixin;\n  scope.nativePrototypeTable = nativePrototypeTable;\n  scope.oneOf = oneOf;\n  scope.registerObject = registerObject;\n  scope.registerWrapper = register;\n  scope.rewrap = rewrap;\n  scope.unwrap = unwrap;\n  scope.unwrapIfNeeded = unwrapIfNeeded;\n  scope.wrap = wrap;\n  scope.wrapIfNeeded = wrapIfNeeded;\n  scope.wrappers = wrappers;\n\n})(window.ShadowDOMPolyfill);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is goverened by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(context) {\n  'use strict';\n\n  var OriginalMutationObserver = window.MutationObserver;\n  var callbacks = [];\n  var pending = false;\n  var timerFunc;\n\n  function handle() {\n    pending = false;\n    var copies = callbacks.slice(0);\n    callbacks = [];\n    for (var i = 0; i < copies.length; i++) {\n      (0, copies[i])();\n    }\n  }\n\n  if (OriginalMutationObserver) {\n    var counter = 1;\n    var observer = new OriginalMutationObserver(handle);\n    var textNode = document.createTextNode(counter);\n    observer.observe(textNode, {characterData: true});\n\n    timerFunc = function() {\n      counter = (counter + 1) % 2;\n      textNode.data = counter;\n    };\n\n  } else {\n    timerFunc = window.setImmediate || window.setTimeout;\n  }\n\n  function setEndOfMicrotask(func) {\n    callbacks.push(func);\n    if (pending)\n      return;\n    pending = true;\n    timerFunc(handle, 0);\n  }\n\n  context.setEndOfMicrotask = setEndOfMicrotask;\n\n})(window.ShadowDOMPolyfill);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is goverened by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n  'use strict';\n\n  var setEndOfMicrotask = scope.setEndOfMicrotask\n  var wrapIfNeeded = scope.wrapIfNeeded\n  var wrappers = scope.wrappers;\n\n  var registrationsTable = new WeakMap();\n  var globalMutationObservers = [];\n  var isScheduled = false;\n\n  function scheduleCallback(observer) {\n    if (isScheduled)\n      return;\n    setEndOfMicrotask(notifyObservers);\n    isScheduled = true;\n  }\n\n  // http://dom.spec.whatwg.org/#mutation-observers\n  function notifyObservers() {\n    isScheduled = false;\n\n    do {\n      var notifyList = globalMutationObservers.slice();\n      var anyNonEmpty = false;\n      for (var i = 0; i < notifyList.length; i++) {\n        var mo = notifyList[i];\n        var queue = mo.takeRecords();\n        removeTransientObserversFor(mo);\n        if (queue.length) {\n          mo.callback_(queue, mo);\n          anyNonEmpty = true;\n        }\n      }\n    } while (anyNonEmpty);\n  }\n\n  /**\n   * @param {string} type\n   * @param {Node} target\n   * @constructor\n   */\n  function MutationRecord(type, target) {\n    this.type = type;\n    this.target = target;\n    this.addedNodes = new wrappers.NodeList();\n    this.removedNodes = new wrappers.NodeList();\n    this.previousSibling = null;\n    this.nextSibling = null;\n    this.attributeName = null;\n    this.attributeNamespace = null;\n    this.oldValue = null;\n  }\n\n  /**\n   * Registers transient observers to ancestor and its ancesors for the node\n   * which was removed.\n   * @param {!Node} ancestor\n   * @param {!Node} node\n   */\n  function registerTransientObservers(ancestor, node) {\n    for (; ancestor; ancestor = ancestor.parentNode) {\n      var registrations = registrationsTable.get(ancestor);\n      if (!registrations)\n        continue;\n      for (var i = 0; i < registrations.length; i++) {\n        var registration = registrations[i];\n        if (registration.options.subtree)\n          registration.addTransientObserver(node);\n      }\n    }\n  }\n\n  function removeTransientObserversFor(observer) {\n    for (var i = 0; i < observer.nodes_.length; i++) {\n      var node = observer.nodes_[i];\n      var registrations = registrationsTable.get(node);\n      if (!registrations)\n        return;\n      for (var j = 0; j < registrations.length; j++) {\n        var registration = registrations[j];\n        if (registration.observer === observer)\n          registration.removeTransientObservers();\n      }\n    }\n  }\n\n  // http://dom.spec.whatwg.org/#queue-a-mutation-record\n  function enqueueMutation(target, type, data) {\n    // 1.\n    var interestedObservers = Object.create(null);\n    var associatedStrings = Object.create(null);\n\n    // 2.\n    for (var node = target; node; node = node.parentNode) {\n      // 3.\n      var registrations = registrationsTable.get(node);\n      if (!registrations)\n        continue;\n      for (var j = 0; j < registrations.length; j++) {\n        var registration = registrations[j];\n        var options = registration.options;\n        // 1.\n        if (node !== target && !options.subtree)\n          continue;\n\n        // 2.\n        if (type === 'attributes' && !options.attributes)\n          continue;\n\n        // 3. If type is \"attributes\", options's attributeFilter is present, and\n        // either options's attributeFilter does not contain name or namespace\n        // is non-null, continue.\n        if (type === 'attributes' && options.attributeFilter &&\n            (data.namespace !== null ||\n             options.attributeFilter.indexOf(data.name) === -1)) {\n          continue;\n        }\n\n        // 4.\n        if (type === 'characterData' && !options.characterData)\n          continue;\n\n        // 5.\n        if (type === 'childList' && !options.childList)\n          continue;\n\n        // 6.\n        var observer = registration.observer;\n        interestedObservers[observer.uid_] = observer;\n\n        // 7. If either type is \"attributes\" and options's attributeOldValue is\n        // true, or type is \"characterData\" and options's characterDataOldValue\n        // is true, set the paired string of registered observer's observer in\n        // interested observers to oldValue.\n        if (type === 'attributes' && options.attributeOldValue ||\n            type === 'characterData' && options.characterDataOldValue) {\n          associatedStrings[observer.uid_] = data.oldValue;\n        }\n      }\n    }\n\n    var anyRecordsEnqueued = false;\n\n    // 4.\n    for (var uid in interestedObservers) {\n      var observer = interestedObservers[uid];\n      var record = new MutationRecord(type, target);\n\n      // 2.\n      if ('name' in data && 'namespace' in data) {\n        record.attributeName = data.name;\n        record.attributeNamespace = data.namespace;\n      }\n\n      // 3.\n      if (data.addedNodes)\n        record.addedNodes = data.addedNodes;\n\n      // 4.\n      if (data.removedNodes)\n        record.removedNodes = data.removedNodes;\n\n      // 5.\n      if (data.previousSibling)\n        record.previousSibling = data.previousSibling;\n\n      // 6.\n      if (data.nextSibling)\n        record.nextSibling = data.nextSibling;\n\n      // 7.\n      if (associatedStrings[uid] !== undefined)\n        record.oldValue = associatedStrings[uid];\n\n      // 8.\n      observer.records_.push(record);\n\n      anyRecordsEnqueued = true;\n    }\n\n    if (anyRecordsEnqueued)\n      scheduleCallback();\n  }\n\n  var slice = Array.prototype.slice;\n\n  /**\n   * @param {!Object} options\n   * @constructor\n   */\n  function MutationObserverOptions(options) {\n    this.childList = !!options.childList;\n    this.subtree = !!options.subtree;\n\n    // 1. If either options' attributeOldValue or attributeFilter is present\n    // and options' attributes is omitted, set options' attributes to true.\n    if (!('attributes' in options) &&\n        ('attributeOldValue' in options || 'attributeFilter' in options)) {\n      this.attributes = true;\n    } else {\n      this.attributes = !!options.attributes;\n    }\n\n    // 2. If options' characterDataOldValue is present and options'\n    // characterData is omitted, set options' characterData to true.\n    if ('characterDataOldValue' in options && !('characterData' in options))\n      this.characterData = true;\n    else\n      this.characterData = !!options.characterData;\n\n    // 3. & 4.\n    if (!this.attributes &&\n        (options.attributeOldValue || 'attributeFilter' in options) ||\n        // 5.\n        !this.characterData && options.characterDataOldValue) {\n      throw new TypeError();\n    }\n\n    this.characterData = !!options.characterData;\n    this.attributeOldValue = !!options.attributeOldValue;\n    this.characterDataOldValue = !!options.characterDataOldValue;\n    if ('attributeFilter' in options) {\n      if (options.attributeFilter == null ||\n          typeof options.attributeFilter !== 'object') {\n        throw new TypeError();\n      }\n      this.attributeFilter = slice.call(options.attributeFilter);\n    } else {\n      this.attributeFilter = null;\n    }\n  }\n\n  var uidCounter = 0;\n\n  /**\n   * The class that maps to the DOM MutationObserver interface.\n   * @param {Function} callback.\n   * @constructor\n   */\n  function MutationObserver(callback) {\n    this.callback_ = callback;\n    this.nodes_ = [];\n    this.records_ = [];\n    this.uid_ = ++uidCounter;\n\n    // This will leak. There is no way to implement this without WeakRefs :'(\n    globalMutationObservers.push(this);\n  }\n\n  MutationObserver.prototype = {\n    // http://dom.spec.whatwg.org/#dom-mutationobserver-observe\n    observe: function(target, options) {\n      target = wrapIfNeeded(target);\n\n      var newOptions = new MutationObserverOptions(options);\n\n      // 6.\n      var registration;\n      var registrations = registrationsTable.get(target);\n      if (!registrations)\n        registrationsTable.set(target, registrations = []);\n\n      for (var i = 0; i < registrations.length; i++) {\n        if (registrations[i].observer === this) {\n          registration = registrations[i];\n          // 6.1.\n          registration.removeTransientObservers();\n          // 6.2.\n          registration.options = newOptions;\n        }\n      }\n\n      // 7.\n      if (!registration) {\n        registration = new Registration(this, target, newOptions);\n        registrations.push(registration);\n        this.nodes_.push(target);\n      }\n    },\n\n    // http://dom.spec.whatwg.org/#dom-mutationobserver-disconnect\n    disconnect: function() {\n      this.nodes_.forEach(function(node) {\n        var registrations = registrationsTable.get(node);\n        for (var i = 0; i < registrations.length; i++) {\n          var registration = registrations[i];\n          if (registration.observer === this) {\n            registrations.splice(i, 1);\n            // Each node can only have one registered observer associated with\n            // this observer.\n            break;\n          }\n        }\n      }, this);\n      this.records_ = [];\n    },\n\n    takeRecords: function() {\n      var copyOfRecords = this.records_;\n      this.records_ = [];\n      return copyOfRecords;\n    }\n  };\n\n  /**\n   * Class used to represent a registered observer.\n   * @param {MutationObserver} observer\n   * @param {Node} target\n   * @param {MutationObserverOptions} options\n   * @constructor\n   */\n  function Registration(observer, target, options) {\n    this.observer = observer;\n    this.target = target;\n    this.options = options;\n    this.transientObservedNodes = [];\n  }\n\n  Registration.prototype = {\n    /**\n     * Adds a transient observer on node. The transient observer gets removed\n     * next time we deliver the change records.\n     * @param {Node} node\n     */\n    addTransientObserver: function(node) {\n      // Don't add transient observers on the target itself. We already have all\n      // the required listeners set up on the target.\n      if (node === this.target)\n        return;\n\n      this.transientObservedNodes.push(node);\n      var registrations = registrationsTable.get(node);\n      if (!registrations)\n        registrationsTable.set(node, registrations = []);\n\n      // We know that registrations does not contain this because we already\n      // checked if node === this.target.\n      registrations.push(this);\n    },\n\n    removeTransientObservers: function() {\n      var transientObservedNodes = this.transientObservedNodes;\n      this.transientObservedNodes = [];\n\n      for (var i = 0; i < transientObservedNodes.length; i++) {\n        var node = transientObservedNodes[i];\n        var registrations = registrationsTable.get(node);\n        for (var j = 0; j < registrations.length; j++) {\n          if (registrations[j] === this) {\n            registrations.splice(j, 1);\n            // Each node can only have one registered observer associated with\n            // this observer.\n            break;\n          }\n        }\n      }\n    }\n  };\n\n  scope.enqueueMutation = enqueueMutation;\n  scope.registerTransientObservers = registerTransientObservers;\n  scope.wrappers.MutationObserver = MutationObserver;\n  scope.wrappers.MutationRecord = MutationRecord;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var forwardMethodsToWrapper = scope.forwardMethodsToWrapper;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n  var wrappers = scope.wrappers;\n\n  var wrappedFuns = new WeakMap();\n  var listenersTable = new WeakMap();\n  var handledEventsTable = new WeakMap();\n  var currentlyDispatchingEvents = new WeakMap();\n  var targetTable = new WeakMap();\n  var currentTargetTable = new WeakMap();\n  var relatedTargetTable = new WeakMap();\n  var eventPhaseTable = new WeakMap();\n  var stopPropagationTable = new WeakMap();\n  var stopImmediatePropagationTable = new WeakMap();\n  var eventHandlersTable = new WeakMap();\n  var eventPathTable = new WeakMap();\n\n  function isShadowRoot(node) {\n    return node instanceof wrappers.ShadowRoot;\n  }\n\n  function isInsertionPoint(node) {\n    var localName = node.localName;\n    return localName === 'content' || localName === 'shadow';\n  }\n\n  function isShadowHost(node) {\n    return !!node.shadowRoot;\n  }\n\n  function getEventParent(node) {\n    var dv;\n    return node.parentNode || (dv = node.defaultView) && wrap(dv) || null;\n  }\n\n  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-adjusted-parent\n  function calculateParents(node, context, ancestors) {\n    if (ancestors.length)\n      return ancestors.shift();\n\n    // 1.\n    if (isShadowRoot(node))\n      return getInsertionParent(node) || node.host;\n\n    // 2.\n    var eventParents = scope.eventParentsTable.get(node);\n    if (eventParents) {\n      // Copy over the remaining event parents for next iteration.\n      for (var i = 1; i < eventParents.length; i++) {\n        ancestors[i - 1] = eventParents[i];\n      }\n      return eventParents[0];\n    }\n\n    // 3.\n    if (context && isInsertionPoint(node)) {\n      var parentNode = node.parentNode;\n      if (parentNode && isShadowHost(parentNode)) {\n        var trees = scope.getShadowTrees(parentNode);\n        var p = getInsertionParent(context);\n        for (var i = 0; i < trees.length; i++) {\n          if (trees[i].contains(p))\n            return p;\n        }\n      }\n    }\n\n    return getEventParent(node);\n  }\n\n  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#event-retargeting\n  function retarget(node) {\n    var stack = [];  // 1.\n    var ancestor = node;  // 2.\n    var targets = [];\n    var ancestors = [];\n    while (ancestor) {  // 3.\n      var context = null;  // 3.2.\n      // TODO(arv): Change order of these. If the stack is empty we always end\n      // up pushing ancestor, no matter what.\n      if (isInsertionPoint(ancestor)) {  // 3.1.\n        context = topMostNotInsertionPoint(stack);  // 3.1.1.\n        var top = stack[stack.length - 1] || ancestor;  // 3.1.2.\n        stack.push(top);\n      } else if (!stack.length) {\n        stack.push(ancestor);  // 3.3.\n      }\n      var target = stack[stack.length - 1];  // 3.4.\n      targets.push({target: target, currentTarget: ancestor});  // 3.5.\n      if (isShadowRoot(ancestor))  // 3.6.\n        stack.pop();  // 3.6.1.\n\n      ancestor = calculateParents(ancestor, context, ancestors);  // 3.7.\n    }\n    return targets;\n  }\n\n  function topMostNotInsertionPoint(stack) {\n    for (var i = stack.length - 1; i >= 0; i--) {\n      if (!isInsertionPoint(stack[i]))\n        return stack[i];\n    }\n    return null;\n  }\n\n  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-adjusted-related-target\n  function adjustRelatedTarget(target, related) {\n    var ancestors = [];\n    while (target) {  // 3.\n      var stack = [];  // 3.1.\n      var ancestor = related;  // 3.2.\n      var last = undefined;  // 3.3. Needs to be reset every iteration.\n      while (ancestor) {\n        var context = null;\n        if (!stack.length) {\n          stack.push(ancestor);\n        } else {\n          if (isInsertionPoint(ancestor)) {  // 3.4.3.\n            context = topMostNotInsertionPoint(stack);\n            // isDistributed is more general than checking whether last is\n            // assigned into ancestor.\n            if (isDistributed(last)) {  // 3.4.3.2.\n              var head = stack[stack.length - 1];\n              stack.push(head);\n            }\n          }\n        }\n\n        if (inSameTree(ancestor, target))  // 3.4.4.\n          return stack[stack.length - 1];\n\n        if (isShadowRoot(ancestor))  // 3.4.5.\n          stack.pop();\n\n        last = ancestor;  // 3.4.6.\n        ancestor = calculateParents(ancestor, context, ancestors);  // 3.4.7.\n      }\n      if (isShadowRoot(target))  // 3.5.\n        target = target.host;\n      else\n        target = target.parentNode;  // 3.6.\n    }\n  }\n\n  function getInsertionParent(node) {\n    return scope.insertionParentTable.get(node);\n  }\n\n  function isDistributed(node) {\n    return getInsertionParent(node);\n  }\n\n  function rootOfNode(node) {\n    var p;\n    while (p = node.parentNode) {\n      node = p;\n    }\n    return node;\n  }\n\n  function inSameTree(a, b) {\n    return rootOfNode(a) === rootOfNode(b);\n  }\n\n  function enclosedBy(a, b) {\n    if (a === b)\n      return true;\n    if (a instanceof wrappers.ShadowRoot)\n      return enclosedBy(rootOfNode(a.host), b);\n    return false;\n  }\n\n\n  function dispatchOriginalEvent(originalEvent) {\n    // Make sure this event is only dispatched once.\n    if (handledEventsTable.get(originalEvent))\n      return;\n    handledEventsTable.set(originalEvent, true);\n\n    return dispatchEvent(wrap(originalEvent), wrap(originalEvent.target));\n  }\n\n  function dispatchEvent(event, originalWrapperTarget) {\n    if (currentlyDispatchingEvents.get(event))\n      throw new Error('InvalidStateError')\n    currentlyDispatchingEvents.set(event, true);\n\n    // Render to ensure that the event path is correct.\n    scope.renderAllPending();\n    var eventPath = retarget(originalWrapperTarget);\n\n    // For window load events the load event is dispatched at the window but\n    // the target is set to the document.\n    //\n    // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#the-end\n    //\n    // TODO(arv): Find a less hacky way to do this.\n    if (event.type === 'load' &&\n        eventPath.length === 2 &&\n        eventPath[0].target instanceof wrappers.Document) {\n      eventPath.shift();\n    }\n\n    eventPathTable.set(event, eventPath);\n\n    if (dispatchCapturing(event, eventPath)) {\n      if (dispatchAtTarget(event, eventPath)) {\n        dispatchBubbling(event, eventPath);\n      }\n    }\n\n    eventPhaseTable.set(event, Event.NONE);\n    currentTargetTable.delete(event, null);\n    currentlyDispatchingEvents.delete(event);\n\n    return event.defaultPrevented;\n  }\n\n  function dispatchCapturing(event, eventPath) {\n    var phase;\n\n    for (var i = eventPath.length - 1; i > 0; i--) {\n      var target = eventPath[i].target;\n      var currentTarget = eventPath[i].currentTarget;\n      if (target === currentTarget)\n        continue;\n\n      phase = Event.CAPTURING_PHASE;\n      if (!invoke(eventPath[i], event, phase))\n        return false;\n    }\n\n    return true;\n  }\n\n  function dispatchAtTarget(event, eventPath) {\n    var phase = Event.AT_TARGET;\n    return invoke(eventPath[0], event, phase);\n  }\n\n  function dispatchBubbling(event, eventPath) {\n    var bubbles = event.bubbles;\n    var phase;\n\n    for (var i = 1; i < eventPath.length; i++) {\n      var target = eventPath[i].target;\n      var currentTarget = eventPath[i].currentTarget;\n      if (target === currentTarget)\n        phase = Event.AT_TARGET;\n      else if (bubbles && !stopImmediatePropagationTable.get(event))\n        phase = Event.BUBBLING_PHASE;\n      else\n        continue;\n\n      if (!invoke(eventPath[i], event, phase))\n        return;\n    }\n  }\n\n  function invoke(tuple, event, phase) {\n    var target = tuple.target;\n    var currentTarget = tuple.currentTarget;\n\n    var listeners = listenersTable.get(currentTarget);\n    if (!listeners)\n      return true;\n\n    if ('relatedTarget' in event) {\n      var originalEvent = unwrap(event);\n      // X-Tag sets relatedTarget on a CustomEvent. If they do that there is no\n      // way to have relatedTarget return the adjusted target but worse is that\n      // the originalEvent might not have a relatedTarget so we hit an assert\n      // when we try to wrap it.\n      if (originalEvent.relatedTarget) {\n        var relatedTarget = wrap(originalEvent.relatedTarget);\n\n        var adjusted = adjustRelatedTarget(currentTarget, relatedTarget);\n        if (adjusted === target)\n          return true;\n\n        relatedTargetTable.set(event, adjusted);\n      }\n    }\n\n    eventPhaseTable.set(event, phase);\n    var type = event.type;\n\n    var anyRemoved = false;\n    targetTable.set(event, target);\n    currentTargetTable.set(event, currentTarget);\n\n    for (var i = 0; i < listeners.length; i++) {\n      var listener = listeners[i];\n      if (listener.removed) {\n        anyRemoved = true;\n        continue;\n      }\n\n      if (listener.type !== type ||\n          !listener.capture && phase === Event.CAPTURING_PHASE ||\n          listener.capture && phase === Event.BUBBLING_PHASE) {\n        continue;\n      }\n\n      try {\n        if (typeof listener.handler === 'function')\n          listener.handler.call(currentTarget, event);\n        else\n          listener.handler.handleEvent(event);\n\n        if (stopImmediatePropagationTable.get(event))\n          return false;\n\n      } catch (ex) {\n        if (window.onerror)\n          window.onerror(ex.message);\n        else\n          console.error(ex, ex.stack);\n      }\n    }\n\n    if (anyRemoved) {\n      var copy = listeners.slice();\n      listeners.length = 0;\n      for (var i = 0; i < copy.length; i++) {\n        if (!copy[i].removed)\n          listeners.push(copy[i]);\n      }\n    }\n\n    return !stopPropagationTable.get(event);\n  }\n\n  function Listener(type, handler, capture) {\n    this.type = type;\n    this.handler = handler;\n    this.capture = Boolean(capture);\n  }\n  Listener.prototype = {\n    equals: function(that) {\n      return this.handler === that.handler && this.type === that.type &&\n          this.capture === that.capture;\n    },\n    get removed() {\n      return this.handler === null;\n    },\n    remove: function() {\n      this.handler = null;\n    }\n  };\n\n  var OriginalEvent = window.Event;\n  OriginalEvent.prototype.polymerBlackList_ = {\n    returnValue: true,\n    // TODO(arv): keyLocation is part of KeyboardEvent but Firefox does not\n    // support constructable KeyboardEvent so we keep it here for now.\n    keyLocation: true\n  };\n\n  /**\n   * Creates a new Event wrapper or wraps an existin native Event object.\n   * @param {string|Event} type\n   * @param {Object=} options\n   * @constructor\n   */\n  function Event(type, options) {\n    if (type instanceof OriginalEvent)\n      this.impl = type;\n    else\n      return wrap(constructEvent(OriginalEvent, 'Event', type, options));\n  }\n  Event.prototype = {\n    get target() {\n      return targetTable.get(this);\n    },\n    get currentTarget() {\n      return currentTargetTable.get(this);\n    },\n    get eventPhase() {\n      return eventPhaseTable.get(this);\n    },\n    get path() {\n      var nodeList = new wrappers.NodeList();\n      var eventPath = eventPathTable.get(this);\n      if (eventPath) {\n        var index = 0;\n        var lastIndex = eventPath.length - 1;\n        var baseRoot = rootOfNode(currentTargetTable.get(this));\n\n        for (var i = 0; i <= lastIndex; i++) {\n          var currentTarget = eventPath[i].currentTarget;\n          var currentRoot = rootOfNode(currentTarget);\n          if (enclosedBy(baseRoot, currentRoot) &&\n              // Make sure we do not add Window to the path.\n              (i !== lastIndex || currentTarget instanceof wrappers.Node)) {\n            nodeList[index++] = currentTarget;\n          }\n        }\n        nodeList.length = index;\n      }\n      return nodeList;\n    },\n    stopPropagation: function() {\n      stopPropagationTable.set(this, true);\n    },\n    stopImmediatePropagation: function() {\n      stopPropagationTable.set(this, true);\n      stopImmediatePropagationTable.set(this, true);\n    }\n  };\n  registerWrapper(OriginalEvent, Event, document.createEvent('Event'));\n\n  function unwrapOptions(options) {\n    if (!options || !options.relatedTarget)\n      return options;\n    return Object.create(options, {\n      relatedTarget: {value: unwrap(options.relatedTarget)}\n    });\n  }\n\n  function registerGenericEvent(name, SuperEvent, prototype) {\n    var OriginalEvent = window[name];\n    var GenericEvent = function(type, options) {\n      if (type instanceof OriginalEvent)\n        this.impl = type;\n      else\n        return wrap(constructEvent(OriginalEvent, name, type, options));\n    };\n    GenericEvent.prototype = Object.create(SuperEvent.prototype);\n    if (prototype)\n      mixin(GenericEvent.prototype, prototype);\n    if (OriginalEvent) {\n      // - Old versions of Safari fails on new FocusEvent (and others?).\n      // - IE does not support event constructors.\n      // - createEvent('FocusEvent') throws in Firefox.\n      // => Try the best practice solution first and fallback to the old way\n      // if needed.\n      try {\n        registerWrapper(OriginalEvent, GenericEvent, new OriginalEvent('temp'));\n      } catch (ex) {\n        registerWrapper(OriginalEvent, GenericEvent,\n                        document.createEvent(name));\n      }\n    }\n    return GenericEvent;\n  }\n\n  var UIEvent = registerGenericEvent('UIEvent', Event);\n  var CustomEvent = registerGenericEvent('CustomEvent', Event);\n\n  var relatedTargetProto = {\n    get relatedTarget() {\n      return relatedTargetTable.get(this) || wrap(unwrap(this).relatedTarget);\n    }\n  };\n\n  function getInitFunction(name, relatedTargetIndex) {\n    return function() {\n      arguments[relatedTargetIndex] = unwrap(arguments[relatedTargetIndex]);\n      var impl = unwrap(this);\n      impl[name].apply(impl, arguments);\n    };\n  }\n\n  var mouseEventProto = mixin({\n    initMouseEvent: getInitFunction('initMouseEvent', 14)\n  }, relatedTargetProto);\n\n  var focusEventProto = mixin({\n    initFocusEvent: getInitFunction('initFocusEvent', 5)\n  }, relatedTargetProto);\n\n  var MouseEvent = registerGenericEvent('MouseEvent', UIEvent, mouseEventProto);\n  var FocusEvent = registerGenericEvent('FocusEvent', UIEvent, focusEventProto);\n\n  // In case the browser does not support event constructors we polyfill that\n  // by calling `createEvent('Foo')` and `initFooEvent` where the arguments to\n  // `initFooEvent` are derived from the registered default event init dict.\n  var defaultInitDicts = Object.create(null);\n\n  var supportsEventConstructors = (function() {\n    try {\n      new window.FocusEvent('focus');\n    } catch (ex) {\n      return false;\n    }\n    return true;\n  })();\n\n  /**\n   * Constructs a new native event.\n   */\n  function constructEvent(OriginalEvent, name, type, options) {\n    if (supportsEventConstructors)\n      return new OriginalEvent(type, unwrapOptions(options));\n\n    // Create the arguments from the default dictionary.\n    var event = unwrap(document.createEvent(name));\n    var defaultDict = defaultInitDicts[name];\n    var args = [type];\n    Object.keys(defaultDict).forEach(function(key) {\n      var v = options != null && key in options ?\n          options[key] : defaultDict[key];\n      if (key === 'relatedTarget')\n        v = unwrap(v);\n      args.push(v);\n    });\n    event['init' + name].apply(event, args);\n    return event;\n  }\n\n  if (!supportsEventConstructors) {\n    var configureEventConstructor = function(name, initDict, superName) {\n      if (superName) {\n        var superDict = defaultInitDicts[superName];\n        initDict = mixin(mixin({}, superDict), initDict);\n      }\n\n      defaultInitDicts[name] = initDict;\n    };\n\n    // The order of the default event init dictionary keys is important, the\n    // arguments to initFooEvent is derived from that.\n    configureEventConstructor('Event', {bubbles: false, cancelable: false});\n    configureEventConstructor('CustomEvent', {detail: null}, 'Event');\n    configureEventConstructor('UIEvent', {view: null, detail: 0}, 'Event');\n    configureEventConstructor('MouseEvent', {\n      screenX: 0,\n      screenY: 0,\n      clientX: 0,\n      clientY: 0,\n      ctrlKey: false,\n      altKey: false,\n      shiftKey: false,\n      metaKey: false,\n      button: 0,\n      relatedTarget: null\n    }, 'UIEvent');\n    configureEventConstructor('FocusEvent', {relatedTarget: null}, 'UIEvent');\n  }\n\n  function BeforeUnloadEvent(impl) {\n    Event.call(this);\n  }\n  BeforeUnloadEvent.prototype = Object.create(Event.prototype);\n  mixin(BeforeUnloadEvent.prototype, {\n    get returnValue() {\n      return this.impl.returnValue;\n    },\n    set returnValue(v) {\n      this.impl.returnValue = v;\n    }\n  });\n\n  function isValidListener(fun) {\n    if (typeof fun === 'function')\n      return true;\n    return fun && fun.handleEvent;\n  }\n\n  function isMutationEvent(type) {\n    switch (type) {\n      case 'DOMAttrModified':\n      case 'DOMAttributeNameChanged':\n      case 'DOMCharacterDataModified':\n      case 'DOMElementNameChanged':\n      case 'DOMNodeInserted':\n      case 'DOMNodeInsertedIntoDocument':\n      case 'DOMNodeRemoved':\n      case 'DOMNodeRemovedFromDocument':\n      case 'DOMSubtreeModified':\n        return true;\n    }\n    return false;\n  }\n\n  var OriginalEventTarget = window.EventTarget;\n\n  /**\n   * This represents a wrapper for an EventTarget.\n   * @param {!EventTarget} impl The original event target.\n   * @constructor\n   */\n  function EventTarget(impl) {\n    this.impl = impl;\n  }\n\n  // Node and Window have different internal type checks in WebKit so we cannot\n  // use the same method as the original function.\n  var methodNames = [\n    'addEventListener',\n    'removeEventListener',\n    'dispatchEvent'\n  ];\n\n  [Node, Window].forEach(function(constructor) {\n    var p = constructor.prototype;\n    methodNames.forEach(function(name) {\n      Object.defineProperty(p, name + '_', {value: p[name]});\n    });\n  });\n\n  function getTargetToListenAt(wrapper) {\n    if (wrapper instanceof wrappers.ShadowRoot)\n      wrapper = wrapper.host;\n    return unwrap(wrapper);\n  }\n\n  EventTarget.prototype = {\n    addEventListener: function(type, fun, capture) {\n      if (!isValidListener(fun) || isMutationEvent(type))\n        return;\n\n      var listener = new Listener(type, fun, capture);\n      var listeners = listenersTable.get(this);\n      if (!listeners) {\n        listeners = [];\n        listenersTable.set(this, listeners);\n      } else {\n        // Might have a duplicate.\n        for (var i = 0; i < listeners.length; i++) {\n          if (listener.equals(listeners[i]))\n            return;\n        }\n      }\n\n      listeners.push(listener);\n\n      var target = getTargetToListenAt(this);\n      target.addEventListener_(type, dispatchOriginalEvent, true);\n    },\n    removeEventListener: function(type, fun, capture) {\n      capture = Boolean(capture);\n      var listeners = listenersTable.get(this);\n      if (!listeners)\n        return;\n      var count = 0, found = false;\n      for (var i = 0; i < listeners.length; i++) {\n        if (listeners[i].type === type && listeners[i].capture === capture) {\n          count++;\n          if (listeners[i].handler === fun) {\n            found = true;\n            listeners[i].remove();\n          }\n        }\n      }\n\n      if (found && count === 1) {\n        var target = getTargetToListenAt(this);\n        target.removeEventListener_(type, dispatchOriginalEvent, true);\n      }\n    },\n    dispatchEvent: function(event) {\n      // We want to use the native dispatchEvent because it triggers the default\n      // actions (like checking a checkbox). However, if there are no listeners\n      // in the composed tree then there are no events that will trigger and\n      // listeners in the non composed tree that are part of the event path are\n      // not notified.\n      //\n      // If we find out that there are no listeners in the composed tree we add\n      // a temporary listener to the target which makes us get called back even\n      // in that case.\n\n      var nativeEvent = unwrap(event);\n      var eventType = nativeEvent.type;\n\n      // Allow dispatching the same event again. This is safe because if user\n      // code calls this during an existing dispatch of the same event the\n      // native dispatchEvent throws (that is required by the spec).\n      handledEventsTable.set(nativeEvent, false);\n\n      // Force rendering since we prefer native dispatch and that works on the\n      // composed tree.\n      scope.renderAllPending();\n\n      var tempListener;\n      if (!hasListenerInAncestors(this, eventType)) {\n        tempListener = function() {};\n        this.addEventListener(eventType, tempListener, true);\n      }\n\n      try {\n        return unwrap(this).dispatchEvent_(nativeEvent);\n      } finally {\n        if (tempListener)\n          this.removeEventListener(eventType, tempListener, true);\n      }\n    }\n  };\n\n  function hasListener(node, type) {\n    var listeners = listenersTable.get(node);\n    if (listeners) {\n      for (var i = 0; i < listeners.length; i++) {\n        if (!listeners[i].removed && listeners[i].type === type)\n          return true;\n      }\n    }\n    return false;\n  }\n\n  function hasListenerInAncestors(target, type) {\n    for (var node = unwrap(target); node; node = node.parentNode) {\n      if (hasListener(wrap(node), type))\n        return true;\n    }\n    return false;\n  }\n\n  if (OriginalEventTarget)\n    registerWrapper(OriginalEventTarget, EventTarget);\n\n  function wrapEventTargetMethods(constructors) {\n    forwardMethodsToWrapper(constructors, methodNames);\n  }\n\n  var originalElementFromPoint = document.elementFromPoint;\n\n  function elementFromPoint(self, document, x, y) {\n    scope.renderAllPending();\n\n    var element = wrap(originalElementFromPoint.call(document.impl, x, y));\n    var targets = retarget(element, this)\n    for (var i = 0; i < targets.length; i++) {\n      var target = targets[i];\n      if (target.currentTarget === self)\n        return target.target;\n    }\n    return null;\n  }\n\n  /**\n   * Returns a function that is to be used as a getter for `onfoo` properties.\n   * @param {string} name\n   * @return {Function}\n   */\n  function getEventHandlerGetter(name) {\n    return function() {\n      var inlineEventHandlers = eventHandlersTable.get(this);\n      return inlineEventHandlers && inlineEventHandlers[name] &&\n          inlineEventHandlers[name].value || null;\n     };\n  }\n\n  /**\n   * Returns a function that is to be used as a setter for `onfoo` properties.\n   * @param {string} name\n   * @return {Function}\n   */\n  function getEventHandlerSetter(name) {\n    var eventType = name.slice(2);\n    return function(value) {\n      var inlineEventHandlers = eventHandlersTable.get(this);\n      if (!inlineEventHandlers) {\n        inlineEventHandlers = Object.create(null);\n        eventHandlersTable.set(this, inlineEventHandlers);\n      }\n\n      var old = inlineEventHandlers[name];\n      if (old)\n        this.removeEventListener(eventType, old.wrapped, false);\n\n      if (typeof value === 'function') {\n        var wrapped = function(e) {\n          var rv = value.call(this, e);\n          if (rv === false)\n            e.preventDefault();\n          else if (name === 'onbeforeunload' && typeof rv === 'string')\n            e.returnValue = rv;\n          // mouseover uses true for preventDefault but preventDefault for\n          // mouseover is ignored by browsers these day.\n        };\n\n        this.addEventListener(eventType, wrapped, false);\n        inlineEventHandlers[name] = {\n          value: value,\n          wrapped: wrapped\n        };\n      }\n    };\n  }\n\n  scope.adjustRelatedTarget = adjustRelatedTarget;\n  scope.elementFromPoint = elementFromPoint;\n  scope.getEventHandlerGetter = getEventHandlerGetter;\n  scope.getEventHandlerSetter = getEventHandlerSetter;\n  scope.wrapEventTargetMethods = wrapEventTargetMethods;\n  scope.wrappers.BeforeUnloadEvent = BeforeUnloadEvent;\n  scope.wrappers.CustomEvent = CustomEvent;\n  scope.wrappers.Event = Event;\n  scope.wrappers.EventTarget = EventTarget;\n  scope.wrappers.FocusEvent = FocusEvent;\n  scope.wrappers.MouseEvent = MouseEvent;\n  scope.wrappers.UIEvent = UIEvent;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2012 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var wrap = scope.wrap;\n\n  function nonEnum(obj, prop) {\n    Object.defineProperty(obj, prop, {enumerable: false});\n  }\n\n  function NodeList() {\n    this.length = 0;\n    nonEnum(this, 'length');\n  }\n  NodeList.prototype = {\n    item: function(index) {\n      return this[index];\n    }\n  };\n  nonEnum(NodeList.prototype, 'item');\n\n  function wrapNodeList(list) {\n    if (list == null)\n      return list;\n    var wrapperList = new NodeList();\n    for (var i = 0, length = list.length; i < length; i++) {\n      wrapperList[i] = wrap(list[i]);\n    }\n    wrapperList.length = length;\n    return wrapperList;\n  }\n\n  function addWrapNodeListMethod(wrapperConstructor, name) {\n    wrapperConstructor.prototype[name] = function() {\n      return wrapNodeList(this.impl[name].apply(this.impl, arguments));\n    };\n  }\n\n  scope.wrappers.NodeList = NodeList;\n  scope.addWrapNodeListMethod = addWrapNodeListMethod;\n  scope.wrapNodeList = wrapNodeList;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2012 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var EventTarget = scope.wrappers.EventTarget;\n  var NodeList = scope.wrappers.NodeList;\n  var assert = scope.assert;\n  var defineWrapGetter = scope.defineWrapGetter;\n  var enqueueMutation = scope.enqueueMutation;\n  var isWrapper = scope.isWrapper;\n  var mixin = scope.mixin;\n  var registerTransientObservers = scope.registerTransientObservers;\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n  var wrapIfNeeded = scope.wrapIfNeeded;\n  var wrappers = scope.wrappers;\n\n  function assertIsNodeWrapper(node) {\n    assert(node instanceof Node);\n  }\n\n  function createOneElementNodeList(node) {\n    var nodes = new NodeList();\n    nodes[0] = node;\n    nodes.length = 1;\n    return nodes;\n  }\n\n  var surpressMutations = false;\n\n  /**\n   * Called before node is inserted into a node to enqueue its removal from its\n   * old parent.\n   * @param {!Node} node The node that is about to be removed.\n   * @param {!Node} parent The parent node that the node is being removed from.\n   * @param {!NodeList} nodes The collected nodes.\n   */\n  function enqueueRemovalForInsertedNodes(node, parent, nodes) {\n    enqueueMutation(parent, 'childList', {\n      removedNodes: nodes,\n      previousSibling: node.previousSibling,\n      nextSibling: node.nextSibling\n    });\n  }\n\n  function enqueueRemovalForInsertedDocumentFragment(df, nodes) {\n    enqueueMutation(df, 'childList', {\n      removedNodes: nodes\n    });\n  }\n\n  /**\n   * Collects nodes from a DocumentFragment or a Node for removal followed\n   * by an insertion.\n   *\n   * This updates the internal pointers for node, previousNode and nextNode.\n   */\n  function collectNodes(node, parentNode, previousNode, nextNode) {\n    if (node instanceof DocumentFragment) {\n      var nodes = collectNodesForDocumentFragment(node);\n\n      // The extra loop is to work around bugs with DocumentFragments in IE.\n      surpressMutations = true;\n      for (var i = nodes.length - 1; i >= 0; i--) {\n        node.removeChild(nodes[i]);\n        nodes[i].parentNode_ = parentNode;\n      }\n      surpressMutations = false;\n\n      for (var i = 0; i < nodes.length; i++) {\n        nodes[i].previousSibling_ = nodes[i - 1] || previousNode;\n        nodes[i].nextSibling_ = nodes[i + 1] || nextNode;\n      }\n\n      if (previousNode)\n        previousNode.nextSibling_ = nodes[0];\n      if (nextNode)\n        nextNode.previousSibling_ = nodes[nodes.length - 1];\n\n      return nodes;\n    }\n\n    var nodes = createOneElementNodeList(node);\n    var oldParent = node.parentNode;\n    if (oldParent) {\n      // This will enqueue the mutation record for the removal as needed.\n      oldParent.removeChild(node);\n    }\n\n    node.parentNode_ = parentNode;\n    node.previousSibling_ = previousNode;\n    node.nextSibling_ = nextNode;\n    if (previousNode)\n      previousNode.nextSibling_ = node;\n    if (nextNode)\n      nextNode.previousSibling_ = node;\n\n    return nodes;\n  }\n\n  function collectNodesNative(node) {\n    if (node instanceof DocumentFragment)\n      return collectNodesForDocumentFragment(node);\n\n    var nodes = createOneElementNodeList(node);\n    var oldParent = node.parentNode;\n    if (oldParent)\n      enqueueRemovalForInsertedNodes(node, oldParent, nodes);\n    return nodes;\n  }\n\n  function collectNodesForDocumentFragment(node) {\n    var nodes = new NodeList();\n    var i = 0;\n    for (var child = node.firstChild; child; child = child.nextSibling) {\n      nodes[i++] = child;\n    }\n    nodes.length = i;\n    enqueueRemovalForInsertedDocumentFragment(node, nodes);\n    return nodes;\n  }\n\n  function snapshotNodeList(nodeList) {\n    // NodeLists are not live at the moment so just return the same object.\n    return nodeList;\n  }\n\n  // http://dom.spec.whatwg.org/#node-is-inserted\n  function nodeWasAdded(node) {\n    node.nodeIsInserted_();\n  }\n\n  function nodesWereAdded(nodes) {\n    for (var i = 0; i < nodes.length; i++) {\n      nodeWasAdded(nodes[i]);\n    }\n  }\n\n  // http://dom.spec.whatwg.org/#node-is-removed\n  function nodeWasRemoved(node) {\n    // Nothing at this point in time.\n  }\n\n  function nodesWereRemoved(nodes) {\n    // Nothing at this point in time.\n  }\n\n  function ensureSameOwnerDocument(parent, child) {\n    var ownerDoc = parent.nodeType === Node.DOCUMENT_NODE ?\n        parent : parent.ownerDocument;\n    if (ownerDoc !== child.ownerDocument)\n      ownerDoc.adoptNode(child);\n  }\n\n  function adoptNodesIfNeeded(owner, nodes) {\n    if (!nodes.length)\n      return;\n\n    var ownerDoc = owner.ownerDocument;\n\n    // All nodes have the same ownerDocument when we get here.\n    if (ownerDoc === nodes[0].ownerDocument)\n      return;\n\n    for (var i = 0; i < nodes.length; i++) {\n      scope.adoptNodeNoRemove(nodes[i], ownerDoc);\n    }\n  }\n\n  function unwrapNodesForInsertion(owner, nodes) {\n    adoptNodesIfNeeded(owner, nodes);\n    var length = nodes.length;\n\n    if (length === 1)\n      return unwrap(nodes[0]);\n\n    var df = unwrap(owner.ownerDocument.createDocumentFragment());\n    for (var i = 0; i < length; i++) {\n      df.appendChild(unwrap(nodes[i]));\n    }\n    return df;\n  }\n\n  function clearChildNodes(wrapper) {\n    if (wrapper.firstChild_ !== undefined) {\n      var child = wrapper.firstChild_;\n      while (child) {\n        var tmp = child;\n        child = child.nextSibling_;\n        tmp.parentNode_ = tmp.previousSibling_ = tmp.nextSibling_ = undefined;\n      }\n    }\n    wrapper.firstChild_ = wrapper.lastChild_ = undefined;\n  }\n\n  function removeAllChildNodes(wrapper) {\n    if (wrapper.invalidateShadowRenderer()) {\n      var childWrapper = wrapper.firstChild;\n      while (childWrapper) {\n        assert(childWrapper.parentNode === wrapper);\n        var nextSibling = childWrapper.nextSibling;\n        var childNode = unwrap(childWrapper);\n        var parentNode = childNode.parentNode;\n        if (parentNode)\n          originalRemoveChild.call(parentNode, childNode);\n        childWrapper.previousSibling_ = childWrapper.nextSibling_ =\n            childWrapper.parentNode_ = null;\n        childWrapper = nextSibling;\n      }\n      wrapper.firstChild_ = wrapper.lastChild_ = null;\n    } else {\n      var node = unwrap(wrapper);\n      var child = node.firstChild;\n      var nextSibling;\n      while (child) {\n        nextSibling = child.nextSibling;\n        originalRemoveChild.call(node, child);\n        child = nextSibling;\n      }\n    }\n  }\n\n  function invalidateParent(node) {\n    var p = node.parentNode;\n    return p && p.invalidateShadowRenderer();\n  }\n\n  function cleanupNodes(nodes) {\n    for (var i = 0, n; i < nodes.length; i++) {\n      n = nodes[i];\n      n.parentNode.removeChild(n);\n    }\n  }\n\n  var originalImportNode = document.importNode;\n  var originalCloneNode = window.Node.prototype.cloneNode;\n\n  function cloneNode(node, deep, opt_doc) {\n    var clone;\n    if (opt_doc)\n      clone = wrap(originalImportNode.call(opt_doc, node.impl, false));\n    else\n      clone = wrap(originalCloneNode.call(node.impl, false));\n\n    if (deep) {\n      for (var child = node.firstChild; child; child = child.nextSibling) {\n        clone.appendChild(cloneNode(child, true, opt_doc));\n      }\n\n      if (node instanceof wrappers.HTMLTemplateElement) {\n        var cloneContent = clone.content;\n        for (var child = node.content.firstChild;\n             child;\n             child = child.nextSibling) {\n         cloneContent.appendChild(cloneNode(child, true, opt_doc));\n        }\n      }\n    }\n    // TODO(arv): Some HTML elements also clone other data like value.\n    return clone;\n  }\n\n  var OriginalNode = window.Node;\n\n  /**\n   * This represents a wrapper of a native DOM node.\n   * @param {!Node} original The original DOM node, aka, the visual DOM node.\n   * @constructor\n   * @extends {EventTarget}\n   */\n  function Node(original) {\n    assert(original instanceof OriginalNode);\n\n    EventTarget.call(this, original);\n\n    // These properties are used to override the visual references with the\n    // logical ones. If the value is undefined it means that the logical is the\n    // same as the visual.\n\n    /**\n     * @type {Node|undefined}\n     * @private\n     */\n    this.parentNode_ = undefined;\n\n    /**\n     * @type {Node|undefined}\n     * @private\n     */\n    this.firstChild_ = undefined;\n\n    /**\n     * @type {Node|undefined}\n     * @private\n     */\n    this.lastChild_ = undefined;\n\n    /**\n     * @type {Node|undefined}\n     * @private\n     */\n    this.nextSibling_ = undefined;\n\n    /**\n     * @type {Node|undefined}\n     * @private\n     */\n    this.previousSibling_ = undefined;\n  }\n\n  var OriginalDocumentFragment = window.DocumentFragment;\n  var originalAppendChild = OriginalNode.prototype.appendChild;\n  var originalCompareDocumentPosition =\n      OriginalNode.prototype.compareDocumentPosition;\n  var originalInsertBefore = OriginalNode.prototype.insertBefore;\n  var originalRemoveChild = OriginalNode.prototype.removeChild;\n  var originalReplaceChild = OriginalNode.prototype.replaceChild;\n\n  var isIe = /Trident/.test(navigator.userAgent);\n\n  var removeChildOriginalHelper = isIe ?\n      function(parent, child) {\n        try {\n          originalRemoveChild.call(parent, child);\n        } catch (ex) {\n          if (!(parent instanceof OriginalDocumentFragment))\n            throw ex;\n        }\n      } :\n      function(parent, child) {\n        originalRemoveChild.call(parent, child);\n      };\n\n  Node.prototype = Object.create(EventTarget.prototype);\n  mixin(Node.prototype, {\n    appendChild: function(childWrapper) {\n      return this.insertBefore(childWrapper, null);\n    },\n\n    insertBefore: function(childWrapper, refWrapper) {\n      assertIsNodeWrapper(childWrapper);\n\n      var refNode;\n      if (refWrapper) {\n        if (isWrapper(refWrapper)) {\n          refNode = unwrap(refWrapper);\n        } else {\n          refNode = refWrapper;\n          refWrapper = wrap(refNode);\n        }\n      } else {\n        refWrapper = null;\n        refNode = null;\n      }\n\n      refWrapper && assert(refWrapper.parentNode === this);\n\n      var nodes;\n      var previousNode =\n          refWrapper ? refWrapper.previousSibling : this.lastChild;\n\n      var useNative = !this.invalidateShadowRenderer() &&\n                      !invalidateParent(childWrapper);\n\n      if (useNative)\n        nodes = collectNodesNative(childWrapper);\n      else\n        nodes = collectNodes(childWrapper, this, previousNode, refWrapper);\n\n      if (useNative) {\n        ensureSameOwnerDocument(this, childWrapper);\n        clearChildNodes(this);\n        originalInsertBefore.call(this.impl, unwrap(childWrapper), refNode);\n      } else {\n        if (!previousNode)\n          this.firstChild_ = nodes[0];\n        if (!refWrapper)\n          this.lastChild_ = nodes[nodes.length - 1];\n\n        var parentNode = refNode ? refNode.parentNode : this.impl;\n\n        // insertBefore refWrapper no matter what the parent is?\n        if (parentNode) {\n          originalInsertBefore.call(parentNode,\n              unwrapNodesForInsertion(this, nodes), refNode);\n        } else {\n          adoptNodesIfNeeded(this, nodes);\n        }\n      }\n\n      enqueueMutation(this, 'childList', {\n        addedNodes: nodes,\n        nextSibling: refWrapper,\n        previousSibling: previousNode\n      });\n\n      nodesWereAdded(nodes);\n\n      return childWrapper;\n    },\n\n    removeChild: function(childWrapper) {\n      assertIsNodeWrapper(childWrapper);\n      if (childWrapper.parentNode !== this) {\n        // IE has invalid DOM trees at times.\n        var found = false;\n        var childNodes = this.childNodes;\n        for (var ieChild = this.firstChild; ieChild;\n             ieChild = ieChild.nextSibling) {\n          if (ieChild === childWrapper) {\n            found = true;\n            break;\n          }\n        }\n        if (!found) {\n          // TODO(arv): DOMException\n          throw new Error('NotFoundError');\n        }\n      }\n\n      var childNode = unwrap(childWrapper);\n      var childWrapperNextSibling = childWrapper.nextSibling;\n      var childWrapperPreviousSibling = childWrapper.previousSibling;\n\n      if (this.invalidateShadowRenderer()) {\n        // We need to remove the real node from the DOM before updating the\n        // pointers. This is so that that mutation event is dispatched before\n        // the pointers have changed.\n        var thisFirstChild = this.firstChild;\n        var thisLastChild = this.lastChild;\n\n        var parentNode = childNode.parentNode;\n        if (parentNode)\n          removeChildOriginalHelper(parentNode, childNode);\n\n        if (thisFirstChild === childWrapper)\n          this.firstChild_ = childWrapperNextSibling;\n        if (thisLastChild === childWrapper)\n          this.lastChild_ = childWrapperPreviousSibling;\n        if (childWrapperPreviousSibling)\n          childWrapperPreviousSibling.nextSibling_ = childWrapperNextSibling;\n        if (childWrapperNextSibling) {\n          childWrapperNextSibling.previousSibling_ =\n              childWrapperPreviousSibling;\n        }\n\n        childWrapper.previousSibling_ = childWrapper.nextSibling_ =\n            childWrapper.parentNode_ = undefined;\n      } else {\n        clearChildNodes(this);\n        removeChildOriginalHelper(this.impl, childNode);\n      }\n\n      if (!surpressMutations) {\n        enqueueMutation(this, 'childList', {\n          removedNodes: createOneElementNodeList(childWrapper),\n          nextSibling: childWrapperNextSibling,\n          previousSibling: childWrapperPreviousSibling\n        });\n      }\n\n      registerTransientObservers(this, childWrapper);\n\n      return childWrapper;\n    },\n\n    replaceChild: function(newChildWrapper, oldChildWrapper) {\n      assertIsNodeWrapper(newChildWrapper);\n\n      var oldChildNode;\n      if (isWrapper(oldChildWrapper)) {\n        oldChildNode = unwrap(oldChildWrapper);\n      } else {\n        oldChildNode = oldChildWrapper;\n        oldChildWrapper = wrap(oldChildNode);\n      }\n\n      if (oldChildWrapper.parentNode !== this) {\n        // TODO(arv): DOMException\n        throw new Error('NotFoundError');\n      }\n\n      var nextNode = oldChildWrapper.nextSibling;\n      var previousNode = oldChildWrapper.previousSibling;\n      var nodes;\n\n      var useNative = !this.invalidateShadowRenderer() &&\n                      !invalidateParent(newChildWrapper);\n\n      if (useNative) {\n        nodes = collectNodesNative(newChildWrapper);\n      } else {\n        if (nextNode === newChildWrapper)\n          nextNode = newChildWrapper.nextSibling;\n        nodes = collectNodes(newChildWrapper, this, previousNode, nextNode);\n      }\n\n      if (!useNative) {\n        if (this.firstChild === oldChildWrapper)\n          this.firstChild_ = nodes[0];\n        if (this.lastChild === oldChildWrapper)\n          this.lastChild_ = nodes[nodes.length - 1];\n\n        oldChildWrapper.previousSibling_ = oldChildWrapper.nextSibling_ =\n            oldChildWrapper.parentNode_ = undefined;\n\n        // replaceChild no matter what the parent is?\n        if (oldChildNode.parentNode) {\n          originalReplaceChild.call(\n              oldChildNode.parentNode,\n              unwrapNodesForInsertion(this, nodes),\n              oldChildNode);\n        }\n      } else {\n        ensureSameOwnerDocument(this, newChildWrapper);\n        clearChildNodes(this);\n        originalReplaceChild.call(this.impl, unwrap(newChildWrapper),\n                                  oldChildNode);\n      }\n\n      enqueueMutation(this, 'childList', {\n        addedNodes: nodes,\n        removedNodes: createOneElementNodeList(oldChildWrapper),\n        nextSibling: nextNode,\n        previousSibling: previousNode\n      });\n\n      nodeWasRemoved(oldChildWrapper);\n      nodesWereAdded(nodes);\n\n      return oldChildWrapper;\n    },\n\n    /**\n     * Called after a node was inserted. Subclasses override this to invalidate\n     * the renderer as needed.\n     * @private\n     */\n    nodeIsInserted_: function() {\n      for (var child = this.firstChild; child; child = child.nextSibling) {\n        child.nodeIsInserted_();\n      }\n    },\n\n    hasChildNodes: function() {\n      return this.firstChild !== null;\n    },\n\n    /** @type {Node} */\n    get parentNode() {\n      // If the parentNode has not been overridden, use the original parentNode.\n      return this.parentNode_ !== undefined ?\n          this.parentNode_ : wrap(this.impl.parentNode);\n    },\n\n    /** @type {Node} */\n    get firstChild() {\n      return this.firstChild_ !== undefined ?\n          this.firstChild_ : wrap(this.impl.firstChild);\n    },\n\n    /** @type {Node} */\n    get lastChild() {\n      return this.lastChild_ !== undefined ?\n          this.lastChild_ : wrap(this.impl.lastChild);\n    },\n\n    /** @type {Node} */\n    get nextSibling() {\n      return this.nextSibling_ !== undefined ?\n          this.nextSibling_ : wrap(this.impl.nextSibling);\n    },\n\n    /** @type {Node} */\n    get previousSibling() {\n      return this.previousSibling_ !== undefined ?\n          this.previousSibling_ : wrap(this.impl.previousSibling);\n    },\n\n    get parentElement() {\n      var p = this.parentNode;\n      while (p && p.nodeType !== Node.ELEMENT_NODE) {\n        p = p.parentNode;\n      }\n      return p;\n    },\n\n    get textContent() {\n      // TODO(arv): This should fallback to this.impl.textContent if there\n      // are no shadow trees below or above the context node.\n      var s = '';\n      for (var child = this.firstChild; child; child = child.nextSibling) {\n        if (child.nodeType != Node.COMMENT_NODE) {\n          s += child.textContent;\n        }\n      }\n      return s;\n    },\n    set textContent(textContent) {\n      var removedNodes = snapshotNodeList(this.childNodes);\n\n      if (this.invalidateShadowRenderer()) {\n        removeAllChildNodes(this);\n        if (textContent !== '') {\n          var textNode = this.impl.ownerDocument.createTextNode(textContent);\n          this.appendChild(textNode);\n        }\n      } else {\n        clearChildNodes(this);\n        this.impl.textContent = textContent;\n      }\n\n      var addedNodes = snapshotNodeList(this.childNodes);\n\n      enqueueMutation(this, 'childList', {\n        addedNodes: addedNodes,\n        removedNodes: removedNodes\n      });\n\n      nodesWereRemoved(removedNodes);\n      nodesWereAdded(addedNodes);\n    },\n\n    get childNodes() {\n      var wrapperList = new NodeList();\n      var i = 0;\n      for (var child = this.firstChild; child; child = child.nextSibling) {\n        wrapperList[i++] = child;\n      }\n      wrapperList.length = i;\n      return wrapperList;\n    },\n\n    cloneNode: function(deep) {\n      return cloneNode(this, deep);\n    },\n\n    contains: function(child) {\n      if (!child)\n        return false;\n\n      child = wrapIfNeeded(child);\n\n      // TODO(arv): Optimize using ownerDocument etc.\n      if (child === this)\n        return true;\n      var parentNode = child.parentNode;\n      if (!parentNode)\n        return false;\n      return this.contains(parentNode);\n    },\n\n    compareDocumentPosition: function(otherNode) {\n      // This only wraps, it therefore only operates on the composed DOM and not\n      // the logical DOM.\n      return originalCompareDocumentPosition.call(this.impl, unwrap(otherNode));\n    },\n\n    normalize: function() {\n      var nodes = snapshotNodeList(this.childNodes);\n      var remNodes = [];\n      var s = '';\n      var modNode;\n\n      for (var i = 0, n; i < nodes.length; i++) {\n        n = nodes[i];\n        if (n.nodeType === Node.TEXT_NODE) {\n          if (!modNode && !n.data.length)\n            this.removeNode(n);\n          else if (!modNode)\n            modNode = n;\n          else {\n            s += n.data;\n            remNodes.push(n);\n          }\n        } else {\n          if (modNode && remNodes.length) {\n            modNode.data += s;\n            cleanUpNodes(remNodes);\n          }\n          remNodes = [];\n          s = '';\n          modNode = null;\n          if (n.childNodes.length)\n            n.normalize();\n        }\n      }\n\n      // handle case where >1 text nodes are the last children\n      if (modNode && remNodes.length) {\n        modNode.data += s;\n        cleanupNodes(remNodes);\n      }\n    }\n  });\n\n  defineWrapGetter(Node, 'ownerDocument');\n\n  // We use a DocumentFragment as a base and then delete the properties of\n  // DocumentFragment.prototype from the wrapper Node. Since delete makes\n  // objects slow in some JS engines we recreate the prototype object.\n  registerWrapper(OriginalNode, Node, document.createDocumentFragment());\n  delete Node.prototype.querySelector;\n  delete Node.prototype.querySelectorAll;\n  Node.prototype = mixin(Object.create(EventTarget.prototype), Node.prototype);\n\n  scope.nodeWasAdded = nodeWasAdded;\n  scope.nodeWasRemoved = nodeWasRemoved;\n  scope.nodesWereAdded = nodesWereAdded;\n  scope.nodesWereRemoved = nodesWereRemoved;\n  scope.snapshotNodeList = snapshotNodeList;\n  scope.wrappers.Node = Node;\n  scope.cloneNode = cloneNode;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  function findOne(node, selector) {\n    var m, el = node.firstElementChild;\n    while (el) {\n      if (el.matches(selector))\n        return el;\n      m = findOne(el, selector);\n      if (m)\n        return m;\n      el = el.nextElementSibling;\n    }\n    return null;\n  }\n\n  function findAll(node, selector, results) {\n    var el = node.firstElementChild;\n    while (el) {\n      if (el.matches(selector))\n        results[results.length++] = el;\n      findAll(el, selector, results);\n      el = el.nextElementSibling;\n    }\n    return results;\n  }\n\n  // find and findAll will only match Simple Selectors,\n  // Structural Pseudo Classes are not guarenteed to be correct\n  // http://www.w3.org/TR/css3-selectors/#simple-selectors\n\n  var SelectorsInterface = {\n    querySelector: function(selector) {\n      return findOne(this, selector);\n    },\n    querySelectorAll: function(selector) {\n      return findAll(this, selector, new NodeList())\n    }\n  };\n\n  var GetElementsByInterface = {\n    getElementsByTagName: function(tagName) {\n      // TODO(arv): Check tagName?\n      return this.querySelectorAll(tagName);\n    },\n    getElementsByClassName: function(className) {\n      // TODO(arv): Check className?\n      return this.querySelectorAll('.' + className);\n    },\n    getElementsByTagNameNS: function(ns, tagName) {\n      if (ns === '*')\n        return this.getElementsByTagName(tagName);\n\n      // TODO(arv): Check tagName?\n      var result = new NodeList;\n      var els = this.getElementsByTagName(tagName);\n      for (var i = 0, j = 0; i < els.length; i++) {\n        if (els[i].namespaceURI === ns)\n          result[j++] = els[i];\n      }\n      result.length = j;\n      return result;\n    }\n  };\n\n  scope.GetElementsByInterface = GetElementsByInterface;\n  scope.SelectorsInterface = SelectorsInterface;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var NodeList = scope.wrappers.NodeList;\n\n  function forwardElement(node) {\n    while (node && node.nodeType !== Node.ELEMENT_NODE) {\n      node = node.nextSibling;\n    }\n    return node;\n  }\n\n  function backwardsElement(node) {\n    while (node && node.nodeType !== Node.ELEMENT_NODE) {\n      node = node.previousSibling;\n    }\n    return node;\n  }\n\n  var ParentNodeInterface = {\n    get firstElementChild() {\n      return forwardElement(this.firstChild);\n    },\n\n    get lastElementChild() {\n      return backwardsElement(this.lastChild);\n    },\n\n    get childElementCount() {\n      var count = 0;\n      for (var child = this.firstElementChild;\n           child;\n           child = child.nextElementSibling) {\n        count++;\n      }\n      return count;\n    },\n\n    get children() {\n      var wrapperList = new NodeList();\n      var i = 0;\n      for (var child = this.firstElementChild;\n           child;\n           child = child.nextElementSibling) {\n        wrapperList[i++] = child;\n      }\n      wrapperList.length = i;\n      return wrapperList;\n    }\n  };\n\n  var ChildNodeInterface = {\n    get nextElementSibling() {\n      return forwardElement(this.nextSibling);\n    },\n\n    get previousElementSibling() {\n      return backwardsElement(this.previousSibling);\n    }\n  };\n\n  scope.ChildNodeInterface = ChildNodeInterface;\n  scope.ParentNodeInterface = ParentNodeInterface;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var ChildNodeInterface = scope.ChildNodeInterface;\n  var Node = scope.wrappers.Node;\n  var enqueueMutation = scope.enqueueMutation;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n\n  var OriginalCharacterData = window.CharacterData;\n\n  function CharacterData(node) {\n    Node.call(this, node);\n  }\n  CharacterData.prototype = Object.create(Node.prototype);\n  mixin(CharacterData.prototype, {\n    get textContent() {\n      return this.data;\n    },\n    set textContent(value) {\n      this.data = value;\n    },\n    get data() {\n      return this.impl.data;\n    },\n    set data(value) {\n      var oldValue = this.impl.data;\n      enqueueMutation(this, 'characterData', {\n        oldValue: oldValue\n      });\n      this.impl.data = value;\n    }\n  });\n\n  mixin(CharacterData.prototype, ChildNodeInterface);\n\n  registerWrapper(OriginalCharacterData, CharacterData,\n                  document.createTextNode(''));\n\n  scope.wrappers.CharacterData = CharacterData;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2014 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var CharacterData = scope.wrappers.CharacterData;\n  var enqueueMutation = scope.enqueueMutation;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n\n  function toUInt32(x) {\n    return x >>> 0;\n  }\n\n  var OriginalText = window.Text;\n\n  function Text(node) {\n    CharacterData.call(this, node);\n  }\n  Text.prototype = Object.create(CharacterData.prototype);\n  mixin(Text.prototype, {\n    splitText: function(offset) {\n      offset = toUInt32(offset);\n      var s = this.data;\n      if (offset > s.length)\n        throw new Error('IndexSizeError');\n      var head = s.slice(0, offset);\n      var tail = s.slice(offset);\n      this.data = head;\n      var newTextNode = this.ownerDocument.createTextNode(tail);\n      if (this.parentNode)\n        this.parentNode.insertBefore(newTextNode, this.nextSibling);\n      return newTextNode;\n    }\n  });\n\n  registerWrapper(OriginalText, Text, document.createTextNode(''));\n\n  scope.wrappers.Text = Text;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var ChildNodeInterface = scope.ChildNodeInterface;\n  var GetElementsByInterface = scope.GetElementsByInterface;\n  var Node = scope.wrappers.Node;\n  var ParentNodeInterface = scope.ParentNodeInterface;\n  var SelectorsInterface = scope.SelectorsInterface;\n  var addWrapNodeListMethod = scope.addWrapNodeListMethod;\n  var enqueueMutation = scope.enqueueMutation;\n  var mixin = scope.mixin;\n  var oneOf = scope.oneOf;\n  var registerWrapper = scope.registerWrapper;\n  var wrappers = scope.wrappers;\n\n  var OriginalElement = window.Element;\n\n  var matchesNames = [\n    'matches',  // needs to come first.\n    'mozMatchesSelector',\n    'msMatchesSelector',\n    'webkitMatchesSelector',\n  ].filter(function(name) {\n    return OriginalElement.prototype[name];\n  });\n\n  var matchesName = matchesNames[0];\n\n  var originalMatches = OriginalElement.prototype[matchesName];\n\n  function invalidateRendererBasedOnAttribute(element, name) {\n    // Only invalidate if parent node is a shadow host.\n    var p = element.parentNode;\n    if (!p || !p.shadowRoot)\n      return;\n\n    var renderer = scope.getRendererForHost(p);\n    if (renderer.dependsOnAttribute(name))\n      renderer.invalidate();\n  }\n\n  function enqueAttributeChange(element, name, oldValue) {\n    // This is not fully spec compliant. We should use localName (which might\n    // have a different case than name) and the namespace (which requires us\n    // to get the Attr object).\n    enqueueMutation(element, 'attributes', {\n      name: name,\n      namespace: null,\n      oldValue: oldValue\n    });\n  }\n\n  function Element(node) {\n    Node.call(this, node);\n  }\n  Element.prototype = Object.create(Node.prototype);\n  mixin(Element.prototype, {\n    createShadowRoot: function() {\n      var newShadowRoot = new wrappers.ShadowRoot(this);\n      this.impl.polymerShadowRoot_ = newShadowRoot;\n\n      var renderer = scope.getRendererForHost(this);\n      renderer.invalidate();\n\n      return newShadowRoot;\n    },\n\n    get shadowRoot() {\n      return this.impl.polymerShadowRoot_ || null;\n    },\n\n    setAttribute: function(name, value) {\n      var oldValue = this.impl.getAttribute(name);\n      this.impl.setAttribute(name, value);\n      enqueAttributeChange(this, name, oldValue);\n      invalidateRendererBasedOnAttribute(this, name);\n    },\n\n    removeAttribute: function(name) {\n      var oldValue = this.impl.getAttribute(name);\n      this.impl.removeAttribute(name);\n      enqueAttributeChange(this, name, oldValue);\n      invalidateRendererBasedOnAttribute(this, name);\n    },\n\n    matches: function(selector) {\n      return originalMatches.call(this.impl, selector);\n    }\n  });\n\n  matchesNames.forEach(function(name) {\n    if (name !== 'matches') {\n      Element.prototype[name] = function(selector) {\n        return this.matches(selector);\n      };\n    }\n  });\n\n  if (OriginalElement.prototype.webkitCreateShadowRoot) {\n    Element.prototype.webkitCreateShadowRoot =\n        Element.prototype.createShadowRoot;\n  }\n\n  /**\n   * Useful for generating the accessor pair for a property that reflects an\n   * attribute.\n   */\n  function setterDirtiesAttribute(prototype, propertyName, opt_attrName) {\n    var attrName = opt_attrName || propertyName;\n    Object.defineProperty(prototype, propertyName, {\n      get: function() {\n        return this.impl[propertyName];\n      },\n      set: function(v) {\n        this.impl[propertyName] = v;\n        invalidateRendererBasedOnAttribute(this, attrName);\n      },\n      configurable: true,\n      enumerable: true\n    });\n  }\n\n  setterDirtiesAttribute(Element.prototype, 'id');\n  setterDirtiesAttribute(Element.prototype, 'className', 'class');\n\n  mixin(Element.prototype, ChildNodeInterface);\n  mixin(Element.prototype, GetElementsByInterface);\n  mixin(Element.prototype, ParentNodeInterface);\n  mixin(Element.prototype, SelectorsInterface);\n\n  registerWrapper(OriginalElement, Element,\n                  document.createElementNS(null, 'x'));\n\n  // TODO(arv): Export setterDirtiesAttribute and apply it to more bindings\n  // that reflect attributes.\n  scope.matchesNames = matchesNames;\n  scope.wrappers.Element = Element;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var Element = scope.wrappers.Element;\n  var defineGetter = scope.defineGetter;\n  var enqueueMutation = scope.enqueueMutation;\n  var mixin = scope.mixin;\n  var nodesWereAdded = scope.nodesWereAdded;\n  var nodesWereRemoved = scope.nodesWereRemoved;\n  var registerWrapper = scope.registerWrapper;\n  var snapshotNodeList = scope.snapshotNodeList;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n  var wrappers = scope.wrappers;\n\n  /////////////////////////////////////////////////////////////////////////////\n  // innerHTML and outerHTML\n\n  // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#escapingString\n  var escapeAttrRegExp = /[&\\u00A0\"]/g;\n  var escapeDataRegExp = /[&\\u00A0<>]/g;\n\n  function escapeReplace(c) {\n    switch (c) {\n      case '&':\n        return '&amp;';\n      case '<':\n        return '&lt;';\n      case '>':\n        return '&gt;';\n      case '\"':\n        return '&quot;'\n      case '\\u00A0':\n        return '&nbsp;';\n    }\n  }\n\n  function escapeAttr(s) {\n    return s.replace(escapeAttrRegExp, escapeReplace);\n  }\n\n  function escapeData(s) {\n    return s.replace(escapeDataRegExp, escapeReplace);\n  }\n\n  function makeSet(arr) {\n    var set = {};\n    for (var i = 0; i < arr.length; i++) {\n      set[arr[i]] = true;\n    }\n    return set;\n  }\n\n  // http://www.whatwg.org/specs/web-apps/current-work/#void-elements\n  var voidElements = makeSet([\n    'area',\n    'base',\n    'br',\n    'col',\n    'command',\n    'embed',\n    'hr',\n    'img',\n    'input',\n    'keygen',\n    'link',\n    'meta',\n    'param',\n    'source',\n    'track',\n    'wbr'\n  ]);\n\n  var plaintextParents = makeSet([\n    'style',\n    'script',\n    'xmp',\n    'iframe',\n    'noembed',\n    'noframes',\n    'plaintext',\n    'noscript'\n  ]);\n\n  function getOuterHTML(node, parentNode) {\n    switch (node.nodeType) {\n      case Node.ELEMENT_NODE:\n        var tagName = node.tagName.toLowerCase();\n        var s = '<' + tagName;\n        var attrs = node.attributes;\n        for (var i = 0, attr; attr = attrs[i]; i++) {\n          s += ' ' + attr.name + '=\"' + escapeAttr(attr.value) + '\"';\n        }\n        s += '>';\n        if (voidElements[tagName])\n          return s;\n\n        return s + getInnerHTML(node) + '</' + tagName + '>';\n\n      case Node.TEXT_NODE:\n        var data = node.data;\n        if (parentNode && plaintextParents[parentNode.localName])\n          return data;\n        return escapeData(data);\n\n      case Node.COMMENT_NODE:\n        return '<!--' + node.data + '-->';\n\n      default:\n        console.error(node);\n        throw new Error('not implemented');\n    }\n  }\n\n  function getInnerHTML(node) {\n    if (node instanceof wrappers.HTMLTemplateElement)\n      node = node.content;\n\n    var s = '';\n    for (var child = node.firstChild; child; child = child.nextSibling) {\n      s += getOuterHTML(child, node);\n    }\n    return s;\n  }\n\n  function setInnerHTML(node, value, opt_tagName) {\n    var tagName = opt_tagName || 'div';\n    node.textContent = '';\n    var tempElement = unwrap(node.ownerDocument.createElement(tagName));\n    tempElement.innerHTML = value;\n    var firstChild;\n    while (firstChild = tempElement.firstChild) {\n      node.appendChild(wrap(firstChild));\n    }\n  }\n\n  // IE11 does not have MSIE in the user agent string.\n  var oldIe = /MSIE/.test(navigator.userAgent);\n\n  var OriginalHTMLElement = window.HTMLElement;\n  var OriginalHTMLTemplateElement = window.HTMLTemplateElement;\n\n  function HTMLElement(node) {\n    Element.call(this, node);\n  }\n  HTMLElement.prototype = Object.create(Element.prototype);\n  mixin(HTMLElement.prototype, {\n    get innerHTML() {\n      return getInnerHTML(this);\n    },\n    set innerHTML(value) {\n      // IE9 does not handle set innerHTML correctly on plaintextParents. It\n      // creates element children. For example\n      //\n      //   scriptElement.innerHTML = '<a>test</a>'\n      //\n      // Creates a single HTMLAnchorElement child.\n      if (oldIe && plaintextParents[this.localName]) {\n        this.textContent = value;\n        return;\n      }\n\n      var removedNodes = snapshotNodeList(this.childNodes);\n\n      if (this.invalidateShadowRenderer()) {\n        if (this instanceof wrappers.HTMLTemplateElement)\n          setInnerHTML(this.content, value);\n        else\n          setInnerHTML(this, value, this.tagName);\n\n      // If we have a non native template element we need to handle this\n      // manually since setting impl.innerHTML would add the html as direct\n      // children and not be moved over to the content fragment.\n      } else if (!OriginalHTMLTemplateElement &&\n                 this instanceof wrappers.HTMLTemplateElement) {\n        setInnerHTML(this.content, value);\n      } else {\n        this.impl.innerHTML = value;\n      }\n\n      var addedNodes = snapshotNodeList(this.childNodes);\n\n      enqueueMutation(this, 'childList', {\n        addedNodes: addedNodes,\n        removedNodes: removedNodes\n      });\n\n      nodesWereRemoved(removedNodes);\n      nodesWereAdded(addedNodes);\n    },\n\n    get outerHTML() {\n      return getOuterHTML(this, this.parentNode);\n    },\n    set outerHTML(value) {\n      var p = this.parentNode;\n      if (p) {\n        p.invalidateShadowRenderer();\n        var df = frag(p, value);\n        p.replaceChild(df, this);\n      }\n    },\n\n    insertAdjacentHTML: function(position, text) {\n      var contextElement, refNode;\n      switch (String(position).toLowerCase()) {\n        case 'beforebegin':\n          contextElement = this.parentNode;\n          refNode = this;\n          break;\n        case 'afterend':\n          contextElement = this.parentNode;\n          refNode = this.nextSibling;\n          break;\n        case 'afterbegin':\n          contextElement = this;\n          refNode = this.firstChild;\n          break;\n        case 'beforeend':\n          contextElement = this;\n          refNode = null;\n          break;\n        default:\n          return;\n      }\n\n      var df = frag(contextElement, text);\n      contextElement.insertBefore(df, refNode);\n    }\n  });\n\n  function frag(contextElement, html) {\n    // TODO(arv): This does not work with SVG and other non HTML elements.\n    var p = unwrap(contextElement.cloneNode(false));\n    p.innerHTML = html;\n    var df = unwrap(document.createDocumentFragment());\n    var c;\n    while (c = p.firstChild) {\n      df.appendChild(c);\n    }\n    return wrap(df);\n  }\n\n  function getter(name) {\n    return function() {\n      scope.renderAllPending();\n      return this.impl[name];\n    };\n  }\n\n  function getterRequiresRendering(name) {\n    defineGetter(HTMLElement, name, getter(name));\n  }\n\n  [\n    'clientHeight',\n    'clientLeft',\n    'clientTop',\n    'clientWidth',\n    'offsetHeight',\n    'offsetLeft',\n    'offsetTop',\n    'offsetWidth',\n    'scrollHeight',\n    'scrollWidth',\n  ].forEach(getterRequiresRendering);\n\n  function getterAndSetterRequiresRendering(name) {\n    Object.defineProperty(HTMLElement.prototype, name, {\n      get: getter(name),\n      set: function(v) {\n        scope.renderAllPending();\n        this.impl[name] = v;\n      },\n      configurable: true,\n      enumerable: true\n    });\n  }\n\n  [\n    'scrollLeft',\n    'scrollTop',\n  ].forEach(getterAndSetterRequiresRendering);\n\n  function methodRequiresRendering(name) {\n    Object.defineProperty(HTMLElement.prototype, name, {\n      value: function() {\n        scope.renderAllPending();\n        return this.impl[name].apply(this.impl, arguments);\n      },\n      configurable: true,\n      enumerable: true\n    });\n  }\n\n  [\n    'getBoundingClientRect',\n    'getClientRects',\n    'scrollIntoView'\n  ].forEach(methodRequiresRendering);\n\n  // HTMLElement is abstract so we use a subclass that has no members.\n  registerWrapper(OriginalHTMLElement, HTMLElement,\n                  document.createElement('b'));\n\n  scope.wrappers.HTMLElement = HTMLElement;\n\n  // TODO: Find a better way to share these two with WrapperShadowRoot.\n  scope.getInnerHTML = getInnerHTML;\n  scope.setInnerHTML = setInnerHTML\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLElement = scope.wrappers.HTMLElement;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var wrap = scope.wrap;\n\n  var OriginalHTMLCanvasElement = window.HTMLCanvasElement;\n\n  function HTMLCanvasElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLCanvasElement.prototype = Object.create(HTMLElement.prototype);\n\n  mixin(HTMLCanvasElement.prototype, {\n    getContext: function() {\n      var context = this.impl.getContext.apply(this.impl, arguments);\n      return context && wrap(context);\n    }\n  });\n\n  registerWrapper(OriginalHTMLCanvasElement, HTMLCanvasElement,\n                  document.createElement('canvas'));\n\n  scope.wrappers.HTMLCanvasElement = HTMLCanvasElement;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLElement = scope.wrappers.HTMLElement;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n\n  var OriginalHTMLContentElement = window.HTMLContentElement;\n\n  function HTMLContentElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLContentElement.prototype = Object.create(HTMLElement.prototype);\n  mixin(HTMLContentElement.prototype, {\n    get select() {\n      return this.getAttribute('select');\n    },\n    set select(value) {\n      this.setAttribute('select', value);\n    },\n\n    setAttribute: function(n, v) {\n      HTMLElement.prototype.setAttribute.call(this, n, v);\n      if (String(n).toLowerCase() === 'select')\n        this.invalidateShadowRenderer(true);\n    }\n\n    // getDistributedNodes is added in ShadowRenderer\n\n    // TODO: attribute boolean resetStyleInheritance;\n  });\n\n  if (OriginalHTMLContentElement)\n    registerWrapper(OriginalHTMLContentElement, HTMLContentElement);\n\n  scope.wrappers.HTMLContentElement = HTMLContentElement;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLElement = scope.wrappers.HTMLElement;\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var rewrap = scope.rewrap;\n\n  var OriginalHTMLImageElement = window.HTMLImageElement;\n\n  function HTMLImageElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLImageElement.prototype = Object.create(HTMLElement.prototype);\n\n  registerWrapper(OriginalHTMLImageElement, HTMLImageElement,\n                  document.createElement('img'));\n\n  function Image(width, height) {\n    if (!(this instanceof Image)) {\n      throw new TypeError(\n          'DOM object constructor cannot be called as a function.');\n    }\n\n    var node = unwrap(document.createElement('img'));\n    HTMLElement.call(this, node);\n    rewrap(node, this);\n\n    if (width !== undefined)\n      node.width = width;\n    if (height !== undefined)\n      node.height = height;\n  }\n\n  Image.prototype = HTMLImageElement.prototype;\n\n  scope.wrappers.HTMLImageElement = HTMLImageElement;\n  scope.wrappers.Image = Image;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLElement = scope.wrappers.HTMLElement;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n\n  var OriginalHTMLShadowElement = window.HTMLShadowElement;\n\n  function HTMLShadowElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLShadowElement.prototype = Object.create(HTMLElement.prototype);\n  mixin(HTMLShadowElement.prototype, {\n    // TODO: attribute boolean resetStyleInheritance;\n  });\n\n  if (OriginalHTMLShadowElement)\n    registerWrapper(OriginalHTMLShadowElement, HTMLShadowElement);\n\n  scope.wrappers.HTMLShadowElement = HTMLShadowElement;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLElement = scope.wrappers.HTMLElement;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n\n  var contentTable = new WeakMap();\n  var templateContentsOwnerTable = new WeakMap();\n\n  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner\n  function getTemplateContentsOwner(doc) {\n    if (!doc.defaultView)\n      return doc;\n    var d = templateContentsOwnerTable.get(doc);\n    if (!d) {\n      // TODO(arv): This should either be a Document or HTMLDocument depending\n      // on doc.\n      d = doc.implementation.createHTMLDocument('');\n      while (d.lastChild) {\n        d.removeChild(d.lastChild);\n      }\n      templateContentsOwnerTable.set(doc, d);\n    }\n    return d;\n  }\n\n  function extractContent(templateElement) {\n    // templateElement is not a wrapper here.\n    var doc = getTemplateContentsOwner(templateElement.ownerDocument);\n    var df = unwrap(doc.createDocumentFragment());\n    var child;\n    while (child = templateElement.firstChild) {\n      df.appendChild(child);\n    }\n    return df;\n  }\n\n  var OriginalHTMLTemplateElement = window.HTMLTemplateElement;\n\n  function HTMLTemplateElement(node) {\n    HTMLElement.call(this, node);\n    if (!OriginalHTMLTemplateElement) {\n      var content = extractContent(node);\n      contentTable.set(this, wrap(content));\n    }\n  }\n  HTMLTemplateElement.prototype = Object.create(HTMLElement.prototype);\n\n  mixin(HTMLTemplateElement.prototype, {\n    get content() {\n      if (OriginalHTMLTemplateElement)\n        return wrap(this.impl.content);\n      return contentTable.get(this);\n    },\n\n    // TODO(arv): cloneNode needs to clone content.\n\n  });\n\n  if (OriginalHTMLTemplateElement)\n    registerWrapper(OriginalHTMLTemplateElement, HTMLTemplateElement);\n\n  scope.wrappers.HTMLTemplateElement = HTMLTemplateElement;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLElement = scope.wrappers.HTMLElement;\n  var registerWrapper = scope.registerWrapper;\n\n  var OriginalHTMLMediaElement = window.HTMLMediaElement;\n\n  function HTMLMediaElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLMediaElement.prototype = Object.create(HTMLElement.prototype);\n\n  registerWrapper(OriginalHTMLMediaElement, HTMLMediaElement,\n                  document.createElement('audio'));\n\n  scope.wrappers.HTMLMediaElement = HTMLMediaElement;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLMediaElement = scope.wrappers.HTMLMediaElement;\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var rewrap = scope.rewrap;\n\n  var OriginalHTMLAudioElement = window.HTMLAudioElement;\n\n  function HTMLAudioElement(node) {\n    HTMLMediaElement.call(this, node);\n  }\n  HTMLAudioElement.prototype = Object.create(HTMLMediaElement.prototype);\n\n  registerWrapper(OriginalHTMLAudioElement, HTMLAudioElement,\n                  document.createElement('audio'));\n\n  function Audio(src) {\n    if (!(this instanceof Audio)) {\n      throw new TypeError(\n          'DOM object constructor cannot be called as a function.');\n    }\n\n    var node = unwrap(document.createElement('audio'));\n    HTMLMediaElement.call(this, node);\n    rewrap(node, this);\n\n    node.setAttribute('preload', 'auto');\n    if (src !== undefined)\n      node.setAttribute('src', src);\n  }\n\n  Audio.prototype = HTMLAudioElement.prototype;\n\n  scope.wrappers.HTMLAudioElement = HTMLAudioElement;\n  scope.wrappers.Audio = Audio;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLElement = scope.wrappers.HTMLElement;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var rewrap = scope.rewrap;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n\n  var OriginalHTMLOptionElement = window.HTMLOptionElement;\n\n  function trimText(s) {\n    return s.replace(/\\s+/g, ' ').trim();\n  }\n\n  function HTMLOptionElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLOptionElement.prototype = Object.create(HTMLElement.prototype);\n  mixin(HTMLOptionElement.prototype, {\n    get text() {\n      return trimText(this.textContent);\n    },\n    set text(value) {\n      this.textContent = trimText(String(value));\n    },\n    get form() {\n      return wrap(unwrap(this).form);\n    }\n  });\n\n  registerWrapper(OriginalHTMLOptionElement, HTMLOptionElement,\n                  document.createElement('option'));\n\n  function Option(text, value, defaultSelected, selected) {\n    if (!(this instanceof Option)) {\n      throw new TypeError(\n          'DOM object constructor cannot be called as a function.');\n    }\n\n    var node = unwrap(document.createElement('option'));\n    HTMLElement.call(this, node);\n    rewrap(node, this);\n\n    if (text !== undefined)\n      node.text = text;\n    if (value !== undefined)\n      node.setAttribute('value', value);\n    if (defaultSelected === true)\n      node.setAttribute('selected', '');\n    node.selected = selected === true;\n  }\n\n  Option.prototype = HTMLOptionElement.prototype;\n\n  scope.wrappers.HTMLOptionElement = HTMLOptionElement;\n  scope.wrappers.Option = Option;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLContentElement = scope.wrappers.HTMLContentElement;\n  var HTMLElement = scope.wrappers.HTMLElement;\n  var HTMLShadowElement = scope.wrappers.HTMLShadowElement;\n  var HTMLTemplateElement = scope.wrappers.HTMLTemplateElement;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n\n  var OriginalHTMLUnknownElement = window.HTMLUnknownElement;\n\n  function HTMLUnknownElement(node) {\n    switch (node.localName) {\n      case 'content':\n        return new HTMLContentElement(node);\n      case 'shadow':\n        return new HTMLShadowElement(node);\n      case 'template':\n        return new HTMLTemplateElement(node);\n    }\n    HTMLElement.call(this, node);\n  }\n  HTMLUnknownElement.prototype = Object.create(HTMLElement.prototype);\n  registerWrapper(OriginalHTMLUnknownElement, HTMLUnknownElement);\n  scope.wrappers.HTMLUnknownElement = HTMLUnknownElement;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2014 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var registerObject = scope.registerObject;\n\n  var SVG_NS = 'http://www.w3.org/2000/svg';\n  var svgTitleElement = document.createElementNS(SVG_NS, 'title');\n  var SVGTitleElement = registerObject(svgTitleElement);\n  var SVGElement = Object.getPrototypeOf(SVGTitleElement.prototype).constructor;\n\n  scope.wrappers.SVGElement = SVGElement;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2014 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n\n  var OriginalSVGUseElement = window.SVGUseElement;\n\n  // IE uses SVGElement as parent interface, SVG2 (Blink & Gecko) uses\n  // SVGGraphicsElement. Use the <g> element to get the right prototype.\n\n  var SVG_NS = 'http://www.w3.org/2000/svg';\n  var gWrapper = wrap(document.createElementNS(SVG_NS, 'g'));\n  var useElement = document.createElementNS(SVG_NS, 'use');\n  var SVGGElement = gWrapper.constructor;\n  var parentInterfacePrototype = Object.getPrototypeOf(SVGGElement.prototype);\n  var parentInterface = parentInterfacePrototype.constructor;\n\n  function SVGUseElement(impl) {\n    parentInterface.call(this, impl);\n  }\n\n  SVGUseElement.prototype = Object.create(parentInterfacePrototype);\n\n  // Firefox does not expose instanceRoot.\n  if ('instanceRoot' in useElement) {\n    mixin(SVGUseElement.prototype, {\n      get instanceRoot() {\n        return wrap(unwrap(this).instanceRoot);\n      },\n      get animatedInstanceRoot() {\n        return wrap(unwrap(this).animatedInstanceRoot);\n      },\n    });\n  }\n\n  registerWrapper(OriginalSVGUseElement, SVGUseElement, useElement);\n\n  scope.wrappers.SVGUseElement = SVGUseElement;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2014 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var EventTarget = scope.wrappers.EventTarget;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var wrap = scope.wrap;\n\n  var OriginalSVGElementInstance = window.SVGElementInstance;\n  if (!OriginalSVGElementInstance)\n    return;\n\n  function SVGElementInstance(impl) {\n    EventTarget.call(this, impl);\n  }\n\n  SVGElementInstance.prototype = Object.create(EventTarget.prototype);\n  mixin(SVGElementInstance.prototype, {\n    /** @type {SVGElement} */\n    get correspondingElement() {\n      return wrap(this.impl.correspondingElement);\n    },\n\n    /** @type {SVGUseElement} */\n    get correspondingUseElement() {\n      return wrap(this.impl.correspondingUseElement);\n    },\n\n    /** @type {SVGElementInstance} */\n    get parentNode() {\n      return wrap(this.impl.parentNode);\n    },\n\n    /** @type {SVGElementInstanceList} */\n    get childNodes() {\n      throw new Error('Not implemented');\n    },\n\n    /** @type {SVGElementInstance} */\n    get firstChild() {\n      return wrap(this.impl.firstChild);\n    },\n\n    /** @type {SVGElementInstance} */\n    get lastChild() {\n      return wrap(this.impl.lastChild);\n    },\n\n    /** @type {SVGElementInstance} */\n    get previousSibling() {\n      return wrap(this.impl.previousSibling);\n    },\n\n    /** @type {SVGElementInstance} */\n    get nextSibling() {\n      return wrap(this.impl.nextSibling);\n    }\n  });\n\n  registerWrapper(OriginalSVGElementInstance, SVGElementInstance);\n\n  scope.wrappers.SVGElementInstance = SVGElementInstance;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var unwrapIfNeeded = scope.unwrapIfNeeded;\n  var wrap = scope.wrap;\n\n  var OriginalCanvasRenderingContext2D = window.CanvasRenderingContext2D;\n\n  function CanvasRenderingContext2D(impl) {\n    this.impl = impl;\n  }\n\n  mixin(CanvasRenderingContext2D.prototype, {\n    get canvas() {\n      return wrap(this.impl.canvas);\n    },\n\n    drawImage: function() {\n      arguments[0] = unwrapIfNeeded(arguments[0]);\n      this.impl.drawImage.apply(this.impl, arguments);\n    },\n\n    createPattern: function() {\n      arguments[0] = unwrap(arguments[0]);\n      return this.impl.createPattern.apply(this.impl, arguments);\n    }\n  });\n\n  registerWrapper(OriginalCanvasRenderingContext2D, CanvasRenderingContext2D,\n                  document.createElement('canvas').getContext('2d'));\n\n  scope.wrappers.CanvasRenderingContext2D = CanvasRenderingContext2D;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var unwrapIfNeeded = scope.unwrapIfNeeded;\n  var wrap = scope.wrap;\n\n  var OriginalWebGLRenderingContext = window.WebGLRenderingContext;\n\n  // IE10 does not have WebGL.\n  if (!OriginalWebGLRenderingContext)\n    return;\n\n  function WebGLRenderingContext(impl) {\n    this.impl = impl;\n  }\n\n  mixin(WebGLRenderingContext.prototype, {\n    get canvas() {\n      return wrap(this.impl.canvas);\n    },\n\n    texImage2D: function() {\n      arguments[5] = unwrapIfNeeded(arguments[5]);\n      this.impl.texImage2D.apply(this.impl, arguments);\n    },\n\n    texSubImage2D: function() {\n      arguments[6] = unwrapIfNeeded(arguments[6]);\n      this.impl.texSubImage2D.apply(this.impl, arguments);\n    }\n  });\n\n  // Blink/WebKit has broken DOM bindings. Usually we would create an instance\n  // of the object and pass it into registerWrapper as a \"blueprint\" but\n  // creating WebGL contexts is expensive and might fail so we use a dummy\n  // object with dummy instance properties for these broken browsers.\n  var instanceProperties = /WebKit/.test(navigator.userAgent) ?\n      {drawingBufferHeight: null, drawingBufferWidth: null} : {};\n\n  registerWrapper(OriginalWebGLRenderingContext, WebGLRenderingContext,\n      instanceProperties);\n\n  scope.wrappers.WebGLRenderingContext = WebGLRenderingContext;\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var unwrapIfNeeded = scope.unwrapIfNeeded;\n  var wrap = scope.wrap;\n\n  var OriginalRange = window.Range;\n\n  function Range(impl) {\n    this.impl = impl;\n  }\n  Range.prototype = {\n    get startContainer() {\n      return wrap(this.impl.startContainer);\n    },\n    get endContainer() {\n      return wrap(this.impl.endContainer);\n    },\n    get commonAncestorContainer() {\n      return wrap(this.impl.commonAncestorContainer);\n    },\n    setStart: function(refNode,offset) {\n      this.impl.setStart(unwrapIfNeeded(refNode), offset);\n    },\n    setEnd: function(refNode,offset) {\n      this.impl.setEnd(unwrapIfNeeded(refNode), offset);\n    },\n    setStartBefore: function(refNode) {\n      this.impl.setStartBefore(unwrapIfNeeded(refNode));\n    },\n    setStartAfter: function(refNode) {\n      this.impl.setStartAfter(unwrapIfNeeded(refNode));\n    },\n    setEndBefore: function(refNode) {\n      this.impl.setEndBefore(unwrapIfNeeded(refNode));\n    },\n    setEndAfter: function(refNode) {\n      this.impl.setEndAfter(unwrapIfNeeded(refNode));\n    },\n    selectNode: function(refNode) {\n      this.impl.selectNode(unwrapIfNeeded(refNode));\n    },\n    selectNodeContents: function(refNode) {\n      this.impl.selectNodeContents(unwrapIfNeeded(refNode));\n    },\n    compareBoundaryPoints: function(how, sourceRange) {\n      return this.impl.compareBoundaryPoints(how, unwrap(sourceRange));\n    },\n    extractContents: function() {\n      return wrap(this.impl.extractContents());\n    },\n    cloneContents: function() {\n      return wrap(this.impl.cloneContents());\n    },\n    insertNode: function(node) {\n      this.impl.insertNode(unwrapIfNeeded(node));\n    },\n    surroundContents: function(newParent) {\n      this.impl.surroundContents(unwrapIfNeeded(newParent));\n    },\n    cloneRange: function() {\n      return wrap(this.impl.cloneRange());\n    },\n    isPointInRange: function(node, offset) {\n      return this.impl.isPointInRange(unwrapIfNeeded(node), offset);\n    },\n    comparePoint: function(node, offset) {\n      return this.impl.comparePoint(unwrapIfNeeded(node), offset);\n    },\n    intersectsNode: function(node) {\n      return this.impl.intersectsNode(unwrapIfNeeded(node));\n    },\n    toString: function() {\n      return this.impl.toString();\n    }\n  };\n\n  // IE9 does not have createContextualFragment.\n  if (OriginalRange.prototype.createContextualFragment) {\n    Range.prototype.createContextualFragment = function(html) {\n      return wrap(this.impl.createContextualFragment(html));\n    };\n  }\n\n  registerWrapper(window.Range, Range, document.createRange());\n\n  scope.wrappers.Range = Range;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var GetElementsByInterface = scope.GetElementsByInterface;\n  var ParentNodeInterface = scope.ParentNodeInterface;\n  var SelectorsInterface = scope.SelectorsInterface;\n  var mixin = scope.mixin;\n  var registerObject = scope.registerObject;\n\n  var DocumentFragment = registerObject(document.createDocumentFragment());\n  mixin(DocumentFragment.prototype, ParentNodeInterface);\n  mixin(DocumentFragment.prototype, SelectorsInterface);\n  mixin(DocumentFragment.prototype, GetElementsByInterface);\n\n  var Comment = registerObject(document.createComment(''));\n\n  scope.wrappers.Comment = Comment;\n  scope.wrappers.DocumentFragment = DocumentFragment;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var DocumentFragment = scope.wrappers.DocumentFragment;\n  var elementFromPoint = scope.elementFromPoint;\n  var getInnerHTML = scope.getInnerHTML;\n  var mixin = scope.mixin;\n  var rewrap = scope.rewrap;\n  var setInnerHTML = scope.setInnerHTML;\n  var unwrap = scope.unwrap;\n\n  var shadowHostTable = new WeakMap();\n  var nextOlderShadowTreeTable = new WeakMap();\n\n  var spaceCharRe = /[ \\t\\n\\r\\f]/;\n\n  function ShadowRoot(hostWrapper) {\n    var node = unwrap(hostWrapper.impl.ownerDocument.createDocumentFragment());\n    DocumentFragment.call(this, node);\n\n    // createDocumentFragment associates the node with a wrapper\n    // DocumentFragment instance. Override that.\n    rewrap(node, this);\n\n    var oldShadowRoot = hostWrapper.shadowRoot;\n    nextOlderShadowTreeTable.set(this, oldShadowRoot);\n\n    shadowHostTable.set(this, hostWrapper);\n  }\n  ShadowRoot.prototype = Object.create(DocumentFragment.prototype);\n  mixin(ShadowRoot.prototype, {\n    get innerHTML() {\n      return getInnerHTML(this);\n    },\n    set innerHTML(value) {\n      setInnerHTML(this, value);\n      this.invalidateShadowRenderer();\n    },\n\n    get olderShadowRoot() {\n      return nextOlderShadowTreeTable.get(this) || null;\n    },\n\n    get host() {\n      return shadowHostTable.get(this) || null;\n    },\n\n    invalidateShadowRenderer: function() {\n      return shadowHostTable.get(this).invalidateShadowRenderer();\n    },\n\n    elementFromPoint: function(x, y) {\n      return elementFromPoint(this, this.ownerDocument, x, y);\n    },\n\n    getElementById: function(id) {\n      if (spaceCharRe.test(id))\n        return null;\n      return this.querySelector('[id=\"' + id + '\"]');\n    }\n  });\n\n  scope.wrappers.ShadowRoot = ShadowRoot;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var Element = scope.wrappers.Element;\n  var HTMLContentElement = scope.wrappers.HTMLContentElement;\n  var HTMLShadowElement = scope.wrappers.HTMLShadowElement;\n  var Node = scope.wrappers.Node;\n  var ShadowRoot = scope.wrappers.ShadowRoot;\n  var assert = scope.assert;\n  var mixin = scope.mixin;\n  var oneOf = scope.oneOf;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n\n  /**\n   * Updates the fields of a wrapper to a snapshot of the logical DOM as needed.\n   * Up means parentNode\n   * Sideways means previous and next sibling.\n   * @param {!Node} wrapper\n   */\n  function updateWrapperUpAndSideways(wrapper) {\n    wrapper.previousSibling_ = wrapper.previousSibling;\n    wrapper.nextSibling_ = wrapper.nextSibling;\n    wrapper.parentNode_ = wrapper.parentNode;\n  }\n\n  /**\n   * Updates the fields of a wrapper to a snapshot of the logical DOM as needed.\n   * Down means first and last child\n   * @param {!Node} wrapper\n   */\n  function updateWrapperDown(wrapper) {\n    wrapper.firstChild_ = wrapper.firstChild;\n    wrapper.lastChild_ = wrapper.lastChild;\n  }\n\n  function updateAllChildNodes(parentNodeWrapper) {\n    assert(parentNodeWrapper instanceof Node);\n    for (var childWrapper = parentNodeWrapper.firstChild;\n         childWrapper;\n         childWrapper = childWrapper.nextSibling) {\n      updateWrapperUpAndSideways(childWrapper);\n    }\n    updateWrapperDown(parentNodeWrapper);\n  }\n\n  function insertBefore(parentNodeWrapper, newChildWrapper, refChildWrapper) {\n    var parentNode = unwrap(parentNodeWrapper);\n    var newChild = unwrap(newChildWrapper);\n    var refChild = refChildWrapper ? unwrap(refChildWrapper) : null;\n\n    remove(newChildWrapper);\n    updateWrapperUpAndSideways(newChildWrapper);\n\n    if (!refChildWrapper) {\n      parentNodeWrapper.lastChild_ = parentNodeWrapper.lastChild;\n      if (parentNodeWrapper.lastChild === parentNodeWrapper.firstChild)\n        parentNodeWrapper.firstChild_ = parentNodeWrapper.firstChild;\n\n      var lastChildWrapper = wrap(parentNode.lastChild);\n      if (lastChildWrapper)\n        lastChildWrapper.nextSibling_ = lastChildWrapper.nextSibling;\n    } else {\n      if (parentNodeWrapper.firstChild === refChildWrapper)\n        parentNodeWrapper.firstChild_ = refChildWrapper;\n\n      refChildWrapper.previousSibling_ = refChildWrapper.previousSibling;\n    }\n\n    parentNode.insertBefore(newChild, refChild);\n  }\n\n  function remove(nodeWrapper) {\n    var node = unwrap(nodeWrapper)\n    var parentNode = node.parentNode;\n    if (!parentNode)\n      return;\n\n    var parentNodeWrapper = wrap(parentNode);\n    updateWrapperUpAndSideways(nodeWrapper);\n\n    if (nodeWrapper.previousSibling)\n      nodeWrapper.previousSibling.nextSibling_ = nodeWrapper;\n    if (nodeWrapper.nextSibling)\n      nodeWrapper.nextSibling.previousSibling_ = nodeWrapper;\n\n    if (parentNodeWrapper.lastChild === nodeWrapper)\n      parentNodeWrapper.lastChild_ = nodeWrapper;\n    if (parentNodeWrapper.firstChild === nodeWrapper)\n      parentNodeWrapper.firstChild_ = nodeWrapper;\n\n    parentNode.removeChild(node);\n  }\n\n  var distributedChildNodesTable = new WeakMap();\n  var eventParentsTable = new WeakMap();\n  var insertionParentTable = new WeakMap();\n  var rendererForHostTable = new WeakMap();\n\n  function distributeChildToInsertionPoint(child, insertionPoint) {\n    getDistributedChildNodes(insertionPoint).push(child);\n    assignToInsertionPoint(child, insertionPoint);\n\n    var eventParents = eventParentsTable.get(child);\n    if (!eventParents)\n      eventParentsTable.set(child, eventParents = []);\n    eventParents.push(insertionPoint);\n  }\n\n  function resetDistributedChildNodes(insertionPoint) {\n    distributedChildNodesTable.set(insertionPoint, []);\n  }\n\n  function getDistributedChildNodes(insertionPoint) {\n    return distributedChildNodesTable.get(insertionPoint);\n  }\n\n  function getChildNodesSnapshot(node) {\n    var result = [], i = 0;\n    for (var child = node.firstChild; child; child = child.nextSibling) {\n      result[i++] = child;\n    }\n    return result;\n  }\n\n  /**\n   * Visits all nodes in the tree that fulfils the |predicate|. If the |visitor|\n   * function returns |false| the traversal is aborted.\n   * @param {!Node} tree\n   * @param {function(!Node) : boolean} predicate\n   * @param {function(!Node) : *} visitor\n   */\n  function visit(tree, predicate, visitor) {\n    // This operates on logical DOM.\n    for (var node = tree.firstChild; node; node = node.nextSibling) {\n      if (predicate(node)) {\n        if (visitor(node) === false)\n          return;\n      } else {\n        visit(node, predicate, visitor);\n      }\n    }\n  }\n\n  // Matching Insertion Points\n  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#matching-insertion-points\n\n  // TODO(arv): Verify this... I don't remember why I picked this regexp.\n  var selectorMatchRegExp = /^[*.:#[a-zA-Z_|]/;\n\n  var allowedPseudoRegExp = new RegExp('^:(' + [\n    'link',\n    'visited',\n    'target',\n    'enabled',\n    'disabled',\n    'checked',\n    'indeterminate',\n    'nth-child',\n    'nth-last-child',\n    'nth-of-type',\n    'nth-last-of-type',\n    'first-child',\n    'last-child',\n    'first-of-type',\n    'last-of-type',\n    'only-of-type',\n  ].join('|') + ')');\n\n\n  /**\n   * @param {Element} node\n   * @oaram {Element} point The insertion point element.\n   * @return {boolean} Whether the node matches the insertion point.\n   */\n  function matchesCriteria(node, point) {\n    var select = point.getAttribute('select');\n    if (!select)\n      return true;\n\n    // Here we know the select attribute is a non empty string.\n    select = select.trim();\n    if (!select)\n      return true;\n\n    if (!(node instanceof Element))\n      return false;\n\n    // The native matches function in IE9 does not correctly work with elements\n    // that are not in the document.\n    // TODO(arv): Implement matching in JS.\n    // https://github.com/Polymer/ShadowDOM/issues/361\n    if (select === '*' || select === node.localName)\n      return true;\n\n    // TODO(arv): This does not seem right. Need to check for a simple selector.\n    if (!selectorMatchRegExp.test(select))\n      return false;\n\n    // TODO(arv): This no longer matches the spec.\n    if (select[0] === ':' && !allowedPseudoRegExp.test(select))\n      return false;\n\n    try {\n      return node.matches(select);\n    } catch (ex) {\n      // Invalid selector.\n      return false;\n    }\n  }\n\n  var request = oneOf(window, [\n    'requestAnimationFrame',\n    'mozRequestAnimationFrame',\n    'webkitRequestAnimationFrame',\n    'setTimeout'\n  ]);\n\n  var pendingDirtyRenderers = [];\n  var renderTimer;\n\n  function renderAllPending() {\n    for (var i = 0; i < pendingDirtyRenderers.length; i++) {\n      pendingDirtyRenderers[i].render();\n    }\n    pendingDirtyRenderers = [];\n  }\n\n  function handleRequestAnimationFrame() {\n    renderTimer = null;\n    renderAllPending();\n  }\n\n  /**\n   * Returns existing shadow renderer for a host or creates it if it is needed.\n   * @params {!Element} host\n   * @return {!ShadowRenderer}\n   */\n  function getRendererForHost(host) {\n    var renderer = rendererForHostTable.get(host);\n    if (!renderer) {\n      renderer = new ShadowRenderer(host);\n      rendererForHostTable.set(host, renderer);\n    }\n    return renderer;\n  }\n\n  function getShadowRootAncestor(node) {\n    for (; node; node = node.parentNode) {\n      if (node instanceof ShadowRoot)\n        return node;\n    }\n    return null;\n  }\n\n  function getRendererForShadowRoot(shadowRoot) {\n    return getRendererForHost(shadowRoot.host);\n  }\n\n  var spliceDiff = new ArraySplice();\n  spliceDiff.equals = function(renderNode, rawNode) {\n    return unwrap(renderNode.node) === rawNode;\n  };\n\n  /**\n   * RenderNode is used as an in memory \"render tree\". When we render the\n   * composed tree we create a tree of RenderNodes, then we diff this against\n   * the real DOM tree and make minimal changes as needed.\n   */\n  function RenderNode(node) {\n    this.skip = false;\n    this.node = node;\n    this.childNodes = [];\n  }\n\n  RenderNode.prototype = {\n    append: function(node) {\n      var rv = new RenderNode(node);\n      this.childNodes.push(rv);\n      return rv;\n    },\n\n    sync: function(opt_added) {\n      if (this.skip)\n        return;\n\n      var nodeWrapper = this.node;\n      // plain array of RenderNodes\n      var newChildren = this.childNodes;\n      // plain array of real nodes.\n      var oldChildren = getChildNodesSnapshot(unwrap(nodeWrapper));\n      var added = opt_added || new WeakMap();\n\n      var splices = spliceDiff.calculateSplices(newChildren, oldChildren);\n\n      var newIndex = 0, oldIndex = 0;\n      var lastIndex = 0;\n      for (var i = 0; i < splices.length; i++) {\n        var splice = splices[i];\n        for (; lastIndex < splice.index; lastIndex++) {\n          oldIndex++;\n          newChildren[newIndex++].sync(added);\n        }\n\n        var removedCount = splice.removed.length;\n        for (var j = 0; j < removedCount; j++) {\n          var wrapper = wrap(oldChildren[oldIndex++]);\n          if (!added.get(wrapper))\n            remove(wrapper);\n        }\n\n        var addedCount = splice.addedCount;\n        var refNode = oldChildren[oldIndex] && wrap(oldChildren[oldIndex]);\n        for (var j = 0; j < addedCount; j++) {\n          var newChildRenderNode = newChildren[newIndex++];\n          var newChildWrapper = newChildRenderNode.node;\n          insertBefore(nodeWrapper, newChildWrapper, refNode);\n\n          // Keep track of added so that we do not remove the node after it\n          // has been added.\n          added.set(newChildWrapper, true);\n\n          newChildRenderNode.sync(added);\n        }\n\n        lastIndex += addedCount;\n      }\n\n      for (var i = lastIndex; i < newChildren.length; i++) {\n        newChildren[i].sync(added);\n      }\n    }\n  };\n\n  function ShadowRenderer(host) {\n    this.host = host;\n    this.dirty = false;\n    this.invalidateAttributes();\n    this.associateNode(host);\n  }\n\n  ShadowRenderer.prototype = {\n\n    // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#rendering-shadow-trees\n    render: function(opt_renderNode) {\n      if (!this.dirty)\n        return;\n\n      this.invalidateAttributes();\n      this.treeComposition();\n\n      var host = this.host;\n      var shadowRoot = host.shadowRoot;\n\n      this.associateNode(host);\n      var topMostRenderer = !renderNode;\n      var renderNode = opt_renderNode || new RenderNode(host);\n\n      for (var node = shadowRoot.firstChild; node; node = node.nextSibling) {\n        this.renderNode(shadowRoot, renderNode, node, false);\n      }\n\n      if (topMostRenderer)\n        renderNode.sync();\n\n      this.dirty = false;\n    },\n\n    invalidate: function() {\n      if (!this.dirty) {\n        this.dirty = true;\n        pendingDirtyRenderers.push(this);\n        if (renderTimer)\n          return;\n        renderTimer = window[request](handleRequestAnimationFrame, 0);\n      }\n    },\n\n    renderNode: function(shadowRoot, renderNode, node, isNested) {\n      if (isShadowHost(node)) {\n        renderNode = renderNode.append(node);\n        var renderer = getRendererForHost(node);\n        renderer.dirty = true;  // Need to rerender due to reprojection.\n        renderer.render(renderNode);\n      } else if (isInsertionPoint(node)) {\n        this.renderInsertionPoint(shadowRoot, renderNode, node, isNested);\n      } else if (isShadowInsertionPoint(node)) {\n        this.renderShadowInsertionPoint(shadowRoot, renderNode, node);\n      } else {\n        this.renderAsAnyDomTree(shadowRoot, renderNode, node, isNested);\n      }\n    },\n\n    renderAsAnyDomTree: function(shadowRoot, renderNode, node, isNested) {\n      renderNode = renderNode.append(node);\n\n      if (isShadowHost(node)) {\n        var renderer = getRendererForHost(node);\n        renderNode.skip = !renderer.dirty;\n        renderer.render(renderNode);\n      } else {\n        for (var child = node.firstChild; child; child = child.nextSibling) {\n          this.renderNode(shadowRoot, renderNode, child, isNested);\n        }\n      }\n    },\n\n    renderInsertionPoint: function(shadowRoot, renderNode, insertionPoint,\n                                   isNested) {\n      var distributedChildNodes = getDistributedChildNodes(insertionPoint);\n      if (distributedChildNodes.length) {\n        this.associateNode(insertionPoint);\n\n        for (var i = 0; i < distributedChildNodes.length; i++) {\n          var child = distributedChildNodes[i];\n          if (isInsertionPoint(child) && isNested)\n            this.renderInsertionPoint(shadowRoot, renderNode, child, isNested);\n          else\n            this.renderAsAnyDomTree(shadowRoot, renderNode, child, isNested);\n        }\n      } else {\n        this.renderFallbackContent(shadowRoot, renderNode, insertionPoint);\n      }\n      this.associateNode(insertionPoint.parentNode);\n    },\n\n    renderShadowInsertionPoint: function(shadowRoot, renderNode,\n                                         shadowInsertionPoint) {\n      var nextOlderTree = shadowRoot.olderShadowRoot;\n      if (nextOlderTree) {\n        assignToInsertionPoint(nextOlderTree, shadowInsertionPoint);\n        this.associateNode(shadowInsertionPoint.parentNode);\n        for (var node = nextOlderTree.firstChild;\n             node;\n             node = node.nextSibling) {\n          this.renderNode(nextOlderTree, renderNode, node, true);\n        }\n      } else {\n        this.renderFallbackContent(shadowRoot, renderNode,\n                                   shadowInsertionPoint);\n      }\n    },\n\n    renderFallbackContent: function(shadowRoot, renderNode, fallbackHost) {\n      this.associateNode(fallbackHost);\n      this.associateNode(fallbackHost.parentNode);\n      for (var node = fallbackHost.firstChild; node; node = node.nextSibling) {\n        this.renderAsAnyDomTree(shadowRoot, renderNode, node, false);\n      }\n    },\n\n    /**\n     * Invalidates the attributes used to keep track of which attributes may\n     * cause the renderer to be invalidated.\n     */\n    invalidateAttributes: function() {\n      this.attributes = Object.create(null);\n    },\n\n    /**\n     * Parses the selector and makes this renderer dependent on the attribute\n     * being used in the selector.\n     * @param {string} selector\n     */\n    updateDependentAttributes: function(selector) {\n      if (!selector)\n        return;\n\n      var attributes = this.attributes;\n\n      // .class\n      if (/\\.\\w+/.test(selector))\n        attributes['class'] = true;\n\n      // #id\n      if (/#\\w+/.test(selector))\n        attributes['id'] = true;\n\n      selector.replace(/\\[\\s*([^\\s=\\|~\\]]+)/g, function(_, name) {\n        attributes[name] = true;\n      });\n\n      // Pseudo selectors have been removed from the spec.\n    },\n\n    dependsOnAttribute: function(name) {\n      return this.attributes[name];\n    },\n\n    // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-distribution-algorithm\n    distribute: function(tree, pool) {\n      var self = this;\n\n      visit(tree, isActiveInsertionPoint,\n          function(insertionPoint) {\n            resetDistributedChildNodes(insertionPoint);\n            self.updateDependentAttributes(\n                insertionPoint.getAttribute('select'));\n\n            for (var i = 0; i < pool.length; i++) {  // 1.2\n              var node = pool[i];  // 1.2.1\n              if (node === undefined)  // removed\n                continue;\n              if (matchesCriteria(node, insertionPoint)) {  // 1.2.2\n                distributeChildToInsertionPoint(node, insertionPoint);  // 1.2.2.1\n                pool[i] = undefined;  // 1.2.2.2\n              }\n            }\n          });\n    },\n\n    // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-tree-composition\n    treeComposition: function () {\n      var shadowHost = this.host;\n      var tree = shadowHost.shadowRoot;  // 1.\n      var pool = [];  // 2.\n\n      for (var child = shadowHost.firstChild;\n           child;\n           child = child.nextSibling) {  // 3.\n        if (isInsertionPoint(child)) {  // 3.2.\n          var reprojected = getDistributedChildNodes(child);  // 3.2.1.\n          // if reprojected is undef... reset it?\n          if (!reprojected || !reprojected.length)  // 3.2.2.\n            reprojected = getChildNodesSnapshot(child);\n          pool.push.apply(pool, reprojected);  // 3.2.3.\n        } else {\n          pool.push(child); // 3.3.\n        }\n      }\n\n      var shadowInsertionPoint, point;\n      while (tree) {  // 4.\n        // 4.1.\n        shadowInsertionPoint = undefined;  // Reset every iteration.\n        visit(tree, isActiveShadowInsertionPoint, function(point) {\n          shadowInsertionPoint = point;\n          return false;\n        });\n        point = shadowInsertionPoint;\n\n        this.distribute(tree, pool);  // 4.2.\n        if (point) {  // 4.3.\n          var nextOlderTree = tree.olderShadowRoot;  // 4.3.1.\n          if (!nextOlderTree) {\n            break;  // 4.3.1.1.\n          } else {\n            tree = nextOlderTree;  // 4.3.2.2.\n            assignToInsertionPoint(tree, point);  // 4.3.2.2.\n            continue;  // 4.3.2.3.\n          }\n        } else {\n          break;  // 4.4.\n        }\n      }\n    },\n\n    associateNode: function(node) {\n      node.impl.polymerShadowRenderer_ = this;\n    }\n  };\n\n  function isInsertionPoint(node) {\n    // Should this include <shadow>?\n    return node instanceof HTMLContentElement;\n  }\n\n  function isActiveInsertionPoint(node) {\n    // <content> inside another <content> or <shadow> is considered inactive.\n    return node instanceof HTMLContentElement;\n  }\n\n  function isShadowInsertionPoint(node) {\n    return node instanceof HTMLShadowElement;\n  }\n\n  function isActiveShadowInsertionPoint(node) {\n    // <shadow> inside another <content> or <shadow> is considered inactive.\n    return node instanceof HTMLShadowElement;\n  }\n\n  function isShadowHost(shadowHost) {\n    return shadowHost.shadowRoot;\n  }\n\n  function getShadowTrees(host) {\n    var trees = [];\n\n    for (var tree = host.shadowRoot; tree; tree = tree.olderShadowRoot) {\n      trees.push(tree);\n    }\n    return trees;\n  }\n\n  function assignToInsertionPoint(tree, point) {\n    insertionParentTable.set(tree, point);\n  }\n\n  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#rendering-shadow-trees\n  function render(host) {\n    new ShadowRenderer(host).render();\n  };\n\n  // Need to rerender shadow host when:\n  //\n  // - a direct child to the ShadowRoot is added or removed\n  // - a direct child to the host is added or removed\n  // - a new shadow root is created\n  // - a direct child to a content/shadow element is added or removed\n  // - a sibling to a content/shadow element is added or removed\n  // - content[select] is changed\n  // - an attribute in a direct child to a host is modified\n\n  /**\n   * This gets called when a node was added or removed to it.\n   */\n  Node.prototype.invalidateShadowRenderer = function(force) {\n    var renderer = this.impl.polymerShadowRenderer_;\n    if (renderer) {\n      renderer.invalidate();\n      return true;\n    }\n\n    return false;\n  };\n\n  HTMLContentElement.prototype.getDistributedNodes = function() {\n    // TODO(arv): We should only rerender the dirty ancestor renderers (from\n    // the root and down).\n    renderAllPending();\n    return getDistributedChildNodes(this);\n  };\n\n  HTMLShadowElement.prototype.nodeIsInserted_ =\n  HTMLContentElement.prototype.nodeIsInserted_ = function() {\n    // Invalidate old renderer if any.\n    this.invalidateShadowRenderer();\n\n    var shadowRoot = getShadowRootAncestor(this);\n    var renderer;\n    if (shadowRoot)\n      renderer = getRendererForShadowRoot(shadowRoot);\n    this.impl.polymerShadowRenderer_ = renderer;\n    if (renderer)\n      renderer.invalidate();\n  };\n\n  scope.eventParentsTable = eventParentsTable;\n  scope.getRendererForHost = getRendererForHost;\n  scope.getShadowTrees = getShadowTrees;\n  scope.insertionParentTable = insertionParentTable;\n  scope.renderAllPending = renderAllPending;\n\n  // Exposed for testing\n  scope.visual = {\n    insertBefore: insertBefore,\n    remove: remove,\n  };\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var HTMLElement = scope.wrappers.HTMLElement;\n  var assert = scope.assert;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n\n  var elementsWithFormProperty = [\n    'HTMLButtonElement',\n    'HTMLFieldSetElement',\n    'HTMLInputElement',\n    'HTMLKeygenElement',\n    'HTMLLabelElement',\n    'HTMLLegendElement',\n    'HTMLObjectElement',\n    // HTMLOptionElement is handled in HTMLOptionElement.js\n    'HTMLOutputElement',\n    'HTMLSelectElement',\n    'HTMLTextAreaElement',\n  ];\n\n  function createWrapperConstructor(name) {\n    if (!window[name])\n      return;\n\n    // Ensure we are not overriding an already existing constructor.\n    assert(!scope.wrappers[name]);\n\n    var GeneratedWrapper = function(node) {\n      // At this point all of them extend HTMLElement.\n      HTMLElement.call(this, node);\n    }\n    GeneratedWrapper.prototype = Object.create(HTMLElement.prototype);\n    mixin(GeneratedWrapper.prototype, {\n      get form() {\n        return wrap(unwrap(this).form);\n      },\n    });\n\n    registerWrapper(window[name], GeneratedWrapper,\n        document.createElement(name.slice(4, -7)));\n    scope.wrappers[name] = GeneratedWrapper;\n  }\n\n  elementsWithFormProperty.forEach(createWrapperConstructor);\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2014 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var registerWrapper = scope.registerWrapper;\n  var unwrap = scope.unwrap;\n  var unwrapIfNeeded = scope.unwrapIfNeeded;\n  var wrap = scope.wrap;\n\n  var OriginalSelection = window.Selection;\n\n  function Selection(impl) {\n    this.impl = impl;\n  }\n  Selection.prototype = {\n    get anchorNode() {\n      return wrap(this.impl.anchorNode);\n    },\n    get focusNode() {\n      return wrap(this.impl.focusNode);\n    },\n    addRange: function(range) {\n      this.impl.addRange(unwrap(range));\n    },\n    collapse: function(node, index) {\n      this.impl.collapse(unwrapIfNeeded(node), index);\n    },\n    containsNode: function(node, allowPartial) {\n      return this.impl.containsNode(unwrapIfNeeded(node), allowPartial);\n    },\n    extend: function(node, offset) {\n      this.impl.extend(unwrapIfNeeded(node), offset);\n    },\n    getRangeAt: function(index) {\n      return wrap(this.impl.getRangeAt(index));\n    },\n    removeRange: function(range) {\n      this.impl.removeRange(unwrap(range));\n    },\n    selectAllChildren: function(node) {\n      this.impl.selectAllChildren(unwrapIfNeeded(node));\n    },\n    toString: function() {\n      return this.impl.toString();\n    }\n  };\n\n  // WebKit extensions. Not implemented.\n  // readonly attribute Node baseNode;\n  // readonly attribute long baseOffset;\n  // readonly attribute Node extentNode;\n  // readonly attribute long extentOffset;\n  // [RaisesException] void setBaseAndExtent([Default=Undefined] optional Node baseNode,\n  //                       [Default=Undefined] optional long baseOffset,\n  //                       [Default=Undefined] optional Node extentNode,\n  //                       [Default=Undefined] optional long extentOffset);\n  // [RaisesException, ImplementedAs=collapse] void setPosition([Default=Undefined] optional Node node,\n  //                  [Default=Undefined] optional long offset);\n\n  registerWrapper(window.Selection, Selection, window.getSelection());\n\n  scope.wrappers.Selection = Selection;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var GetElementsByInterface = scope.GetElementsByInterface;\n  var Node = scope.wrappers.Node;\n  var ParentNodeInterface = scope.ParentNodeInterface;\n  var Selection = scope.wrappers.Selection;\n  var SelectorsInterface = scope.SelectorsInterface;\n  var ShadowRoot = scope.wrappers.ShadowRoot;\n  var cloneNode = scope.cloneNode;\n  var defineWrapGetter = scope.defineWrapGetter;\n  var elementFromPoint = scope.elementFromPoint;\n  var forwardMethodsToWrapper = scope.forwardMethodsToWrapper;\n  var matchesNames = scope.matchesNames;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var renderAllPending = scope.renderAllPending;\n  var rewrap = scope.rewrap;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n  var wrapEventTargetMethods = scope.wrapEventTargetMethods;\n  var wrapNodeList = scope.wrapNodeList;\n\n  var implementationTable = new WeakMap();\n\n  function Document(node) {\n    Node.call(this, node);\n  }\n  Document.prototype = Object.create(Node.prototype);\n\n  defineWrapGetter(Document, 'documentElement');\n\n  // Conceptually both body and head can be in a shadow but suporting that seems\n  // overkill at this point.\n  defineWrapGetter(Document, 'body');\n  defineWrapGetter(Document, 'head');\n\n  // document cannot be overridden so we override a bunch of its methods\n  // directly on the instance.\n\n  function wrapMethod(name) {\n    var original = document[name];\n    Document.prototype[name] = function() {\n      return wrap(original.apply(this.impl, arguments));\n    };\n  }\n\n  [\n    'createComment',\n    'createDocumentFragment',\n    'createElement',\n    'createElementNS',\n    'createEvent',\n    'createEventNS',\n    'createRange',\n    'createTextNode',\n    'getElementById'\n  ].forEach(wrapMethod);\n\n  var originalAdoptNode = document.adoptNode;\n\n  function adoptNodeNoRemove(node, doc) {\n    originalAdoptNode.call(doc.impl, unwrap(node));\n    adoptSubtree(node, doc);\n  }\n\n  function adoptSubtree(node, doc) {\n    if (node.shadowRoot)\n      doc.adoptNode(node.shadowRoot);\n    if (node instanceof ShadowRoot)\n      adoptOlderShadowRoots(node, doc);\n    for (var child = node.firstChild; child; child = child.nextSibling) {\n      adoptSubtree(child, doc);\n    }\n  }\n\n  function adoptOlderShadowRoots(shadowRoot, doc) {\n    var oldShadowRoot = shadowRoot.olderShadowRoot;\n    if (oldShadowRoot)\n      doc.adoptNode(oldShadowRoot);\n  }\n\n  var originalGetSelection = document.getSelection;\n\n  mixin(Document.prototype, {\n    adoptNode: function(node) {\n      if (node.parentNode)\n        node.parentNode.removeChild(node);\n      adoptNodeNoRemove(node, this);\n      return node;\n    },\n    elementFromPoint: function(x, y) {\n      return elementFromPoint(this, this, x, y);\n    },\n    importNode: function(node, deep) {\n      return cloneNode(node, deep, this.impl);\n    },\n    getSelection: function() {\n      renderAllPending();\n      return new Selection(originalGetSelection.call(unwrap(this)));\n    }\n  });\n\n  if (document.registerElement) {\n    var originalRegisterElement = document.registerElement;\n    Document.prototype.registerElement = function(tagName, object) {\n      var prototype = object.prototype;\n\n      // If we already used the object as a prototype for another custom\n      // element.\n      if (scope.nativePrototypeTable.get(prototype)) {\n        // TODO(arv): DOMException\n        throw new Error('NotSupportedError');\n      }\n\n      // Find first object on the prototype chain that already have a native\n      // prototype. Keep track of all the objects before that so we can create\n      // a similar structure for the native case.\n      var proto = Object.getPrototypeOf(prototype);\n      var nativePrototype;\n      var prototypes = [];\n      while (proto) {\n        nativePrototype = scope.nativePrototypeTable.get(proto);\n        if (nativePrototype)\n          break;\n        prototypes.push(proto);\n        proto = Object.getPrototypeOf(proto);\n      }\n\n      if (!nativePrototype) {\n        // TODO(arv): DOMException\n        throw new Error('NotSupportedError');\n      }\n\n      // This works by creating a new prototype object that is empty, but has\n      // the native prototype as its proto. The original prototype object\n      // passed into register is used as the wrapper prototype.\n\n      var newPrototype = Object.create(nativePrototype);\n      for (var i = prototypes.length - 1; i >= 0; i--) {\n        newPrototype = Object.create(newPrototype);\n      }\n\n      // Add callbacks if present.\n      // Names are taken from:\n      //   https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.cpp&sq=package:chromium&type=cs&l=156\n      // and not from the spec since the spec is out of date.\n      [\n        'createdCallback',\n        'attachedCallback',\n        'detachedCallback',\n        'attributeChangedCallback',\n      ].forEach(function(name) {\n        var f = prototype[name];\n        if (!f)\n          return;\n        newPrototype[name] = function() {\n          // if this element has been wrapped prior to registration,\n          // the wrapper is stale; in this case rewrap\n          if (!(wrap(this) instanceof CustomElementConstructor)) {\n            rewrap(this);\n          }\n          f.apply(wrap(this), arguments);\n        };\n      });\n\n      var p = {prototype: newPrototype};\n      if (object.extends)\n        p.extends = object.extends;\n\n      function CustomElementConstructor(node) {\n        if (!node) {\n          if (object.extends) {\n            return document.createElement(object.extends, tagName);\n          } else {\n            return document.createElement(tagName);\n          }\n        }\n        this.impl = node;\n      }\n      CustomElementConstructor.prototype = prototype;\n      CustomElementConstructor.prototype.constructor = CustomElementConstructor;\n\n      scope.constructorTable.set(newPrototype, CustomElementConstructor);\n      scope.nativePrototypeTable.set(prototype, newPrototype);\n\n      // registration is synchronous so do it last\n      var nativeConstructor = originalRegisterElement.call(unwrap(this),\n          tagName, p);\n      return CustomElementConstructor;\n    };\n\n    forwardMethodsToWrapper([\n      window.HTMLDocument || window.Document,  // Gecko adds these to HTMLDocument\n    ], [\n      'registerElement',\n    ]);\n  }\n\n  // We also override some of the methods on document.body and document.head\n  // for convenience.\n  forwardMethodsToWrapper([\n    window.HTMLBodyElement,\n    window.HTMLDocument || window.Document,  // Gecko adds these to HTMLDocument\n    window.HTMLHeadElement,\n    window.HTMLHtmlElement,\n  ], [\n    'appendChild',\n    'compareDocumentPosition',\n    'contains',\n    'getElementsByClassName',\n    'getElementsByTagName',\n    'getElementsByTagNameNS',\n    'insertBefore',\n    'querySelector',\n    'querySelectorAll',\n    'removeChild',\n    'replaceChild',\n  ].concat(matchesNames));\n\n  forwardMethodsToWrapper([\n    window.HTMLDocument || window.Document,  // Gecko adds these to HTMLDocument\n  ], [\n    'adoptNode',\n    'importNode',\n    'contains',\n    'createComment',\n    'createDocumentFragment',\n    'createElement',\n    'createElementNS',\n    'createEvent',\n    'createEventNS',\n    'createRange',\n    'createTextNode',\n    'elementFromPoint',\n    'getElementById',\n    'getSelection',\n  ]);\n\n  mixin(Document.prototype, GetElementsByInterface);\n  mixin(Document.prototype, ParentNodeInterface);\n  mixin(Document.prototype, SelectorsInterface);\n\n  mixin(Document.prototype, {\n    get implementation() {\n      var implementation = implementationTable.get(this);\n      if (implementation)\n        return implementation;\n      implementation =\n          new DOMImplementation(unwrap(this).implementation);\n      implementationTable.set(this, implementation);\n      return implementation;\n    }\n  });\n\n  registerWrapper(window.Document, Document,\n      document.implementation.createHTMLDocument(''));\n\n  // Both WebKit and Gecko uses HTMLDocument for document. HTML5/DOM only has\n  // one Document interface and IE implements the standard correctly.\n  if (window.HTMLDocument)\n    registerWrapper(window.HTMLDocument, Document);\n\n  wrapEventTargetMethods([\n    window.HTMLBodyElement,\n    window.HTMLDocument || window.Document,  // Gecko adds these to HTMLDocument\n    window.HTMLHeadElement,\n  ]);\n\n  function DOMImplementation(impl) {\n    this.impl = impl;\n  }\n\n  function wrapImplMethod(constructor, name) {\n    var original = document.implementation[name];\n    constructor.prototype[name] = function() {\n      return wrap(original.apply(this.impl, arguments));\n    };\n  }\n\n  function forwardImplMethod(constructor, name) {\n    var original = document.implementation[name];\n    constructor.prototype[name] = function() {\n      return original.apply(this.impl, arguments);\n    };\n  }\n\n  wrapImplMethod(DOMImplementation, 'createDocumentType');\n  wrapImplMethod(DOMImplementation, 'createDocument');\n  wrapImplMethod(DOMImplementation, 'createHTMLDocument');\n  forwardImplMethod(DOMImplementation, 'hasFeature');\n\n  registerWrapper(window.DOMImplementation, DOMImplementation);\n\n  forwardMethodsToWrapper([\n    window.DOMImplementation,\n  ], [\n    'createDocumentType',\n    'createDocument',\n    'createHTMLDocument',\n    'hasFeature',\n  ]);\n\n  scope.adoptNodeNoRemove = adoptNodeNoRemove;\n  scope.wrappers.DOMImplementation = DOMImplementation;\n  scope.wrappers.Document = Document;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var EventTarget = scope.wrappers.EventTarget;\n  var Selection = scope.wrappers.Selection;\n  var mixin = scope.mixin;\n  var registerWrapper = scope.registerWrapper;\n  var renderAllPending = scope.renderAllPending;\n  var unwrap = scope.unwrap;\n  var unwrapIfNeeded = scope.unwrapIfNeeded;\n  var wrap = scope.wrap;\n\n  var OriginalWindow = window.Window;\n  var originalGetComputedStyle = window.getComputedStyle;\n  var originalGetSelection = window.getSelection;\n\n  function Window(impl) {\n    EventTarget.call(this, impl);\n  }\n  Window.prototype = Object.create(EventTarget.prototype);\n\n  OriginalWindow.prototype.getComputedStyle = function(el, pseudo) {\n    return wrap(this || window).getComputedStyle(unwrapIfNeeded(el), pseudo);\n  };\n\n  OriginalWindow.prototype.getSelection = function() {\n    return wrap(this || window).getSelection();\n  };\n\n  // Work around for https://bugzilla.mozilla.org/show_bug.cgi?id=943065\n  delete window.getComputedStyle;\n  delete window.getSelection;\n\n  ['addEventListener', 'removeEventListener', 'dispatchEvent'].forEach(\n      function(name) {\n        OriginalWindow.prototype[name] = function() {\n          var w = wrap(this || window);\n          return w[name].apply(w, arguments);\n        };\n\n        // Work around for https://bugzilla.mozilla.org/show_bug.cgi?id=943065\n        delete window[name];\n      });\n\n  mixin(Window.prototype, {\n    getComputedStyle: function(el, pseudo) {\n      renderAllPending();\n      return originalGetComputedStyle.call(unwrap(this), unwrapIfNeeded(el),\n                                           pseudo);\n    },\n    getSelection: function() {\n      renderAllPending();\n      return new Selection(originalGetSelection.call(unwrap(this)));\n    },\n  });\n\n  registerWrapper(OriginalWindow, Window);\n\n  scope.wrappers.Window = Window;\n\n})(window.ShadowDOMPolyfill);\n","// Copyright 2013 The Polymer Authors. All rights reserved.\n// Use of this source code is goverened by a BSD-style\n// license that can be found in the LICENSE file.\n\n(function(scope) {\n  'use strict';\n\n  var isWrapperFor = scope.isWrapperFor;\n\n  // This is a list of the elements we currently override the global constructor\n  // for.\n  var elements = {\n    'a': 'HTMLAnchorElement',\n\n    // Do not create an applet element by default since it shows a warning in\n    // IE.\n    // https://github.com/Polymer/polymer/issues/217\n    // 'applet': 'HTMLAppletElement',\n\n    'area': 'HTMLAreaElement',\n    'br': 'HTMLBRElement',\n    'base': 'HTMLBaseElement',\n    'body': 'HTMLBodyElement',\n    'button': 'HTMLButtonElement',\n    // 'command': 'HTMLCommandElement',  // Not fully implemented in Gecko.\n    'dl': 'HTMLDListElement',\n    'datalist': 'HTMLDataListElement',\n    'data': 'HTMLDataElement',\n    'dir': 'HTMLDirectoryElement',\n    'div': 'HTMLDivElement',\n    'embed': 'HTMLEmbedElement',\n    'fieldset': 'HTMLFieldSetElement',\n    'font': 'HTMLFontElement',\n    'form': 'HTMLFormElement',\n    'frame': 'HTMLFrameElement',\n    'frameset': 'HTMLFrameSetElement',\n    'hr': 'HTMLHRElement',\n    'head': 'HTMLHeadElement',\n    'h1': 'HTMLHeadingElement',\n    'html': 'HTMLHtmlElement',\n    'iframe': 'HTMLIFrameElement',\n    'input': 'HTMLInputElement',\n    'li': 'HTMLLIElement',\n    'label': 'HTMLLabelElement',\n    'legend': 'HTMLLegendElement',\n    'link': 'HTMLLinkElement',\n    'map': 'HTMLMapElement',\n    'marquee': 'HTMLMarqueeElement',\n    'menu': 'HTMLMenuElement',\n    'menuitem': 'HTMLMenuItemElement',\n    'meta': 'HTMLMetaElement',\n    'meter': 'HTMLMeterElement',\n    'del': 'HTMLModElement',\n    'ol': 'HTMLOListElement',\n    'object': 'HTMLObjectElement',\n    'optgroup': 'HTMLOptGroupElement',\n    'option': 'HTMLOptionElement',\n    'output': 'HTMLOutputElement',\n    'p': 'HTMLParagraphElement',\n    'param': 'HTMLParamElement',\n    'pre': 'HTMLPreElement',\n    'progress': 'HTMLProgressElement',\n    'q': 'HTMLQuoteElement',\n    'script': 'HTMLScriptElement',\n    'select': 'HTMLSelectElement',\n    'source': 'HTMLSourceElement',\n    'span': 'HTMLSpanElement',\n    'style': 'HTMLStyleElement',\n    'time': 'HTMLTimeElement',\n    'caption': 'HTMLTableCaptionElement',\n    // WebKit and Moz are wrong:\n    // https://bugs.webkit.org/show_bug.cgi?id=111469\n    // https://bugzilla.mozilla.org/show_bug.cgi?id=848096\n    // 'td': 'HTMLTableCellElement',\n    'col': 'HTMLTableColElement',\n    'table': 'HTMLTableElement',\n    'tr': 'HTMLTableRowElement',\n    'thead': 'HTMLTableSectionElement',\n    'tbody': 'HTMLTableSectionElement',\n    'textarea': 'HTMLTextAreaElement',\n    'track': 'HTMLTrackElement',\n    'title': 'HTMLTitleElement',\n    'ul': 'HTMLUListElement',\n    'video': 'HTMLVideoElement',\n  };\n\n  function overrideConstructor(tagName) {\n    var nativeConstructorName = elements[tagName];\n    var nativeConstructor = window[nativeConstructorName];\n    if (!nativeConstructor)\n      return;\n    var element = document.createElement(tagName);\n    var wrapperConstructor = element.constructor;\n    window[nativeConstructorName] = wrapperConstructor;\n  }\n\n  Object.keys(elements).forEach(overrideConstructor);\n\n  Object.getOwnPropertyNames(scope.wrappers).forEach(function(name) {\n    window[name] = scope.wrappers[name]\n  });\n\n  // Export for testing.\n  scope.knownElements = elements;\n\n})(window.ShadowDOMPolyfill);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function() {\n\n  // convenient global\n  window.wrap = ShadowDOMPolyfill.wrapIfNeeded;\n  window.unwrap = ShadowDOMPolyfill.unwrapIfNeeded;\n\n  // users may want to customize other types\n  // TODO(sjmiles): 'button' is now supported by ShadowDOMPolyfill, but\n  // I've left this code here in case we need to temporarily patch another\n  // type\n  /*\n  (function() {\n    var elts = {HTMLButtonElement: 'button'};\n    for (var c in elts) {\n      window[c] = function() { throw 'Patched Constructor'; };\n      window[c].prototype = Object.getPrototypeOf(\n          document.createElement(elts[c]));\n    }\n  })();\n  */\n\n  // patch in prefixed name\n  Object.defineProperty(Element.prototype, 'webkitShadowRoot',\n      Object.getOwnPropertyDescriptor(Element.prototype, 'shadowRoot'));\n\n  var originalCreateShadowRoot = Element.prototype.createShadowRoot;\n  Element.prototype.createShadowRoot = function() {\n    var root = originalCreateShadowRoot.call(this);\n    CustomElements.watchShadow(this);\n    return root;\n  };\n\n  Element.prototype.webkitCreateShadowRoot = Element.prototype.createShadowRoot;\n})();\n","/*\n * Copyright 2012 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/*\n  This is a limited shim for ShadowDOM css styling.\n  https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#styles\n  \n  The intention here is to support only the styling features which can be \n  relatively simply implemented. The goal is to allow users to avoid the \n  most obvious pitfalls and do so without compromising performance significantly. \n  For ShadowDOM styling that's not covered here, a set of best practices\n  can be provided that should allow users to accomplish more complex styling.\n\n  The following is a list of specific ShadowDOM styling features and a brief\n  discussion of the approach used to shim.\n\n  Shimmed features:\n\n  * :host, :ancestor: ShadowDOM allows styling of the shadowRoot's host\n  element using the :host rule. To shim this feature, the :host styles are \n  reformatted and prefixed with a given scope name and promoted to a \n  document level stylesheet.\n  For example, given a scope name of .foo, a rule like this:\n  \n    :host {\n        background: red;\n      }\n    }\n  \n  becomes:\n  \n    .foo {\n      background: red;\n    }\n  \n  * encapsultion: Styles defined within ShadowDOM, apply only to \n  dom inside the ShadowDOM. Polymer uses one of two techniques to imlement\n  this feature.\n  \n  By default, rules are prefixed with the host element tag name \n  as a descendant selector. This ensures styling does not leak out of the 'top'\n  of the element's ShadowDOM. For example,\n\n  div {\n      font-weight: bold;\n    }\n  \n  becomes:\n\n  x-foo div {\n      font-weight: bold;\n    }\n  \n  becomes:\n\n\n  Alternatively, if Platform.ShadowCSS.strictStyling is set to true then \n  selectors are scoped by adding an attribute selector suffix to each\n  simple selector that contains the host element tag name. Each element \n  in the element's ShadowDOM template is also given the scope attribute. \n  Thus, these rules match only elements that have the scope attribute.\n  For example, given a scope name of x-foo, a rule like this:\n  \n    div {\n      font-weight: bold;\n    }\n  \n  becomes:\n  \n    div[x-foo] {\n      font-weight: bold;\n    }\n\n  Note that elements that are dynamically added to a scope must have the scope\n  selector added to them manually.\n\n  * upper/lower bound encapsulation: Styles which are defined outside a\n  shadowRoot should not cross the ShadowDOM boundary and should not apply\n  inside a shadowRoot.\n\n  This styling behavior is not emulated. Some possible ways to do this that \n  were rejected due to complexity and/or performance concerns include: (1) reset\n  every possible property for every possible selector for a given scope name;\n  (2) re-implement css in javascript.\n  \n  As an alternative, users should make sure to use selectors\n  specific to the scope in which they are working.\n  \n  * ::distributed: This behavior is not emulated. It's often not necessary\n  to style the contents of a specific insertion point and instead, descendants\n  of the host element can be styled selectively. Users can also create an \n  extra node around an insertion point and style that node's contents\n  via descendent selectors. For example, with a shadowRoot like this:\n  \n    <style>\n      ::content(div) {\n        background: red;\n      }\n    </style>\n    <content></content>\n  \n  could become:\n  \n    <style>\n      / *@polyfill .content-container div * / \n      ::content(div) {\n        background: red;\n      }\n    </style>\n    <div class=\"content-container\">\n      <content></content>\n    </div>\n  \n  Note the use of @polyfill in the comment above a ShadowDOM specific style\n  declaration. This is a directive to the styling shim to use the selector \n  in comments in lieu of the next selector when running under polyfill.\n*/\n(function(scope) {\n\nvar ShadowCSS = {\n  strictStyling: false,\n  registry: {},\n  // Shim styles for a given root associated with a name and extendsName\n  // 1. cache root styles by name\n  // 2. optionally tag root nodes with scope name\n  // 3. shim polyfill directives /* @polyfill */ and /* @polyfill-rule */\n  // 4. shim :host and scoping\n  shimStyling: function(root, name, extendsName) {\n    var typeExtension = this.isTypeExtension(extendsName);\n    // use caching to make working with styles nodes easier and to facilitate\n    // lookup of extendee\n    var def = this.registerDefinition(root, name, extendsName);\n    // find styles and apply shimming...\n    if (this.strictStyling) {\n      this.applyScopeToContent(root, name);\n    }\n    var cssText = this.stylesToShimmedCssText(def.rootStyles, def.scopeStyles,\n        name, typeExtension);\n    // provide shimmedStyle for user extensibility\n    def.shimmedStyle = cssTextToStyle(cssText);\n    if (root) {\n      root.shimmedStyle = def.shimmedStyle;\n    }\n    // remove existing style elements\n    for (var i=0, l=def.rootStyles.length, s; (i<l) && (s=def.rootStyles[i]); \n        i++) {\n      s.parentNode.removeChild(s);\n    }\n    // add style to document\n    addCssToDocument(cssText);\n  },\n  // apply @polyfill rules + :host and scope shimming\n  stylesToShimmedCssText: function(rootStyles, scopeStyles, name,\n      typeExtension) {\n    name = name || '';\n    // insert @polyfill and @polyfill-rule rules into style elements\n    // scoping process takes care of shimming these\n    this.insertPolyfillDirectives(rootStyles);\n    this.insertPolyfillRules(rootStyles);\n    var cssText = this.shimScoping(scopeStyles, name, typeExtension);\n    // note: we only need to do rootStyles since these are unscoped.\n    cssText += this.extractPolyfillUnscopedRules(rootStyles);\n    return cssText.trim();\n  },\n  registerDefinition: function(root, name, extendsName) {\n    var def = this.registry[name] = {\n      root: root,\n      name: name,\n      extendsName: extendsName\n    }\n    var styles = root ? root.querySelectorAll('style') : [];\n    styles = styles ? Array.prototype.slice.call(styles, 0) : [];\n    def.rootStyles = styles;\n    def.scopeStyles = def.rootStyles;\n    var extendee = this.registry[def.extendsName];\n    if (extendee && (!root || root.querySelector('shadow'))) {\n      def.scopeStyles = extendee.scopeStyles.concat(def.scopeStyles);\n    }\n    return def;\n  },\n  isTypeExtension: function(extendsName) {\n    return extendsName && extendsName.indexOf('-') < 0;\n  },\n  applyScopeToContent: function(root, name) {\n    if (root) {\n      // add the name attribute to each node in root.\n      Array.prototype.forEach.call(root.querySelectorAll('*'),\n          function(node) {\n            node.setAttribute(name, '');\n          });\n      // and template contents too\n      Array.prototype.forEach.call(root.querySelectorAll('template'),\n          function(template) {\n            this.applyScopeToContent(template.content, name);\n          },\n          this);\n    }\n  },\n  /*\n   * Process styles to convert native ShadowDOM rules that will trip\n   * up the css parser; we rely on decorating the stylesheet with comments.\n   * \n   * For example, we convert this rule:\n   * \n   * (comment start) @polyfill :host menu-item (comment end)\n   * shadow::-webkit-distributed(menu-item) {\n   * \n   * to this:\n   * \n   * scopeName menu-item {\n   *\n  **/\n  insertPolyfillDirectives: function(styles) {\n    if (styles) {\n      Array.prototype.forEach.call(styles, function(s) {\n        s.textContent = this.insertPolyfillDirectivesInCssText(s.textContent);\n      }, this);\n    }\n  },\n  insertPolyfillDirectivesInCssText: function(cssText) {\n    return cssText.replace(cssPolyfillCommentRe, function(match, p1) {\n      // remove end comment delimiter and add block start\n      return p1.slice(0, -2) + '{';\n    });\n  },\n  /*\n   * Process styles to add rules which will only apply under the polyfill\n   * \n   * For example, we convert this rule:\n   * \n   * (comment start) @polyfill-rule :host menu-item { \n   * ... } (comment end)\n   * \n   * to this:\n   * \n   * scopeName menu-item {...}\n   *\n  **/\n  insertPolyfillRules: function(styles) {\n    if (styles) {\n      Array.prototype.forEach.call(styles, function(s) {\n        s.textContent = this.insertPolyfillRulesInCssText(s.textContent);\n      }, this);\n    }\n  },\n  insertPolyfillRulesInCssText: function(cssText) {\n    return cssText.replace(cssPolyfillRuleCommentRe, function(match, p1) {\n      // remove end comment delimiter\n      return p1.slice(0, -1);\n    });\n  },\n  /*\n   * Process styles to add rules which will only apply under the polyfill\n   * and do not process via CSSOM. (CSSOM is destructive to rules on rare \n   * occasions, e.g. -webkit-calc on Safari.)\n   * For example, we convert this rule:\n   * \n   * (comment start) @polyfill-unscoped-rule menu-item { \n   * ... } (comment end)\n   * \n   * to this:\n   * \n   * menu-item {...}\n   *\n  **/\n  extractPolyfillUnscopedRules: function(styles) {\n    var cssText = '';\n    if (styles) {\n      Array.prototype.forEach.call(styles, function(s) {\n        cssText += this.extractPolyfillUnscopedRulesFromCssText(\n            s.textContent) + '\\n\\n';\n      }, this);\n    }\n    return cssText;\n  },\n  extractPolyfillUnscopedRulesFromCssText: function(cssText) {\n    var r = '', matches;\n    while (matches = cssPolyfillUnscopedRuleCommentRe.exec(cssText)) {\n      r += matches[1].slice(0, -1) + '\\n\\n';\n    }\n    return r;\n  },\n  /* Ensure styles are scoped. Pseudo-scoping takes a rule like:\n   * \n   *  .foo {... } \n   *  \n   *  and converts this to\n   *  \n   *  scopeName .foo { ... }\n  */\n  shimScoping: function(styles, name, typeExtension) {\n    if (styles) {\n      return this.convertScopedStyles(styles, name, typeExtension);\n    }\n  },\n  convertScopedStyles: function(styles, name, typeExtension) {\n    var cssText = stylesToCssText(styles);\n    cssText = this.insertPolyfillHostInCssText(cssText);\n    cssText = this.convertColonHost(cssText);\n    cssText = this.convertColonAncestor(cssText);\n    cssText = this.convertCombinators(cssText);\n    if (name) {\n      var rules = cssToRules(cssText);\n      cssText = this.scopeRules(rules, name, typeExtension);\n    }\n    return cssText;\n  },\n  /*\n   * convert a rule like :host(.foo) > .bar { }\n   *\n   * to\n   *\n   * scopeName.foo > .bar\n  */\n  convertColonHost: function(cssText) {\n    return this.convertColonRule(cssText, cssColonHostRe,\n        this.colonHostPartReplacer);\n  },\n  /*\n   * convert a rule like :ancestor(.foo) > .bar { }\n   *\n   * to\n   *\n   * scopeName.foo > .bar, .foo scopeName > .bar { }\n   * \n   * and\n   *\n   * :ancestor(.foo:host) .bar { ... }\n   * \n   * to\n   * \n   * scopeName.foo .bar { ... }\n  */\n  convertColonAncestor: function(cssText) {\n    return this.convertColonRule(cssText, cssColonAncestorRe,\n        this.colonAncestorPartReplacer);\n  },\n  convertColonRule: function(cssText, regExp, partReplacer) {\n    // p1 = :host, p2 = contents of (), p3 rest of rule\n    return cssText.replace(regExp, function(m, p1, p2, p3) {\n      p1 = polyfillHostNoCombinator;\n      if (p2) {\n        var parts = p2.split(','), r = [];\n        for (var i=0, l=parts.length, p; (i<l) && (p=parts[i]); i++) {\n          p = p.trim();\n          r.push(partReplacer(p1, p, p3));\n        }\n        return r.join(',');\n      } else {\n        return p1 + p3;\n      }\n    });\n  },\n  colonAncestorPartReplacer: function(host, part, suffix) {\n    if (part.match(polyfillHost)) {\n      return this.colonHostPartReplacer(host, part, suffix);\n    } else {\n      return host + part + suffix + ', ' + part + ' ' + host + suffix;\n    }\n  },\n  colonHostPartReplacer: function(host, part, suffix) {\n    return host + part.replace(polyfillHost, '') + suffix;\n  },\n  /*\n   * Convert ^ and ^^ combinators by replacing with space.\n  */\n  convertCombinators: function(cssText) {\n    return cssText.replace(/\\^\\^/g, ' ').replace(/\\^/g, ' ');\n  },\n  // change a selector like 'div' to 'name div'\n  scopeRules: function(cssRules, name, typeExtension) {\n    var cssText = '';\n    Array.prototype.forEach.call(cssRules, function(rule) {\n      if (rule.selectorText && (rule.style && rule.style.cssText)) {\n        cssText += this.scopeSelector(rule.selectorText, name, typeExtension, \n          this.strictStyling) + ' {\\n\\t';\n        cssText += this.propertiesFromRule(rule) + '\\n}\\n\\n';\n      } else if (rule.media) {\n        cssText += '@media ' + rule.media.mediaText + ' {\\n';\n        cssText += this.scopeRules(rule.cssRules, name, typeExtension);\n        cssText += '\\n}\\n\\n';\n      } else if (rule.cssText) {\n        cssText += rule.cssText + '\\n\\n';\n      }\n    }, this);\n    return cssText;\n  },\n  scopeSelector: function(selector, name, typeExtension, strict) {\n    var r = [], parts = selector.split(',');\n    parts.forEach(function(p) {\n      p = p.trim();\n      if (this.selectorNeedsScoping(p, name, typeExtension)) {\n        p = (strict && !p.match(polyfillHostNoCombinator)) ? \n            this.applyStrictSelectorScope(p, name) :\n            this.applySimpleSelectorScope(p, name, typeExtension);\n      }\n      r.push(p);\n    }, this);\n    return r.join(', ');\n  },\n  selectorNeedsScoping: function(selector, name, typeExtension) {\n    var re = this.makeScopeMatcher(name, typeExtension);\n    return !selector.match(re);\n  },\n  makeScopeMatcher: function(name, typeExtension) {\n    var matchScope = typeExtension ? '\\\\[is=[\\'\"]?' + name + '[\\'\"]?\\\\]' : name;\n    return new RegExp('^(' + matchScope + ')' + selectorReSuffix, 'm');\n  },\n  // scope via name and [is=name]\n  applySimpleSelectorScope: function(selector, name, typeExtension) {\n    var scoper = typeExtension ? '[is=' + name + ']' : name;\n    if (selector.match(polyfillHostRe)) {\n      selector = selector.replace(polyfillHostNoCombinator, scoper);\n      return selector.replace(polyfillHostRe, scoper + ' ');\n    } else {\n      return scoper + ' ' + selector;\n    }\n  },\n  // return a selector with [name] suffix on each simple selector\n  // e.g. .foo.bar > .zot becomes .foo[name].bar[name] > .zot[name]\n  applyStrictSelectorScope: function(selector, name) {\n    var splits = [' ', '>', '+', '~'],\n      scoped = selector,\n      attrName = '[' + name + ']';\n    splits.forEach(function(sep) {\n      var parts = scoped.split(sep);\n      scoped = parts.map(function(p) {\n        // remove :host since it should be unnecessary\n        var t = p.trim().replace(polyfillHostRe, '');\n        if (t && (splits.indexOf(t) < 0) && (t.indexOf(attrName) < 0)) {\n          p = t.replace(/([^:]*)(:*)(.*)/, '$1' + attrName + '$2$3')\n        }\n        return p;\n      }).join(sep);\n    });\n    return scoped;\n  },\n  insertPolyfillHostInCssText: function(selector) {\n    return selector.replace(hostRe, polyfillHost).replace(colonHostRe,\n        polyfillHost).replace(colonAncestorRe, polyfillAncestor);\n  },\n  propertiesFromRule: function(rule) {\n    // TODO(sorvell): Safari cssom incorrectly removes quotes from the content\n    // property. (https://bugs.webkit.org/show_bug.cgi?id=118045)\n    if (rule.style.content && !rule.style.content.match(/['\"]+/)) {\n      return rule.style.cssText.replace(/content:[^;]*;/g, 'content: \\'' + \n          rule.style.content + '\\';');\n    }\n    return rule.style.cssText;\n  }\n};\n\nvar selectorRe = /([^{]*)({[\\s\\S]*?})/gim,\n    cssCommentRe = /\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\//gim,\n    cssPolyfillCommentRe = /\\/\\*\\s*@polyfill ([^*]*\\*+([^/*][^*]*\\*+)*\\/)([^{]*?){/gim,\n    cssPolyfillRuleCommentRe = /\\/\\*\\s@polyfill-rule([^*]*\\*+([^/*][^*]*\\*+)*)\\//gim,\n    cssPolyfillUnscopedRuleCommentRe = /\\/\\*\\s@polyfill-unscoped-rule([^*]*\\*+([^/*][^*]*\\*+)*)\\//gim,\n    cssPseudoRe = /::(x-[^\\s{,(]*)/gim,\n    cssPartRe = /::part\\(([^)]*)\\)/gim,\n    // note: :host pre-processed to -shadowcsshost.\n    polyfillHost = '-shadowcsshost',\n    // note: :ancestor pre-processed to -shadowcssancestor.\n    polyfillAncestor = '-shadowcssancestor',\n    parenSuffix = ')(?:\\\\((' +\n        '(?:\\\\([^)(]*\\\\)|[^)(]*)+?' +\n        ')\\\\))?([^,{]*)';\n    cssColonHostRe = new RegExp('(' + polyfillHost + parenSuffix, 'gim'),\n    cssColonAncestorRe = new RegExp('(' + polyfillAncestor + parenSuffix, 'gim'),\n    selectorReSuffix = '([>\\\\s~+\\[.,{:][\\\\s\\\\S]*)?$',\n    hostRe = /@host/gim,\n    colonHostRe = /\\:host/gim,\n    colonAncestorRe = /\\:ancestor/gim,\n    /* host name without combinator */\n    polyfillHostNoCombinator = polyfillHost + '-no-combinator',\n    polyfillHostRe = new RegExp(polyfillHost, 'gim');\n    polyfillAncestorRe = new RegExp(polyfillAncestor, 'gim');\n\nfunction stylesToCssText(styles, preserveComments) {\n  var cssText = '';\n  Array.prototype.forEach.call(styles, function(s) {\n    cssText += s.textContent + '\\n\\n';\n  });\n  // strip comments for easier processing\n  if (!preserveComments) {\n    cssText = cssText.replace(cssCommentRe, '');\n  }\n  return cssText;\n}\n\nfunction cssTextToStyle(cssText) {\n  var style = document.createElement('style');\n  style.textContent = cssText;\n  return style;\n}\n\nfunction cssToRules(cssText) {\n  var style = cssTextToStyle(cssText);\n  document.head.appendChild(style);\n  var rules = style.sheet.cssRules;\n  style.parentNode.removeChild(style);\n  return rules;\n}\n\nfunction rulesToCss(cssRules) {\n  for (var i=0, css=[]; i < cssRules.length; i++) {\n    css.push(cssRules[i].cssText);\n  }\n  return css.join('\\n\\n');\n}\n\nfunction addCssToDocument(cssText) {\n  if (cssText) {\n    getSheet().appendChild(document.createTextNode(cssText));\n  }\n}\n\nvar SHIM_ATTRIBUTE = 'shim-shadowdom';\nvar SHIMMED_ATTRIBUTE = 'shim-shadowdom-css';\n\nvar sheet;\nfunction getSheet() {\n  if (!sheet) {\n    sheet = document.createElement(\"style\");\n    sheet.setAttribute(SHIMMED_ATTRIBUTE, '');\n    sheet[SHIMMED_ATTRIBUTE] = true;\n  }\n  return sheet;\n}\n\n// add polyfill stylesheet to document\nif (window.ShadowDOMPolyfill) {\n  addCssToDocument('style { display: none !important; }\\n');\n  var doc = wrap(document);\n  var head = doc.querySelector('head');\n  head.insertBefore(getSheet(), head.childNodes[0]);\n\n  // TODO(sorvell): monkey-patching HTMLImports is abusive;\n  // consider a better solution.\n  document.addEventListener('DOMContentLoaded', function() {\n    var urlResolver = scope.urlResolver;\n    \n    if (window.HTMLImports && !HTMLImports.useNative) {\n      var SHIM_SHEET_SELECTOR = 'link[rel=stylesheet]' +\n          '[' + SHIM_ATTRIBUTE + ']';\n      var SHIM_STYLE_SELECTOR = 'style[' + SHIM_ATTRIBUTE + ']';\n      HTMLImports.importer.documentPreloadSelectors += ',' + SHIM_SHEET_SELECTOR;\n      HTMLImports.importer.importsPreloadSelectors += ',' + SHIM_SHEET_SELECTOR;\n\n      HTMLImports.parser.documentSelectors = [\n        HTMLImports.parser.documentSelectors,\n        SHIM_SHEET_SELECTOR,\n        SHIM_STYLE_SELECTOR\n      ].join(',');\n  \n      var originalParseGeneric = HTMLImports.parser.parseGeneric;\n\n      HTMLImports.parser.parseGeneric = function(elt) {\n        if (elt[SHIMMED_ATTRIBUTE]) {\n          return;\n        }\n        var style = elt.__importElement || elt;\n        if (!style.hasAttribute(SHIM_ATTRIBUTE)) {\n          originalParseGeneric.call(this, elt);\n          return;\n        }\n        if (elt.__resource) {\n          style = elt.ownerDocument.createElement('style');\n          style.textContent = urlResolver.resolveCssText(\n              elt.__resource, elt.href);\n        } else {\n          urlResolver.resolveStyle(style);  \n        }\n        var styles = [style];\n        style.textContent = ShadowCSS.stylesToShimmedCssText(styles, styles);\n        style.removeAttribute(SHIM_ATTRIBUTE, '');\n        style.setAttribute(SHIMMED_ATTRIBUTE, '');\n        style[SHIMMED_ATTRIBUTE] = true;\n        // place in document\n        if (style.parentNode !== head) {\n          // replace links in head\n          if (elt.parentNode === head) {\n            head.replaceChild(style, elt);\n          } else {\n            head.appendChild(style);\n          }\n        }\n        style.__importParsed = true;\n        this.markParsingComplete(elt);\n      }\n\n      var hasResource = HTMLImports.parser.hasResource;\n      HTMLImports.parser.hasResource = function(node) {\n        if (node.localName === 'link' && node.rel === 'stylesheet' &&\n            node.hasAttribute(SHIM_ATTRIBUTE)) {\n          return (node.__resource);\n        } else {\n          return hasResource.call(this, node);\n        }\n      }\n\n    }\n  });\n}\n\n// exports\nscope.ShadowCSS = ShadowCSS;\n\n})(window.Platform);","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function() {\n\n  // poor man's adapter for template.content on various platform scenarios\n  window.templateContent = window.templateContent || function(inTemplate) {\n    return inTemplate.content;\n  };\n\n  // so we can call wrap/unwrap without testing for ShadowDOMPolyfill\n\n  window.wrap = window.unwrap = function(n){\n    return n;\n  }\n\n  var originalCreateShadowRoot = Element.prototype.webkitCreateShadowRoot;\n  Element.prototype.webkitCreateShadowRoot = function() {\n    var elderRoot = this.webkitShadowRoot;\n    var root = originalCreateShadowRoot.call(this);\n    root.olderShadowRoot = elderRoot;\n    root.host = this;\n    CustomElements.watchShadow(this);\n    return root;\n  }\n\n  Object.defineProperties(Element.prototype, {\n    shadowRoot: {\n      get: function() {\n        return this.webkitShadowRoot;\n      }\n    },\n    createShadowRoot: {\n      value: function() {\n        return this.webkitCreateShadowRoot();\n      }\n    }\n  });\n\n  window.templateContent = function(inTemplate) {\n    // if MDV exists, it may need to boostrap this template to reveal content\n    if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) {\n      HTMLTemplateElement.bootstrap(inTemplate);\n    }\n    // fallback when there is no Shadow DOM polyfill, no MDV polyfill, and no\n    // native template support\n    if (!inTemplate.content && !inTemplate._content) {\n      var frag = document.createDocumentFragment();\n      while (inTemplate.firstChild) {\n        frag.appendChild(inTemplate.firstChild);\n      }\n      inTemplate._content = frag;\n    }\n    return inTemplate.content || inTemplate._content;\n  };\n\n})();","/* Any copyright is dedicated to the Public Domain.\n * http://creativecommons.org/publicdomain/zero/1.0/ */\n\n(function(scope) {\n  'use strict';\n\n  // feature detect for URL constructor\n  var hasWorkingUrl = false;\n  if (!scope.forceJURL) {\n    try {\n      var u = new URL('b', 'http://a');\n      hasWorkingUrl = u.href === 'http://a/b';\n    } catch(e) {}\n  }\n\n  if (hasWorkingUrl)\n    return;\n\n  var relative = Object.create(null);\n  relative['ftp'] = 21;\n  relative['file'] = 0;\n  relative['gopher'] = 70;\n  relative['http'] = 80;\n  relative['https'] = 443;\n  relative['ws'] = 80;\n  relative['wss'] = 443;\n\n  var relativePathDotMapping = Object.create(null);\n  relativePathDotMapping['%2e'] = '.';\n  relativePathDotMapping['.%2e'] = '..';\n  relativePathDotMapping['%2e.'] = '..';\n  relativePathDotMapping['%2e%2e'] = '..';\n\n  function isRelativeScheme(scheme) {\n    return relative[scheme] !== undefined;\n  }\n\n  function invalid() {\n    clear.call(this);\n    this._isInvalid = true;\n  }\n\n  function IDNAToASCII(h) {\n    if ('' == h) {\n      invalid.call(this)\n    }\n    // XXX\n    return h.toLowerCase()\n  }\n\n  function percentEscape(c) {\n    var unicode = c.charCodeAt(0);\n    if (unicode > 0x20 &&\n       unicode < 0x7F &&\n       // \" # < > ? `\n       [0x22, 0x23, 0x3C, 0x3E, 0x3F, 0x60].indexOf(unicode) == -1\n      ) {\n      return c;\n    }\n    return encodeURIComponent(c);\n  }\n\n  function percentEscapeQuery(c) {\n    // XXX This actually needs to encode c using encoding and then\n    // convert the bytes one-by-one.\n\n    var unicode = c.charCodeAt(0);\n    if (unicode > 0x20 &&\n       unicode < 0x7F &&\n       // \" # < > ` (do not escape '?')\n       [0x22, 0x23, 0x3C, 0x3E, 0x60].indexOf(unicode) == -1\n      ) {\n      return c;\n    }\n    return encodeURIComponent(c);\n  }\n\n  var EOF = undefined,\n      ALPHA = /[a-zA-Z]/,\n      ALPHANUMERIC = /[a-zA-Z0-9\\+\\-\\.]/;\n\n  function parse(input, stateOverride, base) {\n    function err(message) {\n      errors.push(message)\n    }\n\n    var state = stateOverride || 'scheme start',\n        cursor = 0,\n        buffer = '',\n        seenAt = false,\n        seenBracket = false,\n        errors = [];\n\n    loop: while ((input[cursor - 1] != EOF || cursor == 0) && !this._isInvalid) {\n      var c = input[cursor];\n      switch (state) {\n        case 'scheme start':\n          if (c && ALPHA.test(c)) {\n            buffer += c.toLowerCase(); // ASCII-safe\n            state = 'scheme';\n          } else if (!stateOverride) {\n            buffer = '';\n            state = 'no scheme';\n            continue;\n          } else {\n            err('Invalid scheme.');\n            break loop;\n          }\n          break;\n\n        case 'scheme':\n          if (c && ALPHANUMERIC.test(c)) {\n            buffer += c.toLowerCase(); // ASCII-safe\n          } else if (':' == c) {\n            this._scheme = buffer;\n            buffer = '';\n            if (stateOverride) {\n              break loop;\n            }\n            if (isRelativeScheme(this._scheme)) {\n              this._isRelative = true;\n            }\n            if ('file' == this._scheme) {\n              state = 'relative';\n            } else if (this._isRelative && base && base._scheme == this._scheme) {\n              state = 'relative or authority';\n            } else if (this._isRelative) {\n              state = 'authority first slash';\n            } else {\n              state = 'scheme data';\n            }\n          } else if (!stateOverride) {\n            buffer = '';\n            cursor = 0;\n            state = 'no scheme';\n            continue;\n          } else if (EOF == c) {\n            break loop;\n          } else {\n            err('Code point not allowed in scheme: ' + c)\n            break loop;\n          }\n          break;\n\n        case 'scheme data':\n          if ('?' == c) {\n            query = '?';\n            state = 'query';\n          } else if ('#' == c) {\n            this._fragment = '#';\n            state = 'fragment';\n          } else {\n            // XXX error handling\n            if (EOF != c && '\\t' != c && '\\n' != c && '\\r' != c) {\n              this._schemeData += percentEscape(c);\n            }\n          }\n          break;\n\n        case 'no scheme':\n          if (!base || !(isRelativeScheme(base._scheme))) {\n            err('Missing scheme.');\n            invalid.call(this);\n          } else {\n            state = 'relative';\n            continue;\n          }\n          break;\n\n        case 'relative or authority':\n          if ('/' == c && '/' == input[cursor+1]) {\n            state = 'authority ignore slashes';\n          } else {\n            err('Expected /, got: ' + c);\n            state = 'relative';\n            continue\n          }\n          break;\n\n        case 'relative':\n          this._isRelative = true;\n          if ('file' != this._scheme)\n            this._scheme = base._scheme;\n          if (EOF == c) {\n            this._host = base._host;\n            this._port = base._port;\n            this._path = base._path.slice();\n            this._query = base._query;\n            break loop;\n          } else if ('/' == c || '\\\\' == c) {\n            if ('\\\\' == c)\n              err('\\\\ is an invalid code point.');\n            state = 'relative slash';\n          } else if ('?' == c) {\n            this._host = base._host;\n            this._port = base._port;\n            this._path = base._path.slice();\n            this._query = '?';\n            state = 'query';\n          } else if ('#' == c) {\n            this._host = base._host;\n            this._port = base._port;\n            this._path = base._path.slice();\n            this._query = base._query;\n            this._fragment = '#';\n            state = 'fragment';\n          } else {\n            var nextC = input[cursor+1]\n            var nextNextC = input[cursor+2]\n            if (\n              'file' != this._scheme || !ALPHA.test(c) ||\n              (nextC != ':' && nextC != '|') ||\n              (EOF != nextNextC && '/' != nextNextC && '\\\\' != nextNextC && '?' != nextNextC && '#' != nextNextC)) {\n              this._host = base._host;\n              this._port = base._port;\n              this._path = base._path.slice();\n              this._path.pop();\n            }\n            state = 'relative path';\n            continue;\n          }\n          break;\n\n        case 'relative slash':\n          if ('/' == c || '\\\\' == c) {\n            if ('\\\\' == c) {\n              err('\\\\ is an invalid code point.');\n            }\n            if ('file' == this._scheme) {\n              state = 'file host';\n            } else {\n              state = 'authority ignore slashes';\n            }\n          } else {\n            if ('file' != this._scheme) {\n              this._host = base._host;\n              this._port = base._port;\n            }\n            state = 'relative path';\n            continue;\n          }\n          break;\n\n        case 'authority first slash':\n          if ('/' == c) {\n            state = 'authority second slash';\n          } else {\n            err(\"Expected '/', got: \" + c);\n            state = 'authority ignore slashes';\n            continue;\n          }\n          break;\n\n        case 'authority second slash':\n          state = 'authority ignore slashes';\n          if ('/' != c) {\n            err(\"Expected '/', got: \" + c);\n            continue;\n          }\n          break;\n\n        case 'authority ignore slashes':\n          if ('/' != c && '\\\\' != c) {\n            state = 'authority';\n            continue;\n          } else {\n            err('Expected authority, got: ' + c);\n          }\n          break;\n\n        case 'authority':\n          if ('@' == c) {\n            if (seenAt) {\n              err('@ already seen.');\n              buffer += '%40';\n            }\n            seenAt = true;\n            for (var i = 0; i < buffer.length; i++) {\n              var cp = buffer[i];\n              if ('\\t' == cp || '\\n' == cp || '\\r' == cp) {\n                err('Invalid whitespace in authority.');\n                continue;\n              }\n              // XXX check URL code points\n              if (':' == cp && null === this._password) {\n                this._password = '';\n                continue;\n              }\n              var tempC = percentEscape(cp);\n              (null !== this._password) ? this._password += tempC : this._username += tempC;\n            }\n            buffer = '';\n          } else if (EOF == c || '/' == c || '\\\\' == c || '?' == c || '#' == c) {\n            cursor -= buffer.length;\n            buffer = '';\n            state = 'host';\n            continue;\n          } else {\n            buffer += c;\n          }\n          break;\n\n        case 'file host':\n          if (EOF == c || '/' == c || '\\\\' == c || '?' == c || '#' == c) {\n            if (buffer.length == 2 && ALPHA.test(buffer[0]) && (buffer[1] == ':' || buffer[1] == '|')) {\n              state = 'relative path';\n            } else if (buffer.length == 0) {\n              state = 'relative path start';\n            } else {\n              this._host = IDNAToASCII.call(this, buffer);\n              buffer = '';\n              state = 'relative path start';\n            }\n            continue;\n          } else if ('\\t' == c || '\\n' == c || '\\r' == c) {\n            err('Invalid whitespace in file host.');\n          } else {\n            buffer += c;\n          }\n          break;\n\n        case 'host':\n        case 'hostname':\n          if (':' == c && !seenBracket) {\n            // XXX host parsing\n            this._host = IDNAToASCII.call(this, buffer);\n            buffer = '';\n            state = 'port';\n            if ('hostname' == stateOverride) {\n              break loop;\n            }\n          } else if (EOF == c || '/' == c || '\\\\' == c || '?' == c || '#' == c) {\n            this._host = IDNAToASCII.call(this, buffer);\n            buffer = '';\n            state = 'relative path start';\n            if (stateOverride) {\n              break loop;\n            }\n            continue;\n          } else if ('\\t' != c && '\\n' != c && '\\r' != c) {\n            if ('[' == c) {\n              seenBracket = true;\n            } else if (']' == c) {\n              seenBracket = false;\n            }\n            buffer += c;\n          } else {\n            err('Invalid code point in host/hostname: ' + c);\n          }\n          break;\n\n        case 'port':\n          if (/[0-9]/.test(c)) {\n            buffer += c;\n          } else if (EOF == c || '/' == c || '\\\\' == c || '?' == c || '#' == c || stateOverride) {\n            if ('' != buffer) {\n              var temp = parseInt(buffer, 10);\n              if (temp != relative[this._scheme]) {\n                this._port = temp + '';\n              }\n              buffer = '';\n            }\n            if (stateOverride) {\n              break loop;\n            }\n            state = 'relative path start';\n            continue;\n          } else if ('\\t' == c || '\\n' == c || '\\r' == c) {\n            err('Invalid code point in port: ' + c);\n          } else {\n            invalid.call(this);\n          }\n          break;\n\n        case 'relative path start':\n          if ('\\\\' == c)\n            err(\"'\\\\' not allowed in path.\");\n          state = 'relative path';\n          if ('/' != c && '\\\\' != c) {\n            continue;\n          }\n          break;\n\n        case 'relative path':\n          if (EOF == c || '/' == c || '\\\\' == c || (!stateOverride && ('?' == c || '#' == c))) {\n            if ('\\\\' == c) {\n              err('\\\\ not allowed in relative path.');\n            }\n            var tmp;\n            if (tmp = relativePathDotMapping[buffer.toLowerCase()]) {\n              buffer = tmp;\n            }\n            if ('..' == buffer) {\n              this._path.pop();\n              if ('/' != c && '\\\\' != c) {\n                this._path.push('');\n              }\n            } else if ('.' == buffer && '/' != c && '\\\\' != c) {\n              this._path.push('');\n            } else if ('.' != buffer) {\n              if ('file' == this._scheme && this._path.length == 0 && buffer.length == 2 && ALPHA.test(buffer[0]) && buffer[1] == '|') {\n                buffer = buffer[0] + ':';\n              }\n              this._path.push(buffer);\n            }\n            buffer = '';\n            if ('?' == c) {\n              this._query = '?';\n              state = 'query';\n            } else if ('#' == c) {\n              this._fragment = '#';\n              state = 'fragment';\n            }\n          } else if ('\\t' != c && '\\n' != c && '\\r' != c) {\n            buffer += percentEscape(c);\n          }\n          break;\n\n        case 'query':\n          if (!stateOverride && '#' == c) {\n            this._fragment = '#';\n            state = 'fragment';\n          } else if (EOF != c && '\\t' != c && '\\n' != c && '\\r' != c) {\n            this._query += percentEscapeQuery(c);\n          }\n          break;\n\n        case 'fragment':\n          if (EOF != c && '\\t' != c && '\\n' != c && '\\r' != c) {\n            this._fragment += c;\n          }\n          break;\n      }\n\n      cursor++;\n    }\n  }\n\n  function clear() {\n    this._scheme = '';\n    this._schemeData = '';\n    this._username = '';\n    this._password = null;\n    this._host = '';\n    this._port = '';\n    this._path = [];\n    this._query = '';\n    this._fragment = '';\n    this._isInvalid = false;\n    this._isRelative = false;\n  }\n\n  // Does not process domain names or IP addresses.\n  // Does not handle encoding for the query parameter.\n  function jURL(url, base /* , encoding */) {\n    if (base !== undefined && !(base instanceof jURL))\n      base = new jURL(String(base));\n\n    this._url = url;\n    clear.call(this);\n\n    var input = url.replace(/^[ \\t\\r\\n\\f]+|[ \\t\\r\\n\\f]+$/g, '');\n    // encoding = encoding || 'utf-8'\n\n    parse.call(this, input, null, base);\n  }\n\n  jURL.prototype = {\n    get href() {\n      if (this._isInvalid)\n        return this._url;\n\n      var authority = '';\n      if ('' != this._username || null != this._password) {\n        authority = this._username +\n            (null != this._password ? ':' + this._password : '') + '@';\n      }\n\n      return this.protocol +\n          (this._isRelative ? '//' + authority + this.host : '') +\n          this.pathname + this._query + this._fragment;\n    },\n    set href(href) {\n      clear.call(this);\n      parse.call(this, href);\n    },\n\n    get protocol() {\n      return this._scheme + ':';\n    },\n    set protocol(protocol) {\n      if (this._isInvalid)\n        return;\n      parse.call(this, protocol + ':', 'scheme start');\n    },\n\n    get host() {\n      return this._isInvalid ? '' : this._port ?\n          this._host + ':' + this._port : this._host;\n    },\n    set host(host) {\n      if (this._isInvalid || !this._isRelative)\n        return;\n      parse.call(this, host, 'host');\n    },\n\n    get hostname() {\n      return this._host;\n    },\n    set hostname(hostname) {\n      if (this._isInvalid || !this._isRelative)\n        return;\n      parse.call(this, hostname, 'hostname');\n    },\n\n    get port() {\n      return this._port;\n    },\n    set port(port) {\n      if (this._isInvalid || !this._isRelative)\n        return;\n      parse.call(this, port, 'port');\n    },\n\n    get pathname() {\n      return this._isInvalid ? '' : this._isRelative ?\n          '/' + this._path.join('/') : this._schemeData;\n    },\n    set pathname(pathname) {\n      if (this._isInvalid || !this._isRelative)\n        return;\n      this._path = [];\n      parse.call(this, pathname, 'relative path start');\n    },\n\n    get search() {\n      return this._isInvalid || !this._query || '?' == this._query ?\n          '' : this._query;\n    },\n    set search(search) {\n      if (this._isInvalid || !this._isRelative)\n        return;\n      this._query = '?';\n      if ('?' == search[0])\n        search = search.slice(1);\n      parse.call(this, search, 'query');\n    },\n\n    get hash() {\n      return this._isInvalid || !this._fragment || '#' == this._fragment ?\n          '' : this._fragment;\n    },\n    set hash(hash) {\n      if (this._isInvalid)\n        return;\n      this._fragment = '#';\n      if ('#' == hash[0])\n        hash = hash.slice(1);\n      parse.call(this, hash, 'fragment');\n    }\n  };\n\n  scope.URL = jURL;\n\n})(window);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n\n// Old versions of iOS do not have bind.\n\nif (!Function.prototype.bind) {\n  Function.prototype.bind = function(scope) {\n    var self = this;\n    var args = Array.prototype.slice.call(arguments, 1);\n    return function() {\n      var args2 = args.slice();\n      args2.push.apply(args2, arguments);\n      return self.apply(scope, args2);\n    };\n  };\n}\n\n// mixin\n\n// copy all properties from inProps (et al) to inObj\nfunction mixin(inObj/*, inProps, inMoreProps, ...*/) {\n  var obj = inObj || {};\n  for (var i = 1; i < arguments.length; i++) {\n    var p = arguments[i];\n    try {\n      for (var n in p) {\n        copyProperty(n, p, obj);\n      }\n    } catch(x) {\n    }\n  }\n  return obj;\n}\n\n// copy property inName from inSource object to inTarget object\nfunction copyProperty(inName, inSource, inTarget) {\n  var pd = getPropertyDescriptor(inSource, inName);\n  Object.defineProperty(inTarget, inName, pd);\n}\n\n// get property descriptor for inName on inObject, even if\n// inName exists on some link in inObject's prototype chain\nfunction getPropertyDescriptor(inObject, inName) {\n  if (inObject) {\n    var pd = Object.getOwnPropertyDescriptor(inObject, inName);\n    return pd || getPropertyDescriptor(Object.getPrototypeOf(inObject), inName);\n  }\n}\n\n// export\n\nscope.mixin = mixin;\n\n})(window.Platform);","// Copyright 2011 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n(function(scope) {\n\n  'use strict';\n\n  // polyfill DOMTokenList\n  // * add/remove: allow these methods to take multiple classNames\n  // * toggle: add a 2nd argument which forces the given state rather\n  //  than toggling.\n\n  var add = DOMTokenList.prototype.add;\n  var remove = DOMTokenList.prototype.remove;\n  DOMTokenList.prototype.add = function() {\n    for (var i = 0; i < arguments.length; i++) {\n      add.call(this, arguments[i]);\n    }\n  };\n  DOMTokenList.prototype.remove = function() {\n    for (var i = 0; i < arguments.length; i++) {\n      remove.call(this, arguments[i]);\n    }\n  };\n  DOMTokenList.prototype.toggle = function(name, bool) {\n    if (arguments.length == 1) {\n      bool = !this.contains(name);\n    }\n    bool ? this.add(name) : this.remove(name);\n  };\n  DOMTokenList.prototype.switch = function(oldName, newName) {\n    oldName && this.remove(oldName);\n    newName && this.add(newName);\n  };\n\n  // add array() to NodeList, NamedNodeMap, HTMLCollection\n\n  var ArraySlice = function() {\n    return Array.prototype.slice.call(this);\n  };\n\n  var namedNodeMap = (window.NamedNodeMap || window.MozNamedAttrMap || {});\n\n  NodeList.prototype.array = ArraySlice;\n  namedNodeMap.prototype.array = ArraySlice;\n  HTMLCollection.prototype.array = ArraySlice;\n\n  // polyfill performance.now\n\n  if (!window.performance) {\n    var start = Date.now();\n    // only at millisecond precision\n    window.performance = {now: function(){ return Date.now() - start }};\n  }\n\n  // polyfill for requestAnimationFrame\n\n  if (!window.requestAnimationFrame) {\n    window.requestAnimationFrame = (function() {\n      var nativeRaf = window.webkitRequestAnimationFrame ||\n        window.mozRequestAnimationFrame;\n\n      return nativeRaf ?\n        function(callback) {\n          return nativeRaf(function() {\n            callback(performance.now());\n          });\n        } :\n        function( callback ){\n          return window.setTimeout(callback, 1000 / 60);\n        };\n    })();\n  }\n\n  if (!window.cancelAnimationFrame) {\n    window.cancelAnimationFrame = (function() {\n      return  window.webkitCancelAnimationFrame ||\n        window.mozCancelAnimationFrame ||\n        function(id) {\n          clearTimeout(id);\n        };\n    })();\n  }\n\n  // TODO(sorvell): workaround for bug:\n  // https://code.google.com/p/chromium/issues/detail?id=229142\n  // remove when this bug is addressed\n  // give main document templates a base that allows them to fetch eagerly\n  // resolved paths relative to the main document\n  var template = document.createElement('template');\n  var base = document.createElement('base');\n  base.href = document.baseURI;\n  template.content.ownerDocument.appendChild(base);\n  \n\n  // utility\n\n  function createDOM(inTagOrNode, inHTML, inAttrs) {\n    var dom = typeof inTagOrNode == 'string' ?\n        document.createElement(inTagOrNode) : inTagOrNode.cloneNode(true);\n    dom.innerHTML = inHTML;\n    if (inAttrs) {\n      for (var n in inAttrs) {\n        dom.setAttribute(n, inAttrs[n]);\n      }\n    }\n    return dom;\n  }\n  // Make a stub for Polymer() for polyfill purposes; under the HTMLImports\n  // polyfill, scripts in the main document run before imports. That means\n  // if (1) polymer is imported and (2) Polymer() is called in the main document\n  // in a script after the import, 2 occurs before 1. We correct this here\n  // by specfiically patching Polymer(); this is not necessary under native\n  // HTMLImports.\n  var elementDeclarations = [];\n\n  var polymerStub = function(name, dictionary) {\n    elementDeclarations.push(arguments);\n  }\n  window.Polymer = polymerStub;\n\n  // deliver queued delcarations\n  scope.deliverDeclarations = function() {\n    scope.deliverDeclarations = null;\n    return elementDeclarations;\n  }\n\n  // Once DOMContent has loaded, any main document scripts that depend on\n  // Polymer() should have run. Calling Polymer() now is an error until\n  // polymer is imported.\n  window.addEventListener('DOMContentLoaded', function() {\n    if (window.Polymer === polymerStub) {\n      window.Polymer = function() {\n        console.error('You tried to use polymer without loading it first. To ' +\n          'load polymer, <link rel=\"import\" href=\"' + \n          'components/polymer/polymer.html\">');\n      };\n    }\n  });\n\n  // exports\n  scope.createDOM = createDOM;\n\n})(window.Platform);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n// poor man's adapter for template.content on various platform scenarios\nwindow.templateContent = window.templateContent || function(inTemplate) {\n  return inTemplate.content;\n};","(function(scope) {\n  \n  scope = scope || (window.Inspector = {});\n  \n  var inspector;\n\n  window.sinspect = function(inNode, inProxy) {\n    if (!inspector) {\n      inspector = window.open('', 'ShadowDOM Inspector', null, true);\n      inspector.document.write(inspectorHTML);\n      //inspector.document.close();\n      inspector.api = {\n        shadowize: shadowize\n      };\n    }\n    inspect(inNode || wrap(document.body), inProxy);\n  };\n\n  var inspectorHTML = [\n    '<!DOCTYPE html>',\n    '<html>',\n    '  <head>',\n    '    <title>ShadowDOM Inspector</title>',\n    '    <style>',\n    '      body {',\n    '      }',\n    '      pre {',\n    '        font: 9pt \"Courier New\", monospace;',\n    '        line-height: 1.5em;',\n    '      }',\n    '      tag {',\n    '        color: purple;',\n    '      }',\n    '      ul {',\n    '         margin: 0;',\n    '         padding: 0;',\n    '         list-style: none;',\n    '      }',\n    '      li {',\n    '         display: inline-block;',\n    '         background-color: #f1f1f1;',\n    '         padding: 4px 6px;',\n    '         border-radius: 4px;',\n    '         margin-right: 4px;',\n    '      }',\n    '    </style>',\n    '  </head>',\n    '  <body>',\n    '    <ul id=\"crumbs\">',\n    '    </ul>',\n    '    <div id=\"tree\"></div>',\n    '  </body>',\n    '</html>'\n  ].join('\\n');\n  \n  var crumbs = [];\n\n  var displayCrumbs = function() {\n    // alias our document\n    var d = inspector.document;\n    // get crumbbar\n    var cb = d.querySelector('#crumbs');\n    // clear crumbs\n    cb.textContent = '';\n    // build new crumbs\n    for (var i=0, c; c=crumbs[i]; i++) {\n      var a = d.createElement('a');\n      a.href = '#';\n      a.textContent = c.localName;\n      a.idx = i;\n      a.onclick = function(event) {\n        var c;\n        while (crumbs.length > this.idx) {\n          c = crumbs.pop();\n        }\n        inspect(c.shadow || c, c);\n        event.preventDefault();\n      };\n      cb.appendChild(d.createElement('li')).appendChild(a);\n    }\n  };\n\n  var inspect = function(inNode, inProxy) {\n    // alias our document\n    var d = inspector.document;\n    // reset list of drillable nodes\n    drillable = [];\n    // memoize our crumb proxy\n    var proxy = inProxy || inNode;\n    crumbs.push(proxy);\n    // update crumbs\n    displayCrumbs();\n    // reflect local tree\n    d.body.querySelector('#tree').innerHTML =\n        '<pre>' + output(inNode, inNode.childNodes) + '</pre>';\n  };\n\n  var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);\n\n  var blacklisted = {STYLE:1, SCRIPT:1, \"#comment\": 1, TEMPLATE: 1};\n  var blacklist = function(inNode) {\n    return blacklisted[inNode.nodeName];\n  };\n\n  var output = function(inNode, inChildNodes, inIndent) {\n    if (blacklist(inNode)) {\n      return '';\n    }\n    var indent = inIndent || '';\n    if (inNode.localName || inNode.nodeType == 11) {\n      var name = inNode.localName || 'shadow-root';\n      //inChildNodes = ShadowDOM.localNodes(inNode);\n      var info = indent + describe(inNode);\n      // if only textNodes\n      // TODO(sjmiles): make correct for ShadowDOM\n      /*if (!inNode.children.length && inNode.localName !== 'content' && inNode.localName !== 'shadow') {\n        info += catTextContent(inChildNodes);\n      } else*/ {\n        // TODO(sjmiles): native <shadow> has no reference to its projection\n        if (name == 'content' /*|| name == 'shadow'*/) {\n          inChildNodes = inNode.getDistributedNodes();\n        }\n        info += '<br/>';\n        var ind = indent + '&nbsp;&nbsp;';\n        forEach(inChildNodes, function(n) {\n          info += output(n, n.childNodes, ind);\n        });\n        info += indent;\n      }\n      if (!({br:1}[name])) {\n        info += '<tag>&lt;/' + name + '&gt;</tag>';\n        info += '<br/>';\n      }\n    } else {\n      var text = inNode.textContent.trim();\n      info = text ? indent + '\"' + text + '\"' + '<br/>' : '';\n    }\n    return info;\n  };\n\n  var catTextContent = function(inChildNodes) {\n    var info = '';\n    forEach(inChildNodes, function(n) {\n      info += n.textContent.trim();\n    });\n    return info;\n  };\n\n  var drillable = [];\n\n  var describe = function(inNode) {\n    var tag = '<tag>' + '&lt;';\n    var name = inNode.localName || 'shadow-root';\n    if (inNode.webkitShadowRoot || inNode.shadowRoot) {\n      tag += ' <button idx=\"' + drillable.length +\n        '\" onclick=\"api.shadowize.call(this)\">' + name + '</button>';\n      drillable.push(inNode);\n    } else {\n      tag += name || 'shadow-root';\n    }\n    if (inNode.attributes) {\n      forEach(inNode.attributes, function(a) {\n        tag += ' ' + a.name + (a.value ? '=\"' + a.value + '\"' : '');\n      });\n    }\n    tag += '&gt;'+ '</tag>';\n    return tag;\n  };\n\n  // remote api\n\n  shadowize = function() {\n    var idx = Number(this.attributes.idx.value);\n    //alert(idx);\n    var node = drillable[idx];\n    if (node) {\n      inspect(node.webkitShadowRoot || node.shadowRoot, node)\n    } else {\n      console.log(\"bad shadowize node\");\n      console.dir(this);\n    }\n  };\n  \n  // export\n  \n  scope.output = output;\n  \n})(window.Inspector);\n\n\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function(scope) {\n\n  // TODO(sorvell): It's desireable to provide a default stylesheet \n  // that's convenient for styling unresolved elements, but\n  // it's cumbersome to have to include this manually in every page.\n  // It would make sense to put inside some HTMLImport but \n  // the HTMLImports polyfill does not allow loading of stylesheets \n  // that block rendering. Therefore this injection is tolerated here.\n\n  var style = document.createElement('style');\n  style.textContent = ''\n      + 'body {'\n      + 'transition: opacity ease-in 0.2s;' \n      + ' } \\n'\n      + 'body[unresolved] {'\n      + 'opacity: 0; display: block; overflow: hidden;' \n      + ' } \\n'\n      ;\n  var head = document.querySelector('head');\n  head.insertBefore(style, head.firstChild);\n\n})(Platform);\n","(function(scope) {\n\n  function withDependencies(task, depends) {\n    depends = depends || [];\n    if (!depends.map) {\n      depends = [depends];\n    }\n    return task.apply(this, depends.map(marshal));\n  }\n\n  function module(name, dependsOrFactory, moduleFactory) {\n    var module;\n    switch (arguments.length) {\n      case 0:\n        return;\n      case 1:\n        module = null;\n        break;\n      case 2:\n        module = dependsOrFactory.apply(this);\n        break;\n      default:\n        module = withDependencies(moduleFactory, dependsOrFactory);\n        break;\n    }\n    modules[name] = module;\n  };\n\n  function marshal(name) {\n    return modules[name];\n  }\n\n  var modules = {};\n\n  function using(depends, task) {\n    HTMLImports.whenImportsReady(function() {\n      withDependencies(task, depends);\n    });\n  };\n\n  // exports\n\n  scope.marshal = marshal;\n  scope.module = module;\n  scope.using = using;\n\n})(window);","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function(scope) {\n\nvar iterations = 0;\nvar callbacks = [];\nvar twiddle = document.createTextNode('');\n\nfunction endOfMicrotask(callback) {\n  twiddle.textContent = iterations++;\n  callbacks.push(callback);\n}\n\nfunction atEndOfMicrotask() {\n  while (callbacks.length) {\n    callbacks.shift()();\n  }\n}\n\nnew (window.MutationObserver || JsMutationObserver)(atEndOfMicrotask)\n  .observe(twiddle, {characterData: true})\n  ;\n\n// exports\n\nscope.endOfMicrotask = endOfMicrotask;\n\n})(Platform);\n\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n\nvar urlResolver = {\n  resolveDom: function(root, url) {\n    url = url || root.ownerDocument.baseURI;\n    this.resolveAttributes(root, url);\n    this.resolveStyles(root, url);\n    // handle template.content\n    var templates = root.querySelectorAll('template');\n    if (templates) {\n      for (var i = 0, l = templates.length, t; (i < l) && (t = templates[i]); i++) {\n        if (t.content) {\n          this.resolveDom(t.content, url);\n        }\n      }\n    }\n  },\n  resolveStyles: function(root, url) {\n    var styles = root.querySelectorAll('style');\n    if (styles) {\n      for (var i = 0, l = styles.length, s; (i < l) && (s = styles[i]); i++) {\n        this.resolveStyle(s, url);\n      }\n    }\n  },\n  resolveStyle: function(style, url) {\n    url = url || style.ownerDocument.baseURI;\n    style.textContent = this.resolveCssText(style.textContent, url);\n  },\n  resolveCssText: function(cssText, baseUrl) {\n    cssText = replaceUrlsInCssText(cssText, baseUrl, CSS_URL_REGEXP);\n    return replaceUrlsInCssText(cssText, baseUrl, CSS_IMPORT_REGEXP);\n  },\n  resolveAttributes: function(root, url) {\n    if (root.hasAttributes && root.hasAttributes()) {\n      this.resolveElementAttributes(root, url);\n    }\n    // search for attributes that host urls\n    var nodes = root && root.querySelectorAll(URL_ATTRS_SELECTOR);\n    if (nodes) {\n      for (var i = 0, l = nodes.length, n; (i < l) && (n = nodes[i]); i++) {\n        this.resolveElementAttributes(n, url);\n      }\n    }\n  },\n  resolveElementAttributes: function(node, url) {\n    url = url || node.ownerDocument.baseURI;\n    URL_ATTRS.forEach(function(v) {\n      var attr = node.attributes[v];\n      if (attr && attr.value &&\n         (attr.value.search(URL_TEMPLATE_SEARCH) < 0)) {\n        var urlPath = resolveRelativeUrl(url, attr.value);\n        attr.value = urlPath;\n      }\n    });\n  }\n};\n\nvar CSS_URL_REGEXP = /(url\\()([^)]*)(\\))/g;\nvar CSS_IMPORT_REGEXP = /(@import[\\s]+(?!url\\())([^;]*)(;)/g;\nvar URL_ATTRS = ['href', 'src', 'action'];\nvar URL_ATTRS_SELECTOR = '[' + URL_ATTRS.join('],[') + ']';\nvar URL_TEMPLATE_SEARCH = '{{.*}}';\n\nfunction replaceUrlsInCssText(cssText, baseUrl, regexp) {\n  return cssText.replace(regexp, function(m, pre, url, post) {\n    var urlPath = url.replace(/[\"']/g, '');\n    urlPath = resolveRelativeUrl(baseUrl, urlPath);\n    return pre + '\\'' + urlPath + '\\'' + post;\n  });\n}\n\nfunction resolveRelativeUrl(baseUrl, url) {\n  var u = new URL(url, baseUrl);\n  return makeDocumentRelPath(u.href);\n}\n\nfunction makeDocumentRelPath(url) {\n  var root = document.baseURI;\n  var u = new URL(url, root);\n  if (u.host === root.host && u.port === root.port &&\n      u.protocol === root.protocol) {\n    return makeRelPath(root.pathname, u.pathname);\n  } else {\n    return url;\n  }\n}\n\n// make a relative path from source to target\nfunction makeRelPath(source, target) {\n  var s = source.split('/');\n  var t = target.split('/');\n  while (s.length && s[0] === t[0]){\n    s.shift();\n    t.shift();\n  }\n  for (var i = 0, l = s.length - 1; i < l; i++) {\n    t.unshift('..');\n  }\n  return t.join('/');\n}\n\n// exports\nscope.urlResolver = urlResolver;\n\n})(Platform);\n","/*\n * Copyright 2012 The Polymer Authors. All rights reserved.\n * Use of this source code is goverened by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(global) {\n\n  var registrationsTable = new WeakMap();\n\n  // We use setImmediate or postMessage for our future callback.\n  var setImmediate = window.msSetImmediate;\n\n  // Use post message to emulate setImmediate.\n  if (!setImmediate) {\n    var setImmediateQueue = [];\n    var sentinel = String(Math.random());\n    window.addEventListener('message', function(e) {\n      if (e.data === sentinel) {\n        var queue = setImmediateQueue;\n        setImmediateQueue = [];\n        queue.forEach(function(func) {\n          func();\n        });\n      }\n    });\n    setImmediate = function(func) {\n      setImmediateQueue.push(func);\n      window.postMessage(sentinel, '*');\n    };\n  }\n\n  // This is used to ensure that we never schedule 2 callas to setImmediate\n  var isScheduled = false;\n\n  // Keep track of observers that needs to be notified next time.\n  var scheduledObservers = [];\n\n  /**\n   * Schedules |dispatchCallback| to be called in the future.\n   * @param {MutationObserver} observer\n   */\n  function scheduleCallback(observer) {\n    scheduledObservers.push(observer);\n    if (!isScheduled) {\n      isScheduled = true;\n      setImmediate(dispatchCallbacks);\n    }\n  }\n\n  function wrapIfNeeded(node) {\n    return window.ShadowDOMPolyfill &&\n        window.ShadowDOMPolyfill.wrapIfNeeded(node) ||\n        node;\n  }\n\n  function dispatchCallbacks() {\n    // http://dom.spec.whatwg.org/#mutation-observers\n\n    isScheduled = false; // Used to allow a new setImmediate call above.\n\n    var observers = scheduledObservers;\n    scheduledObservers = [];\n    // Sort observers based on their creation UID (incremental).\n    observers.sort(function(o1, o2) {\n      return o1.uid_ - o2.uid_;\n    });\n\n    var anyNonEmpty = false;\n    observers.forEach(function(observer) {\n\n      // 2.1, 2.2\n      var queue = observer.takeRecords();\n      // 2.3. Remove all transient registered observers whose observer is mo.\n      removeTransientObserversFor(observer);\n\n      // 2.4\n      if (queue.length) {\n        observer.callback_(queue, observer);\n        anyNonEmpty = true;\n      }\n    });\n\n    // 3.\n    if (anyNonEmpty)\n      dispatchCallbacks();\n  }\n\n  function removeTransientObserversFor(observer) {\n    observer.nodes_.forEach(function(node) {\n      var registrations = registrationsTable.get(node);\n      if (!registrations)\n        return;\n      registrations.forEach(function(registration) {\n        if (registration.observer === observer)\n          registration.removeTransientObservers();\n      });\n    });\n  }\n\n  /**\n   * This function is used for the \"For each registered observer observer (with\n   * observer's options as options) in target's list of registered observers,\n   * run these substeps:\" and the \"For each ancestor ancestor of target, and for\n   * each registered observer observer (with options options) in ancestor's list\n   * of registered observers, run these substeps:\" part of the algorithms. The\n   * |options.subtree| is checked to ensure that the callback is called\n   * correctly.\n   *\n   * @param {Node} target\n   * @param {function(MutationObserverInit):MutationRecord} callback\n   */\n  function forEachAncestorAndObserverEnqueueRecord(target, callback) {\n    for (var node = target; node; node = node.parentNode) {\n      var registrations = registrationsTable.get(node);\n\n      if (registrations) {\n        for (var j = 0; j < registrations.length; j++) {\n          var registration = registrations[j];\n          var options = registration.options;\n\n          // Only target ignores subtree.\n          if (node !== target && !options.subtree)\n            continue;\n\n          var record = callback(options);\n          if (record)\n            registration.enqueue(record);\n        }\n      }\n    }\n  }\n\n  var uidCounter = 0;\n\n  /**\n   * The class that maps to the DOM MutationObserver interface.\n   * @param {Function} callback.\n   * @constructor\n   */\n  function JsMutationObserver(callback) {\n    this.callback_ = callback;\n    this.nodes_ = [];\n    this.records_ = [];\n    this.uid_ = ++uidCounter;\n  }\n\n  JsMutationObserver.prototype = {\n    observe: function(target, options) {\n      target = wrapIfNeeded(target);\n\n      // 1.1\n      if (!options.childList && !options.attributes && !options.characterData ||\n\n          // 1.2\n          options.attributeOldValue && !options.attributes ||\n\n          // 1.3\n          options.attributeFilter && options.attributeFilter.length &&\n              !options.attributes ||\n\n          // 1.4\n          options.characterDataOldValue && !options.characterData) {\n\n        throw new SyntaxError();\n      }\n\n      var registrations = registrationsTable.get(target);\n      if (!registrations)\n        registrationsTable.set(target, registrations = []);\n\n      // 2\n      // If target's list of registered observers already includes a registered\n      // observer associated with the context object, replace that registered\n      // observer's options with options.\n      var registration;\n      for (var i = 0; i < registrations.length; i++) {\n        if (registrations[i].observer === this) {\n          registration = registrations[i];\n          registration.removeListeners();\n          registration.options = options;\n          break;\n        }\n      }\n\n      // 3.\n      // Otherwise, add a new registered observer to target's list of registered\n      // observers with the context object as the observer and options as the\n      // options, and add target to context object's list of nodes on which it\n      // is registered.\n      if (!registration) {\n        registration = new Registration(this, target, options);\n        registrations.push(registration);\n        this.nodes_.push(target);\n      }\n\n      registration.addListeners();\n    },\n\n    disconnect: function() {\n      this.nodes_.forEach(function(node) {\n        var registrations = registrationsTable.get(node);\n        for (var i = 0; i < registrations.length; i++) {\n          var registration = registrations[i];\n          if (registration.observer === this) {\n            registration.removeListeners();\n            registrations.splice(i, 1);\n            // Each node can only have one registered observer associated with\n            // this observer.\n            break;\n          }\n        }\n      }, this);\n      this.records_ = [];\n    },\n\n    takeRecords: function() {\n      var copyOfRecords = this.records_;\n      this.records_ = [];\n      return copyOfRecords;\n    }\n  };\n\n  /**\n   * @param {string} type\n   * @param {Node} target\n   * @constructor\n   */\n  function MutationRecord(type, target) {\n    this.type = type;\n    this.target = target;\n    this.addedNodes = [];\n    this.removedNodes = [];\n    this.previousSibling = null;\n    this.nextSibling = null;\n    this.attributeName = null;\n    this.attributeNamespace = null;\n    this.oldValue = null;\n  }\n\n  function copyMutationRecord(original) {\n    var record = new MutationRecord(original.type, original.target);\n    record.addedNodes = original.addedNodes.slice();\n    record.removedNodes = original.removedNodes.slice();\n    record.previousSibling = original.previousSibling;\n    record.nextSibling = original.nextSibling;\n    record.attributeName = original.attributeName;\n    record.attributeNamespace = original.attributeNamespace;\n    record.oldValue = original.oldValue;\n    return record;\n  };\n\n  // We keep track of the two (possibly one) records used in a single mutation.\n  var currentRecord, recordWithOldValue;\n\n  /**\n   * Creates a record without |oldValue| and caches it as |currentRecord| for\n   * later use.\n   * @param {string} oldValue\n   * @return {MutationRecord}\n   */\n  function getRecord(type, target) {\n    return currentRecord = new MutationRecord(type, target);\n  }\n\n  /**\n   * Gets or creates a record with |oldValue| based in the |currentRecord|\n   * @param {string} oldValue\n   * @return {MutationRecord}\n   */\n  function getRecordWithOldValue(oldValue) {\n    if (recordWithOldValue)\n      return recordWithOldValue;\n    recordWithOldValue = copyMutationRecord(currentRecord);\n    recordWithOldValue.oldValue = oldValue;\n    return recordWithOldValue;\n  }\n\n  function clearRecords() {\n    currentRecord = recordWithOldValue = undefined;\n  }\n\n  /**\n   * @param {MutationRecord} record\n   * @return {boolean} Whether the record represents a record from the current\n   * mutation event.\n   */\n  function recordRepresentsCurrentMutation(record) {\n    return record === recordWithOldValue || record === currentRecord;\n  }\n\n  /**\n   * Selects which record, if any, to replace the last record in the queue.\n   * This returns |null| if no record should be replaced.\n   *\n   * @param {MutationRecord} lastRecord\n   * @param {MutationRecord} newRecord\n   * @param {MutationRecord}\n   */\n  function selectRecord(lastRecord, newRecord) {\n    if (lastRecord === newRecord)\n      return lastRecord;\n\n    // Check if the the record we are adding represents the same record. If\n    // so, we keep the one with the oldValue in it.\n    if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord))\n      return recordWithOldValue;\n\n    return null;\n  }\n\n  /**\n   * Class used to represent a registered observer.\n   * @param {MutationObserver} observer\n   * @param {Node} target\n   * @param {MutationObserverInit} options\n   * @constructor\n   */\n  function Registration(observer, target, options) {\n    this.observer = observer;\n    this.target = target;\n    this.options = options;\n    this.transientObservedNodes = [];\n  }\n\n  Registration.prototype = {\n    enqueue: function(record) {\n      var records = this.observer.records_;\n      var length = records.length;\n\n      // There are cases where we replace the last record with the new record.\n      // For example if the record represents the same mutation we need to use\n      // the one with the oldValue. If we get same record (this can happen as we\n      // walk up the tree) we ignore the new record.\n      if (records.length > 0) {\n        var lastRecord = records[length - 1];\n        var recordToReplaceLast = selectRecord(lastRecord, record);\n        if (recordToReplaceLast) {\n          records[length - 1] = recordToReplaceLast;\n          return;\n        }\n      } else {\n        scheduleCallback(this.observer);\n      }\n\n      records[length] = record;\n    },\n\n    addListeners: function() {\n      this.addListeners_(this.target);\n    },\n\n    addListeners_: function(node) {\n      var options = this.options;\n      if (options.attributes)\n        node.addEventListener('DOMAttrModified', this, true);\n\n      if (options.characterData)\n        node.addEventListener('DOMCharacterDataModified', this, true);\n\n      if (options.childList)\n        node.addEventListener('DOMNodeInserted', this, true);\n\n      if (options.childList || options.subtree)\n        node.addEventListener('DOMNodeRemoved', this, true);\n    },\n\n    removeListeners: function() {\n      this.removeListeners_(this.target);\n    },\n\n    removeListeners_: function(node) {\n      var options = this.options;\n      if (options.attributes)\n        node.removeEventListener('DOMAttrModified', this, true);\n\n      if (options.characterData)\n        node.removeEventListener('DOMCharacterDataModified', this, true);\n\n      if (options.childList)\n        node.removeEventListener('DOMNodeInserted', this, true);\n\n      if (options.childList || options.subtree)\n        node.removeEventListener('DOMNodeRemoved', this, true);\n    },\n\n    /**\n     * Adds a transient observer on node. The transient observer gets removed\n     * next time we deliver the change records.\n     * @param {Node} node\n     */\n    addTransientObserver: function(node) {\n      // Don't add transient observers on the target itself. We already have all\n      // the required listeners set up on the target.\n      if (node === this.target)\n        return;\n\n      this.addListeners_(node);\n      this.transientObservedNodes.push(node);\n      var registrations = registrationsTable.get(node);\n      if (!registrations)\n        registrationsTable.set(node, registrations = []);\n\n      // We know that registrations does not contain this because we already\n      // checked if node === this.target.\n      registrations.push(this);\n    },\n\n    removeTransientObservers: function() {\n      var transientObservedNodes = this.transientObservedNodes;\n      this.transientObservedNodes = [];\n\n      transientObservedNodes.forEach(function(node) {\n        // Transient observers are never added to the target.\n        this.removeListeners_(node);\n\n        var registrations = registrationsTable.get(node);\n        for (var i = 0; i < registrations.length; i++) {\n          if (registrations[i] === this) {\n            registrations.splice(i, 1);\n            // Each node can only have one registered observer associated with\n            // this observer.\n            break;\n          }\n        }\n      }, this);\n    },\n\n    handleEvent: function(e) {\n      // Stop propagation since we are managing the propagation manually.\n      // This means that other mutation events on the page will not work\n      // correctly but that is by design.\n      e.stopImmediatePropagation();\n\n      switch (e.type) {\n        case 'DOMAttrModified':\n          // http://dom.spec.whatwg.org/#concept-mo-queue-attributes\n\n          var name = e.attrName;\n          var namespace = e.relatedNode.namespaceURI;\n          var target = e.target;\n\n          // 1.\n          var record = new getRecord('attributes', target);\n          record.attributeName = name;\n          record.attributeNamespace = namespace;\n\n          // 2.\n          var oldValue =\n              e.attrChange === MutationEvent.ADDITION ? null : e.prevValue;\n\n          forEachAncestorAndObserverEnqueueRecord(target, function(options) {\n            // 3.1, 4.2\n            if (!options.attributes)\n              return;\n\n            // 3.2, 4.3\n            if (options.attributeFilter && options.attributeFilter.length &&\n                options.attributeFilter.indexOf(name) === -1 &&\n                options.attributeFilter.indexOf(namespace) === -1) {\n              return;\n            }\n            // 3.3, 4.4\n            if (options.attributeOldValue)\n              return getRecordWithOldValue(oldValue);\n\n            // 3.4, 4.5\n            return record;\n          });\n\n          break;\n\n        case 'DOMCharacterDataModified':\n          // http://dom.spec.whatwg.org/#concept-mo-queue-characterdata\n          var target = e.target;\n\n          // 1.\n          var record = getRecord('characterData', target);\n\n          // 2.\n          var oldValue = e.prevValue;\n\n\n          forEachAncestorAndObserverEnqueueRecord(target, function(options) {\n            // 3.1, 4.2\n            if (!options.characterData)\n              return;\n\n            // 3.2, 4.3\n            if (options.characterDataOldValue)\n              return getRecordWithOldValue(oldValue);\n\n            // 3.3, 4.4\n            return record;\n          });\n\n          break;\n\n        case 'DOMNodeRemoved':\n          this.addTransientObserver(e.target);\n          // Fall through.\n        case 'DOMNodeInserted':\n          // http://dom.spec.whatwg.org/#concept-mo-queue-childlist\n          var target = e.relatedNode;\n          var changedNode = e.target;\n          var addedNodes, removedNodes;\n          if (e.type === 'DOMNodeInserted') {\n            addedNodes = [changedNode];\n            removedNodes = [];\n          } else {\n\n            addedNodes = [];\n            removedNodes = [changedNode];\n          }\n          var previousSibling = changedNode.previousSibling;\n          var nextSibling = changedNode.nextSibling;\n\n          // 1.\n          var record = getRecord('childList', target);\n          record.addedNodes = addedNodes;\n          record.removedNodes = removedNodes;\n          record.previousSibling = previousSibling;\n          record.nextSibling = nextSibling;\n\n          forEachAncestorAndObserverEnqueueRecord(target, function(options) {\n            // 2.1, 3.2\n            if (!options.childList)\n              return;\n\n            // 2.2, 3.3\n            return record;\n          });\n\n      }\n\n      clearRecords();\n    }\n  };\n\n  global.JsMutationObserver = JsMutationObserver;\n\n  if (!global.MutationObserver)\n    global.MutationObserver = JsMutationObserver;\n\n\n})(this);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\nwindow.HTMLImports = window.HTMLImports || {flags:{}};","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n\n  // imports\n  var path = scope.path;\n  var xhr = scope.xhr;\n  var flags = scope.flags;\n\n  // TODO(sorvell): this loader supports a dynamic list of urls\n  // and an oncomplete callback that is called when the loader is done.\n  // The polyfill currently does *not* need this dynamism or the onComplete\n  // concept. Because of this, the loader could be simplified quite a bit.\n  var Loader = function(onLoad, onComplete) {\n    this.cache = {};\n    this.onload = onLoad;\n    this.oncomplete = onComplete;\n    this.inflight = 0;\n    this.pending = {};\n  };\n\n  Loader.prototype = {\n    addNodes: function(nodes) {\n      // number of transactions to complete\n      this.inflight += nodes.length;\n      // commence transactions\n      for (var i=0, l=nodes.length, n; (i<l) && (n=nodes[i]); i++) {\n        this.require(n);\n      }\n      // anything to do?\n      this.checkDone();\n    },\n    addNode: function(node) {\n      // number of transactions to complete\n      this.inflight++;\n      // commence transactions\n      this.require(node);\n      // anything to do?\n      this.checkDone();\n    },\n    require: function(elt) {\n      var url = elt.src || elt.href;\n      // ensure we have a standard url that can be used\n      // reliably for deduping.\n      // TODO(sjmiles): ad-hoc\n      elt.__nodeUrl = url;\n      // deduplication\n      if (!this.dedupe(url, elt)) {\n        // fetch this resource\n        this.fetch(url, elt);\n      }\n    },\n    dedupe: function(url, elt) {\n      if (this.pending[url]) {\n        // add to list of nodes waiting for inUrl\n        this.pending[url].push(elt);\n        // don't need fetch\n        return true;\n      }\n      var resource;\n      if (this.cache[url]) {\n        this.onload(url, elt, this.cache[url]);\n        // finished this transaction\n        this.tail();\n        // don't need fetch\n        return true;\n      }\n      // first node waiting for inUrl\n      this.pending[url] = [elt];\n      // need fetch (not a dupe)\n      return false;\n    },\n    fetch: function(url, elt) {\n      flags.load && console.log('fetch', url, elt);\n      var receiveXhr = function(err, resource) {\n        this.receive(url, elt, err, resource);\n      }.bind(this);\n      xhr.load(url, receiveXhr);\n      // TODO(sorvell): blocked on\n      // https://code.google.com/p/chromium/issues/detail?id=257221\n      // xhr'ing for a document makes scripts in imports runnable; otherwise\n      // they are not; however, it requires that we have doctype=html in\n      // the import which is unacceptable. This is only needed on Chrome\n      // to avoid the bug above.\n      /*\n      if (isDocumentLink(elt)) {\n        xhr.loadDocument(url, receiveXhr);\n      } else {\n        xhr.load(url, receiveXhr);\n      }\n      */\n    },\n    receive: function(url, elt, err, resource) {\n      this.cache[url] = resource;\n      var $p = this.pending[url];\n      for (var i=0, l=$p.length, p; (i<l) && (p=$p[i]); i++) {\n        //if (!err) {\n          this.onload(url, p, resource);\n        //}\n        this.tail();\n      }\n      this.pending[url] = null;\n    },\n    tail: function() {\n      --this.inflight;\n      this.checkDone();\n    },\n    checkDone: function() {\n      if (!this.inflight) {\n        this.oncomplete();\n      }\n    }\n  };\n\n  xhr = xhr || {\n    async: true,\n    ok: function(request) {\n      return (request.status >= 200 && request.status < 300)\n          || (request.status === 304)\n          || (request.status === 0);\n    },\n    load: function(url, next, nextContext) {\n      var request = new XMLHttpRequest();\n      if (scope.flags.debug || scope.flags.bust) {\n        url += '?' + Math.random();\n      }\n      request.open('GET', url, xhr.async);\n      request.addEventListener('readystatechange', function(e) {\n        if (request.readyState === 4) {\n          next.call(nextContext, !xhr.ok(request) && request,\n              request.response || request.responseText, url);\n        }\n      });\n      request.send();\n      return request;\n    },\n    loadDocument: function(url, next, nextContext) {\n      this.load(url, next, nextContext).responseType = 'document';\n    }\n  };\n\n  // exports\n  scope.xhr = xhr;\n  scope.Loader = Loader;\n\n})(window.HTMLImports);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n\nvar IMPORT_LINK_TYPE = 'import';\nvar flags = scope.flags;\nvar isIe = /Trident/.test(navigator.userAgent);\n// TODO(sorvell): SD polyfill intrusion\nvar mainDoc = window.ShadowDOMPolyfill ? \n    window.ShadowDOMPolyfill.wrapIfNeeded(document) : document;\n\n// importParser\n// highlander object to manage parsing of imports\n// parses import related elements\n// and ensures proper parse order\n// parse order is enforced by crawling the tree and monitoring which elements\n// have been parsed; async parsing is also supported.\n\n// highlander object for parsing a document tree\nvar importParser = {\n  // parse selectors for main document elements\n  documentSelectors: 'link[rel=' + IMPORT_LINK_TYPE + ']',\n  // parse selectors for import document elements\n  importsSelectors: [\n    'link[rel=' + IMPORT_LINK_TYPE + ']',\n    'link[rel=stylesheet]',\n    'style',\n    'script:not([type])',\n    'script[type=\"text/javascript\"]'\n  ].join(','),\n  map: {\n    link: 'parseLink',\n    script: 'parseScript',\n    style: 'parseStyle'\n  },\n  // try to parse the next import in the tree\n  parseNext: function() {\n    var next = this.nextToParse();\n    if (next) {\n      this.parse(next);\n    }\n  },\n  parse: function(elt) {\n    if (this.isParsed(elt)) {\n      flags.parse && console.log('[%s] is already parsed', elt.localName);\n      return;\n    }\n    var fn = this[this.map[elt.localName]];\n    if (fn) {\n      this.markParsing(elt);\n      fn.call(this, elt);\n    }\n  },\n  // only 1 element may be parsed at a time; parsing is async so, each\n  // parsing implementation must inform the system that parsing is complete\n  // via markParsingComplete.\n  markParsing: function(elt) {\n    flags.parse && console.log('parsing', elt);\n    this.parsingElement = elt;\n  },\n  markParsingComplete: function(elt) {\n    elt.__importParsed = true;\n    if (elt.__importElement) {\n      elt.__importElement.__importParsed = true;\n    }\n    this.parsingElement = null;\n    flags.parse && console.log('completed', elt);\n    this.parseNext();\n  },\n  parseImport: function(elt) {\n    elt.import.__importParsed = true;\n    // TODO(sorvell): consider if there's a better way to do this;\n    // expose an imports parsing hook; this is needed, for example, by the\n    // CustomElements polyfill.\n    if (HTMLImports.__importsParsingHook) {\n      HTMLImports.__importsParsingHook(elt);\n    }\n    // fire load event\n    if (elt.__resource) {\n      elt.dispatchEvent(new CustomEvent('load', {bubbles: false}));    \n    } else {\n      elt.dispatchEvent(new CustomEvent('error', {bubbles: false}));\n    }\n    // TODO(sorvell): workaround for Safari addEventListener not working\n    // for elements not in the main document.\n    if (elt.__pending) {\n      var fn;\n      while (elt.__pending.length) {\n        fn = elt.__pending.shift();\n        if (fn) {\n          fn({target: elt});\n        }\n      }\n    }\n    this.markParsingComplete(elt);\n  },\n  parseLink: function(linkElt) {\n    if (nodeIsImport(linkElt)) {\n      this.parseImport(linkElt);\n    } else {\n      // make href absolute\n      linkElt.href = linkElt.href;\n      this.parseGeneric(linkElt);\n    }\n  },\n  parseStyle: function(elt) {\n    // TODO(sorvell): style element load event can just not fire so clone styles\n    var src = elt;\n    elt = cloneStyle(elt);\n    elt.__importElement = src;\n    this.parseGeneric(elt);\n  },\n  parseGeneric: function(elt) {\n    this.trackElement(elt);\n    document.head.appendChild(elt);\n  },\n  // tracks when a loadable element has loaded\n  trackElement: function(elt) {\n    var self = this;\n    var done = function() {\n      self.markParsingComplete(elt);\n    };\n    elt.addEventListener('load', done);\n    elt.addEventListener('error', done);\n\n    // NOTE: IE does not fire \"load\" event for styles that have already loaded\n    // This is in violation of the spec, so we try our hardest to work around it\n    if (isIe && elt.localName === 'style') {\n      var fakeLoad = false;\n      // If there's not @import in the textContent, assume it has loaded\n      if (elt.textContent.indexOf('@import') == -1) {\n        fakeLoad = true;\n      // if we have a sheet, we have been parsed\n      } else if (elt.sheet) {\n        fakeLoad = true;\n        var csr = elt.sheet.cssRules;\n        var len = csr ? csr.length : 0;\n        // search the rules for @import's\n        for (var i = 0, r; (i < len) && (r = csr[i]); i++) {\n          if (r.type === CSSRule.IMPORT_RULE) {\n            // if every @import has resolved, fake the load\n            fakeLoad = fakeLoad && Boolean(r.styleSheet);\n          }\n        }\n      }\n      // dispatch a fake load event and continue parsing\n      if (fakeLoad) {\n        elt.dispatchEvent(new CustomEvent('load', {bubbles: false}));\n      }\n    }\n  },\n  parseScript: function(scriptElt) {\n    // acquire code to execute\n    var code = (scriptElt.__resource || scriptElt.textContent).trim();\n    if (code) {\n      // calculate source map hint\n      var moniker = scriptElt.__nodeUrl;\n      if (!moniker) {\n        moniker = scriptElt.ownerDocument.baseURI;\n        // there could be more than one script this url\n        var tag = '[' + Math.floor((Math.random()+1)*1000) + ']';\n        // TODO(sjmiles): Polymer hack, should be pluggable if we need to allow \n        // this sort of thing\n        var matches = code.match(/Polymer\\(['\"]([^'\"]*)/);\n        tag = matches && matches[1] || tag;\n        // tag the moniker\n        moniker += '/' + tag + '.js';\n      }\n      // source map hint\n      code += \"\\n//# sourceURL=\" + moniker + \"\\n\";\n      // evaluate the code\n      scope.currentScript = scriptElt;\n      eval.call(window, code);\n      scope.currentScript = null;\n    }\n    this.markParsingComplete(scriptElt);\n  },\n  // determine the next element in the tree which should be parsed\n  nextToParse: function() {\n    return !this.parsingElement && this.nextToParseInDoc(mainDoc);\n  },\n  nextToParseInDoc: function(doc, link) {\n    var nodes = doc.querySelectorAll(this.parseSelectorsForNode(doc));\n    for (var i=0, l=nodes.length, p=0, n; (i<l) && (n=nodes[i]); i++) {\n      if (!this.isParsed(n)) {\n        if (this.hasResource(n)) {\n          return nodeIsImport(n) ? this.nextToParseInDoc(n.import, n) : n;\n        } else {\n          return;\n        }\n      }\n    }\n    // all nodes have been parsed, ready to parse import, if any\n    return link;\n  },\n  // return the set of parse selectors relevant for this node.\n  parseSelectorsForNode: function(node) {\n    var doc = node.ownerDocument || node;\n    return doc === mainDoc ? this.documentSelectors : this.importsSelectors;\n  },\n  isParsed: function(node) {\n    return node.__importParsed;\n  },\n  hasResource: function(node) {\n    if (nodeIsImport(node) && !node.import) {\n      return false;\n    }\n    if (node.localName === 'script' && node.src && !node.__resource) {\n      return false;\n    }\n    return true;\n  }\n};\n\nfunction nodeIsImport(elt) {\n  return (elt.localName === 'link') && (elt.rel === IMPORT_LINK_TYPE);\n}\n\n// style/stylesheet handling\n\n// clone style with proper path resolution for main document\n// NOTE: styles are the only elements that require direct path fixup.\nfunction cloneStyle(style) {\n  var clone = style.ownerDocument.createElement('style');\n  clone.textContent = style.textContent;\n  path.resolveUrlsInStyle(clone);\n  return clone;\n}\n\n// path fixup: style elements in imports must be made relative to the main \n// document. We fixup url's in url() and @import.\nvar CSS_URL_REGEXP = /(url\\()([^)]*)(\\))/g;\nvar CSS_IMPORT_REGEXP = /(@import[\\s]+(?!url\\())([^;]*)(;)/g;\n\nvar path = {\n  resolveUrlsInStyle: function(style) {\n    var doc = style.ownerDocument;\n    var resolver = doc.createElement('a');\n    style.textContent = this.resolveUrlsInCssText(style.textContent, resolver);\n    return style;  \n  },\n  resolveUrlsInCssText: function(cssText, urlObj) {\n    var r = this.replaceUrls(cssText, urlObj, CSS_URL_REGEXP);\n    r = this.replaceUrls(r, urlObj, CSS_IMPORT_REGEXP);\n    return r;\n  },\n  replaceUrls: function(text, urlObj, regexp) {\n    return text.replace(regexp, function(m, pre, url, post) {\n      var urlPath = url.replace(/[\"']/g, '');\n      urlObj.href = urlPath;\n      urlPath = urlObj.href;\n      return pre + '\\'' + urlPath + '\\'' + post;\n    });    \n  }\n}\n\n// exports\nscope.parser = importParser;\nscope.path = path;\nscope.isIE = isIe;\n\n})(HTMLImports);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n\nvar hasNative = ('import' in document.createElement('link'));\nvar useNative = hasNative;\nvar flags = scope.flags;\nvar IMPORT_LINK_TYPE = 'import';\n\n// TODO(sorvell): SD polyfill intrusion\nvar mainDoc = window.ShadowDOMPolyfill ? \n    ShadowDOMPolyfill.wrapIfNeeded(document) : document;\n\nif (!useNative) {\n\n  // imports\n  var xhr = scope.xhr;\n  var Loader = scope.Loader;\n  var parser = scope.parser;\n\n  // importer\n  // highlander object to manage loading of imports\n\n  // for any document, importer:\n  // - loads any linked import documents (with deduping)\n  // for any import document, importer also:\n  // - loads text of external script tags\n\n  var importer = {\n    documents: {},\n    // nodes to load in the mian document\n    documentPreloadSelectors: 'link[rel=' + IMPORT_LINK_TYPE + ']',\n    // nodes to load in imports\n    importsPreloadSelectors: [\n        'link[rel=' + IMPORT_LINK_TYPE + ']',\n        'script[src]:not([type])',\n        'script[src][type=\"text/javascript\"]'\n    ].join(','),\n    loadNode: function(node) {\n      importLoader.addNode(node);\n    },\n    // load all loadable elements within the parent element\n    loadSubtree: function(parent) {\n      var nodes = this.marshalNodes(parent);\n      // add these nodes to loader's queue\n      importLoader.addNodes(nodes);\n    },\n    marshalNodes: function(parent) {\n      // all preloadable nodes in inDocument\n      return parent.querySelectorAll(this.loadSelectorsForNode(parent));\n    },\n    // find the proper set of load selectors for a given node\n    loadSelectorsForNode: function(node) {\n      var doc = node.ownerDocument || node;\n      return doc === mainDoc ? this.documentPreloadSelectors :\n          this.importsPreloadSelectors;\n    },\n    loaded: function(url, elt, resource) {\n      flags.load && console.log('loaded', url, elt);\n      // store generic resource\n      // TODO(sorvell): fails for nodes inside <template>.content\n      // see https://code.google.com/p/chromium/issues/detail?id=249381.\n      elt.__resource = resource;\n      if (isDocumentLink(elt)) {\n        var doc = this.documents[url];\n        // if we've never seen a document at this url\n        if (!doc) {\n          // generate an HTMLDocument from data\n          doc = makeDocument(resource, url);\n          doc.__importLink = elt;\n          // TODO(sorvell): we cannot use MO to detect parsed nodes because\n          // SD polyfill does not report these as mutations.\n          this.bootDocument(doc);\n          // cache document\n          this.documents[url] = doc;\n        }\n        // don't store import record until we're actually loaded\n        // store document resource\n        elt.import = doc;\n      }\n      parser.parseNext();\n    },\n    bootDocument: function(doc) {\n      this.loadSubtree(doc);\n      this.observe(doc);\n      parser.parseNext();\n    },\n    loadedAll: function() {\n      parser.parseNext();\n    }\n  };\n\n  // loader singleton\n  var importLoader = new Loader(importer.loaded.bind(importer), \n      importer.loadedAll.bind(importer));\n\n  function isDocumentLink(elt) {\n    return isLinkRel(elt, IMPORT_LINK_TYPE);\n  }\n\n  function isLinkRel(elt, rel) {\n    return elt.localName === 'link' && elt.getAttribute('rel') === rel;\n  }\n\n  function isScript(elt) {\n    return elt.localName === 'script';\n  }\n\n  function makeDocument(resource, url) {\n    // create a new HTML document\n    var doc = resource;\n    if (!(doc instanceof Document)) {\n      doc = document.implementation.createHTMLDocument(IMPORT_LINK_TYPE);\n    }\n    // cache the new document's source url\n    doc._URL = url;\n    // establish a relative path via <base>\n    var base = doc.createElement('base');\n    base.setAttribute('href', url);\n    // add baseURI support to browsers (IE) that lack it.\n    if (!doc.baseURI) {\n      doc.baseURI = url;\n    }\n    doc.head.appendChild(base);\n    // install HTML last as it may trigger CustomElement upgrades\n    // TODO(sjmiles): problem wrt to template boostrapping below,\n    // template bootstrapping must (?) come before element upgrade\n    // but we cannot bootstrap templates until they are in a document\n    // which is too late\n    if (!(resource instanceof Document)) {\n      // install html\n      doc.body.innerHTML = resource;\n    }\n    // TODO(sorvell): ideally this code is not aware of Template polyfill,\n    // but for now the polyfill needs help to bootstrap these templates\n    if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) {\n      HTMLTemplateElement.bootstrap(doc);\n    }\n    return doc;\n  }\n} else {\n  // do nothing if using native imports\n  var importer = {};\n}\n\n// NOTE: We cannot polyfill document.currentScript because it's not possible\n// both to override and maintain the ability to capture the native value;\n// therefore we choose to expose _currentScript both when native imports\n// and the polyfill are in use.\nvar currentScriptDescriptor = {\n  get: function() {\n    return HTMLImports.currentScript || document.currentScript;\n  },\n  configurable: true\n};\n\nObject.defineProperty(document, '_currentScript', currentScriptDescriptor);\nObject.defineProperty(mainDoc, '_currentScript', currentScriptDescriptor);\n\n// Polyfill document.baseURI for browsers without it.\nif (!document.baseURI) {\n  var baseURIDescriptor = {\n    get: function() {\n      return window.location.href;\n    },\n    configurable: true\n  };\n\n  Object.defineProperty(document, 'baseURI', baseURIDescriptor);\n  Object.defineProperty(mainDoc, 'baseURI', baseURIDescriptor);\n}\n\n// call a callback when all HTMLImports in the document at call (or at least\n//  document ready) time have loaded.\n// 1. ensure the document is in a ready state (has dom), then \n// 2. watch for loading of imports and call callback when done\nfunction whenImportsReady(callback, doc) {\n  doc = doc || mainDoc;\n  // if document is loading, wait and try again\n  whenDocumentReady(function() {\n    watchImportsLoad(callback, doc);\n  }, doc);\n}\n\n// call the callback when the document is in a ready state (has dom)\nvar requiredReadyState = HTMLImports.isIE ? 'complete' : 'interactive';\nvar READY_EVENT = 'readystatechange';\nfunction isDocumentReady(doc) {\n  return (doc.readyState === 'complete' ||\n      doc.readyState === requiredReadyState);\n}\n\n// call <callback> when we ensure the document is in a ready state\nfunction whenDocumentReady(callback, doc) {\n  if (!isDocumentReady(doc)) {\n    var checkReady = function() {\n      if (doc.readyState === 'complete' || \n          doc.readyState === requiredReadyState) {\n        doc.removeEventListener(READY_EVENT, checkReady);\n        whenDocumentReady(callback, doc);\n      }\n    }\n    doc.addEventListener(READY_EVENT, checkReady);\n  } else if (callback) {\n    callback();\n  }\n}\n\n// call <callback> when we ensure all imports have loaded\nfunction watchImportsLoad(callback, doc) {\n  var imports = doc.querySelectorAll('link[rel=import]');\n  var loaded = 0, l = imports.length;\n  function checkDone(d) { \n    if (loaded == l) {\n      // go async to ensure parser isn't stuck on a script tag\n      requestAnimationFrame(callback);\n    }\n  }\n  function loadedImport(e) {\n    loaded++;\n    checkDone();\n  }\n  if (l) {\n    for (var i=0, imp; (i<l) && (imp=imports[i]); i++) {\n      if (isImportLoaded(imp)) {\n        loadedImport.call(imp);\n      } else {\n        imp.addEventListener('load', loadedImport);\n        imp.addEventListener('error', loadedImport);\n      }\n    }\n  } else {\n    checkDone();\n  }\n}\n\nfunction isImportLoaded(link) {\n  return useNative ? (link.import && (link.import.readyState !== 'loading')) :\n      link.__importParsed;\n}\n\n// exports\nscope.hasNative = hasNative;\nscope.useNative = useNative;\nscope.importer = importer;\nscope.whenImportsReady = whenImportsReady;\nscope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;\nscope.isImportLoaded = isImportLoaded;\nscope.importLoader = importLoader;\n\n})(window.HTMLImports);\n"," /*\nCopyright 2013 The Polymer Authors. All rights reserved.\nUse of this source code is governed by a BSD-style\nlicense that can be found in the LICENSE file.\n*/\n\n(function(scope){\n\nvar IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;\nvar importSelector = 'link[rel=' + IMPORT_LINK_TYPE + ']';\nvar importer = scope.importer;\n\n// we track mutations for addedNodes, looking for imports\nfunction handler(mutations) {\n  for (var i=0, l=mutations.length, m; (i<l) && (m=mutations[i]); i++) {\n    if (m.type === 'childList' && m.addedNodes.length) {\n      addedNodes(m.addedNodes);\n    }\n  }\n}\n\n// find loadable elements and add them to the importer\nfunction addedNodes(nodes) {\n  for (var i=0, l=nodes.length, n; (i<l) && (n=nodes[i]); i++) {\n    if (shouldLoadNode(n)) {\n      importer.loadNode(n);\n    }\n    if (n.children && n.children.length) {\n      addedNodes(n.children);\n    }\n  }\n}\n\nfunction shouldLoadNode(node) {\n  return (node.nodeType === 1) && matches.call(node,\n      importer.loadSelectorsForNode(node));\n}\n\n// x-plat matches\nvar matches = HTMLElement.prototype.matches || \n    HTMLElement.prototype.matchesSelector || \n    HTMLElement.prototype.webkitMatchesSelector ||\n    HTMLElement.prototype.mozMatchesSelector ||\n    HTMLElement.prototype.msMatchesSelector;\n\nvar observer = new MutationObserver(handler);\n\n// observe the given root for loadable elements\nfunction observe(root) {\n  observer.observe(root, {childList: true, subtree: true});\n}\n\n// exports\n// TODO(sorvell): factor so can put on scope\nscope.observe = observe;\nimporter.observe = observe;\n\n})(HTMLImports);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function(){\n\n// bootstrap\n\n// IE shim for CustomEvent\nif (typeof window.CustomEvent !== 'function') {\n  window.CustomEvent = function(inType, dictionary) {\n     var e = document.createEvent('HTMLEvents');\n     e.initEvent(inType,\n        dictionary.bubbles === false ? false : true,\n        dictionary.cancelable === false ? false : true,\n        dictionary.detail);\n     return e;\n  };\n}\n\n// TODO(sorvell): SD polyfill intrusion\nvar doc = window.ShadowDOMPolyfill ? \n    window.ShadowDOMPolyfill.wrapIfNeeded(document) : document;\n\n// Fire the 'HTMLImportsLoaded' event when imports in document at load time \n// have loaded. This event is required to simulate the script blocking \n// behavior of native imports. A main document script that needs to be sure\n// imports have loaded should wait for this event.\nHTMLImports.whenImportsReady(function() {\n  HTMLImports.ready = true;\n  HTMLImports.readyTime = new Date().getTime();\n  doc.dispatchEvent(\n    new CustomEvent('HTMLImportsLoaded', {bubbles: true})\n  );\n});\n\n\n// no need to bootstrap the polyfill when native imports is available.\nif (!HTMLImports.useNative) {\n  function bootstrap() {\n    HTMLImports.importer.bootDocument(doc);\n  }\n    \n  // TODO(sorvell): SD polyfill does *not* generate mutations for nodes added\n  // by the parser. For this reason, we must wait until the dom exists to \n  // bootstrap.\n  if (document.readyState === 'complete' ||\n      (document.readyState === 'interactive' && !window.attachEvent)) {\n    bootstrap();\n  } else {\n    document.addEventListener('DOMContentLoaded', bootstrap);\n  }\n}\n\n})();\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\nwindow.CustomElements = window.CustomElements || {flags:{}};"," /*\r\nCopyright 2013 The Polymer Authors. All rights reserved.\r\nUse of this source code is governed by a BSD-style\r\nlicense that can be found in the LICENSE file.\r\n*/\r\n\r\n(function(scope){\r\n\r\nvar logFlags = window.logFlags || {};\r\nvar IMPORT_LINK_TYPE = window.HTMLImports ? HTMLImports.IMPORT_LINK_TYPE : 'none';\r\n\r\n// walk the subtree rooted at node, applying 'find(element, data)' function\r\n// to each element\r\n// if 'find' returns true for 'element', do not search element's subtree\r\nfunction findAll(node, find, data) {\r\n  var e = node.firstElementChild;\r\n  if (!e) {\r\n    e = node.firstChild;\r\n    while (e && e.nodeType !== Node.ELEMENT_NODE) {\r\n      e = e.nextSibling;\r\n    }\r\n  }\r\n  while (e) {\r\n    if (find(e, data) !== true) {\r\n      findAll(e, find, data);\r\n    }\r\n    e = e.nextElementSibling;\r\n  }\r\n  return null;\r\n}\r\n\r\n// walk all shadowRoots on a given node.\r\nfunction forRoots(node, cb) {\r\n  var root = node.shadowRoot;\r\n  while(root) {\r\n    forSubtree(root, cb);\r\n    root = root.olderShadowRoot;\r\n  }\r\n}\r\n\r\n// walk the subtree rooted at node, including descent into shadow-roots,\r\n// applying 'cb' to each element\r\nfunction forSubtree(node, cb) {\r\n  //logFlags.dom && node.childNodes && node.childNodes.length && console.group('subTree: ', node);\r\n  findAll(node, function(e) {\r\n    if (cb(e)) {\r\n      return true;\r\n    }\r\n    forRoots(e, cb);\r\n  });\r\n  forRoots(node, cb);\r\n  //logFlags.dom && node.childNodes && node.childNodes.length && console.groupEnd();\r\n}\r\n\r\n// manage lifecycle on added node\r\nfunction added(node) {\r\n  if (upgrade(node)) {\r\n    insertedNode(node);\r\n    return true;\r\n  }\r\n  inserted(node);\r\n}\r\n\r\n// manage lifecycle on added node's subtree only\r\nfunction addedSubtree(node) {\r\n  forSubtree(node, function(e) {\r\n    if (added(e)) {\r\n      return true;\r\n    }\r\n  });\r\n}\r\n\r\n// manage lifecycle on added node and it's subtree\r\nfunction addedNode(node) {\r\n  return added(node) || addedSubtree(node);\r\n}\r\n\r\n// upgrade custom elements at node, if applicable\r\nfunction upgrade(node) {\r\n  if (!node.__upgraded__ && node.nodeType === Node.ELEMENT_NODE) {\r\n    var type = node.getAttribute('is') || node.localName;\r\n    var definition = scope.registry[type];\r\n    if (definition) {\r\n      logFlags.dom && console.group('upgrade:', node.localName);\r\n      scope.upgrade(node);\r\n      logFlags.dom && console.groupEnd();\r\n      return true;\r\n    }\r\n  }\r\n}\r\n\r\nfunction insertedNode(node) {\r\n  inserted(node);\r\n  if (inDocument(node)) {\r\n    forSubtree(node, function(e) {\r\n      inserted(e);\r\n    });\r\n  }\r\n}\r\n\r\n// TODO(sorvell): on platforms without MutationObserver, mutations may not be\r\n// reliable and therefore attached/detached are not reliable.\r\n// To make these callbacks less likely to fail, we defer all inserts and removes\r\n// to give a chance for elements to be inserted into dom.\r\n// This ensures attachedCallback fires for elements that are created and\r\n// immediately added to dom.\r\nvar hasPolyfillMutations = (!window.MutationObserver ||\r\n    (window.MutationObserver === window.JsMutationObserver));\r\nscope.hasPolyfillMutations = hasPolyfillMutations;\r\n\r\nvar isPendingMutations = false;\r\nvar pendingMutations = [];\r\nfunction deferMutation(fn) {\r\n  pendingMutations.push(fn);\r\n  if (!isPendingMutations) {\r\n    isPendingMutations = true;\r\n    var async = (window.Platform && window.Platform.endOfMicrotask) ||\r\n        setTimeout;\r\n    async(takeMutations);\r\n  }\r\n}\r\n\r\nfunction takeMutations() {\r\n  isPendingMutations = false;\r\n  var $p = pendingMutations;\r\n  for (var i=0, l=$p.length, p; (i<l) && (p=$p[i]); i++) {\r\n    p();\r\n  }\r\n  pendingMutations = [];\r\n}\r\n\r\nfunction inserted(element) {\r\n  if (hasPolyfillMutations) {\r\n    deferMutation(function() {\r\n      _inserted(element);\r\n    });\r\n  } else {\r\n    _inserted(element);\r\n  }\r\n}\r\n\r\n// TODO(sjmiles): if there are descents into trees that can never have inDocument(*) true, fix this\r\nfunction _inserted(element) {\r\n  // TODO(sjmiles): it's possible we were inserted and removed in the space\r\n  // of one microtask, in which case we won't be 'inDocument' here\r\n  // But there are other cases where we are testing for inserted without\r\n  // specific knowledge of mutations, and must test 'inDocument' to determine\r\n  // whether to call inserted\r\n  // If we can factor these cases into separate code paths we can have\r\n  // better diagnostics.\r\n  // TODO(sjmiles): when logging, do work on all custom elements so we can\r\n  // track behavior even when callbacks not defined\r\n  //console.log('inserted: ', element.localName);\r\n  if (element.attachedCallback || element.detachedCallback || (element.__upgraded__ && logFlags.dom)) {\r\n    logFlags.dom && console.group('inserted:', element.localName);\r\n    if (inDocument(element)) {\r\n      element.__inserted = (element.__inserted || 0) + 1;\r\n      // if we are in a 'removed' state, bluntly adjust to an 'inserted' state\r\n      if (element.__inserted < 1) {\r\n        element.__inserted = 1;\r\n      }\r\n      // if we are 'over inserted', squelch the callback\r\n      if (element.__inserted > 1) {\r\n        logFlags.dom && console.warn('inserted:', element.localName,\r\n          'insert/remove count:', element.__inserted)\r\n      } else if (element.attachedCallback) {\r\n        logFlags.dom && console.log('inserted:', element.localName);\r\n        element.attachedCallback();\r\n      }\r\n    }\r\n    logFlags.dom && console.groupEnd();\r\n  }\r\n}\r\n\r\nfunction removedNode(node) {\r\n  removed(node);\r\n  forSubtree(node, function(e) {\r\n    removed(e);\r\n  });\r\n}\r\n\r\nfunction removed(element) {\r\n  if (hasPolyfillMutations) {\r\n    deferMutation(function() {\r\n      _removed(element);\r\n    });\r\n  } else {\r\n    _removed(element);\r\n  }\r\n}\r\n\r\nfunction _removed(element) {\r\n  // TODO(sjmiles): temporary: do work on all custom elements so we can track\r\n  // behavior even when callbacks not defined\r\n  if (element.attachedCallback || element.detachedCallback || (element.__upgraded__ && logFlags.dom)) {\r\n    logFlags.dom && console.group('removed:', element.localName);\r\n    if (!inDocument(element)) {\r\n      element.__inserted = (element.__inserted || 0) - 1;\r\n      // if we are in a 'inserted' state, bluntly adjust to an 'removed' state\r\n      if (element.__inserted > 0) {\r\n        element.__inserted = 0;\r\n      }\r\n      // if we are 'over removed', squelch the callback\r\n      if (element.__inserted < 0) {\r\n        logFlags.dom && console.warn('removed:', element.localName,\r\n            'insert/remove count:', element.__inserted)\r\n      } else if (element.detachedCallback) {\r\n        element.detachedCallback();\r\n      }\r\n    }\r\n    logFlags.dom && console.groupEnd();\r\n  }\r\n}\r\n\r\n// SD polyfill intrustion due mainly to the fact that 'document'\r\n// is not entirely wrapped\r\nfunction wrapIfNeeded(node) {\r\n  return window.ShadowDOMPolyfill ? ShadowDOMPolyfill.wrapIfNeeded(node)\r\n      : node;\r\n}\r\n\r\nfunction inDocument(element) {\r\n  var p = element;\r\n  var doc = wrapIfNeeded(document);\r\n  while (p) {\r\n    if (p == doc) {\r\n      return true;\r\n    }\r\n    p = p.parentNode || p.host;\r\n  }\r\n}\r\n\r\nfunction watchShadow(node) {\r\n  if (node.shadowRoot && !node.shadowRoot.__watched) {\r\n    logFlags.dom && console.log('watching shadow-root for: ', node.localName);\r\n    // watch all unwatched roots...\r\n    var root = node.shadowRoot;\r\n    while (root) {\r\n      watchRoot(root);\r\n      root = root.olderShadowRoot;\r\n    }\r\n  }\r\n}\r\n\r\nfunction watchRoot(root) {\r\n  if (!root.__watched) {\r\n    observe(root);\r\n    root.__watched = true;\r\n  }\r\n}\r\n\r\nfunction handler(mutations) {\r\n  //\r\n  if (logFlags.dom) {\r\n    var mx = mutations[0];\r\n    if (mx && mx.type === 'childList' && mx.addedNodes) {\r\n        if (mx.addedNodes) {\r\n          var d = mx.addedNodes[0];\r\n          while (d && d !== document && !d.host) {\r\n            d = d.parentNode;\r\n          }\r\n          var u = d && (d.URL || d._URL || (d.host && d.host.localName)) || '';\r\n          u = u.split('/?').shift().split('/').pop();\r\n        }\r\n    }\r\n    console.group('mutations (%d) [%s]', mutations.length, u || '');\r\n  }\r\n  //\r\n  mutations.forEach(function(mx) {\r\n    //logFlags.dom && console.group('mutation');\r\n    if (mx.type === 'childList') {\r\n      forEach(mx.addedNodes, function(n) {\r\n        //logFlags.dom && console.log(n.localName);\r\n        if (!n.localName) {\r\n          return;\r\n        }\r\n        // nodes added may need lifecycle management\r\n        addedNode(n);\r\n      });\r\n      // removed nodes may need lifecycle management\r\n      forEach(mx.removedNodes, function(n) {\r\n        //logFlags.dom && console.log(n.localName);\r\n        if (!n.localName) {\r\n          return;\r\n        }\r\n        removedNode(n);\r\n      });\r\n    }\r\n    //logFlags.dom && console.groupEnd();\r\n  });\r\n  logFlags.dom && console.groupEnd();\r\n};\r\n\r\nvar observer = new MutationObserver(handler);\r\n\r\nfunction takeRecords() {\r\n  // TODO(sjmiles): ask Raf why we have to call handler ourselves\r\n  handler(observer.takeRecords());\r\n  takeMutations();\r\n}\r\n\r\nvar forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);\r\n\r\nfunction observe(inRoot) {\r\n  observer.observe(inRoot, {childList: true, subtree: true});\r\n}\r\n\r\nfunction observeDocument(doc) {\r\n  observe(doc);\r\n}\r\n\r\nfunction upgradeDocument(doc) {\r\n  logFlags.dom && console.group('upgradeDocument: ', (doc.baseURI).split('/').pop());\r\n  addedNode(doc);\r\n  logFlags.dom && console.groupEnd();\r\n}\r\n\r\nfunction upgradeDocumentTree(doc) {\r\n  doc = wrapIfNeeded(doc);\r\n  upgradeDocument(doc);\r\n  //console.log('upgradeDocumentTree: ', (doc.baseURI).split('/').pop());\r\n  // upgrade contained imported documents\r\n  var imports = doc.querySelectorAll('link[rel=' + IMPORT_LINK_TYPE + ']');\r\n  for (var i=0, l=imports.length, n; (i<l) && (n=imports[i]); i++) {\r\n    if (n.import && n.import.__parsed) {\r\n      upgradeDocumentTree(n.import);\r\n    }\r\n  }\r\n}\r\n\r\n// exports\r\nscope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;\r\nscope.watchShadow = watchShadow;\r\nscope.upgradeDocumentTree = upgradeDocumentTree;\r\nscope.upgradeAll = addedNode;\r\nscope.upgradeSubtree = addedSubtree;\r\nscope.insertedNode = insertedNode;\r\n\r\nscope.observeDocument = observeDocument;\r\nscope.upgradeDocument = upgradeDocument;\r\n\r\nscope.takeRecords = takeRecords;\r\n\r\n})(window.CustomElements);\r\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * Implements `document.register`\n * @module CustomElements\n*/\n\n/**\n * Polyfilled extensions to the `document` object.\n * @class Document\n*/\n\n(function(scope) {\n\n// imports\n\nif (!scope) {\n  scope = window.CustomElements = {flags:{}};\n}\nvar flags = scope.flags;\n\n// native document.registerElement?\n\nvar hasNative = Boolean(document.registerElement);\n// TODO(sorvell): See https://github.com/Polymer/polymer/issues/399\n// we'll address this by defaulting to CE polyfill in the presence of the SD\n// polyfill. This will avoid spamming excess attached/detached callbacks.\n// If there is a compelling need to run CE native with SD polyfill,\n// we'll need to fix this issue.\nvar useNative = !flags.register && hasNative && !window.ShadowDOMPolyfill;\n\nif (useNative) {\n\n  // stub\n  var nop = function() {};\n\n  // exports\n  scope.registry = {};\n  scope.upgradeElement = nop;\n\n  scope.watchShadow = nop;\n  scope.upgrade = nop;\n  scope.upgradeAll = nop;\n  scope.upgradeSubtree = nop;\n  scope.observeDocument = nop;\n  scope.upgradeDocument = nop;\n  scope.upgradeDocumentTree = nop;\n  scope.takeRecords = nop;\n\n} else {\n\n  /**\n   * Registers a custom tag name with the document.\n   *\n   * When a registered element is created, a `readyCallback` method is called\n   * in the scope of the element. The `readyCallback` method can be specified on\n   * either `options.prototype` or `options.lifecycle` with the latter taking\n   * precedence.\n   *\n   * @method register\n   * @param {String} name The tag name to register. Must include a dash ('-'),\n   *    for example 'x-component'.\n   * @param {Object} options\n   *    @param {String} [options.extends]\n   *      (_off spec_) Tag name of an element to extend (or blank for a new\n   *      element). This parameter is not part of the specification, but instead\n   *      is a hint for the polyfill because the extendee is difficult to infer.\n   *      Remember that the input prototype must chain to the extended element's\n   *      prototype (or HTMLElement.prototype) regardless of the value of\n   *      `extends`.\n   *    @param {Object} options.prototype The prototype to use for the new\n   *      element. The prototype must inherit from HTMLElement.\n   *    @param {Object} [options.lifecycle]\n   *      Callbacks that fire at important phases in the life of the custom\n   *      element.\n   *\n   * @example\n   *      FancyButton = document.registerElement(\"fancy-button\", {\n   *        extends: 'button',\n   *        prototype: Object.create(HTMLButtonElement.prototype, {\n   *          readyCallback: {\n   *            value: function() {\n   *              console.log(\"a fancy-button was created\",\n   *            }\n   *          }\n   *        })\n   *      });\n   * @return {Function} Constructor for the newly registered type.\n   */\n  function register(name, options) {\n    //console.warn('document.registerElement(\"' + name + '\", ', options, ')');\n    // construct a defintion out of options\n    // TODO(sjmiles): probably should clone options instead of mutating it\n    var definition = options || {};\n    if (!name) {\n      // TODO(sjmiles): replace with more appropriate error (EricB can probably\n      // offer guidance)\n      throw new Error('document.registerElement: first argument `name` must not be empty');\n    }\n    if (name.indexOf('-') < 0) {\n      // TODO(sjmiles): replace with more appropriate error (EricB can probably\n      // offer guidance)\n      throw new Error('document.registerElement: first argument (\\'name\\') must contain a dash (\\'-\\'). Argument provided was \\'' + String(name) + '\\'.');\n    }\n    // elements may only be registered once\n    if (getRegisteredDefinition(name)) {\n      throw new Error('DuplicateDefinitionError: a type with name \\'' + String(name) + '\\' is already registered');\n    }\n    // must have a prototype, default to an extension of HTMLElement\n    // TODO(sjmiles): probably should throw if no prototype, check spec\n    if (!definition.prototype) {\n      // TODO(sjmiles): replace with more appropriate error (EricB can probably\n      // offer guidance)\n      throw new Error('Options missing required prototype property');\n    }\n    // record name\n    definition.__name = name.toLowerCase();\n    // ensure a lifecycle object so we don't have to null test it\n    definition.lifecycle = definition.lifecycle || {};\n    // build a list of ancestral custom elements (for native base detection)\n    // TODO(sjmiles): we used to need to store this, but current code only\n    // uses it in 'resolveTagName': it should probably be inlined\n    definition.ancestry = ancestry(definition.extends);\n    // extensions of native specializations of HTMLElement require localName\n    // to remain native, and use secondary 'is' specifier for extension type\n    resolveTagName(definition);\n    // some platforms require modifications to the user-supplied prototype\n    // chain\n    resolvePrototypeChain(definition);\n    // overrides to implement attributeChanged callback\n    overrideAttributeApi(definition.prototype);\n    // 7.1.5: Register the DEFINITION with DOCUMENT\n    registerDefinition(definition.__name, definition);\n    // 7.1.7. Run custom element constructor generation algorithm with PROTOTYPE\n    // 7.1.8. Return the output of the previous step.\n    definition.ctor = generateConstructor(definition);\n    definition.ctor.prototype = definition.prototype;\n    // force our .constructor to be our actual constructor\n    definition.prototype.constructor = definition.ctor;\n    // if initial parsing is complete\n    if (scope.ready) {\n      // upgrade any pre-existing nodes of this type\n      scope.upgradeDocumentTree(document);\n    }\n    return definition.ctor;\n  }\n\n  function ancestry(extnds) {\n    var extendee = getRegisteredDefinition(extnds);\n    if (extendee) {\n      return ancestry(extendee.extends).concat([extendee]);\n    }\n    return [];\n  }\n\n  function resolveTagName(definition) {\n    // if we are explicitly extending something, that thing is our\n    // baseTag, unless it represents a custom component\n    var baseTag = definition.extends;\n    // if our ancestry includes custom components, we only have a\n    // baseTag if one of them does\n    for (var i=0, a; (a=definition.ancestry[i]); i++) {\n      baseTag = a.is && a.tag;\n    }\n    // our tag is our baseTag, if it exists, and otherwise just our name\n    definition.tag = baseTag || definition.__name;\n    if (baseTag) {\n      // if there is a base tag, use secondary 'is' specifier\n      definition.is = definition.__name;\n    }\n  }\n\n  function resolvePrototypeChain(definition) {\n    // if we don't support __proto__ we need to locate the native level\n    // prototype for precise mixing in\n    if (!Object.__proto__) {\n      // default prototype\n      var nativePrototype = HTMLElement.prototype;\n      // work out prototype when using type-extension\n      if (definition.is) {\n        var inst = document.createElement(definition.tag);\n        nativePrototype = Object.getPrototypeOf(inst);\n      }\n      // ensure __proto__ reference is installed at each point on the prototype\n      // chain.\n      // NOTE: On platforms without __proto__, a mixin strategy is used instead\n      // of prototype swizzling. In this case, this generated __proto__ provides\n      // limited support for prototype traversal.\n      var proto = definition.prototype, ancestor;\n      while (proto && (proto !== nativePrototype)) {\n        var ancestor = Object.getPrototypeOf(proto);\n        proto.__proto__ = ancestor;\n        proto = ancestor;\n      }\n    }\n    // cache this in case of mixin\n    definition.native = nativePrototype;\n  }\n\n  // SECTION 4\n\n  function instantiate(definition) {\n    // 4.a.1. Create a new object that implements PROTOTYPE\n    // 4.a.2. Let ELEMENT by this new object\n    //\n    // the custom element instantiation algorithm must also ensure that the\n    // output is a valid DOM element with the proper wrapper in place.\n    //\n    return upgrade(domCreateElement(definition.tag), definition);\n  }\n\n  function upgrade(element, definition) {\n    // some definitions specify an 'is' attribute\n    if (definition.is) {\n      element.setAttribute('is', definition.is);\n    }\n    // remove 'unresolved' attr, which is a standin for :unresolved.\n    element.removeAttribute('unresolved');\n    // make 'element' implement definition.prototype\n    implement(element, definition);\n    // flag as upgraded\n    element.__upgraded__ = true;\n    // lifecycle management\n    created(element);\n    // attachedCallback fires in tree order, call before recursing\n    scope.insertedNode(element);\n    // there should never be a shadow root on element at this point\n    scope.upgradeSubtree(element);\n    // OUTPUT\n    return element;\n  }\n\n  function implement(element, definition) {\n    // prototype swizzling is best\n    if (Object.__proto__) {\n      element.__proto__ = definition.prototype;\n    } else {\n      // where above we can re-acquire inPrototype via\n      // getPrototypeOf(Element), we cannot do so when\n      // we use mixin, so we install a magic reference\n      customMixin(element, definition.prototype, definition.native);\n      element.__proto__ = definition.prototype;\n    }\n  }\n\n  function customMixin(inTarget, inSrc, inNative) {\n    // TODO(sjmiles): 'used' allows us to only copy the 'youngest' version of\n    // any property. This set should be precalculated. We also need to\n    // consider this for supporting 'super'.\n    var used = {};\n    // start with inSrc\n    var p = inSrc;\n    // sometimes the default is HTMLUnknownElement.prototype instead of\n    // HTMLElement.prototype, so we add a test\n    // the idea is to avoid mixing in native prototypes, so adding\n    // the second test is WLOG\n    while (p !== inNative && p !== HTMLUnknownElement.prototype) {\n      var keys = Object.getOwnPropertyNames(p);\n      for (var i=0, k; k=keys[i]; i++) {\n        if (!used[k]) {\n          Object.defineProperty(inTarget, k,\n              Object.getOwnPropertyDescriptor(p, k));\n          used[k] = 1;\n        }\n      }\n      p = Object.getPrototypeOf(p);\n    }\n  }\n\n  function created(element) {\n    // invoke createdCallback\n    if (element.createdCallback) {\n      element.createdCallback();\n    }\n  }\n\n  // attribute watching\n\n  function overrideAttributeApi(prototype) {\n    // overrides to implement callbacks\n    // TODO(sjmiles): should support access via .attributes NamedNodeMap\n    // TODO(sjmiles): preserves user defined overrides, if any\n    if (prototype.setAttribute._polyfilled) {\n      return;\n    }\n    var setAttribute = prototype.setAttribute;\n    prototype.setAttribute = function(name, value) {\n      changeAttribute.call(this, name, value, setAttribute);\n    }\n    var removeAttribute = prototype.removeAttribute;\n    prototype.removeAttribute = function(name) {\n      changeAttribute.call(this, name, null, removeAttribute);\n    }\n    prototype.setAttribute._polyfilled = true;\n  }\n\n  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/\n  // index.html#dfn-attribute-changed-callback\n  function changeAttribute(name, value, operation) {\n    var oldValue = this.getAttribute(name);\n    operation.apply(this, arguments);\n    var newValue = this.getAttribute(name);\n    if (this.attributeChangedCallback\n        && (newValue !== oldValue)) {\n      this.attributeChangedCallback(name, oldValue, newValue);\n    }\n  }\n\n  // element registry (maps tag names to definitions)\n\n  var registry = {};\n\n  function getRegisteredDefinition(name) {\n    if (name) {\n      return registry[name.toLowerCase()];\n    }\n  }\n\n  function registerDefinition(name, definition) {\n    registry[name] = definition;\n  }\n\n  function generateConstructor(definition) {\n    return function() {\n      return instantiate(definition);\n    };\n  }\n\n  function createElement(tag, typeExtension) {\n    // TODO(sjmiles): ignore 'tag' when using 'typeExtension', we could\n    // error check it, or perhaps there should only ever be one argument\n    var definition = getRegisteredDefinition(typeExtension || tag);\n    if (definition) {\n      if (tag == definition.tag && typeExtension == definition.is) {\n        return new definition.ctor();\n      }\n      // Handle empty string for type extension.\n      if (!typeExtension && !definition.is) {\n        return new definition.ctor();\n      }\n    }\n\n    if (typeExtension) {\n      var element = createElement(tag);\n      element.setAttribute('is', typeExtension);\n      return element;\n    }\n    var element = domCreateElement(tag);\n    // Custom tags should be HTMLElements even if not upgraded.\n    if (tag.indexOf('-') >= 0) {\n      implement(element, HTMLElement);\n    }\n    return element;\n  }\n\n  function upgradeElement(element) {\n    if (!element.__upgraded__ && (element.nodeType === Node.ELEMENT_NODE)) {\n      var is = element.getAttribute('is');\n      var definition = getRegisteredDefinition(is || element.localName);\n      if (definition) {\n        if (is && definition.tag == element.localName) {\n          return upgrade(element, definition);\n        } else if (!is && !definition.extends) {\n          return upgrade(element, definition);\n        }\n      }\n    }\n  }\n\n  function cloneNode(deep) {\n    // call original clone\n    var n = domCloneNode.call(this, deep);\n    // upgrade the element and subtree\n    scope.upgradeAll(n);\n    // return the clone\n    return n;\n  }\n  // capture native createElement before we override it\n\n  var domCreateElement = document.createElement.bind(document);\n\n  // capture native cloneNode before we override it\n\n  var domCloneNode = Node.prototype.cloneNode;\n\n  // exports\n\n  document.registerElement = register;\n  document.createElement = createElement; // override\n  Node.prototype.cloneNode = cloneNode; // override\n\n  scope.registry = registry;\n\n  /**\n   * Upgrade an element to a custom element. Upgrading an element\n   * causes the custom prototype to be applied, an `is` attribute\n   * to be attached (as needed), and invocation of the `readyCallback`.\n   * `upgrade` does nothing if the element is already upgraded, or\n   * if it matches no registered custom tag name.\n   *\n   * @method ugprade\n   * @param {Element} element The element to upgrade.\n   * @return {Element} The upgraded element.\n   */\n  scope.upgrade = upgradeElement;\n}\n\n// bc\ndocument.register = document.registerElement;\n\nscope.hasNative = hasNative;\nscope.useNative = useNative;\n\n})(window.CustomElements);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n\n// import\n\nvar IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;\n\n// highlander object for parsing a document tree\n\nvar parser = {\n  selectors: [\n    'link[rel=' + IMPORT_LINK_TYPE + ']'\n  ],\n  map: {\n    link: 'parseLink'\n  },\n  parse: function(inDocument) {\n    if (!inDocument.__parsed) {\n      // only parse once\n      inDocument.__parsed = true;\n      // all parsable elements in inDocument (depth-first pre-order traversal)\n      var elts = inDocument.querySelectorAll(parser.selectors);\n      // for each parsable node type, call the mapped parsing method\n      forEach(elts, function(e) {\n        parser[parser.map[e.localName]](e);\n      });\n      // upgrade all upgradeable static elements, anything dynamically\n      // created should be caught by observer\n      CustomElements.upgradeDocument(inDocument);\n      // observe document for dom changes\n      CustomElements.observeDocument(inDocument);\n    }\n  },\n  parseLink: function(linkElt) {\n    // imports\n    if (isDocumentLink(linkElt)) {\n      this.parseImport(linkElt);\n    }\n  },\n  parseImport: function(linkElt) {\n    if (linkElt.import) {\n      parser.parse(linkElt.import);\n    }\n  }\n};\n\nfunction isDocumentLink(inElt) {\n  return (inElt.localName === 'link'\n      && inElt.getAttribute('rel') === IMPORT_LINK_TYPE);\n}\n\nvar forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);\n\n// exports\n\nscope.parser = parser;\nscope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;\n\n})(window.CustomElements);","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function(scope){\n\n// bootstrap parsing\nfunction bootstrap() {\n  // parse document\n  CustomElements.parser.parse(document);\n  // one more pass before register is 'live'\n  CustomElements.upgradeDocument(document);\n  // choose async\n  var async = window.Platform && Platform.endOfMicrotask ? \n    Platform.endOfMicrotask :\n    setTimeout;\n  async(function() {\n    // set internal 'ready' flag, now document.registerElement will trigger \n    // synchronous upgrades\n    CustomElements.ready = true;\n    // capture blunt profiling data\n    CustomElements.readyTime = Date.now();\n    if (window.HTMLImports) {\n      CustomElements.elapsed = CustomElements.readyTime - HTMLImports.readyTime;\n    }\n    // notify the system that we are bootstrapped\n    document.dispatchEvent(\n      new CustomEvent('WebComponentsReady', {bubbles: true})\n    );\n\n    // install upgrade hook if HTMLImports are available\n    if (window.HTMLImports) {\n      HTMLImports.__importsParsingHook = function(elt) {\n        CustomElements.parser.parse(elt.import);\n      }\n    }\n  });\n}\n\n// CustomEvent shim for IE\nif (typeof window.CustomEvent !== 'function') {\n  window.CustomEvent = function(inType) {\n    var e = document.createEvent('HTMLEvents');\n    e.initEvent(inType, true, true);\n    return e;\n  };\n}\n\n// When loading at readyState complete time (or via flag), boot custom elements\n// immediately.\n// If relevant, HTMLImports must already be loaded.\nif (document.readyState === 'complete' || scope.flags.eager) {\n  bootstrap();\n// When loading at readyState interactive time, bootstrap only if HTMLImports\n// are not pending. Also avoid IE as the semantics of this state are unreliable.\n} else if (document.readyState === 'interactive' && !window.attachEvent &&\n    (!window.HTMLImports || window.HTMLImports.ready)) {\n  bootstrap();\n// When loading at other readyStates, wait for the appropriate DOM event to \n// bootstrap.\n} else {\n  var loadEvent = window.HTMLImports && !HTMLImports.ready ?\n      'HTMLImportsLoaded' : 'DOMContentLoaded';\n  window.addEventListener(loadEvent, bootstrap);\n}\n\n})(window.CustomElements);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function() {\n\n// inject style sheet\nvar style = document.createElement('style');\nstyle.textContent = 'element {display: none !important;} /* injected by platform.js */';\nvar head = document.querySelector('head');\nhead.insertBefore(style, head.firstChild);\n\nif (window.ShadowDOMPolyfill) {\n\n  // ensure wrapped inputs for these functions\n  var fns = ['upgradeAll', 'upgradeSubtree', 'observeDocument',\n      'upgradeDocument'];\n\n  // cache originals\n  var original = {};\n  fns.forEach(function(fn) {\n    original[fn] = CustomElements[fn];\n  });\n\n  // override\n  fns.forEach(function(fn) {\n    CustomElements[fn] = function(inNode) {\n      return original[fn](wrap(inNode));\n    };\n  });\n\n}\n\n})();\n","/*\n * Copyright 2014 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function(scope) {\n\nvar STYLE_SELECTOR = 'style';\n\nvar urlResolver = scope.urlResolver;\n\nvar loader = {\n  cacheStyles: function(styles, callback) {\n    var css = [];\n    for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) {\n      css.push(s.textContent);\n    }\n    cacheCssText(css.join('\\n'), callback);\n  },\n  xhrStyles: function(styles, callback) {\n    var loaded=0, l = styles.length;\n    // called in the context of the style\n    function loadedStyle(style) {\n      //console.log(style.textContent);\n      loaded++;\n      if (loaded === l && callback) {\n        callback();\n      }\n    }\n    for (var i=0, s; (i<l) && (s=styles[i]); i++) {\n      xhrLoadStyle(s, loadedStyle);\n    }\n  }\n};\n\n// use the platform to preload styles\nvar preloadElement = document.createElement('preloader');\npreloadElement.style.display = 'none';\nvar preloadRoot = preloadElement.createShadowRoot();\ndocument.head.appendChild(preloadElement);\n\nfunction cacheCssText(cssText, callback) {\n  var style = createStyleElement(cssText);\n  if (callback) {\n    style.addEventListener('load', callback);\n    style.addEventListener('error', callback);\n  }\n  preloadRoot.appendChild(style);\n}\n\nfunction createStyleElement(cssText, scope) {\n  scope = scope || document;\n  scope = scope.createElement ? scope : scope.ownerDocument;\n  var style = scope.createElement('style');\n  style.textContent = cssText;\n  return style;\n}\n\n// TODO(sorvell): use a common loader shared with HTMLImports polyfill\n// currently, this just loads the first @import per style element \n// and does not recurse into loaded elements; we'll address this with a \n// generalized loader that's built out of the one in the HTMLImports polyfill.\n// polyfill the loading of a style element's @import via xhr\nfunction xhrLoadStyle(style, callback) {\n  HTMLImports.xhr.load(atImportUrlFromStyle(style), function (err, resource,\n      url) {\n    replaceAtImportWithCssText(this, url, resource);\n    this.textContent = urlResolver.resolveCssText(this.textContent, url);\n    callback && callback(this);\n  }, style);\n}\n\nvar atImportRe = /@import\\s[(]?['\"]?([^\\s'\";)]*)/;\n\n// get the first @import rule from a style\nfunction atImportUrlFromStyle(style) {\n  var matches = style.textContent.match(atImportRe);\n  return matches && matches[1];\n}\n\nfunction replaceAtImportWithCssText(style, url, cssText) {\n  var re = new RegExp('@import[^;]*' + url + '[^;]*;', 'i');\n  style.textContent = style.textContent.replace(re, cssText);\n}\n\n// exports\nscope.loader = loader;\n\n})(window.Platform);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n  scope = scope || {};\n  scope.external = scope.external || {};\n  var target = {\n    shadow: function(inEl) {\n      if (inEl) {\n        return inEl.shadowRoot || inEl.webkitShadowRoot;\n      }\n    },\n    canTarget: function(shadow) {\n      return shadow && Boolean(shadow.elementFromPoint);\n    },\n    targetingShadow: function(inEl) {\n      var s = this.shadow(inEl);\n      if (this.canTarget(s)) {\n        return s;\n      }\n    },\n    olderShadow: function(shadow) {\n      var os = shadow.olderShadowRoot;\n      if (!os) {\n        var se = shadow.querySelector('shadow');\n        if (se) {\n          os = se.olderShadowRoot;\n        }\n      }\n      return os;\n    },\n    allShadows: function(element) {\n      var shadows = [], s = this.shadow(element);\n      while(s) {\n        shadows.push(s);\n        s = this.olderShadow(s);\n      }\n      return shadows;\n    },\n    searchRoot: function(inRoot, x, y) {\n      if (inRoot) {\n        var t = inRoot.elementFromPoint(x, y);\n        var st, sr, os;\n        // is element a shadow host?\n        sr = this.targetingShadow(t);\n        while (sr) {\n          // find the the element inside the shadow root\n          st = sr.elementFromPoint(x, y);\n          if (!st) {\n            // check for older shadows\n            sr = this.olderShadow(sr);\n          } else {\n            // shadowed element may contain a shadow root\n            var ssr = this.targetingShadow(st);\n            return this.searchRoot(ssr, x, y) || st;\n          }\n        }\n        // light dom element is the target\n        return t;\n      }\n    },\n    owner: function(element) {\n      var s = element;\n      // walk up until you hit the shadow root or document\n      while (s.parentNode) {\n        s = s.parentNode;\n      }\n      // the owner element is expected to be a Document or ShadowRoot\n      if (s.nodeType != Node.DOCUMENT_NODE && s.nodeType != Node.DOCUMENT_FRAGMENT_NODE) {\n        s = document;\n      }\n      return s;\n    },\n    findTarget: function(inEvent) {\n      var x = inEvent.clientX, y = inEvent.clientY;\n      // if the listener is in the shadow root, it is much faster to start there\n      var s = this.owner(inEvent.target);\n      // if x, y is not in this root, fall back to document search\n      if (!s.elementFromPoint(x, y)) {\n        s = document;\n      }\n      return this.searchRoot(s, x, y);\n    }\n  };\n  scope.targetFinding = target;\n  scope.findTarget = target.findTarget.bind(target);\n\n  window.PointerEventsPolyfill = scope;\n})(window.PointerEventsPolyfill);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function() {\n  function shadowSelector(v) {\n    return 'body ^^ ' + selector(v);\n  }\n  function selector(v) {\n    return '[touch-action=\"' + v + '\"]';\n  }\n  function rule(v) {\n    return '{ -ms-touch-action: ' + v + '; touch-action: ' + v + '; touch-action-delay: none; }';\n  }\n  var attrib2css = [\n    'none',\n    'auto',\n    'pan-x',\n    'pan-y',\n    {\n      rule: 'pan-x pan-y',\n      selectors: [\n        'pan-x pan-y',\n        'pan-y pan-x'\n      ]\n    }\n  ];\n  var styles = '';\n  attrib2css.forEach(function(r) {\n    if (String(r) === r) {\n      styles += selector(r) + rule(r) + '\\n';\n      styles += shadowSelector(r) + rule(r) + '\\n';\n    } else {\n      styles += r.selectors.map(selector) + rule(r.rule) + '\\n';\n      styles += r.selectors.map(shadowSelector) + rule(r.rule) + '\\n';\n    }\n  });\n  var el = document.createElement('style');\n  el.textContent = styles;\n  document.head.appendChild(el);\n})();\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This is the constructor for new PointerEvents.\n *\n * New Pointer Events must be given a type, and an optional dictionary of\n * initialization properties.\n *\n * Due to certain platform requirements, events returned from the constructor\n * identify as MouseEvents.\n *\n * @constructor\n * @param {String} inType The type of the event to create.\n * @param {Object} [inDict] An optional dictionary of initial event properties.\n * @return {Event} A new PointerEvent of type `inType` and initialized with properties from `inDict`.\n */\n(function(scope) {\n  // test for DOM Level 4 Events\n  var NEW_MOUSE_EVENT = false;\n  var HAS_BUTTONS = false;\n  try {\n    var ev = new MouseEvent('click', {buttons: 1});\n    NEW_MOUSE_EVENT = true;\n    HAS_BUTTONS = ev.buttons === 1;\n  } catch(e) {\n  }\n\n  var MOUSE_PROPS = [\n    'bubbles',\n    'cancelable',\n    'view',\n    'detail',\n    'screenX',\n    'screenY',\n    'clientX',\n    'clientY',\n    'ctrlKey',\n    'altKey',\n    'shiftKey',\n    'metaKey',\n    'button',\n    'relatedTarget',\n  ];\n\n  var MOUSE_DEFAULTS = [\n    false,\n    false,\n    null,\n    null,\n    0,\n    0,\n    0,\n    0,\n    false,\n    false,\n    false,\n    false,\n    0,\n    null\n  ];\n\n  function PointerEvent(inType, inDict) {\n    inDict = inDict || {};\n    // According to the w3c spec,\n    // http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-button\n    // MouseEvent.button == 0 can mean either no mouse button depressed, or the\n    // left mouse button depressed.\n    //\n    // As of now, the only way to distinguish between the two states of\n    // MouseEvent.button is by using the deprecated MouseEvent.which property, as\n    // this maps mouse buttons to positive integers > 0, and uses 0 to mean that\n    // no mouse button is held.\n    //\n    // MouseEvent.which is derived from MouseEvent.button at MouseEvent creation,\n    // but initMouseEvent does not expose an argument with which to set\n    // MouseEvent.which. Calling initMouseEvent with a buttonArg of 0 will set\n    // MouseEvent.button == 0 and MouseEvent.which == 1, breaking the expectations\n    // of app developers.\n    //\n    // The only way to propagate the correct state of MouseEvent.which and\n    // MouseEvent.button to a new MouseEvent.button == 0 and MouseEvent.which == 0\n    // is to call initMouseEvent with a buttonArg value of -1.\n    //\n    // This is fixed with DOM Level 4's use of buttons\n    var buttons;\n    if (inDict.buttons || HAS_BUTTONS) {\n      buttons = inDict.buttons;\n    } else {\n      switch (inDict.which) {\n        case 1: buttons = 1; break;\n        case 2: buttons = 4; break;\n        case 3: buttons = 2; break;\n        default: buttons = 0;\n      }\n    }\n\n    var e;\n    if (NEW_MOUSE_EVENT) {\n      e = new MouseEvent(inType, inDict);\n    } else {\n      e = document.createEvent('MouseEvent');\n\n      // import values from the given dictionary\n      var props = {}, p;\n      for(var i = 0; i < MOUSE_PROPS.length; i++) {\n        p = MOUSE_PROPS[i];\n        props[p] = inDict[p] || MOUSE_DEFAULTS[i];\n      }\n\n      // define the properties inherited from MouseEvent\n      e.initMouseEvent(\n        inType, props.bubbles, props.cancelable, props.view, props.detail,\n        props.screenX, props.screenY, props.clientX, props.clientY, props.ctrlKey,\n        props.altKey, props.shiftKey, props.metaKey, props.button, props.relatedTarget\n      );\n    }\n\n    // make the event pass instanceof checks\n    e.__proto__ = PointerEvent.prototype;\n\n    // define the buttons property according to DOM Level 3 spec\n    if (!HAS_BUTTONS) {\n      // IE 10 has buttons on MouseEvent.prototype as a getter w/o any setting\n      // mechanism\n      Object.defineProperty(e, 'buttons', {get: function(){ return buttons; }, enumerable: true});\n    }\n\n    // Spec requires that pointers without pressure specified use 0.5 for down\n    // state and 0 for up state.\n    var pressure = 0;\n    if (inDict.pressure) {\n      pressure = inDict.pressure;\n    } else {\n      pressure = buttons ? 0.5 : 0;\n    }\n\n    // define the properties of the PointerEvent interface\n    Object.defineProperties(e, {\n      pointerId: { value: inDict.pointerId || 0, enumerable: true },\n      width: { value: inDict.width || 0, enumerable: true },\n      height: { value: inDict.height || 0, enumerable: true },\n      pressure: { value: pressure, enumerable: true },\n      tiltX: { value: inDict.tiltX || 0, enumerable: true },\n      tiltY: { value: inDict.tiltY || 0, enumerable: true },\n      pointerType: { value: inDict.pointerType || '', enumerable: true },\n      hwTimestamp: { value: inDict.hwTimestamp || 0, enumerable: true },\n      isPrimary: { value: inDict.isPrimary || false, enumerable: true }\n    });\n    return e;\n  }\n\n  // PointerEvent extends MouseEvent\n  PointerEvent.prototype = Object.create(MouseEvent.prototype);\n\n  // attach to window\n  if (!scope.PointerEvent) {\n    scope.PointerEvent = PointerEvent;\n  }\n})(window);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This module implements an map of pointer states\n */\n(function(scope) {\n  var USE_MAP = window.Map && window.Map.prototype.forEach;\n  var POINTERS_FN = function(){ return this.size; };\n  function PointerMap() {\n    if (USE_MAP) {\n      var m = new Map();\n      m.pointers = POINTERS_FN;\n      return m;\n    } else {\n      this.keys = [];\n      this.values = [];\n    }\n  }\n\n  PointerMap.prototype = {\n    set: function(inId, inEvent) {\n      var i = this.keys.indexOf(inId);\n      if (i > -1) {\n        this.values[i] = inEvent;\n      } else {\n        this.keys.push(inId);\n        this.values.push(inEvent);\n      }\n    },\n    has: function(inId) {\n      return this.keys.indexOf(inId) > -1;\n    },\n    'delete': function(inId) {\n      var i = this.keys.indexOf(inId);\n      if (i > -1) {\n        this.keys.splice(i, 1);\n        this.values.splice(i, 1);\n      }\n    },\n    get: function(inId) {\n      var i = this.keys.indexOf(inId);\n      return this.values[i];\n    },\n    clear: function() {\n      this.keys.length = 0;\n      this.values.length = 0;\n    },\n    // return value, key, map\n    forEach: function(callback, thisArg) {\n      this.values.forEach(function(v, i) {\n        callback.call(thisArg, v, this.keys[i], this);\n      }, this);\n    },\n    pointers: function() {\n      return this.keys.length;\n    }\n  };\n\n  scope.PointerMap = PointerMap;\n})(window.PointerEventsPolyfill);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n  var CLONE_PROPS = [\n    // MouseEvent\n    'bubbles',\n    'cancelable',\n    'view',\n    'detail',\n    'screenX',\n    'screenY',\n    'clientX',\n    'clientY',\n    'ctrlKey',\n    'altKey',\n    'shiftKey',\n    'metaKey',\n    'button',\n    'relatedTarget',\n    // DOM Level 3\n    'buttons',\n    // PointerEvent\n    'pointerId',\n    'width',\n    'height',\n    'pressure',\n    'tiltX',\n    'tiltY',\n    'pointerType',\n    'hwTimestamp',\n    'isPrimary',\n    // event instance\n    'type',\n    'target',\n    'currentTarget',\n    'which'\n  ];\n\n  var CLONE_DEFAULTS = [\n    // MouseEvent\n    false,\n    false,\n    null,\n    null,\n    0,\n    0,\n    0,\n    0,\n    false,\n    false,\n    false,\n    false,\n    0,\n    null,\n    // DOM Level 3\n    0,\n    // PointerEvent\n    0,\n    0,\n    0,\n    0,\n    0,\n    0,\n    '',\n    0,\n    false,\n    // event instance\n    '',\n    null,\n    null,\n    0\n  ];\n\n  var HAS_SVG_INSTANCE = (typeof SVGElementInstance !== 'undefined');\n\n  /**\n   * This module is for normalizing events. Mouse and Touch events will be\n   * collected here, and fire PointerEvents that have the same semantics, no\n   * matter the source.\n   * Events fired:\n   *   - pointerdown: a pointing is added\n   *   - pointerup: a pointer is removed\n   *   - pointermove: a pointer is moved\n   *   - pointerover: a pointer crosses into an element\n   *   - pointerout: a pointer leaves an element\n   *   - pointercancel: a pointer will no longer generate events\n   */\n  var dispatcher = {\n    targets: new WeakMap(),\n    handledEvents: new WeakMap(),\n    pointermap: new scope.PointerMap(),\n    eventMap: {},\n    // Scope objects for native events.\n    // This exists for ease of testing.\n    eventSources: {},\n    eventSourceList: [],\n    /**\n     * Add a new event source that will generate pointer events.\n     *\n     * `inSource` must contain an array of event names named `events`, and\n     * functions with the names specified in the `events` array.\n     * @param {string} name A name for the event source\n     * @param {Object} source A new source of platform events.\n     */\n    registerSource: function(name, source) {\n      var s = source;\n      var newEvents = s.events;\n      if (newEvents) {\n        newEvents.forEach(function(e) {\n          if (s[e]) {\n            this.eventMap[e] = s[e].bind(s);\n          }\n        }, this);\n        this.eventSources[name] = s;\n        this.eventSourceList.push(s);\n      }\n    },\n    register: function(element) {\n      var l = this.eventSourceList.length;\n      for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) {\n        // call eventsource register\n        es.register.call(es, element);\n      }\n    },\n    unregister: function(element) {\n      var l = this.eventSourceList.length;\n      for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) {\n        // call eventsource register\n        es.unregister.call(es, element);\n      }\n    },\n    contains: scope.external.contains || function(container, contained) {\n      return container.contains(contained);\n    },\n    // EVENTS\n    down: function(inEvent) {\n      this.fireEvent('pointerdown', inEvent);\n    },\n    move: function(inEvent) {\n      this.fireEvent('pointermove', inEvent);\n    },\n    up: function(inEvent) {\n      this.fireEvent('pointerup', inEvent);\n    },\n    enter: function(inEvent) {\n      inEvent.bubbles = false;\n      this.fireEvent('pointerenter', inEvent);\n    },\n    leave: function(inEvent) {\n      inEvent.bubbles = false;\n      this.fireEvent('pointerleave', inEvent);\n    },\n    over: function(inEvent) {\n      inEvent.bubbles = true;\n      this.fireEvent('pointerover', inEvent);\n    },\n    out: function(inEvent) {\n      inEvent.bubbles = true;\n      this.fireEvent('pointerout', inEvent);\n    },\n    cancel: function(inEvent) {\n      this.fireEvent('pointercancel', inEvent);\n    },\n    leaveOut: function(event) {\n      this.out(event);\n      if (!this.contains(event.target, event.relatedTarget)) {\n        this.leave(event);\n      }\n    },\n    enterOver: function(event) {\n      this.over(event);\n      if (!this.contains(event.target, event.relatedTarget)) {\n        this.enter(event);\n      }\n    },\n    // LISTENER LOGIC\n    eventHandler: function(inEvent) {\n      // This is used to prevent multiple dispatch of pointerevents from\n      // platform events. This can happen when two elements in different scopes\n      // are set up to create pointer events, which is relevant to Shadow DOM.\n      if (this.handledEvents.get(inEvent)) {\n        return;\n      }\n      var type = inEvent.type;\n      var fn = this.eventMap && this.eventMap[type];\n      if (fn) {\n        fn(inEvent);\n      }\n      this.handledEvents.set(inEvent, true);\n    },\n    // set up event listeners\n    listen: function(target, events) {\n      events.forEach(function(e) {\n        this.addEvent(target, e);\n      }, this);\n    },\n    // remove event listeners\n    unlisten: function(target, events) {\n      events.forEach(function(e) {\n        this.removeEvent(target, e);\n      }, this);\n    },\n    addEvent: scope.external.addEvent || function(target, eventName) {\n      target.addEventListener(eventName, this.boundHandler);\n    },\n    removeEvent: scope.external.removeEvent || function(target, eventName) {\n      target.removeEventListener(eventName, this.boundHandler);\n    },\n    // EVENT CREATION AND TRACKING\n    /**\n     * Creates a new Event of type `inType`, based on the information in\n     * `inEvent`.\n     *\n     * @param {string} inType A string representing the type of event to create\n     * @param {Event} inEvent A platform event with a target\n     * @return {Event} A PointerEvent of type `inType`\n     */\n    makeEvent: function(inType, inEvent) {\n      // relatedTarget must be null if pointer is captured\n      if (this.captureInfo) {\n        inEvent.relatedTarget = null;\n      }\n      var e = new PointerEvent(inType, inEvent);\n      if (inEvent.preventDefault) {\n        e.preventDefault = inEvent.preventDefault;\n      }\n      this.targets.set(e, this.targets.get(inEvent) || inEvent.target);\n      return e;\n    },\n    // make and dispatch an event in one call\n    fireEvent: function(inType, inEvent) {\n      var e = this.makeEvent(inType, inEvent);\n      return this.dispatchEvent(e);\n    },\n    /**\n     * Returns a snapshot of inEvent, with writable properties.\n     *\n     * @param {Event} inEvent An event that contains properties to copy.\n     * @return {Object} An object containing shallow copies of `inEvent`'s\n     *    properties.\n     */\n    cloneEvent: function(inEvent) {\n      var eventCopy = {}, p;\n      for (var i = 0; i < CLONE_PROPS.length; i++) {\n        p = CLONE_PROPS[i];\n        eventCopy[p] = inEvent[p] || CLONE_DEFAULTS[i];\n        // Work around SVGInstanceElement shadow tree\n        // Return the <use> element that is represented by the instance for Safari, Chrome, IE.\n        // This is the behavior implemented by Firefox.\n        if (HAS_SVG_INSTANCE && (p === 'target' || p === 'relatedTarget')) {\n          if (eventCopy[p] instanceof SVGElementInstance) {\n            eventCopy[p] = eventCopy[p].correspondingUseElement;\n          }\n        }\n      }\n      // keep the semantics of preventDefault\n      if (inEvent.preventDefault) {\n        eventCopy.preventDefault = function() {\n          inEvent.preventDefault();\n        };\n      }\n      return eventCopy;\n    },\n    getTarget: function(inEvent) {\n      // if pointer capture is set, route all events for the specified pointerId\n      // to the capture target\n      if (this.captureInfo) {\n        if (this.captureInfo.id === inEvent.pointerId) {\n          return this.captureInfo.target;\n        }\n      }\n      return this.targets.get(inEvent);\n    },\n    setCapture: function(inPointerId, inTarget) {\n      if (this.captureInfo) {\n        this.releaseCapture(this.captureInfo.id);\n      }\n      this.captureInfo = {id: inPointerId, target: inTarget};\n      var e = new PointerEvent('gotpointercapture', { bubbles: true });\n      this.implicitRelease = this.releaseCapture.bind(this, inPointerId);\n      document.addEventListener('pointerup', this.implicitRelease);\n      document.addEventListener('pointercancel', this.implicitRelease);\n      this.targets.set(e, inTarget);\n      this.asyncDispatchEvent(e);\n    },\n    releaseCapture: function(inPointerId) {\n      if (this.captureInfo && this.captureInfo.id === inPointerId) {\n        var e = new PointerEvent('lostpointercapture', { bubbles: true });\n        var t = this.captureInfo.target;\n        this.captureInfo = null;\n        document.removeEventListener('pointerup', this.implicitRelease);\n        document.removeEventListener('pointercancel', this.implicitRelease);\n        this.targets.set(e, t);\n        this.asyncDispatchEvent(e);\n      }\n    },\n    /**\n     * Dispatches the event to its target.\n     *\n     * @param {Event} inEvent The event to be dispatched.\n     * @return {Boolean} True if an event handler returns true, false otherwise.\n     */\n    dispatchEvent: scope.external.dispatchEvent || function(inEvent) {\n      var t = this.getTarget(inEvent);\n      if (t) {\n        return t.dispatchEvent(inEvent);\n      }\n    },\n    asyncDispatchEvent: function(inEvent) {\n      setTimeout(this.dispatchEvent.bind(this, inEvent), 0);\n    }\n  };\n  dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher);\n  scope.dispatcher = dispatcher;\n  scope.register = dispatcher.register.bind(dispatcher);\n  scope.unregister = dispatcher.unregister.bind(dispatcher);\n})(window.PointerEventsPolyfill);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This module uses Mutation Observers to dynamically adjust which nodes will\n * generate Pointer Events.\n *\n * All nodes that wish to generate Pointer Events must have the attribute\n * `touch-action` set to `none`.\n */\n(function(scope) {\n  var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);\n  var map = Array.prototype.map.call.bind(Array.prototype.map);\n  var toArray = Array.prototype.slice.call.bind(Array.prototype.slice);\n  var filter = Array.prototype.filter.call.bind(Array.prototype.filter);\n  var MO = window.MutationObserver || window.WebKitMutationObserver;\n  var SELECTOR = '[touch-action]';\n  var OBSERVER_INIT = {\n    subtree: true,\n    childList: true,\n    attributes: true,\n    attributeOldValue: true,\n    attributeFilter: ['touch-action']\n  };\n\n  function Installer(add, remove, changed, binder) {\n    this.addCallback = add.bind(binder);\n    this.removeCallback = remove.bind(binder);\n    this.changedCallback = changed.bind(binder);\n    if (MO) {\n      this.observer = new MO(this.mutationWatcher.bind(this));\n    }\n  }\n\n  Installer.prototype = {\n    watchSubtree: function(target) {\n      // Only watch scopes that can target find, as these are top-level.\n      // Otherwise we can see duplicate additions and removals that add noise.\n      //\n      // TODO(dfreedman): For some instances with ShadowDOMPolyfill, we can see\n      // a removal without an insertion when a node is redistributed among\n      // shadows. Since it all ends up correct in the document, watching only\n      // the document will yield the correct mutations to watch.\n      if (scope.targetFinding.canTarget(target)) {\n        this.observer.observe(target, OBSERVER_INIT);\n      }\n    },\n    enableOnSubtree: function(target) {\n      this.watchSubtree(target);\n      if (target === document && document.readyState !== 'complete') {\n        this.installOnLoad();\n      } else {\n        this.installNewSubtree(target);\n      }\n    },\n    installNewSubtree: function(target) {\n      forEach(this.findElements(target), this.addElement, this);\n    },\n    findElements: function(target) {\n      if (target.querySelectorAll) {\n        return target.querySelectorAll(SELECTOR);\n      }\n      return [];\n    },\n    removeElement: function(el) {\n      this.removeCallback(el);\n    },\n    addElement: function(el) {\n      this.addCallback(el);\n    },\n    elementChanged: function(el, oldValue) {\n      this.changedCallback(el, oldValue);\n    },\n    concatLists: function(accum, list) {\n      return accum.concat(toArray(list));\n    },\n    // register all touch-action = none nodes on document load\n    installOnLoad: function() {\n      document.addEventListener('DOMContentLoaded', this.installNewSubtree.bind(this, document));\n    },\n    isElement: function(n) {\n      return n.nodeType === Node.ELEMENT_NODE;\n    },\n    flattenMutationTree: function(inNodes) {\n      // find children with touch-action\n      var tree = map(inNodes, this.findElements, this);\n      // make sure the added nodes are accounted for\n      tree.push(filter(inNodes, this.isElement));\n      // flatten the list\n      return tree.reduce(this.concatLists, []);\n    },\n    mutationWatcher: function(mutations) {\n      mutations.forEach(this.mutationHandler, this);\n    },\n    mutationHandler: function(m) {\n      if (m.type === 'childList') {\n        var added = this.flattenMutationTree(m.addedNodes);\n        added.forEach(this.addElement, this);\n        var removed = this.flattenMutationTree(m.removedNodes);\n        removed.forEach(this.removeElement, this);\n      } else if (m.type === 'attributes') {\n        this.elementChanged(m.target, m.oldValue);\n      }\n    }\n  };\n\n  if (!MO) {\n    Installer.prototype.watchSubtree = function(){\n      console.warn('PointerEventsPolyfill: MutationObservers not found, touch-action will not be dynamically detected');\n    };\n  }\n\n  scope.Installer = Installer;\n})(window.PointerEventsPolyfill);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function (scope) {\n  var dispatcher = scope.dispatcher;\n  var pointermap = dispatcher.pointermap;\n  // radius around touchend that swallows mouse events\n  var DEDUP_DIST = 25;\n\n  // handler block for native mouse events\n  var mouseEvents = {\n    POINTER_ID: 1,\n    POINTER_TYPE: 'mouse',\n    events: [\n      'mousedown',\n      'mousemove',\n      'mouseup',\n      'mouseover',\n      'mouseout'\n    ],\n    register: function(target) {\n      dispatcher.listen(target, this.events);\n    },\n    unregister: function(target) {\n      dispatcher.unlisten(target, this.events);\n    },\n    lastTouches: [],\n    // collide with the global mouse listener\n    isEventSimulatedFromTouch: function(inEvent) {\n      var lts = this.lastTouches;\n      var x = inEvent.clientX, y = inEvent.clientY;\n      for (var i = 0, l = lts.length, t; i < l && (t = lts[i]); i++) {\n        // simulated mouse events will be swallowed near a primary touchend\n        var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y);\n        if (dx <= DEDUP_DIST && dy <= DEDUP_DIST) {\n          return true;\n        }\n      }\n    },\n    prepareEvent: function(inEvent) {\n      var e = dispatcher.cloneEvent(inEvent);\n      // forward mouse preventDefault\n      var pd = e.preventDefault;\n      e.preventDefault = function() {\n        inEvent.preventDefault();\n        pd();\n      };\n      e.pointerId = this.POINTER_ID;\n      e.isPrimary = true;\n      e.pointerType = this.POINTER_TYPE;\n      return e;\n    },\n    mousedown: function(inEvent) {\n      if (!this.isEventSimulatedFromTouch(inEvent)) {\n        var p = pointermap.has(this.POINTER_ID);\n        // TODO(dfreedman) workaround for some elements not sending mouseup\n        // http://crbug/149091\n        if (p) {\n          this.cancel(inEvent);\n        }\n        var e = this.prepareEvent(inEvent);\n        pointermap.set(this.POINTER_ID, inEvent);\n        dispatcher.down(e);\n      }\n    },\n    mousemove: function(inEvent) {\n      if (!this.isEventSimulatedFromTouch(inEvent)) {\n        var e = this.prepareEvent(inEvent);\n        dispatcher.move(e);\n      }\n    },\n    mouseup: function(inEvent) {\n      if (!this.isEventSimulatedFromTouch(inEvent)) {\n        var p = pointermap.get(this.POINTER_ID);\n        if (p && p.button === inEvent.button) {\n          var e = this.prepareEvent(inEvent);\n          dispatcher.up(e);\n          this.cleanupMouse();\n        }\n      }\n    },\n    mouseover: function(inEvent) {\n      if (!this.isEventSimulatedFromTouch(inEvent)) {\n        var e = this.prepareEvent(inEvent);\n        dispatcher.enterOver(e);\n      }\n    },\n    mouseout: function(inEvent) {\n      if (!this.isEventSimulatedFromTouch(inEvent)) {\n        var e = this.prepareEvent(inEvent);\n        dispatcher.leaveOut(e);\n      }\n    },\n    cancel: function(inEvent) {\n      var e = this.prepareEvent(inEvent);\n      dispatcher.cancel(e);\n      this.cleanupMouse();\n    },\n    cleanupMouse: function() {\n      pointermap['delete'](this.POINTER_ID);\n    }\n  };\n\n  scope.mouseEvents = mouseEvents;\n})(window.PointerEventsPolyfill);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n  var dispatcher = scope.dispatcher;\n  var findTarget = scope.findTarget;\n  var allShadows = scope.targetFinding.allShadows.bind(scope.targetFinding);\n  var pointermap = dispatcher.pointermap;\n  var touchMap = Array.prototype.map.call.bind(Array.prototype.map);\n  // This should be long enough to ignore compat mouse events made by touch\n  var DEDUP_TIMEOUT = 2500;\n  var CLICK_COUNT_TIMEOUT = 200;\n  var ATTRIB = 'touch-action';\n  var INSTALLER;\n  // The presence of touch event handlers blocks scrolling, and so we must be careful to\n  // avoid adding handlers unnecessarily.  Chrome plans to add a touch-action-delay property\n  // (crbug.com/329559) to address this, and once we have that we can opt-in to a simpler\n  // handler registration mechanism.  Rather than try to predict how exactly to opt-in to\n  // that we'll just leave this disabled until there is a build of Chrome to test.\n  var HAS_TOUCH_ACTION_DELAY = false;\n  \n  // handler block for native touch events\n  var touchEvents = {\n    scrollType: new WeakMap(),\n    events: [\n      'touchstart',\n      'touchmove',\n      'touchend',\n      'touchcancel'\n    ],\n    register: function(target) {\n      if (HAS_TOUCH_ACTION_DELAY) {\n        dispatcher.listen(target, this.events);\n      } else {\n        INSTALLER.enableOnSubtree(target);\n      }\n    },\n    unregister: function(target) {\n      if (HAS_TOUCH_ACTION_DELAY) {\n        dispatcher.unlisten(target, this.events);\n      } else {\n        // TODO(dfreedman): is it worth it to disconnect the MO?\n      }\n    },\n    elementAdded: function(el) {\n      var a = el.getAttribute(ATTRIB);\n      var st = this.touchActionToScrollType(a);\n      if (st) {\n        this.scrollType.set(el, st);\n        dispatcher.listen(el, this.events);\n        // set touch-action on shadows as well\n        allShadows(el).forEach(function(s) {\n          this.scrollType.set(s, st);\n          dispatcher.listen(s, this.events);\n        }, this);\n      }\n    },\n    elementRemoved: function(el) {\n      this.scrollType['delete'](el);\n      dispatcher.unlisten(el, this.events);\n      // remove touch-action from shadow\n      allShadows(el).forEach(function(s) {\n        this.scrollType['delete'](s);\n        dispatcher.unlisten(s, this.events);\n      }, this);\n    },\n    elementChanged: function(el, oldValue) {\n      var a = el.getAttribute(ATTRIB);\n      var st = this.touchActionToScrollType(a);\n      var oldSt = this.touchActionToScrollType(oldValue);\n      // simply update scrollType if listeners are already established\n      if (st && oldSt) {\n        this.scrollType.set(el, st);\n        allShadows(el).forEach(function(s) {\n          this.scrollType.set(s, st);\n        }, this);\n      } else if (oldSt) {\n        this.elementRemoved(el);\n      } else if (st) {\n        this.elementAdded(el);\n      }\n    },\n    scrollTypes: {\n      EMITTER: 'none',\n      XSCROLLER: 'pan-x',\n      YSCROLLER: 'pan-y',\n      SCROLLER: /^(?:pan-x pan-y)|(?:pan-y pan-x)|auto$/\n    },\n    touchActionToScrollType: function(touchAction) {\n      var t = touchAction;\n      var st = this.scrollTypes;\n      if (t === 'none') {\n        return 'none';\n      } else if (t === st.XSCROLLER) {\n        return 'X';\n      } else if (t === st.YSCROLLER) {\n        return 'Y';\n      } else if (st.SCROLLER.exec(t)) {\n        return 'XY';\n      }\n    },\n    POINTER_TYPE: 'touch',\n    firstTouch: null,\n    isPrimaryTouch: function(inTouch) {\n      return this.firstTouch === inTouch.identifier;\n    },\n    setPrimaryTouch: function(inTouch) {\n      // set primary touch if there no pointers, or the only pointer is the mouse\n      if (pointermap.pointers() === 0 || (pointermap.pointers() === 1 && pointermap.has(1))) {\n        this.firstTouch = inTouch.identifier;\n        this.firstXY = {X: inTouch.clientX, Y: inTouch.clientY};\n        this.scrolling = false;\n        this.cancelResetClickCount();\n      }\n    },\n    removePrimaryPointer: function(inPointer) {\n      if (inPointer.isPrimary) {\n        this.firstTouch = null;\n        this.firstXY = null;\n        this.resetClickCount();\n      }\n    },\n    clickCount: 0,\n    resetId: null,\n    resetClickCount: function() {\n      var fn = function() {\n        this.clickCount = 0;\n        this.resetId = null;\n      }.bind(this);\n      this.resetId = setTimeout(fn, CLICK_COUNT_TIMEOUT);\n    },\n    cancelResetClickCount: function() {\n      if (this.resetId) {\n        clearTimeout(this.resetId);\n      }\n    },\n    touchToPointer: function(inTouch) {\n      var e = dispatcher.cloneEvent(inTouch);\n      // Spec specifies that pointerId 1 is reserved for Mouse.\n      // Touch identifiers can start at 0.\n      // Add 2 to the touch identifier for compatibility.\n      e.pointerId = inTouch.identifier + 2;\n      e.target = findTarget(e);\n      e.bubbles = true;\n      e.cancelable = true;\n      e.detail = this.clickCount;\n      e.button = 0;\n      e.buttons = 1;\n      e.width = inTouch.webkitRadiusX || inTouch.radiusX || 0;\n      e.height = inTouch.webkitRadiusY || inTouch.radiusY || 0;\n      e.pressure = inTouch.webkitForce || inTouch.force || 0.5;\n      e.isPrimary = this.isPrimaryTouch(inTouch);\n      e.pointerType = this.POINTER_TYPE;\n      return e;\n    },\n    processTouches: function(inEvent, inFunction) {\n      var tl = inEvent.changedTouches;\n      var pointers = touchMap(tl, this.touchToPointer, this);\n      // forward touch preventDefaults\n      pointers.forEach(function(p) {\n        p.preventDefault = function() {\n          this.scrolling = false;\n          this.firstXY = null;\n          inEvent.preventDefault();\n        };\n      }, this);\n      pointers.forEach(inFunction, this);\n    },\n    // For single axis scrollers, determines whether the element should emit\n    // pointer events or behave as a scroller\n    shouldScroll: function(inEvent) {\n      if (this.firstXY) {\n        var ret;\n        var scrollAxis = this.scrollType.get(inEvent.currentTarget);\n        if (scrollAxis === 'none') {\n          // this element is a touch-action: none, should never scroll\n          ret = false;\n        } else if (scrollAxis === 'XY') {\n          // this element should always scroll\n          ret = true;\n        } else {\n          var t = inEvent.changedTouches[0];\n          // check the intended scroll axis, and other axis\n          var a = scrollAxis;\n          var oa = scrollAxis === 'Y' ? 'X' : 'Y';\n          var da = Math.abs(t['client' + a] - this.firstXY[a]);\n          var doa = Math.abs(t['client' + oa] - this.firstXY[oa]);\n          // if delta in the scroll axis > delta other axis, scroll instead of\n          // making events\n          ret = da >= doa;\n        }\n        this.firstXY = null;\n        return ret;\n      }\n    },\n    findTouch: function(inTL, inId) {\n      for (var i = 0, l = inTL.length, t; i < l && (t = inTL[i]); i++) {\n        if (t.identifier === inId) {\n          return true;\n        }\n      }\n    },\n    // In some instances, a touchstart can happen without a touchend. This\n    // leaves the pointermap in a broken state.\n    // Therefore, on every touchstart, we remove the touches that did not fire a\n    // touchend event.\n    // To keep state globally consistent, we fire a\n    // pointercancel for this \"abandoned\" touch\n    vacuumTouches: function(inEvent) {\n      var tl = inEvent.touches;\n      // pointermap.pointers() should be < tl.length here, as the touchstart has not\n      // been processed yet.\n      if (pointermap.pointers() >= tl.length) {\n        var d = [];\n        pointermap.forEach(function(value, key) {\n          // Never remove pointerId == 1, which is mouse.\n          // Touch identifiers are 2 smaller than their pointerId, which is the\n          // index in pointermap.\n          if (key !== 1 && !this.findTouch(tl, key - 2)) {\n            var p = value.out;\n            d.push(this.touchToPointer(p));\n          }\n        }, this);\n        d.forEach(this.cancelOut, this);\n      }\n    },\n    touchstart: function(inEvent) {\n      this.vacuumTouches(inEvent);\n      this.setPrimaryTouch(inEvent.changedTouches[0]);\n      this.dedupSynthMouse(inEvent);\n      if (!this.scrolling) {\n        this.clickCount++;\n        this.processTouches(inEvent, this.overDown);\n      }\n    },\n    overDown: function(inPointer) {\n      var p = pointermap.set(inPointer.pointerId, {\n        target: inPointer.target,\n        out: inPointer,\n        outTarget: inPointer.target\n      });\n      dispatcher.over(inPointer);\n      dispatcher.enter(inPointer);\n      dispatcher.down(inPointer);\n    },\n    touchmove: function(inEvent) {\n      if (!this.scrolling) {\n        if (this.shouldScroll(inEvent)) {\n          this.scrolling = true;\n          this.touchcancel(inEvent);\n        } else {\n          inEvent.preventDefault();\n          this.processTouches(inEvent, this.moveOverOut);\n        }\n      }\n    },\n    moveOverOut: function(inPointer) {\n      var event = inPointer;\n      var pointer = pointermap.get(event.pointerId);\n      // a finger drifted off the screen, ignore it\n      if (!pointer) {\n        return;\n      }\n      var outEvent = pointer.out;\n      var outTarget = pointer.outTarget;\n      dispatcher.move(event);\n      if (outEvent && outTarget !== event.target) {\n        outEvent.relatedTarget = event.target;\n        event.relatedTarget = outTarget;\n        // recover from retargeting by shadow\n        outEvent.target = outTarget;\n        if (event.target) {\n          dispatcher.leaveOut(outEvent);\n          dispatcher.enterOver(event);\n        } else {\n          // clean up case when finger leaves the screen\n          event.target = outTarget;\n          event.relatedTarget = null;\n          this.cancelOut(event);\n        }\n      }\n      pointer.out = event;\n      pointer.outTarget = event.target;\n    },\n    touchend: function(inEvent) {\n      this.dedupSynthMouse(inEvent);\n      this.processTouches(inEvent, this.upOut);\n    },\n    upOut: function(inPointer) {\n      if (!this.scrolling) {\n        dispatcher.up(inPointer);\n        dispatcher.out(inPointer);\n        dispatcher.leave(inPointer);\n      }\n      this.cleanUpPointer(inPointer);\n    },\n    touchcancel: function(inEvent) {\n      this.processTouches(inEvent, this.cancelOut);\n    },\n    cancelOut: function(inPointer) {\n      dispatcher.cancel(inPointer);\n      dispatcher.out(inPointer);\n      dispatcher.leave(inPointer);\n      this.cleanUpPointer(inPointer);\n    },\n    cleanUpPointer: function(inPointer) {\n      pointermap['delete'](inPointer.pointerId);\n      this.removePrimaryPointer(inPointer);\n    },\n    // prevent synth mouse events from creating pointer events\n    dedupSynthMouse: function(inEvent) {\n      var lts = scope.mouseEvents.lastTouches;\n      var t = inEvent.changedTouches[0];\n      // only the primary finger will synth mouse events\n      if (this.isPrimaryTouch(t)) {\n        // remember x/y of last touch\n        var lt = {x: t.clientX, y: t.clientY};\n        lts.push(lt);\n        var fn = (function(lts, lt){\n          var i = lts.indexOf(lt);\n          if (i > -1) {\n            lts.splice(i, 1);\n          }\n        }).bind(null, lts, lt);\n        setTimeout(fn, DEDUP_TIMEOUT);\n      }\n    }\n  };\n\n  if (!HAS_TOUCH_ACTION_DELAY) {\n    INSTALLER = new scope.Installer(touchEvents.elementAdded, touchEvents.elementRemoved, touchEvents.elementChanged, touchEvents);\n  }\n\n  scope.touchEvents = touchEvents;\n})(window.PointerEventsPolyfill);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n  var dispatcher = scope.dispatcher;\n  var pointermap = dispatcher.pointermap;\n  var HAS_BITMAP_TYPE = window.MSPointerEvent && typeof window.MSPointerEvent.MSPOINTER_TYPE_MOUSE === 'number';\n  var msEvents = {\n    events: [\n      'MSPointerDown',\n      'MSPointerMove',\n      'MSPointerUp',\n      'MSPointerOut',\n      'MSPointerOver',\n      'MSPointerCancel',\n      'MSGotPointerCapture',\n      'MSLostPointerCapture'\n    ],\n    register: function(target) {\n      dispatcher.listen(target, this.events);\n    },\n    unregister: function(target) {\n      dispatcher.unlisten(target, this.events);\n    },\n    POINTER_TYPES: [\n      '',\n      'unavailable',\n      'touch',\n      'pen',\n      'mouse'\n    ],\n    prepareEvent: function(inEvent) {\n      var e = inEvent;\n      if (HAS_BITMAP_TYPE) {\n        e = dispatcher.cloneEvent(inEvent);\n        e.pointerType = this.POINTER_TYPES[inEvent.pointerType];\n      }\n      return e;\n    },\n    cleanup: function(id) {\n      pointermap['delete'](id);\n    },\n    MSPointerDown: function(inEvent) {\n      pointermap.set(inEvent.pointerId, inEvent);\n      var e = this.prepareEvent(inEvent);\n      dispatcher.down(e);\n    },\n    MSPointerMove: function(inEvent) {\n      var e = this.prepareEvent(inEvent);\n      dispatcher.move(e);\n    },\n    MSPointerUp: function(inEvent) {\n      var e = this.prepareEvent(inEvent);\n      dispatcher.up(e);\n      this.cleanup(inEvent.pointerId);\n    },\n    MSPointerOut: function(inEvent) {\n      var e = this.prepareEvent(inEvent);\n      dispatcher.leaveOut(e);\n    },\n    MSPointerOver: function(inEvent) {\n      var e = this.prepareEvent(inEvent);\n      dispatcher.enterOver(e);\n    },\n    MSPointerCancel: function(inEvent) {\n      var e = this.prepareEvent(inEvent);\n      dispatcher.cancel(e);\n      this.cleanup(inEvent.pointerId);\n    },\n    MSLostPointerCapture: function(inEvent) {\n      var e = dispatcher.makeEvent('lostpointercapture', inEvent);\n      dispatcher.dispatchEvent(e);\n    },\n    MSGotPointerCapture: function(inEvent) {\n      var e = dispatcher.makeEvent('gotpointercapture', inEvent);\n      dispatcher.dispatchEvent(e);\n    }\n  };\n\n  scope.msEvents = msEvents;\n})(window.PointerEventsPolyfill);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This module contains the handlers for native platform events.\n * From here, the dispatcher is called to create unified pointer events.\n * Included are touch events (v1), mouse events, and MSPointerEvents.\n */\n(function(scope) {\n  var dispatcher = scope.dispatcher;\n\n  // only activate if this platform does not have pointer events\n  if (window.navigator.pointerEnabled === undefined) {\n    Object.defineProperty(window.navigator, 'pointerEnabled', {value: true, enumerable: true});\n\n    if (window.navigator.msPointerEnabled) {\n      var tp = window.navigator.msMaxTouchPoints;\n      Object.defineProperty(window.navigator, 'maxTouchPoints', {\n        value: tp,\n        enumerable: true\n      });\n      dispatcher.registerSource('ms', scope.msEvents);\n    } else {\n      dispatcher.registerSource('mouse', scope.mouseEvents);\n      if (window.ontouchstart !== undefined) {\n        dispatcher.registerSource('touch', scope.touchEvents);\n      }\n    }\n\n    dispatcher.register(document);\n  }\n})(window.PointerEventsPolyfill);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n  var dispatcher = scope.dispatcher;\n  var n = window.navigator;\n  var s, r;\n  function assertDown(id) {\n    if (!dispatcher.pointermap.has(id)) {\n      throw new Error('InvalidPointerId');\n    }\n  }\n  if (n.msPointerEnabled) {\n    s = function(pointerId) {\n      assertDown(pointerId);\n      this.msSetPointerCapture(pointerId);\n    };\n    r = function(pointerId) {\n      assertDown(pointerId);\n      this.msReleasePointerCapture(pointerId);\n    };\n  } else {\n    s = function setPointerCapture(pointerId) {\n      assertDown(pointerId);\n      dispatcher.setCapture(pointerId, this);\n    };\n    r = function releasePointerCapture(pointerId) {\n      assertDown(pointerId);\n      dispatcher.releaseCapture(pointerId, this);\n    };\n  }\n  if (window.Element && !Element.prototype.setPointerCapture) {\n    Object.defineProperties(Element.prototype, {\n      'setPointerCapture': {\n        value: s\n      },\n      'releasePointerCapture': {\n        value: r\n      }\n    });\n  }\n})(window.PointerEventsPolyfill);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n  /**\n   * This class contains the gesture recognizers that create the PointerGesture\n   * events.\n   *\n   * @class PointerGestures\n   * @static\n   */\n  scope = scope || {};\n  scope.utils = {\n    LCA: {\n      // Determines the lowest node in the ancestor chain of a and b\n      find: function(a, b) {\n        if (a === b) {\n          return a;\n        }\n        // fast case, a is a direct descendant of b or vice versa\n        if (a.contains) {\n          if (a.contains(b)) {\n            return a;\n          }\n          if (b.contains(a)) {\n            return b;\n          }\n        }\n        var adepth = this.depth(a);\n        var bdepth = this.depth(b);\n        var d = adepth - bdepth;\n        if (d > 0) {\n          a = this.walk(a, d);\n        } else {\n          b = this.walk(b, -d);\n        }\n        while(a && b && a !== b) {\n          a = this.walk(a, 1);\n          b = this.walk(b, 1);\n        }\n        return a;\n      },\n      walk: function(n, u) {\n        for (var i = 0; i < u; i++) {\n          n = n.parentNode;\n        }\n        return n;\n      },\n      depth: function(n) {\n        var d = 0;\n        while(n) {\n          d++;\n          n = n.parentNode;\n        }\n        return d;\n      }\n    }\n  };\n  scope.findLCA = function(a, b) {\n    return scope.utils.LCA.find(a, b);\n  }\n  window.PointerGestures = scope;\n})(window.PointerGestures);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This module implements an map of pointer states\n */\n(function(scope) {\n  var USE_MAP = window.Map && window.Map.prototype.forEach;\n  var POINTERS_FN = function(){ return this.size; };\n  function PointerMap() {\n    if (USE_MAP) {\n      var m = new Map();\n      m.pointers = POINTERS_FN;\n      return m;\n    } else {\n      this.keys = [];\n      this.values = [];\n    }\n  }\n\n  PointerMap.prototype = {\n    set: function(inId, inEvent) {\n      var i = this.keys.indexOf(inId);\n      if (i > -1) {\n        this.values[i] = inEvent;\n      } else {\n        this.keys.push(inId);\n        this.values.push(inEvent);\n      }\n    },\n    has: function(inId) {\n      return this.keys.indexOf(inId) > -1;\n    },\n    'delete': function(inId) {\n      var i = this.keys.indexOf(inId);\n      if (i > -1) {\n        this.keys.splice(i, 1);\n        this.values.splice(i, 1);\n      }\n    },\n    get: function(inId) {\n      var i = this.keys.indexOf(inId);\n      return this.values[i];\n    },\n    clear: function() {\n      this.keys.length = 0;\n      this.values.length = 0;\n    },\n    // return value, key, map\n    forEach: function(callback, thisArg) {\n      this.values.forEach(function(v, i) {\n        callback.call(thisArg, v, this.keys[i], this);\n      }, this);\n    },\n    pointers: function() {\n      return this.keys.length;\n    }\n  };\n\n  scope.PointerMap = PointerMap;\n})(window.PointerGestures);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n(function(scope) {\n  var CLONE_PROPS = [\n    // MouseEvent\n    'bubbles',\n    'cancelable',\n    'view',\n    'detail',\n    'screenX',\n    'screenY',\n    'clientX',\n    'clientY',\n    'ctrlKey',\n    'altKey',\n    'shiftKey',\n    'metaKey',\n    'button',\n    'relatedTarget',\n    // DOM Level 3\n    'buttons',\n    // PointerEvent\n    'pointerId',\n    'width',\n    'height',\n    'pressure',\n    'tiltX',\n    'tiltY',\n    'pointerType',\n    'hwTimestamp',\n    'isPrimary',\n    // event instance\n    'type',\n    'target',\n    'currentTarget',\n    'screenX',\n    'screenY',\n    'pageX',\n    'pageY',\n    'tapPrevented'\n  ];\n\n  var CLONE_DEFAULTS = [\n    // MouseEvent\n    false,\n    false,\n    null,\n    null,\n    0,\n    0,\n    0,\n    0,\n    false,\n    false,\n    false,\n    false,\n    0,\n    null,\n    // DOM Level 3\n    0,\n    // PointerEvent\n    0,\n    0,\n    0,\n    0,\n    0,\n    0,\n    '',\n    0,\n    false,\n    // event instance\n    '',\n    null,\n    null,\n    0,\n    0,\n    0,\n    0\n  ];\n\n  var dispatcher = {\n    handledEvents: new WeakMap(),\n    targets: new WeakMap(),\n    handlers: {},\n    recognizers: {},\n    events: {},\n    // Add a new gesture recognizer to the event listeners.\n    // Recognizer needs an `events` property.\n    registerRecognizer: function(inName, inRecognizer) {\n      var r = inRecognizer;\n      this.recognizers[inName] = r;\n      r.events.forEach(function(e) {\n        if (r[e]) {\n          this.events[e] = true;\n          var f = r[e].bind(r);\n          this.addHandler(e, f);\n        }\n      }, this);\n    },\n    addHandler: function(inEvent, inFn) {\n      var e = inEvent;\n      if (!this.handlers[e]) {\n        this.handlers[e] = [];\n      }\n      this.handlers[e].push(inFn);\n    },\n    // add event listeners for inTarget\n    registerTarget: function(inTarget) {\n      this.listen(Object.keys(this.events), inTarget);\n    },\n    // remove event listeners for inTarget\n    unregisterTarget: function(inTarget) {\n      this.unlisten(Object.keys(this.events), inTarget);\n    },\n    // LISTENER LOGIC\n    eventHandler: function(inEvent) {\n      if (this.handledEvents.get(inEvent)) {\n        return;\n      }\n      var type = inEvent.type, fns = this.handlers[type];\n      if (fns) {\n        this.makeQueue(fns, inEvent);\n      }\n      this.handledEvents.set(inEvent, true);\n    },\n    // queue event for async dispatch\n    makeQueue: function(inHandlerFns, inEvent) {\n      // must clone events to keep the (possibly shadowed) target correct for\n      // async dispatching\n      var e = this.cloneEvent(inEvent);\n      setTimeout(this.runQueue.bind(this, inHandlerFns, e), 0);\n    },\n    // Dispatch the queued events\n    runQueue: function(inHandlers, inEvent) {\n      this.currentPointerId = inEvent.pointerId;\n      for (var i = 0, f, l = inHandlers.length; (i < l) && (f = inHandlers[i]); i++) {\n        f(inEvent);\n      }\n      this.currentPointerId = 0;\n    },\n    // set up event listeners\n    listen: function(inEvents, inTarget) {\n      inEvents.forEach(function(e) {\n        this.addEvent(e, this.boundHandler, false, inTarget);\n      }, this);\n    },\n    // remove event listeners\n    unlisten: function(inEvents) {\n      inEvents.forEach(function(e) {\n        this.removeEvent(e, this.boundHandler, false, inTarget);\n      }, this);\n    },\n    addEvent: function(inEventName, inEventHandler, inCapture, inTarget) {\n      inTarget.addEventListener(inEventName, inEventHandler, inCapture);\n    },\n    removeEvent: function(inEventName, inEventHandler, inCapture, inTarget) {\n      inTarget.removeEventListener(inEventName, inEventHandler, inCapture);\n    },\n    // EVENT CREATION AND TRACKING\n    // Creates a new Event of type `inType`, based on the information in\n    // `inEvent`.\n    makeEvent: function(inType, inDict) {\n      return new PointerGestureEvent(inType, inDict);\n    },\n    /*\n     * Returns a snapshot of inEvent, with writable properties.\n     *\n     * @method cloneEvent\n     * @param {Event} inEvent An event that contains properties to copy.\n     * @return {Object} An object containing shallow copies of `inEvent`'s\n     *    properties.\n     */\n    cloneEvent: function(inEvent) {\n      var eventCopy = {}, p;\n      for (var i = 0; i < CLONE_PROPS.length; i++) {\n        p = CLONE_PROPS[i];\n        eventCopy[p] = inEvent[p] || CLONE_DEFAULTS[i];\n      }\n      return eventCopy;\n    },\n    // Dispatches the event to its target.\n    dispatchEvent: function(inEvent, inTarget) {\n      var t = inTarget || this.targets.get(inEvent);\n      if (t) {\n        t.dispatchEvent(inEvent);\n        if (inEvent.tapPrevented) {\n          this.preventTap(this.currentPointerId);\n        }\n      }\n    },\n    asyncDispatchEvent: function(inEvent, inTarget) {\n      var fn = function() {\n        this.dispatchEvent(inEvent, inTarget);\n      }.bind(this);\n      setTimeout(fn, 0);\n    },\n    preventTap: function(inPointerId) {\n      var t = this.recognizers.tap;\n      if (t){\n        t.preventTap(inPointerId);\n      }\n    }\n  };\n  dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher);\n  scope.dispatcher = dispatcher;\n  var registerQueue = [];\n  var immediateRegister = false;\n  /**\n   * Enable gesture events for a given scope, typically\n   * [ShadowRoots](https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#shadow-root-object).\n   *\n   * @for PointerGestures\n   * @method register\n   * @param {ShadowRoot} scope A top level scope to enable gesture\n   * support on.\n   */\n  scope.register = function(inScope) {\n    if (immediateRegister) {\n      var pe = window.PointerEventsPolyfill;\n      if (pe) {\n        pe.register(inScope);\n      }\n      scope.dispatcher.registerTarget(inScope);\n    } else {\n      registerQueue.push(inScope);\n    }\n  };\n  // wait to register scopes until recognizers load\n  document.addEventListener('DOMContentLoaded', function() {\n    immediateRegister = true;\n    registerQueue.push(document);\n    registerQueue.forEach(scope.register);\n  });\n})(window.PointerGestures);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This event is fired when a pointer is held down for 200ms.\n *\n * @module PointerGestures\n * @submodule Events\n * @class hold\n */\n/**\n * Milliseconds pointer has been held down.\n * @type Number\n * @property holdTime\n */\n/**\n * Type of pointer that made the holding event.\n * @type String\n * @property pointerType\n */\n/**\n * This event is fired every 200ms while a pointer is held down.\n *\n * @class holdpulse\n * @extends hold\n */\n/**\n * This event is fired when a held pointer is released or moved.\n *\n * @class released\n */\n/**\n * Type of pointer that made the holding event.\n * @type String\n * @property pointerType\n */\n\n(function(scope) {\n  var dispatcher = scope.dispatcher;\n  var hold = {\n    // wait at least HOLD_DELAY ms between hold and pulse events\n    HOLD_DELAY: 200,\n    // pointer can move WIGGLE_THRESHOLD pixels before not counting as a hold\n    WIGGLE_THRESHOLD: 16,\n    events: [\n      'pointerdown',\n      'pointermove',\n      'pointerup',\n      'pointercancel'\n    ],\n    heldPointer: null,\n    holdJob: null,\n    pulse: function() {\n      var hold = Date.now() - this.heldPointer.timeStamp;\n      var type = this.held ? 'holdpulse' : 'hold';\n      this.fireHold(type, hold);\n      this.held = true;\n    },\n    cancel: function() {\n      clearInterval(this.holdJob);\n      if (this.held) {\n        this.fireHold('release');\n      }\n      this.held = false;\n      this.heldPointer = null;\n      this.target = null;\n      this.holdJob = null;\n    },\n    pointerdown: function(inEvent) {\n      if (inEvent.isPrimary && !this.heldPointer) {\n        this.heldPointer = inEvent;\n        this.target = inEvent.target;\n        this.holdJob = setInterval(this.pulse.bind(this), this.HOLD_DELAY);\n      }\n    },\n    pointerup: function(inEvent) {\n      if (this.heldPointer && this.heldPointer.pointerId === inEvent.pointerId) {\n        this.cancel();\n      }\n    },\n    pointercancel: function(inEvent) {\n      this.cancel();\n    },\n    pointermove: function(inEvent) {\n      if (this.heldPointer && this.heldPointer.pointerId === inEvent.pointerId) {\n        var x = inEvent.clientX - this.heldPointer.clientX;\n        var y = inEvent.clientY - this.heldPointer.clientY;\n        if ((x * x + y * y) > this.WIGGLE_THRESHOLD) {\n          this.cancel();\n        }\n      }\n    },\n    fireHold: function(inType, inHoldTime) {\n      var p = {\n        pointerType: this.heldPointer.pointerType\n      };\n      if (inHoldTime) {\n        p.holdTime = inHoldTime;\n      }\n      var e = dispatcher.makeEvent(inType, p);\n      dispatcher.dispatchEvent(e, this.target);\n      if (e.tapPrevented) {\n        dispatcher.preventTap(this.heldPointer.pointerId);\n      }\n    }\n  };\n  dispatcher.registerRecognizer('hold', hold);\n})(window.PointerGestures);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This event denotes the beginning of a series of tracking events.\n *\n * @module PointerGestures\n * @submodule Events\n * @class trackstart\n */\n/**\n * Pixels moved in the x direction since trackstart.\n * @type Number\n * @property dx\n */\n/**\n * Pixes moved in the y direction since trackstart.\n * @type Number\n * @property dy\n */\n/**\n * Pixels moved in the x direction since the last track.\n * @type Number\n * @property ddx\n */\n/**\n * Pixles moved in the y direction since the last track.\n * @type Number\n * @property ddy\n */\n/**\n * The clientX position of the track gesture.\n * @type Number\n * @property clientX\n */\n/**\n * The clientY position of the track gesture.\n * @type Number\n * @property clientY\n */\n/**\n * The pageX position of the track gesture.\n * @type Number\n * @property pageX\n */\n/**\n * The pageY position of the track gesture.\n * @type Number\n * @property pageY\n */\n/**\n * The screenX position of the track gesture.\n * @type Number\n * @property screenX\n */\n/**\n * The screenY position of the track gesture.\n * @type Number\n * @property screenY\n */\n/**\n * The last x axis direction of the pointer.\n * @type Number\n * @property xDirection\n */\n/**\n * The last y axis direction of the pointer.\n * @type Number\n * @property yDirection\n */\n/**\n * A shared object between all tracking events.\n * @type Object\n * @property trackInfo\n */\n/**\n * The element currently under the pointer.\n * @type Element\n * @property relatedTarget\n */\n/**\n * The type of pointer that make the track gesture.\n * @type String\n * @property pointerType\n */\n/**\n *\n * This event fires for all pointer movement being tracked.\n *\n * @class track\n * @extends trackstart\n */\n/**\n * This event fires when the pointer is no longer being tracked.\n *\n * @class trackend\n * @extends trackstart\n */\n\n (function(scope) {\n   var dispatcher = scope.dispatcher;\n   var pointermap = new scope.PointerMap();\n   var track = {\n     events: [\n       'pointerdown',\n       'pointermove',\n       'pointerup',\n       'pointercancel'\n     ],\n     WIGGLE_THRESHOLD: 4,\n     clampDir: function(inDelta) {\n       return inDelta > 0 ? 1 : -1;\n     },\n     calcPositionDelta: function(inA, inB) {\n       var x = 0, y = 0;\n       if (inA && inB) {\n         x = inB.pageX - inA.pageX;\n         y = inB.pageY - inA.pageY;\n       }\n       return {x: x, y: y};\n     },\n     fireTrack: function(inType, inEvent, inTrackingData) {\n       var t = inTrackingData;\n       var d = this.calcPositionDelta(t.downEvent, inEvent);\n       var dd = this.calcPositionDelta(t.lastMoveEvent, inEvent);\n       if (dd.x) {\n         t.xDirection = this.clampDir(dd.x);\n       }\n       if (dd.y) {\n         t.yDirection = this.clampDir(dd.y);\n       }\n       var trackData = {\n         dx: d.x,\n         dy: d.y,\n         ddx: dd.x,\n         ddy: dd.y,\n         clientX: inEvent.clientX,\n         clientY: inEvent.clientY,\n         pageX: inEvent.pageX,\n         pageY: inEvent.pageY,\n         screenX: inEvent.screenX,\n         screenY: inEvent.screenY,\n         xDirection: t.xDirection,\n         yDirection: t.yDirection,\n         trackInfo: t.trackInfo,\n         relatedTarget: inEvent.target,\n         pointerType: inEvent.pointerType\n       };\n       var e = dispatcher.makeEvent(inType, trackData);\n       t.lastMoveEvent = inEvent;\n       dispatcher.dispatchEvent(e, t.downTarget);\n     },\n     pointerdown: function(inEvent) {\n       if (inEvent.isPrimary && (inEvent.pointerType === 'mouse' ? inEvent.buttons === 1 : true)) {\n         var p = {\n           downEvent: inEvent,\n           downTarget: inEvent.target,\n           trackInfo: {},\n           lastMoveEvent: null,\n           xDirection: 0,\n           yDirection: 0,\n           tracking: false\n         };\n         pointermap.set(inEvent.pointerId, p);\n       }\n     },\n     pointermove: function(inEvent) {\n       var p = pointermap.get(inEvent.pointerId);\n       if (p) {\n         if (!p.tracking) {\n           var d = this.calcPositionDelta(p.downEvent, inEvent);\n           var move = d.x * d.x + d.y * d.y;\n           // start tracking only if finger moves more than WIGGLE_THRESHOLD\n           if (move > this.WIGGLE_THRESHOLD) {\n             p.tracking = true;\n             this.fireTrack('trackstart', p.downEvent, p);\n             this.fireTrack('track', inEvent, p);\n           }\n         } else {\n           this.fireTrack('track', inEvent, p);\n         }\n       }\n     },\n     pointerup: function(inEvent) {\n       var p = pointermap.get(inEvent.pointerId);\n       if (p) {\n         if (p.tracking) {\n           this.fireTrack('trackend', inEvent, p);\n         }\n         pointermap.delete(inEvent.pointerId);\n       }\n     },\n     pointercancel: function(inEvent) {\n       this.pointerup(inEvent);\n     }\n   };\n   dispatcher.registerRecognizer('track', track);\n })(window.PointerGestures);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This event denotes a rapid down/move/up sequence from a pointer.\n *\n * The event is sent to the first element the pointer went down on.\n *\n * @module PointerGestures\n * @submodule Events\n * @class flick\n */\n/**\n * Signed velocity of the flick in the x direction.\n * @property xVelocity\n * @type Number\n */\n/**\n * Signed velocity of the flick in the y direction.\n * @type Number\n * @property yVelocity\n */\n/**\n * Unsigned total velocity of the flick.\n * @type Number\n * @property velocity\n */\n/**\n * Angle of the flick in degrees, with 0 along the\n * positive x axis.\n * @type Number\n * @property angle\n */\n/**\n * Axis with the greatest absolute velocity. Denoted\n * with 'x' or 'y'.\n * @type String\n * @property majorAxis\n */\n/**\n * Type of the pointer that made the flick.\n * @type String\n * @property pointerType\n */\n\n(function(scope) {\n  var dispatcher = scope.dispatcher;\n  var flick = {\n    // TODO(dfreedman): value should be low enough for low speed flicks, but\n    // high enough to remove accidental flicks\n    MIN_VELOCITY: 0.5 /* px/ms */,\n    MAX_QUEUE: 4,\n    moveQueue: [],\n    target: null,\n    pointerId: null,\n    events: [\n      'pointerdown',\n      'pointermove',\n      'pointerup',\n      'pointercancel'\n    ],\n    pointerdown: function(inEvent) {\n      if (inEvent.isPrimary && !this.pointerId) {\n        this.pointerId = inEvent.pointerId;\n        this.target = inEvent.target;\n        this.addMove(inEvent);\n      }\n    },\n    pointermove: function(inEvent) {\n      if (inEvent.pointerId === this.pointerId) {\n        this.addMove(inEvent);\n      }\n    },\n    pointerup: function(inEvent) {\n      if (inEvent.pointerId === this.pointerId) {\n        this.fireFlick(inEvent);\n      }\n      this.cleanup();\n    },\n    pointercancel: function(inEvent) {\n      this.cleanup();\n    },\n    cleanup: function() {\n      this.moveQueue = [];\n      this.target = null;\n      this.pointerId = null;\n    },\n    addMove: function(inEvent) {\n      if (this.moveQueue.length >= this.MAX_QUEUE) {\n        this.moveQueue.shift();\n      }\n      this.moveQueue.push(inEvent);\n    },\n    fireFlick: function(inEvent) {\n      var e = inEvent;\n      var l = this.moveQueue.length;\n      var dt, dx, dy, tx, ty, tv, x = 0, y = 0, v = 0;\n      // flick based off the fastest segment of movement\n      for (var i = 0, m; i < l && (m = this.moveQueue[i]); i++) {\n        dt = e.timeStamp - m.timeStamp;\n        dx = e.clientX - m.clientX, dy = e.clientY - m.clientY;\n        tx = dx / dt, ty = dy / dt, tv = Math.sqrt(tx * tx + ty * ty);\n        if (tv > v) {\n          x = tx, y = ty, v = tv;\n        }\n      }\n      var ma = Math.abs(x) > Math.abs(y) ? 'x' : 'y';\n      var a = this.calcAngle(x, y);\n      if (Math.abs(v) >= this.MIN_VELOCITY) {\n        var ev = dispatcher.makeEvent('flick', {\n          xVelocity: x,\n          yVelocity: y,\n          velocity: v,\n          angle: a,\n          majorAxis: ma,\n          pointerType: inEvent.pointerType\n        });\n        dispatcher.dispatchEvent(ev, this.target);\n      }\n    },\n    calcAngle: function(inX, inY) {\n      return (Math.atan2(inY, inX) * 180 / Math.PI);\n    }\n  };\n  dispatcher.registerRecognizer('flick', flick);\n})(window.PointerGestures);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/*\n * Basic strategy: find the farthest apart points, use as diameter of circle\n * react to size change and rotation of the chord\n */\n\n/**\n * @module PointerGestures\n * @submodule Events\n * @class pinch\n */\n/**\n * Scale of the pinch zoom gesture\n * @property scale\n * @type Number\n */\n/**\n * Center X position of pointers causing pinch\n * @property centerX\n * @type Number\n */\n/**\n * Center Y position of pointers causing pinch\n * @property centerY\n * @type Number\n */\n\n/**\n * @module PointerGestures\n * @submodule Events\n * @class rotate\n */\n/**\n * Angle (in degrees) of rotation. Measured from starting positions of pointers.\n * @property angle\n * @type Number\n */\n/**\n * Center X position of pointers causing rotation\n * @property centerX\n * @type Number\n */\n/**\n * Center Y position of pointers causing rotation\n * @property centerY\n * @type Number\n */\n(function(scope) {\n  var dispatcher = scope.dispatcher;\n  var pointermap = new scope.PointerMap();\n  var RAD_TO_DEG = 180 / Math.PI;\n  var pinch = {\n    events: [\n      'pointerdown',\n      'pointermove',\n      'pointerup',\n      'pointercancel'\n    ],\n    reference: {},\n    pointerdown: function(ev) {\n      pointermap.set(ev.pointerId, ev);\n      if (pointermap.pointers() == 2) {\n        var points = this.calcChord();\n        var angle = this.calcAngle(points);\n        this.reference = {\n          angle: angle,\n          diameter: points.diameter,\n          target: scope.findLCA(points.a.target, points.b.target)\n        };\n      }\n    },\n    pointerup: function(ev) {\n      pointermap.delete(ev.pointerId);\n    },\n    pointermove: function(ev) {\n      if (pointermap.has(ev.pointerId)) {\n        pointermap.set(ev.pointerId, ev);\n        if (pointermap.pointers() > 1) {\n          this.calcPinchRotate();\n        }\n      }\n    },\n    pointercancel: function(ev) {\n      this.pointerup(ev);\n    },\n    dispatchPinch: function(diameter, points) {\n      var zoom = diameter / this.reference.diameter;\n      var ev = dispatcher.makeEvent('pinch', {\n        scale: zoom,\n        centerX: points.center.x,\n        centerY: points.center.y\n      });\n      dispatcher.dispatchEvent(ev, this.reference.target);\n    },\n    dispatchRotate: function(angle, points) {\n      var diff = Math.round((angle - this.reference.angle) % 360);\n      var ev = dispatcher.makeEvent('rotate', {\n        angle: diff,\n        centerX: points.center.x,\n        centerY: points.center.y\n      });\n      dispatcher.dispatchEvent(ev, this.reference.target);\n    },\n    calcPinchRotate: function() {\n      var points = this.calcChord();\n      var diameter = points.diameter;\n      var angle = this.calcAngle(points);\n      if (diameter != this.reference.diameter) {\n        this.dispatchPinch(diameter, points);\n      }\n      if (angle != this.reference.angle) {\n        this.dispatchRotate(angle, points);\n      }\n    },\n    calcChord: function() {\n      var pointers = [];\n      pointermap.forEach(function(p) {\n        pointers.push(p);\n      });\n      var dist = 0;\n      var points = {};\n      var x, y, d;\n      for (var i = 0; i < pointers.length; i++) {\n        var a = pointers[i];\n        for (var j = i + 1; j < pointers.length; j++) {\n          var b = pointers[j];\n          x = Math.abs(a.clientX - b.clientX);\n          y = Math.abs(a.clientY - b.clientY);\n          d = x + y;\n          if (d > dist) {\n            dist = d;\n            points = {a: a, b: b};\n          }\n        }\n      }\n      x = Math.abs(points.a.clientX + points.b.clientX) / 2;\n      y = Math.abs(points.a.clientY + points.b.clientY) / 2;\n      points.center = { x: x, y: y };\n      points.diameter = dist;\n      return points;\n    },\n    calcAngle: function(points) {\n      var x = points.a.clientX - points.b.clientX;\n      var y = points.a.clientY - points.b.clientY;\n      return (360 + Math.atan2(y, x) * RAD_TO_DEG) % 360;\n    },\n  };\n  dispatcher.registerRecognizer('pinch', pinch);\n})(window.PointerGestures);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This event is fired when a pointer quickly goes down and up, and is used to\n * denote activation.\n *\n * Any gesture event can prevent the tap event from being created by calling\n * `event.preventTap`.\n *\n * Any pointer event can prevent the tap by setting the `tapPrevented` property\n * on itself.\n *\n * @module PointerGestures\n * @submodule Events\n * @class tap\n */\n/**\n * X axis position of the tap.\n * @property x\n * @type Number\n */\n/**\n * Y axis position of the tap.\n * @property y\n * @type Number\n */\n/**\n * Type of the pointer that made the tap.\n * @property pointerType\n * @type String\n */\n(function(scope) {\n  var dispatcher = scope.dispatcher;\n  var pointermap = new scope.PointerMap();\n  var tap = {\n    events: [\n      'pointerdown',\n      'pointermove',\n      'pointerup',\n      'pointercancel',\n      'keyup'\n    ],\n    pointerdown: function(inEvent) {\n      if (inEvent.isPrimary && !inEvent.tapPrevented) {\n        pointermap.set(inEvent.pointerId, {\n          target: inEvent.target,\n          x: inEvent.clientX,\n          y: inEvent.clientY\n        });\n      }\n    },\n    pointermove: function(inEvent) {\n      if (inEvent.isPrimary) {\n        var start = pointermap.get(inEvent.pointerId);\n        if (start) {\n          if (inEvent.tapPrevented) {\n            pointermap.delete(inEvent.pointerId);\n          }\n        }\n      }\n    },\n    pointerup: function(inEvent) {\n      var start = pointermap.get(inEvent.pointerId);\n      if (start && !inEvent.tapPrevented) {\n        var t = scope.findLCA(start.target, inEvent.target);\n        if (t) {\n          var e = dispatcher.makeEvent('tap', {\n            x: inEvent.clientX,\n            y: inEvent.clientY,\n            detail: inEvent.detail,\n            pointerType: inEvent.pointerType\n          });\n          dispatcher.dispatchEvent(e, t);\n        }\n      }\n      pointermap.delete(inEvent.pointerId);\n    },\n    pointercancel: function(inEvent) {\n      pointermap.delete(inEvent.pointerId);\n    },\n    keyup: function(inEvent) {\n      var code = inEvent.keyCode;\n      // 32 == spacebar\n      if (code === 32) {\n        var t = inEvent.target;\n        if (!(t instanceof HTMLInputElement || t instanceof HTMLTextAreaElement)) {\n          dispatcher.dispatchEvent(dispatcher.makeEvent('tap', {\n            x: 0,\n            y: 0,\n            detail: 0,\n            pointerType: 'unavailable'\n          }), t);\n        }\n      }\n    },\n    preventTap: function(inPointerId) {\n      pointermap.delete(inPointerId);\n    }\n  };\n  dispatcher.registerRecognizer('tap', tap);\n})(window.PointerGestures);\n","// Copyright 2011 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n(function(global) {\n  'use strict';\n\n  var filter = Array.prototype.filter.call.bind(Array.prototype.filter);\n\n  function getTreeScope(node) {\n    while (node.parentNode) {\n      node = node.parentNode;\n    }\n\n    return typeof node.getElementById === 'function' ? node : null;\n  }\n\n  // JScript does not have __proto__. We wrap all object literals with\n  // createObject which uses Object.create, Object.defineProperty and\n  // Object.getOwnPropertyDescriptor to create a new object that does the exact\n  // same thing. The main downside to this solution is that we have to extract\n  // all those property descriptors for IE.\n  var createObject = ('__proto__' in {}) ?\n      function(obj) { return obj; } :\n      function(obj) {\n        var proto = obj.__proto__;\n        if (!proto)\n          return obj;\n        var newObject = Object.create(proto);\n        Object.getOwnPropertyNames(obj).forEach(function(name) {\n          Object.defineProperty(newObject, name,\n                               Object.getOwnPropertyDescriptor(obj, name));\n        });\n        return newObject;\n      };\n\n  // IE does not support have Document.prototype.contains.\n  if (typeof document.contains != 'function') {\n    Document.prototype.contains = function(node) {\n      if (node === this || node.parentNode === this)\n        return true;\n      return this.documentElement.contains(node);\n    }\n  }\n\n  Node.prototype.bind = function(name, observable) {\n    console.error('Unhandled binding to Node: ', this, name, observable);\n  };\n\n  function unbind(node, name) {\n    var bindings = node.bindings;\n    if (!bindings) {\n      node.bindings = {};\n      return;\n    }\n\n    var binding = bindings[name];\n    if (!binding)\n      return;\n\n    binding.close();\n    bindings[name] = undefined;\n  }\n\n  Node.prototype.unbind = function(name) {\n    unbind(this, name);\n  };\n\n  Node.prototype.unbindAll = function() {\n    if (!this.bindings)\n      return;\n    var names = Object.keys(this.bindings);\n    for (var i = 0; i < names.length; i++) {\n      var binding = this.bindings[names[i]];\n      if (binding)\n        binding.close();\n    }\n\n    this.bindings = {};\n  };\n\n  function sanitizeValue(value) {\n    return value == null ? '' : value;\n  }\n\n  function updateText(node, value) {\n    node.data = sanitizeValue(value);\n  }\n\n  function textBinding(node) {\n    return function(value) {\n      return updateText(node, value);\n    };\n  }\n\n  Text.prototype.bind = function(name, value, oneTime) {\n    if (name !== 'textContent')\n      return Node.prototype.bind.call(this, name, value, oneTime);\n\n    if (oneTime)\n      return updateText(this, value);\n\n    unbind(this, 'textContent');\n    updateText(this, value.open(textBinding(this)));\n    return this.bindings.textContent = value;\n  }\n\n  function updateAttribute(el, name, conditional, value) {\n    if (conditional) {\n      if (value)\n        el.setAttribute(name, '');\n      else\n        el.removeAttribute(name);\n      return;\n    }\n\n    el.setAttribute(name, sanitizeValue(value));\n  }\n\n  function attributeBinding(el, name, conditional) {\n    return function(value) {\n      updateAttribute(el, name, conditional, value);\n    };\n  }\n\n  Element.prototype.bind = function(name, value, oneTime) {\n    var conditional = name[name.length - 1] == '?';\n    if (conditional) {\n      this.removeAttribute(name);\n      name = name.slice(0, -1);\n    }\n\n    if (oneTime)\n      return updateAttribute(this, name, conditional, value);\n\n    unbind(this, name);\n    updateAttribute(this, name, conditional,\n        value.open(attributeBinding(this, name, conditional)));\n\n    return this.bindings[name] = value;\n  };\n\n  var checkboxEventType;\n  (function() {\n    // Attempt to feature-detect which event (change or click) is fired first\n    // for checkboxes.\n    var div = document.createElement('div');\n    var checkbox = div.appendChild(document.createElement('input'));\n    checkbox.setAttribute('type', 'checkbox');\n    var first;\n    var count = 0;\n    checkbox.addEventListener('click', function(e) {\n      count++;\n      first = first || 'click';\n    });\n    checkbox.addEventListener('change', function() {\n      count++;\n      first = first || 'change';\n    });\n\n    var event = document.createEvent('MouseEvent');\n    event.initMouseEvent(\"click\", true, true, window, 0, 0, 0, 0, 0, false,\n        false, false, false, 0, null);\n    checkbox.dispatchEvent(event);\n    // WebKit/Blink don't fire the change event if the element is outside the\n    // document, so assume 'change' for that case.\n    checkboxEventType = count == 1 ? 'change' : first;\n  })();\n\n  function getEventForInputType(element) {\n    switch (element.type) {\n      case 'checkbox':\n        return checkboxEventType;\n      case 'radio':\n      case 'select-multiple':\n      case 'select-one':\n        return 'change';\n      default:\n        return 'input';\n    }\n  }\n\n  function updateInput(input, property, value, santizeFn) {\n    input[property] = (santizeFn || sanitizeValue)(value);\n  }\n\n  function inputBinding(input, property, santizeFn) {\n    return function(value) {\n      return updateInput(input, property, value, santizeFn);\n    }\n  }\n\n  function noop() {}\n\n  function bindInputEvent(input, property, observable, postEventFn) {\n    var eventType = getEventForInputType(input);\n\n    function eventHandler() {\n      observable.setValue(input[property]);\n      observable.discardChanges();\n      (postEventFn || noop)(input);\n      Platform.performMicrotaskCheckpoint();\n    }\n    input.addEventListener(eventType, eventHandler);\n\n    var capturedClose = observable.close;\n    observable.close = function() {\n      if (!capturedClose)\n        return;\n      input.removeEventListener(eventType, eventHandler);\n\n      observable.close = capturedClose;\n      observable.close();\n      capturedClose = undefined;\n    }\n  }\n\n  function booleanSanitize(value) {\n    return Boolean(value);\n  }\n\n  // |element| is assumed to be an HTMLInputElement with |type| == 'radio'.\n  // Returns an array containing all radio buttons other than |element| that\n  // have the same |name|, either in the form that |element| belongs to or,\n  // if no form, in the document tree to which |element| belongs.\n  //\n  // This implementation is based upon the HTML spec definition of a\n  // \"radio button group\":\n  //   http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state.html#radio-button-group\n  //\n  function getAssociatedRadioButtons(element) {\n    if (element.form) {\n      return filter(element.form.elements, function(el) {\n        return el != element &&\n            el.tagName == 'INPUT' &&\n            el.type == 'radio' &&\n            el.name == element.name;\n      });\n    } else {\n      var treeScope = getTreeScope(element);\n      if (!treeScope)\n        return [];\n      var radios = treeScope.querySelectorAll(\n          'input[type=\"radio\"][name=\"' + element.name + '\"]');\n      return filter(radios, function(el) {\n        return el != element && !el.form;\n      });\n    }\n  }\n\n  function checkedPostEvent(input) {\n    // Only the radio button that is getting checked gets an event. We\n    // therefore find all the associated radio buttons and update their\n    // check binding manually.\n    if (input.tagName === 'INPUT' &&\n        input.type === 'radio') {\n      getAssociatedRadioButtons(input).forEach(function(radio) {\n        var checkedBinding = radio.bindings.checked;\n        if (checkedBinding) {\n          // Set the value directly to avoid an infinite call stack.\n          checkedBinding.setValue(false);\n        }\n      });\n    }\n  }\n\n  HTMLInputElement.prototype.bind = function(name, value, oneTime) {\n    if (name !== 'value' && name !== 'checked')\n      return HTMLElement.prototype.bind.call(this, name, value, oneTime);\n\n\n    this.removeAttribute(name);\n    var sanitizeFn = name == 'checked' ? booleanSanitize : sanitizeValue;\n    var postEventFn = name == 'checked' ? checkedPostEvent : noop;\n\n    if (oneTime)\n      return updateInput(this, name, value, sanitizeFn);\n\n    unbind(this, name);\n    bindInputEvent(this, name, value, postEventFn);\n    updateInput(this, name,\n                value.open(inputBinding(this, name, sanitizeFn)),\n                sanitizeFn);\n\n    return this.bindings[name] = value;\n  }\n\n  HTMLTextAreaElement.prototype.bind = function(name, value, oneTime) {\n    if (name !== 'value')\n      return HTMLElement.prototype.bind.call(this, name, value, oneTime);\n\n    this.removeAttribute('value');\n\n    if (oneTime)\n      return updateInput(this, 'value', value);\n\n    unbind(this, 'value');\n    bindInputEvent(this, 'value', value);\n    updateInput(this, 'value',\n                value.open(inputBinding(this, 'value', sanitizeValue)));\n\n    return this.bindings.value = value;\n  }\n\n  function updateOption(option, value) {\n    var parentNode = option.parentNode;;\n    var select;\n    var selectBinding;\n    var oldValue;\n    if (parentNode instanceof HTMLSelectElement &&\n        parentNode.bindings &&\n        parentNode.bindings.value) {\n      select = parentNode;\n      selectBinding = select.bindings.value;\n      oldValue = select.value;\n    }\n\n    option.value = sanitizeValue(value);\n\n    if (select && select.value != oldValue) {\n      selectBinding.setValue(select.value);\n      selectBinding.discardChanges();\n      Platform.performMicrotaskCheckpoint();\n    }\n  }\n\n  function optionBinding(option) {\n    return function(value) {\n      updateOption(option, value);\n    }\n  }\n\n  HTMLOptionElement.prototype.bind = function(name, value, oneTime) {\n    if (name !== 'value')\n      return HTMLElement.prototype.bind.call(this, name, value, oneTime);\n\n    this.removeAttribute('value');\n\n    if (oneTime)\n      return updateOption(this, value);\n\n    unbind(this, 'value');\n    bindInputEvent(this, 'value', value);\n    updateOption(this, value.open(optionBinding(this)));\n    return this.bindings.value = value;\n  }\n\n  HTMLSelectElement.prototype.bind = function(name, value, oneTime) {\n    if (name === 'selectedindex')\n      name = 'selectedIndex';\n\n    if (name !== 'selectedIndex' && name !== 'value')\n      return HTMLElement.prototype.bind.call(this, name, value, oneTime);\n\n    this.removeAttribute(name);\n\n    if (oneTime)\n      return updateInput(this, name, value);\n\n    unbind(this, name);\n    bindInputEvent(this, name, value);\n    updateInput(this, name,\n                value.open(inputBinding(this, name)));\n    return this.bindings[name] = value;\n  }\n})(this);\n","// Copyright 2011 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n(function(global) {\n  'use strict';\n\n  function assert(v) {\n    if (!v)\n      throw new Error('Assertion failed');\n  }\n\n  var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);\n\n  function getFragmentRoot(node) {\n    var p;\n    while (p = node.parentNode) {\n      node = p;\n    }\n\n    return node;\n  }\n\n  function searchRefId(node, id) {\n    if (!id)\n      return;\n\n    var ref;\n    var selector = '#' + id;\n    while (!ref) {\n      node = getFragmentRoot(node);\n\n      if (node.protoContent_)\n        ref = node.protoContent_.querySelector(selector);\n      else if (node.getElementById)\n        ref = node.getElementById(id);\n\n      if (ref || !node.templateCreator_)\n        break\n\n      node = node.templateCreator_;\n    }\n\n    return ref;\n  }\n\n  function getInstanceRoot(node) {\n    while (node.parentNode) {\n      node = node.parentNode;\n    }\n    return node.templateCreator_ ? node : null;\n  }\n\n  var Map;\n  if (global.Map && typeof global.Map.prototype.forEach === 'function') {\n    Map = global.Map;\n  } else {\n    Map = function() {\n      this.keys = [];\n      this.values = [];\n    };\n\n    Map.prototype = {\n      set: function(key, value) {\n        var index = this.keys.indexOf(key);\n        if (index < 0) {\n          this.keys.push(key);\n          this.values.push(value);\n        } else {\n          this.values[index] = value;\n        }\n      },\n\n      get: function(key) {\n        var index = this.keys.indexOf(key);\n        if (index < 0)\n          return;\n\n        return this.values[index];\n      },\n\n      delete: function(key, value) {\n        var index = this.keys.indexOf(key);\n        if (index < 0)\n          return false;\n\n        this.keys.splice(index, 1);\n        this.values.splice(index, 1);\n        return true;\n      },\n\n      forEach: function(f, opt_this) {\n        for (var i = 0; i < this.keys.length; i++)\n          f.call(opt_this || this, this.values[i], this.keys[i], this);\n      }\n    };\n  }\n\n  // JScript does not have __proto__. We wrap all object literals with\n  // createObject which uses Object.create, Object.defineProperty and\n  // Object.getOwnPropertyDescriptor to create a new object that does the exact\n  // same thing. The main downside to this solution is that we have to extract\n  // all those property descriptors for IE.\n  var createObject = ('__proto__' in {}) ?\n      function(obj) { return obj; } :\n      function(obj) {\n        var proto = obj.__proto__;\n        if (!proto)\n          return obj;\n        var newObject = Object.create(proto);\n        Object.getOwnPropertyNames(obj).forEach(function(name) {\n          Object.defineProperty(newObject, name,\n                               Object.getOwnPropertyDescriptor(obj, name));\n        });\n        return newObject;\n      };\n\n  // IE does not support have Document.prototype.contains.\n  if (typeof document.contains != 'function') {\n    Document.prototype.contains = function(node) {\n      if (node === this || node.parentNode === this)\n        return true;\n      return this.documentElement.contains(node);\n    }\n  }\n\n  var BIND = 'bind';\n  var REPEAT = 'repeat';\n  var IF = 'if';\n\n  var templateAttributeDirectives = {\n    'template': true,\n    'repeat': true,\n    'bind': true,\n    'ref': true\n  };\n\n  var semanticTemplateElements = {\n    'THEAD': true,\n    'TBODY': true,\n    'TFOOT': true,\n    'TH': true,\n    'TR': true,\n    'TD': true,\n    'COLGROUP': true,\n    'COL': true,\n    'CAPTION': true,\n    'OPTION': true,\n    'OPTGROUP': true\n  };\n\n  var hasTemplateElement = typeof HTMLTemplateElement !== 'undefined';\n\n  var allTemplatesSelectors = 'template, ' +\n      Object.keys(semanticTemplateElements).map(function(tagName) {\n        return tagName.toLowerCase() + '[template]';\n      }).join(', ');\n\n  function isSVGTemplate(el) {\n    return el.tagName == 'template' &&\n           el.namespaceURI == 'http://www.w3.org/2000/svg';\n  }\n\n  function isHTMLTemplate(el) {\n    return el.tagName == 'TEMPLATE' &&\n           el.namespaceURI == 'http://www.w3.org/1999/xhtml';\n  }\n\n  function isAttributeTemplate(el) {\n    return Boolean(semanticTemplateElements[el.tagName] &&\n                   el.hasAttribute('template'));\n  }\n\n  function isTemplate(el) {\n    if (el.isTemplate_ === undefined)\n      el.isTemplate_ = el.tagName == 'TEMPLATE' || isAttributeTemplate(el);\n\n    return el.isTemplate_;\n  }\n\n  // FIXME: Observe templates being added/removed from documents\n  // FIXME: Expose imperative API to decorate and observe templates in\n  // \"disconnected tress\" (e.g. ShadowRoot)\n  document.addEventListener('DOMContentLoaded', function(e) {\n    bootstrapTemplatesRecursivelyFrom(document);\n    // FIXME: Is this needed? Seems like it shouldn't be.\n    Platform.performMicrotaskCheckpoint();\n  }, false);\n\n  function forAllTemplatesFrom(node, fn) {\n    var subTemplates = node.querySelectorAll(allTemplatesSelectors);\n\n    if (isTemplate(node))\n      fn(node)\n    forEach(subTemplates, fn);\n  }\n\n  function bootstrapTemplatesRecursivelyFrom(node) {\n    function bootstrap(template) {\n      if (!HTMLTemplateElement.decorate(template))\n        bootstrapTemplatesRecursivelyFrom(template.content);\n    }\n\n    forAllTemplatesFrom(node, bootstrap);\n  }\n\n  if (!hasTemplateElement) {\n    /**\n     * This represents a <template> element.\n     * @constructor\n     * @extends {HTMLElement}\n     */\n    global.HTMLTemplateElement = function() {\n      throw TypeError('Illegal constructor');\n    };\n  }\n\n  var hasProto = '__proto__' in {};\n\n  function mixin(to, from) {\n    Object.getOwnPropertyNames(from).forEach(function(name) {\n      Object.defineProperty(to, name,\n                            Object.getOwnPropertyDescriptor(from, name));\n    });\n  }\n\n  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner\n  function getOrCreateTemplateContentsOwner(template) {\n    var doc = template.ownerDocument\n    if (!doc.defaultView)\n      return doc;\n    var d = doc.templateContentsOwner_;\n    if (!d) {\n      // TODO(arv): This should either be a Document or HTMLDocument depending\n      // on doc.\n      d = doc.implementation.createHTMLDocument('');\n      while (d.lastChild) {\n        d.removeChild(d.lastChild);\n      }\n      doc.templateContentsOwner_ = d;\n    }\n    return d;\n  }\n\n  function getTemplateStagingDocument(template) {\n    if (!template.stagingDocument_) {\n      var owner = template.ownerDocument;\n      if (!owner.stagingDocument_) {\n        owner.stagingDocument_ = owner.implementation.createHTMLDocument('');\n        owner.stagingDocument_.stagingDocument_ = owner.stagingDocument_;\n      }\n\n      template.stagingDocument_ = owner.stagingDocument_;\n    }\n\n    return template.stagingDocument_;\n  }\n\n  // For non-template browsers, the parser will disallow <template> in certain\n  // locations, so we allow \"attribute templates\" which combine the template\n  // element with the top-level container node of the content, e.g.\n  //\n  //   <tr template repeat=\"{{ foo }}\"\" class=\"bar\"><td>Bar</td></tr>\n  //\n  // becomes\n  //\n  //   <template repeat=\"{{ foo }}\">\n  //   + #document-fragment\n  //     + <tr class=\"bar\">\n  //       + <td>Bar</td>\n  //\n  function extractTemplateFromAttributeTemplate(el) {\n    var template = el.ownerDocument.createElement('template');\n    el.parentNode.insertBefore(template, el);\n\n    var attribs = el.attributes;\n    var count = attribs.length;\n    while (count-- > 0) {\n      var attrib = attribs[count];\n      if (templateAttributeDirectives[attrib.name]) {\n        if (attrib.name !== 'template')\n          template.setAttribute(attrib.name, attrib.value);\n        el.removeAttribute(attrib.name);\n      }\n    }\n\n    return template;\n  }\n\n  function extractTemplateFromSVGTemplate(el) {\n    var template = el.ownerDocument.createElement('template');\n    el.parentNode.insertBefore(template, el);\n\n    var attribs = el.attributes;\n    var count = attribs.length;\n    while (count-- > 0) {\n      var attrib = attribs[count];\n      template.setAttribute(attrib.name, attrib.value);\n      el.removeAttribute(attrib.name);\n    }\n\n    el.parentNode.removeChild(el);\n    return template;\n  }\n\n  function liftNonNativeTemplateChildrenIntoContent(template, el, useRoot) {\n    var content = template.content;\n    if (useRoot) {\n      content.appendChild(el);\n      return;\n    }\n\n    var child;\n    while (child = el.firstChild) {\n      content.appendChild(child);\n    }\n  }\n\n  var templateObserver;\n  if (typeof MutationObserver == 'function') {\n    templateObserver = new MutationObserver(function(records) {\n      for (var i = 0; i < records.length; i++) {\n        records[i].target.refChanged_();\n      }\n    });\n  }\n\n  /**\n   * Ensures proper API and content model for template elements.\n   * @param {HTMLTemplateElement} opt_instanceRef The template element which\n   *     |el| template element will return as the value of its ref(), and whose\n   *     content will be used as source when createInstance() is invoked.\n   */\n  HTMLTemplateElement.decorate = function(el, opt_instanceRef) {\n    if (el.templateIsDecorated_)\n      return false;\n\n    var templateElement = el;\n    templateElement.templateIsDecorated_ = true;\n\n    var isNativeHTMLTemplate = isHTMLTemplate(templateElement) &&\n                               hasTemplateElement;\n    var bootstrapContents = isNativeHTMLTemplate;\n    var liftContents = !isNativeHTMLTemplate;\n    var liftRoot = false;\n\n    if (!isNativeHTMLTemplate) {\n      if (isAttributeTemplate(templateElement)) {\n        assert(!opt_instanceRef);\n        templateElement = extractTemplateFromAttributeTemplate(el);\n        templateElement.templateIsDecorated_ = true;\n        isNativeHTMLTemplate = hasTemplateElement;\n        liftRoot = true;\n      } else if (isSVGTemplate(templateElement)) {\n        templateElement = extractTemplateFromSVGTemplate(el);\n        templateElement.templateIsDecorated_ = true;\n        isNativeHTMLTemplate = hasTemplateElement;\n      }\n    }\n\n    if (!isNativeHTMLTemplate) {\n      fixTemplateElementPrototype(templateElement);\n      var doc = getOrCreateTemplateContentsOwner(templateElement);\n      templateElement.content_ = doc.createDocumentFragment();\n    }\n\n    if (opt_instanceRef) {\n      // template is contained within an instance, its direct content must be\n      // empty\n      templateElement.instanceRef_ = opt_instanceRef;\n    } else if (liftContents) {\n      liftNonNativeTemplateChildrenIntoContent(templateElement,\n                                               el,\n                                               liftRoot);\n    } else if (bootstrapContents) {\n      bootstrapTemplatesRecursivelyFrom(templateElement.content);\n    }\n\n    return true;\n  };\n\n  // TODO(rafaelw): This used to decorate recursively all templates from a given\n  // node. This happens by default on 'DOMContentLoaded', but may be needed\n  // in subtrees not descendent from document (e.g. ShadowRoot).\n  // Review whether this is the right public API.\n  HTMLTemplateElement.bootstrap = bootstrapTemplatesRecursivelyFrom;\n\n  var htmlElement = global.HTMLUnknownElement || HTMLElement;\n\n  var contentDescriptor = {\n    get: function() {\n      return this.content_;\n    },\n    enumerable: true,\n    configurable: true\n  };\n\n  if (!hasTemplateElement) {\n    // Gecko is more picky with the prototype than WebKit. Make sure to use the\n    // same prototype as created in the constructor.\n    HTMLTemplateElement.prototype = Object.create(htmlElement.prototype);\n\n    Object.defineProperty(HTMLTemplateElement.prototype, 'content',\n                          contentDescriptor);\n  }\n\n  function fixTemplateElementPrototype(el) {\n    if (hasProto)\n      el.__proto__ = HTMLTemplateElement.prototype;\n    else\n      mixin(el, HTMLTemplateElement.prototype);\n  }\n\n  function ensureSetModelScheduled(template) {\n    if (!template.setModelFn_) {\n      template.setModelFn_ = function() {\n        template.setModelFnScheduled_ = false;\n        var map = getBindings(template,\n            template.delegate_ && template.delegate_.prepareBinding);\n        processBindings(template, map, template.model_);\n      };\n    }\n\n    if (!template.setModelFnScheduled_) {\n      template.setModelFnScheduled_ = true;\n      Observer.runEOM_(template.setModelFn_);\n    }\n  }\n\n  mixin(HTMLTemplateElement.prototype, {\n    bind: function(name, value, oneTime) {\n      if (name != 'ref')\n        return Element.prototype.bind.call(this, name, value, oneTime);\n\n      var self = this;\n      var ref = oneTime ? value : value.open(function(ref) {\n        self.setAttribute('ref', ref);\n        self.refChanged_();\n      });\n\n      this.setAttribute('ref', ref);\n      this.refChanged_();\n      if (oneTime)\n        return;\n\n      this.unbind('ref');\n      return this.bindings.ref = value;\n    },\n\n    processBindingDirectives_: function(directives) {\n      if (this.iterator_)\n        this.iterator_.closeDeps();\n\n      if (!directives.if && !directives.bind && !directives.repeat) {\n        if (this.iterator_) {\n          this.iterator_.close();\n          this.iterator_ = undefined;\n          this.bindings.iterator = undefined;\n        }\n\n        return;\n      }\n\n      if (!this.iterator_) {\n        this.iterator_ = new TemplateIterator(this);\n        this.bindings = this.bindings || {};\n        this.bindings.iterator = this.iterator_;\n      }\n\n      this.iterator_.updateDependencies(directives, this.model_);\n\n      if (templateObserver) {\n        templateObserver.observe(this, { attributes: true,\n                                         attributeFilter: ['ref'] });\n      }\n\n      return this.iterator_;\n    },\n\n    createInstance: function(model, bindingDelegate, delegate_,\n                             instanceBindings_) {\n      if (bindingDelegate)\n        delegate_ = this.newDelegate_(bindingDelegate);\n\n      if (!this.refContent_)\n        this.refContent_ = this.ref_.content;\n      var content = this.refContent_;\n      var map = this.bindingMap_;\n      if (!map || map.content !== content) {\n        // TODO(rafaelw): Setup a MutationObserver on content to detect\n        // when the instanceMap is invalid.\n        map = createInstanceBindingMap(content,\n            delegate_ && delegate_.prepareBinding) || [];\n        map.content = content;\n        this.bindingMap_ = map;\n      }\n\n      var stagingDocument = getTemplateStagingDocument(this);\n      var instance = stagingDocument.createDocumentFragment();\n      instance.templateCreator_ = this;\n      instance.protoContent_ = content;\n\n      var instanceRecord = {\n        firstNode: null,\n        lastNode: null,\n        model: model\n      };\n\n      var i = 0;\n      for (var child = content.firstChild; child; child = child.nextSibling) {\n        var clone = cloneAndBindInstance(child, instance, stagingDocument,\n                                         map.children[i++],\n                                         model,\n                                         delegate_,\n                                         instanceBindings_);\n        clone.templateInstance_ = instanceRecord;\n      }\n\n      instanceRecord.firstNode = instance.firstChild;\n      instanceRecord.lastNode = instance.lastChild;\n      instance.templateCreator_ = undefined;\n      instance.protoContent_ = undefined;\n      return instance;\n    },\n\n    get model() {\n      return this.model_;\n    },\n\n    set model(model) {\n      this.model_ = model;\n      ensureSetModelScheduled(this);\n    },\n\n    get bindingDelegate() {\n      return this.delegate_ && this.delegate_.raw;\n    },\n\n    refChanged_: function() {\n      if (!this.iterator_ || this.refContent_ === this.ref_.content)\n        return;\n\n      this.refContent_ = undefined;\n      this.iterator_.valueChanged();\n      this.iterator_.updateIteratedValue();\n    },\n\n    clear: function() {\n      this.model_ = undefined;\n      this.delegate_ = undefined;\n      this.bindings_ = undefined;\n      this.refContent_ = undefined;\n      if (!this.iterator_)\n        return;\n      this.iterator_.valueChanged();\n      this.iterator_.close()\n      this.iterator_ = undefined;\n    },\n\n    setDelegate_: function(delegate) {\n      this.delegate_ = delegate;\n      this.bindingMap_ = undefined;\n      if (this.iterator_) {\n        this.iterator_.instancePositionChangedFn_ = undefined;\n        this.iterator_.instanceModelFn_ = undefined;\n      }\n    },\n\n    newDelegate_: function(bindingDelegate) {\n      if (!bindingDelegate)\n        return {};\n\n      function delegateFn(name) {\n        var fn = bindingDelegate && bindingDelegate[name];\n        if (typeof fn != 'function')\n          return;\n\n        return function() {\n          return fn.apply(bindingDelegate, arguments);\n        };\n      }\n\n      return {\n        raw: bindingDelegate,\n        prepareBinding: delegateFn('prepareBinding'),\n        prepareInstanceModel: delegateFn('prepareInstanceModel'),\n        prepareInstancePositionChanged:\n            delegateFn('prepareInstancePositionChanged')\n      };\n    },\n\n    // TODO(rafaelw): Assigning .bindingDelegate always succeeds. It may\n    // make sense to issue a warning or even throw if the template is already\n    // \"activated\", since this would be a strange thing to do.\n    set bindingDelegate(bindingDelegate) {\n      if (this.delegate_) {\n        throw Error('Template must be cleared before a new bindingDelegate ' +\n                    'can be assigned');\n      }\n\n      this.setDelegate_(this.newDelegate_(bindingDelegate));\n    },\n\n    get ref_() {\n      var ref = searchRefId(this, this.getAttribute('ref'));\n      if (!ref)\n        ref = this.instanceRef_;\n\n      if (!ref)\n        return this;\n\n      var nextRef = ref.ref_;\n      return nextRef ? nextRef : ref;\n    }\n  });\n\n  // Returns\n  //   a) undefined if there are no mustaches.\n  //   b) [TEXT, (ONE_TIME?, PATH, DELEGATE_FN, TEXT)+] if there is at least one mustache.\n  function parseMustaches(s, name, node, prepareBindingFn) {\n    if (!s || !s.length)\n      return;\n\n    var tokens;\n    var length = s.length;\n    var startIndex = 0, lastIndex = 0, endIndex = 0;\n    var onlyOneTime = true;\n    while (lastIndex < length) {\n      var startIndex = s.indexOf('{{', lastIndex);\n      var oneTimeStart = s.indexOf('[[', lastIndex);\n      var oneTime = false;\n      var terminator = '}}';\n\n      if (oneTimeStart >= 0 &&\n          (startIndex < 0 || oneTimeStart < startIndex)) {\n        startIndex = oneTimeStart;\n        oneTime = true;\n        terminator = ']]';\n      }\n\n      endIndex = startIndex < 0 ? -1 : s.indexOf(terminator, startIndex + 2);\n\n      if (endIndex < 0) {\n        if (!tokens)\n          return;\n\n        tokens.push(s.slice(lastIndex)); // TEXT\n        break;\n      }\n\n      tokens = tokens || [];\n      tokens.push(s.slice(lastIndex, startIndex)); // TEXT\n      var pathString = s.slice(startIndex + 2, endIndex).trim();\n      tokens.push(oneTime); // ONE_TIME?\n      onlyOneTime = onlyOneTime && oneTime;\n      tokens.push(Path.get(pathString)); // PATH\n      var delegateFn = prepareBindingFn &&\n                       prepareBindingFn(pathString, name, node);\n      tokens.push(delegateFn); // DELEGATE_FN\n      lastIndex = endIndex + 2;\n    }\n\n    if (lastIndex === length)\n      tokens.push(''); // TEXT\n\n    tokens.hasOnePath = tokens.length === 5;\n    tokens.isSimplePath = tokens.hasOnePath &&\n                          tokens[0] == '' &&\n                          tokens[4] == '';\n    tokens.onlyOneTime = onlyOneTime;\n\n    tokens.combinator = function(values) {\n      var newValue = tokens[0];\n\n      for (var i = 1; i < tokens.length; i += 4) {\n        var value = tokens.hasOnePath ? values : values[(i - 1) / 4];\n        if (value !== undefined)\n          newValue += value;\n        newValue += tokens[i + 3];\n      }\n\n      return newValue;\n    }\n\n    return tokens;\n  };\n\n  function processOneTimeBinding(name, tokens, node, model) {\n    if (tokens.hasOnePath) {\n      var delegateFn = tokens[3];\n      var value = delegateFn ? delegateFn(model, node, true) :\n                               tokens[2].getValueFrom(model);\n      return tokens.isSimplePath ? value : tokens.combinator(value);\n    }\n\n    var values = [];\n    for (var i = 1; i < tokens.length; i += 4) {\n      var delegateFn = tokens[i + 2];\n      values[(i - 1) / 4] = delegateFn ? delegateFn(model, node) :\n          tokens[i + 1].getValueFrom(model);\n    }\n\n    return tokens.combinator(values);\n  }\n\n  function processSinglePathBinding(name, tokens, node, model) {\n    var delegateFn = tokens[3];\n    var observer = delegateFn ? delegateFn(model, node, false) :\n        new PathObserver(model, tokens[2]);\n\n    return tokens.isSimplePath ? observer :\n        new ObserverTransform(observer, tokens.combinator);\n  }\n\n  function processBinding(name, tokens, node, model) {\n    if (tokens.onlyOneTime)\n      return processOneTimeBinding(name, tokens, node, model);\n\n    if (tokens.hasOnePath)\n      return processSinglePathBinding(name, tokens, node, model);\n\n    var observer = new CompoundObserver();\n\n    for (var i = 1; i < tokens.length; i += 4) {\n      var oneTime = tokens[i];\n      var delegateFn = tokens[i + 2];\n\n      if (delegateFn) {\n        var value = delegateFn(model, node, oneTime);\n        if (oneTime)\n          observer.addPath(value)\n        else\n          observer.addObserver(value);\n        continue;\n      }\n\n      var path = tokens[i + 1];\n      if (oneTime)\n        observer.addPath(path.getValueFrom(model))\n      else\n        observer.addPath(model, path);\n    }\n\n    return new ObserverTransform(observer, tokens.combinator);\n  }\n\n  function processBindings(node, bindings, model, instanceBindings) {\n    for (var i = 0; i < bindings.length; i += 2) {\n      var name = bindings[i]\n      var tokens = bindings[i + 1];\n      var value = processBinding(name, tokens, node, model);\n      var binding = node.bind(name, value, tokens.onlyOneTime);\n      if (binding && instanceBindings)\n        instanceBindings.push(binding);\n    }\n\n    if (!bindings.isTemplate)\n      return;\n\n    node.model_ = model;\n    var iter = node.processBindingDirectives_(bindings);\n    if (instanceBindings && iter)\n      instanceBindings.push(iter);\n  }\n\n  function parseWithDefault(el, name, prepareBindingFn) {\n    var v = el.getAttribute(name);\n    return parseMustaches(v == '' ? '{{}}' : v, name, el, prepareBindingFn);\n  }\n\n  function parseAttributeBindings(element, prepareBindingFn) {\n    assert(element);\n\n    var bindings = [];\n    var ifFound = false;\n    var bindFound = false;\n\n    for (var i = 0; i < element.attributes.length; i++) {\n      var attr = element.attributes[i];\n      var name = attr.name;\n      var value = attr.value;\n\n      // Allow bindings expressed in attributes to be prefixed with underbars.\n      // We do this to allow correct semantics for browsers that don't implement\n      // <template> where certain attributes might trigger side-effects -- and\n      // for IE which sanitizes certain attributes, disallowing mustache\n      // replacements in their text.\n      while (name[0] === '_') {\n        name = name.substring(1);\n      }\n\n      if (isTemplate(element) &&\n          (name === IF || name === BIND || name === REPEAT)) {\n        continue;\n      }\n\n      var tokens = parseMustaches(value, name, element,\n                                  prepareBindingFn);\n      if (!tokens)\n        continue;\n\n      bindings.push(name, tokens);\n    }\n\n    if (isTemplate(element)) {\n      bindings.isTemplate = true;\n      bindings.if = parseWithDefault(element, IF, prepareBindingFn);\n      bindings.bind = parseWithDefault(element, BIND, prepareBindingFn);\n      bindings.repeat = parseWithDefault(element, REPEAT, prepareBindingFn);\n\n      if (bindings.if && !bindings.bind && !bindings.repeat)\n        bindings.bind = parseMustaches('{{}}', BIND, element, prepareBindingFn);\n    }\n\n    return bindings;\n  }\n\n  function getBindings(node, prepareBindingFn) {\n    if (node.nodeType === Node.ELEMENT_NODE)\n      return parseAttributeBindings(node, prepareBindingFn);\n\n    if (node.nodeType === Node.TEXT_NODE) {\n      var tokens = parseMustaches(node.data, 'textContent', node,\n                                  prepareBindingFn);\n      if (tokens)\n        return ['textContent', tokens];\n    }\n\n    return [];\n  }\n\n  function cloneAndBindInstance(node, parent, stagingDocument, bindings, model,\n                                delegate,\n                                instanceBindings,\n                                instanceRecord) {\n    var clone = parent.appendChild(stagingDocument.importNode(node, false));\n\n    var i = 0;\n    for (var child = node.firstChild; child; child = child.nextSibling) {\n      cloneAndBindInstance(child, clone, stagingDocument,\n                            bindings.children[i++],\n                            model,\n                            delegate,\n                            instanceBindings);\n    }\n\n    if (bindings.isTemplate) {\n      HTMLTemplateElement.decorate(clone, node);\n      if (delegate)\n        clone.setDelegate_(delegate);\n    }\n\n    processBindings(clone, bindings, model, instanceBindings);\n    return clone;\n  }\n\n  function createInstanceBindingMap(node, prepareBindingFn) {\n    var map = getBindings(node, prepareBindingFn);\n    map.children = {};\n    var index = 0;\n    for (var child = node.firstChild; child; child = child.nextSibling) {\n      map.children[index++] = createInstanceBindingMap(child, prepareBindingFn);\n    }\n\n    return map;\n  }\n\n  Object.defineProperty(Node.prototype, 'templateInstance', {\n    get: function() {\n      var instance = this.templateInstance_;\n      return instance ? instance :\n          (this.parentNode ? this.parentNode.templateInstance : undefined);\n    }\n  });\n\n  function TemplateIterator(templateElement) {\n    this.closed = false;\n    this.templateElement_ = templateElement;\n\n    // Flattened array of tuples:\n    //   <instanceTerminatorNode, [bindingsSetupByInstance]>\n    this.terminators = [];\n\n    this.deps = undefined;\n    this.iteratedValue = [];\n    this.presentValue = undefined;\n    this.arrayObserver = undefined;\n  }\n\n  TemplateIterator.prototype = {\n    closeDeps: function() {\n      var deps = this.deps;\n      if (deps) {\n        if (deps.ifOneTime === false)\n          deps.ifValue.close();\n        if (deps.oneTime === false)\n          deps.value.close();\n      }\n    },\n\n    updateDependencies: function(directives, model) {\n      this.closeDeps();\n\n      var deps = this.deps = {};\n      var template = this.templateElement_;\n\n      if (directives.if) {\n        deps.hasIf = true;\n        deps.ifOneTime = directives.if.onlyOneTime;\n        deps.ifValue = processBinding(IF, directives.if, template, model);\n\n        // oneTime if & predicate is false. nothing else to do.\n        if (deps.ifOneTime && !deps.ifValue) {\n          this.updateIteratedValue();\n          return;\n        }\n\n        if (!deps.ifOneTime)\n          deps.ifValue.open(this.updateIteratedValue, this);\n      }\n\n      if (directives.repeat) {\n        deps.repeat = true;\n        deps.oneTime = directives.repeat.onlyOneTime;\n        deps.value = processBinding(REPEAT, directives.repeat, template, model);\n      } else {\n        deps.repeat = false;\n        deps.oneTime = directives.bind.onlyOneTime;\n        deps.value = processBinding(BIND, directives.bind, template, model);\n      }\n\n      if (!deps.oneTime)\n        deps.value.open(this.updateIteratedValue, this);\n\n      this.updateIteratedValue();\n    },\n\n    updateIteratedValue: function() {\n      if (this.deps.hasIf) {\n        var ifValue = this.deps.ifValue;\n        if (!this.deps.ifOneTime)\n          ifValue = ifValue.discardChanges();\n        if (!ifValue) {\n          this.valueChanged();\n          return;\n        }\n      }\n\n      var value = this.deps.value;\n      if (!this.deps.oneTime)\n        value = value.discardChanges();\n      if (!this.deps.repeat)\n        value = [value];\n      var observe = this.deps.repeat &&\n                    !this.deps.oneTime &&\n                    Array.isArray(value);\n      this.valueChanged(value, observe);\n    },\n\n    valueChanged: function(value, observeValue) {\n      if (!Array.isArray(value))\n        value = [];\n\n      if (value === this.iteratedValue)\n        return;\n\n      this.unobserve();\n      this.presentValue = value;\n      if (observeValue) {\n        this.arrayObserver = new ArrayObserver(this.presentValue);\n        this.arrayObserver.open(this.handleSplices, this);\n      }\n\n      this.handleSplices(ArrayObserver.calculateSplices(this.presentValue,\n                                                        this.iteratedValue));\n    },\n\n    getTerminatorAt: function(index) {\n      if (index == -1)\n        return this.templateElement_;\n      var terminator = this.terminators[index*2];\n      if (terminator.nodeType !== Node.ELEMENT_NODE ||\n          this.templateElement_ === terminator) {\n        return terminator;\n      }\n\n      var subIterator = terminator.iterator_;\n      if (!subIterator)\n        return terminator;\n\n      return subIterator.getTerminatorAt(subIterator.terminators.length/2 - 1);\n    },\n\n    // TODO(rafaelw): If we inserting sequences of instances we can probably\n    // avoid lots of calls to getTerminatorAt(), or cache its result.\n    insertInstanceAt: function(index, fragment, instanceNodes,\n                               instanceBindings) {\n      var previousTerminator = this.getTerminatorAt(index - 1);\n      var terminator = previousTerminator;\n      if (fragment)\n        terminator = fragment.lastChild || terminator;\n      else if (instanceNodes)\n        terminator = instanceNodes[instanceNodes.length - 1] || terminator;\n\n      this.terminators.splice(index*2, 0, terminator, instanceBindings);\n      var parent = this.templateElement_.parentNode;\n      var insertBeforeNode = previousTerminator.nextSibling;\n\n      if (fragment) {\n        parent.insertBefore(fragment, insertBeforeNode);\n      } else if (instanceNodes) {\n        for (var i = 0; i < instanceNodes.length; i++)\n          parent.insertBefore(instanceNodes[i], insertBeforeNode);\n      }\n    },\n\n    extractInstanceAt: function(index) {\n      var instanceNodes = [];\n      var previousTerminator = this.getTerminatorAt(index - 1);\n      var terminator = this.getTerminatorAt(index);\n      instanceNodes.instanceBindings = this.terminators[index*2 + 1];\n      this.terminators.splice(index*2, 2);\n\n      var parent = this.templateElement_.parentNode;\n      while (terminator !== previousTerminator) {\n        var node = previousTerminator.nextSibling;\n        if (node == terminator)\n          terminator = previousTerminator;\n\n        parent.removeChild(node);\n        instanceNodes.push(node);\n      }\n\n      return instanceNodes;\n    },\n\n    getDelegateFn: function(fn) {\n      fn = fn && fn(this.templateElement_);\n      return typeof fn === 'function' ? fn : null;\n    },\n\n    handleSplices: function(splices) {\n      if (this.closed || !splices.length)\n        return;\n\n      var template = this.templateElement_;\n\n      if (!template.parentNode) {\n        this.close();\n        return;\n      }\n\n      ArrayObserver.applySplices(this.iteratedValue, this.presentValue,\n                                 splices);\n\n      var delegate = template.delegate_;\n      if (this.instanceModelFn_ === undefined) {\n        this.instanceModelFn_ =\n            this.getDelegateFn(delegate && delegate.prepareInstanceModel);\n      }\n\n      if (this.instancePositionChangedFn_ === undefined) {\n        this.instancePositionChangedFn_ =\n            this.getDelegateFn(delegate &&\n                               delegate.prepareInstancePositionChanged);\n      }\n\n      var instanceCache = new Map;\n      var removeDelta = 0;\n      splices.forEach(function(splice) {\n        splice.removed.forEach(function(model) {\n          var instanceNodes =\n              this.extractInstanceAt(splice.index + removeDelta);\n          instanceCache.set(model, instanceNodes);\n        }, this);\n\n        removeDelta -= splice.addedCount;\n      }, this);\n\n      splices.forEach(function(splice) {\n        var addIndex = splice.index;\n        for (; addIndex < splice.index + splice.addedCount; addIndex++) {\n          var model = this.iteratedValue[addIndex];\n          var fragment = undefined;\n          var instanceNodes = instanceCache.get(model);\n          var instanceBindings;\n          if (instanceNodes) {\n            instanceCache.delete(model);\n            instanceBindings = instanceNodes.instanceBindings;\n          } else {\n            instanceBindings = [];\n            if (this.instanceModelFn_)\n              model = this.instanceModelFn_(model);\n\n            if (model !== undefined) {\n              fragment = template.createInstance(model, undefined, delegate,\n                                                 instanceBindings);\n            }\n          }\n\n          this.insertInstanceAt(addIndex, fragment, instanceNodes,\n                                instanceBindings);\n        }\n      }, this);\n\n      instanceCache.forEach(function(instanceNodes) {\n        this.closeInstanceBindings(instanceNodes.instanceBindings);\n      }, this);\n\n      if (this.instancePositionChangedFn_)\n        this.reportInstancesMoved(splices);\n    },\n\n    reportInstanceMoved: function(index) {\n      var previousTerminator = this.getTerminatorAt(index - 1);\n      var terminator = this.getTerminatorAt(index);\n      if (previousTerminator === terminator)\n        return; // instance has zero nodes.\n\n      // We must use the first node of the instance, because any subsequent\n      // nodes may have been generated by sub-templates.\n      // TODO(rafaelw): This is brittle WRT instance mutation -- e.g. if the\n      // first node was removed by script.\n      var templateInstance = previousTerminator.nextSibling.templateInstance;\n      this.instancePositionChangedFn_(templateInstance, index);\n    },\n\n    reportInstancesMoved: function(splices) {\n      var index = 0;\n      var offset = 0;\n      for (var i = 0; i < splices.length; i++) {\n        var splice = splices[i];\n        if (offset != 0) {\n          while (index < splice.index) {\n            this.reportInstanceMoved(index);\n            index++;\n          }\n        } else {\n          index = splice.index;\n        }\n\n        while (index < splice.index + splice.addedCount) {\n          this.reportInstanceMoved(index);\n          index++;\n        }\n\n        offset += splice.addedCount - splice.removed.length;\n      }\n\n      if (offset == 0)\n        return;\n\n      var length = this.terminators.length / 2;\n      while (index < length) {\n        this.reportInstanceMoved(index);\n        index++;\n      }\n    },\n\n    closeInstanceBindings: function(instanceBindings) {\n      for (var i = 0; i < instanceBindings.length; i++) {\n        instanceBindings[i].close();\n      }\n    },\n\n    unobserve: function() {\n      if (!this.arrayObserver)\n        return;\n\n      this.arrayObserver.close();\n      this.arrayObserver = undefined;\n    },\n\n    close: function() {\n      if (this.closed)\n        return;\n      this.unobserve();\n      for (var i = 1; i < this.terminators.length; i += 2) {\n        this.closeInstanceBindings(this.terminators[i]);\n      }\n\n      this.terminators.length = 0;\n      this.closeDeps();\n      this.templateElement_.iterator_ = undefined;\n      this.closed = true;\n    }\n  };\n\n  // Polyfill-specific API.\n  HTMLTemplateElement.forAllTemplatesFrom_ = forAllTemplatesFrom;\n})(this);\n","/*\n  Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com>\n  Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com>\n  Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>\n  Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>\n  Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>\n  Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>\n  Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>\n  Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>\n  Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n(function (global) {\n    'use strict';\n\n    var Token,\n        TokenName,\n        Syntax,\n        Messages,\n        source,\n        index,\n        length,\n        delegate,\n        lookahead,\n        state;\n\n    Token = {\n        BooleanLiteral: 1,\n        EOF: 2,\n        Identifier: 3,\n        Keyword: 4,\n        NullLiteral: 5,\n        NumericLiteral: 6,\n        Punctuator: 7,\n        StringLiteral: 8\n    };\n\n    TokenName = {};\n    TokenName[Token.BooleanLiteral] = 'Boolean';\n    TokenName[Token.EOF] = '<end>';\n    TokenName[Token.Identifier] = 'Identifier';\n    TokenName[Token.Keyword] = 'Keyword';\n    TokenName[Token.NullLiteral] = 'Null';\n    TokenName[Token.NumericLiteral] = 'Numeric';\n    TokenName[Token.Punctuator] = 'Punctuator';\n    TokenName[Token.StringLiteral] = 'String';\n\n    Syntax = {\n        ArrayExpression: 'ArrayExpression',\n        BinaryExpression: 'BinaryExpression',\n        CallExpression: 'CallExpression',\n        ConditionalExpression: 'ConditionalExpression',\n        EmptyStatement: 'EmptyStatement',\n        ExpressionStatement: 'ExpressionStatement',\n        Identifier: 'Identifier',\n        Literal: 'Literal',\n        LabeledStatement: 'LabeledStatement',\n        LogicalExpression: 'LogicalExpression',\n        MemberExpression: 'MemberExpression',\n        ObjectExpression: 'ObjectExpression',\n        Program: 'Program',\n        Property: 'Property',\n        ThisExpression: 'ThisExpression',\n        UnaryExpression: 'UnaryExpression'\n    };\n\n    // Error messages should be identical to V8.\n    Messages = {\n        UnexpectedToken:  'Unexpected token %0',\n        UnknownLabel: 'Undefined label \\'%0\\'',\n        Redeclaration: '%0 \\'%1\\' has already been declared'\n    };\n\n    // Ensure the condition is true, otherwise throw an error.\n    // This is only to have a better contract semantic, i.e. another safety net\n    // to catch a logic error. The condition shall be fulfilled in normal case.\n    // Do NOT use this to enforce a certain condition on any user input.\n\n    function assert(condition, message) {\n        if (!condition) {\n            throw new Error('ASSERT: ' + message);\n        }\n    }\n\n    function isDecimalDigit(ch) {\n        return (ch >= 48 && ch <= 57);   // 0..9\n    }\n\n\n    // 7.2 White Space\n\n    function isWhiteSpace(ch) {\n        return (ch === 32) ||  // space\n            (ch === 9) ||      // tab\n            (ch === 0xB) ||\n            (ch === 0xC) ||\n            (ch === 0xA0) ||\n            (ch >= 0x1680 && '\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\uFEFF'.indexOf(String.fromCharCode(ch)) > 0);\n    }\n\n    // 7.3 Line Terminators\n\n    function isLineTerminator(ch) {\n        return (ch === 10) || (ch === 13) || (ch === 0x2028) || (ch === 0x2029);\n    }\n\n    // 7.6 Identifier Names and Identifiers\n\n    function isIdentifierStart(ch) {\n        return (ch === 36) || (ch === 95) ||  // $ (dollar) and _ (underscore)\n            (ch >= 65 && ch <= 90) ||         // A..Z\n            (ch >= 97 && ch <= 122);          // a..z\n    }\n\n    function isIdentifierPart(ch) {\n        return (ch === 36) || (ch === 95) ||  // $ (dollar) and _ (underscore)\n            (ch >= 65 && ch <= 90) ||         // A..Z\n            (ch >= 97 && ch <= 122) ||        // a..z\n            (ch >= 48 && ch <= 57);           // 0..9\n    }\n\n    // 7.6.1.1 Keywords\n\n    function isKeyword(id) {\n        return (id === 'this')\n    }\n\n    // 7.4 Comments\n\n    function skipWhitespace() {\n        while (index < length && isWhiteSpace(source.charCodeAt(index))) {\n           ++index;\n        }\n    }\n\n    function getIdentifier() {\n        var start, ch;\n\n        start = index++;\n        while (index < length) {\n            ch = source.charCodeAt(index);\n            if (isIdentifierPart(ch)) {\n                ++index;\n            } else {\n                break;\n            }\n        }\n\n        return source.slice(start, index);\n    }\n\n    function scanIdentifier() {\n        var start, id, type;\n\n        start = index;\n\n        id = getIdentifier();\n\n        // There is no keyword or literal with only one character.\n        // Thus, it must be an identifier.\n        if (id.length === 1) {\n            type = Token.Identifier;\n        } else if (isKeyword(id)) {\n            type = Token.Keyword;\n        } else if (id === 'null') {\n            type = Token.NullLiteral;\n        } else if (id === 'true' || id === 'false') {\n            type = Token.BooleanLiteral;\n        } else {\n            type = Token.Identifier;\n        }\n\n        return {\n            type: type,\n            value: id,\n            range: [start, index]\n        };\n    }\n\n\n    // 7.7 Punctuators\n\n    function scanPunctuator() {\n        var start = index,\n            code = source.charCodeAt(index),\n            code2,\n            ch1 = source[index],\n            ch2;\n\n        switch (code) {\n\n        // Check for most common single-character punctuators.\n        case 46:   // . dot\n        case 40:   // ( open bracket\n        case 41:   // ) close bracket\n        case 59:   // ; semicolon\n        case 44:   // , comma\n        case 123:  // { open curly brace\n        case 125:  // } close curly brace\n        case 91:   // [\n        case 93:   // ]\n        case 58:   // :\n        case 63:   // ?\n            ++index;\n            return {\n                type: Token.Punctuator,\n                value: String.fromCharCode(code),\n                range: [start, index]\n            };\n\n        default:\n            code2 = source.charCodeAt(index + 1);\n\n            // '=' (char #61) marks an assignment or comparison operator.\n            if (code2 === 61) {\n                switch (code) {\n                case 37:  // %\n                case 38:  // &\n                case 42:  // *:\n                case 43:  // +\n                case 45:  // -\n                case 47:  // /\n                case 60:  // <\n                case 62:  // >\n                case 124: // |\n                    index += 2;\n                    return {\n                        type: Token.Punctuator,\n                        value: String.fromCharCode(code) + String.fromCharCode(code2),\n                        range: [start, index]\n                    };\n\n                case 33: // !\n                case 61: // =\n                    index += 2;\n\n                    // !== and ===\n                    if (source.charCodeAt(index) === 61) {\n                        ++index;\n                    }\n                    return {\n                        type: Token.Punctuator,\n                        value: source.slice(start, index),\n                        range: [start, index]\n                    };\n                default:\n                    break;\n                }\n            }\n            break;\n        }\n\n        // Peek more characters.\n\n        ch2 = source[index + 1];\n\n        // Other 2-character punctuators: && ||\n\n        if (ch1 === ch2 && ('&|'.indexOf(ch1) >= 0)) {\n            index += 2;\n            return {\n                type: Token.Punctuator,\n                value: ch1 + ch2,\n                range: [start, index]\n            };\n        }\n\n        if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {\n            ++index;\n            return {\n                type: Token.Punctuator,\n                value: ch1,\n                range: [start, index]\n            };\n        }\n\n        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n    }\n\n    // 7.8.3 Numeric Literals\n    function scanNumericLiteral() {\n        var number, start, ch;\n\n        ch = source[index];\n        assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'),\n            'Numeric literal must start with a decimal digit or a decimal point');\n\n        start = index;\n        number = '';\n        if (ch !== '.') {\n            number = source[index++];\n            ch = source[index];\n\n            // Hex number starts with '0x'.\n            // Octal number starts with '0'.\n            if (number === '0') {\n                // decimal number starts with '0' such as '09' is illegal.\n                if (ch && isDecimalDigit(ch.charCodeAt(0))) {\n                    throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n                }\n            }\n\n            while (isDecimalDigit(source.charCodeAt(index))) {\n                number += source[index++];\n            }\n            ch = source[index];\n        }\n\n        if (ch === '.') {\n            number += source[index++];\n            while (isDecimalDigit(source.charCodeAt(index))) {\n                number += source[index++];\n            }\n            ch = source[index];\n        }\n\n        if (ch === 'e' || ch === 'E') {\n            number += source[index++];\n\n            ch = source[index];\n            if (ch === '+' || ch === '-') {\n                number += source[index++];\n            }\n            if (isDecimalDigit(source.charCodeAt(index))) {\n                while (isDecimalDigit(source.charCodeAt(index))) {\n                    number += source[index++];\n                }\n            } else {\n                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n            }\n        }\n\n        if (isIdentifierStart(source.charCodeAt(index))) {\n            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n        }\n\n        return {\n            type: Token.NumericLiteral,\n            value: parseFloat(number),\n            range: [start, index]\n        };\n    }\n\n    // 7.8.4 String Literals\n\n    function scanStringLiteral() {\n        var str = '', quote, start, ch, octal = false;\n\n        quote = source[index];\n        assert((quote === '\\'' || quote === '\"'),\n            'String literal must starts with a quote');\n\n        start = index;\n        ++index;\n\n        while (index < length) {\n            ch = source[index++];\n\n            if (ch === quote) {\n                quote = '';\n                break;\n            } else if (ch === '\\\\') {\n                ch = source[index++];\n                if (!ch || !isLineTerminator(ch.charCodeAt(0))) {\n                    switch (ch) {\n                    case 'n':\n                        str += '\\n';\n                        break;\n                    case 'r':\n                        str += '\\r';\n                        break;\n                    case 't':\n                        str += '\\t';\n                        break;\n                    case 'b':\n                        str += '\\b';\n                        break;\n                    case 'f':\n                        str += '\\f';\n                        break;\n                    case 'v':\n                        str += '\\x0B';\n                        break;\n\n                    default:\n                        str += ch;\n                        break;\n                    }\n                } else {\n                    if (ch ===  '\\r' && source[index] === '\\n') {\n                        ++index;\n                    }\n                }\n            } else if (isLineTerminator(ch.charCodeAt(0))) {\n                break;\n            } else {\n                str += ch;\n            }\n        }\n\n        if (quote !== '') {\n            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n        }\n\n        return {\n            type: Token.StringLiteral,\n            value: str,\n            octal: octal,\n            range: [start, index]\n        };\n    }\n\n    function isIdentifierName(token) {\n        return token.type === Token.Identifier ||\n            token.type === Token.Keyword ||\n            token.type === Token.BooleanLiteral ||\n            token.type === Token.NullLiteral;\n    }\n\n    function advance() {\n        var ch;\n\n        skipWhitespace();\n\n        if (index >= length) {\n            return {\n                type: Token.EOF,\n                range: [index, index]\n            };\n        }\n\n        ch = source.charCodeAt(index);\n\n        // Very common: ( and ) and ;\n        if (ch === 40 || ch === 41 || ch === 58) {\n            return scanPunctuator();\n        }\n\n        // String literal starts with single quote (#39) or double quote (#34).\n        if (ch === 39 || ch === 34) {\n            return scanStringLiteral();\n        }\n\n        if (isIdentifierStart(ch)) {\n            return scanIdentifier();\n        }\n\n        // Dot (.) char #46 can also start a floating-point number, hence the need\n        // to check the next character.\n        if (ch === 46) {\n            if (isDecimalDigit(source.charCodeAt(index + 1))) {\n                return scanNumericLiteral();\n            }\n            return scanPunctuator();\n        }\n\n        if (isDecimalDigit(ch)) {\n            return scanNumericLiteral();\n        }\n\n        return scanPunctuator();\n    }\n\n    function lex() {\n        var token;\n\n        token = lookahead;\n        index = token.range[1];\n\n        lookahead = advance();\n\n        index = token.range[1];\n\n        return token;\n    }\n\n    function peek() {\n        var pos;\n\n        pos = index;\n        lookahead = advance();\n        index = pos;\n    }\n\n    // Throw an exception\n\n    function throwError(token, messageFormat) {\n        var error,\n            args = Array.prototype.slice.call(arguments, 2),\n            msg = messageFormat.replace(\n                /%(\\d)/g,\n                function (whole, index) {\n                    assert(index < args.length, 'Message reference must be in range');\n                    return args[index];\n                }\n            );\n\n        error = new Error(msg);\n        error.index = index;\n        error.description = msg;\n        throw error;\n    }\n\n    // Throw an exception because of the token.\n\n    function throwUnexpected(token) {\n        throwError(token, Messages.UnexpectedToken, token.value);\n    }\n\n    // Expect the next token to match the specified punctuator.\n    // If not, an exception will be thrown.\n\n    function expect(value) {\n        var token = lex();\n        if (token.type !== Token.Punctuator || token.value !== value) {\n            throwUnexpected(token);\n        }\n    }\n\n    // Return true if the next token matches the specified punctuator.\n\n    function match(value) {\n        return lookahead.type === Token.Punctuator && lookahead.value === value;\n    }\n\n    // Return true if the next token matches the specified keyword\n\n    function matchKeyword(keyword) {\n        return lookahead.type === Token.Keyword && lookahead.value === keyword;\n    }\n\n    function consumeSemicolon() {\n        // Catch the very common case first: immediately a semicolon (char #59).\n        if (source.charCodeAt(index) === 59) {\n            lex();\n            return;\n        }\n\n        skipWhitespace();\n\n        if (match(';')) {\n            lex();\n            return;\n        }\n\n        if (lookahead.type !== Token.EOF && !match('}')) {\n            throwUnexpected(lookahead);\n        }\n    }\n\n    // 11.1.4 Array Initialiser\n\n    function parseArrayInitialiser() {\n        var elements = [];\n\n        expect('[');\n\n        while (!match(']')) {\n            if (match(',')) {\n                lex();\n                elements.push(null);\n            } else {\n                elements.push(parseExpression());\n\n                if (!match(']')) {\n                    expect(',');\n                }\n            }\n        }\n\n        expect(']');\n\n        return delegate.createArrayExpression(elements);\n    }\n\n    // 11.1.5 Object Initialiser\n\n    function parseObjectPropertyKey() {\n        var token;\n\n        skipWhitespace();\n        token = lex();\n\n        // Note: This function is called only from parseObjectProperty(), where\n        // EOF and Punctuator tokens are already filtered out.\n        if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {\n            return delegate.createLiteral(token);\n        }\n\n        return delegate.createIdentifier(token.value);\n    }\n\n    function parseObjectProperty() {\n        var token, key;\n\n        token = lookahead;\n        skipWhitespace();\n\n        if (token.type === Token.EOF || token.type === Token.Punctuator) {\n            throwUnexpected(token);\n        }\n\n        key = parseObjectPropertyKey();\n        expect(':');\n        return delegate.createProperty('init', key, parseExpression());\n    }\n\n    function parseObjectInitialiser() {\n        var properties = [];\n\n        expect('{');\n\n        while (!match('}')) {\n            properties.push(parseObjectProperty());\n\n            if (!match('}')) {\n                expect(',');\n            }\n        }\n\n        expect('}');\n\n        return delegate.createObjectExpression(properties);\n    }\n\n    // 11.1.6 The Grouping Operator\n\n    function parseGroupExpression() {\n        var expr;\n\n        expect('(');\n\n        expr = parseExpression();\n\n        expect(')');\n\n        return expr;\n    }\n\n\n    // 11.1 Primary Expressions\n\n    function parsePrimaryExpression() {\n        var type, token, expr;\n\n        if (match('(')) {\n            return parseGroupExpression();\n        }\n\n        type = lookahead.type;\n\n        if (type === Token.Identifier) {\n            expr = delegate.createIdentifier(lex().value);\n        } else if (type === Token.StringLiteral || type === Token.NumericLiteral) {\n            expr = delegate.createLiteral(lex());\n        } else if (type === Token.Keyword) {\n            if (matchKeyword('this')) {\n                lex();\n                expr = delegate.createThisExpression();\n            }\n        } else if (type === Token.BooleanLiteral) {\n            token = lex();\n            token.value = (token.value === 'true');\n            expr = delegate.createLiteral(token);\n        } else if (type === Token.NullLiteral) {\n            token = lex();\n            token.value = null;\n            expr = delegate.createLiteral(token);\n        } else if (match('[')) {\n            expr = parseArrayInitialiser();\n        } else if (match('{')) {\n            expr = parseObjectInitialiser();\n        }\n\n        if (expr) {\n            return expr;\n        }\n\n        throwUnexpected(lex());\n    }\n\n    // 11.2 Left-Hand-Side Expressions\n\n    function parseArguments() {\n        var args = [];\n\n        expect('(');\n\n        if (!match(')')) {\n            while (index < length) {\n                args.push(parseExpression());\n                if (match(')')) {\n                    break;\n                }\n                expect(',');\n            }\n        }\n\n        expect(')');\n\n        return args;\n    }\n\n    function parseNonComputedProperty() {\n        var token;\n\n        token = lex();\n\n        if (!isIdentifierName(token)) {\n            throwUnexpected(token);\n        }\n\n        return delegate.createIdentifier(token.value);\n    }\n\n    function parseNonComputedMember() {\n        expect('.');\n\n        return parseNonComputedProperty();\n    }\n\n    function parseComputedMember() {\n        var expr;\n\n        expect('[');\n\n        expr = parseExpression();\n\n        expect(']');\n\n        return expr;\n    }\n\n    function parseLeftHandSideExpression() {\n        var expr, property;\n\n        expr = parsePrimaryExpression();\n\n        while (match('.') || match('[')) {\n            if (match('[')) {\n                property = parseComputedMember();\n                expr = delegate.createMemberExpression('[', expr, property);\n            } else {\n                property = parseNonComputedMember();\n                expr = delegate.createMemberExpression('.', expr, property);\n            }\n        }\n\n        return expr;\n    }\n\n    // 11.3 Postfix Expressions\n\n    var parsePostfixExpression = parseLeftHandSideExpression;\n\n    // 11.4 Unary Operators\n\n    function parseUnaryExpression() {\n        var token, expr;\n\n        if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) {\n            expr = parsePostfixExpression();\n        } else if (match('+') || match('-') || match('!')) {\n            token = lex();\n            expr = parseUnaryExpression();\n            expr = delegate.createUnaryExpression(token.value, expr);\n        } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {\n            throwError({}, Messages.UnexpectedToken);\n        } else {\n            expr = parsePostfixExpression();\n        }\n\n        return expr;\n    }\n\n    function binaryPrecedence(token) {\n        var prec = 0;\n\n        if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {\n            return 0;\n        }\n\n        switch (token.value) {\n        case '||':\n            prec = 1;\n            break;\n\n        case '&&':\n            prec = 2;\n            break;\n\n        case '==':\n        case '!=':\n        case '===':\n        case '!==':\n            prec = 6;\n            break;\n\n        case '<':\n        case '>':\n        case '<=':\n        case '>=':\n        case 'instanceof':\n            prec = 7;\n            break;\n\n        case 'in':\n            prec = 7;\n            break;\n\n        case '+':\n        case '-':\n            prec = 9;\n            break;\n\n        case '*':\n        case '/':\n        case '%':\n            prec = 11;\n            break;\n\n        default:\n            break;\n        }\n\n        return prec;\n    }\n\n    // 11.5 Multiplicative Operators\n    // 11.6 Additive Operators\n    // 11.7 Bitwise Shift Operators\n    // 11.8 Relational Operators\n    // 11.9 Equality Operators\n    // 11.10 Binary Bitwise Operators\n    // 11.11 Binary Logical Operators\n\n    function parseBinaryExpression() {\n        var expr, token, prec, stack, right, operator, left, i;\n\n        left = parseUnaryExpression();\n\n        token = lookahead;\n        prec = binaryPrecedence(token);\n        if (prec === 0) {\n            return left;\n        }\n        token.prec = prec;\n        lex();\n\n        right = parseUnaryExpression();\n\n        stack = [left, token, right];\n\n        while ((prec = binaryPrecedence(lookahead)) > 0) {\n\n            // Reduce: make a binary expression from the three topmost entries.\n            while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {\n                right = stack.pop();\n                operator = stack.pop().value;\n                left = stack.pop();\n                expr = delegate.createBinaryExpression(operator, left, right);\n                stack.push(expr);\n            }\n\n            // Shift.\n            token = lex();\n            token.prec = prec;\n            stack.push(token);\n            expr = parseUnaryExpression();\n            stack.push(expr);\n        }\n\n        // Final reduce to clean-up the stack.\n        i = stack.length - 1;\n        expr = stack[i];\n        while (i > 1) {\n            expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr);\n            i -= 2;\n        }\n\n        return expr;\n    }\n\n\n    // 11.12 Conditional Operator\n\n    function parseConditionalExpression() {\n        var expr, consequent, alternate;\n\n        expr = parseBinaryExpression();\n\n        if (match('?')) {\n            lex();\n            consequent = parseConditionalExpression();\n            expect(':');\n            alternate = parseConditionalExpression();\n\n            expr = delegate.createConditionalExpression(expr, consequent, alternate);\n        }\n\n        return expr;\n    }\n\n    // Simplification since we do not support AssignmentExpression.\n    var parseExpression = parseConditionalExpression;\n\n    // Polymer Syntax extensions\n\n    // Filter ::\n    //   Identifier\n    //   Identifier \"(\" \")\"\n    //   Identifier \"(\" FilterArguments \")\"\n\n    function parseFilter() {\n        var identifier, args;\n\n        identifier = lex();\n\n        if (identifier.type !== Token.Identifier) {\n            throwUnexpected(identifier);\n        }\n\n        args = match('(') ? parseArguments() : [];\n\n        return delegate.createFilter(identifier.value, args);\n    }\n\n    // Filters ::\n    //   \"|\" Filter\n    //   Filters \"|\" Filter\n\n    function parseFilters() {\n        while (match('|')) {\n            lex();\n            parseFilter();\n        }\n    }\n\n    // TopLevel ::\n    //   LabelledExpressions\n    //   AsExpression\n    //   InExpression\n    //   FilterExpression\n\n    // AsExpression ::\n    //   FilterExpression as Identifier\n\n    // InExpression ::\n    //   Identifier, Identifier in FilterExpression\n    //   Identifier in FilterExpression\n\n    // FilterExpression ::\n    //   Expression\n    //   Expression Filters\n\n    function parseTopLevel() {\n        skipWhitespace();\n        peek();\n\n        var expr = parseExpression();\n        if (expr) {\n            if (lookahead.value === ',' || lookahead.value == 'in' &&\n                       expr.type === Syntax.Identifier) {\n                parseInExpression(expr);\n            } else {\n                parseFilters();\n                if (lookahead.value === 'as') {\n                    parseAsExpression(expr);\n                } else {\n                    delegate.createTopLevel(expr);\n                }\n            }\n        }\n\n        if (lookahead.type !== Token.EOF) {\n            throwUnexpected(lookahead);\n        }\n    }\n\n    function parseAsExpression(expr) {\n        lex();  // as\n        var identifier = lex().value;\n        delegate.createAsExpression(expr, identifier);\n    }\n\n    function parseInExpression(identifier) {\n        var indexName;\n        if (lookahead.value === ',') {\n            lex();\n            if (lookahead.type !== Token.Identifier)\n                throwUnexpected(lookahead);\n            indexName = lex().value;\n        }\n\n        lex();  // in\n        var expr = parseExpression();\n        parseFilters();\n        delegate.createInExpression(identifier.name, indexName, expr);\n    }\n\n    function parse(code, inDelegate) {\n        delegate = inDelegate;\n        source = code;\n        index = 0;\n        length = source.length;\n        lookahead = null;\n        state = {\n            labelSet: {}\n        };\n\n        return parseTopLevel();\n    }\n\n    global.esprima = {\n        parse: parse\n    };\n})(this);\n","// Copyright 2013 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n(function (global) {\n  'use strict';\n\n  // JScript does not have __proto__. We wrap all object literals with\n  // createObject which uses Object.create, Object.defineProperty and\n  // Object.getOwnPropertyDescriptor to create a new object that does the exact\n  // same thing. The main downside to this solution is that we have to extract\n  // all those property descriptors for IE.\n  var createObject = ('__proto__' in {}) ?\n      function(obj) { return obj; } :\n      function(obj) {\n        var proto = obj.__proto__;\n        if (!proto)\n          return obj;\n        var newObject = Object.create(proto);\n        Object.getOwnPropertyNames(obj).forEach(function(name) {\n          Object.defineProperty(newObject, name,\n                               Object.getOwnPropertyDescriptor(obj, name));\n        });\n        return newObject;\n      };\n\n  function prepareBinding(expressionText, name, node, filterRegistry) {\n    var expression;\n    try {\n      expression = getExpression(expressionText);\n      if (expression.scopeIdent &&\n          (node.nodeType !== Node.ELEMENT_NODE ||\n           node.tagName !== 'TEMPLATE' ||\n           (name !== 'bind' && name !== 'repeat'))) {\n        throw Error('as and in can only be used within <template bind/repeat>');\n      }\n    } catch (ex) {\n      console.error('Invalid expression syntax: ' + expressionText, ex);\n      return;\n    }\n\n    return function(model, node, oneTime) {\n      var binding = expression.getBinding(model, filterRegistry, oneTime);\n      if (expression.scopeIdent && binding) {\n        node.polymerExpressionScopeIdent_ = expression.scopeIdent;\n        if (expression.indexIdent)\n          node.polymerExpressionIndexIdent_ = expression.indexIdent;\n      }\n\n      return binding;\n    }\n  }\n\n  // TODO(rafaelw): Implement simple LRU.\n  var expressionParseCache = Object.create(null);\n\n  function getExpression(expressionText) {\n    var expression = expressionParseCache[expressionText];\n    if (!expression) {\n      var delegate = new ASTDelegate();\n      esprima.parse(expressionText, delegate);\n      expression = new Expression(delegate);\n      expressionParseCache[expressionText] = expression;\n    }\n    return expression;\n  }\n\n  function Literal(value) {\n    this.value = value;\n    this.valueFn_ = undefined;\n  }\n\n  Literal.prototype = {\n    valueFn: function() {\n      if (!this.valueFn_) {\n        var value = this.value;\n        this.valueFn_ = function() {\n          return value;\n        }\n      }\n\n      return this.valueFn_;\n    }\n  }\n\n  function IdentPath(name) {\n    this.name = name;\n    this.path = Path.get(name);\n  }\n\n  IdentPath.prototype = {\n    valueFn: function() {\n      if (!this.valueFn_) {\n        var name = this.name;\n        var path = this.path;\n        this.valueFn_ = function(model, observer) {\n          if (observer)\n            observer.addPath(model, path);\n\n          return path.getValueFrom(model);\n        }\n      }\n\n      return this.valueFn_;\n    },\n\n    setValue: function(model, newValue) {\n      if (this.path.length == 1);\n        model = findScope(model, this.path[0]);\n\n      return this.path.setValueFrom(model, newValue);\n    }\n  };\n\n  function MemberExpression(object, property, accessor) {\n    // convert literal computed property access where literal value is a value\n    // path to ident dot-access.\n    if (accessor == '[' &&\n        property instanceof Literal &&\n        Path.get(property.value).valid) {\n      accessor = '.';\n      property = new IdentPath(property.value);\n    }\n\n    this.dynamicDeps = typeof object == 'function' || object.dynamic;\n\n    this.dynamic = typeof property == 'function' ||\n                   property.dynamic ||\n                   accessor == '[';\n\n    this.simplePath =\n        !this.dynamic &&\n        !this.dynamicDeps &&\n        property instanceof IdentPath &&\n        (object instanceof MemberExpression || object instanceof IdentPath);\n\n    this.object = this.simplePath ? object : getFn(object);\n    this.property = accessor == '.' ? property : getFn(property);\n  }\n\n  MemberExpression.prototype = {\n    get fullPath() {\n      if (!this.fullPath_) {\n        var last = this.object instanceof IdentPath ?\n            this.object.name : this.object.fullPath;\n        this.fullPath_ = Path.get(last + '.' + this.property.name);\n      }\n\n      return this.fullPath_;\n    },\n\n    valueFn: function() {\n      if (!this.valueFn_) {\n        var object = this.object;\n\n        if (this.simplePath) {\n          var path = this.fullPath;\n\n          this.valueFn_ = function(model, observer) {\n            if (observer)\n              observer.addPath(model, path);\n\n            return path.getValueFrom(model);\n          };\n        } else if (this.property instanceof IdentPath) {\n          var path = Path.get(this.property.name);\n\n          this.valueFn_ = function(model, observer) {\n            var context = object(model, observer);\n\n            if (observer)\n              observer.addPath(context, path);\n\n            return path.getValueFrom(context);\n          }\n        } else {\n          // Computed property.\n          var property = this.property;\n\n          this.valueFn_ = function(model, observer) {\n            var context = object(model, observer);\n            var propName = property(model, observer);\n            if (observer)\n              observer.addPath(context, propName);\n\n            return context ? context[propName] : undefined;\n          };\n        }\n      }\n      return this.valueFn_;\n    },\n\n    setValue: function(model, newValue) {\n      if (this.simplePath) {\n        this.fullPath.setValueFrom(model, newValue);\n        return newValue;\n      }\n\n      var object = this.object(model);\n      var propName = this.property instanceof IdentPath ? this.property.name :\n          this.property(model);\n      return object[propName] = newValue;\n    }\n  };\n\n  function Filter(name, args) {\n    this.name = name;\n    this.args = [];\n    for (var i = 0; i < args.length; i++) {\n      this.args[i] = getFn(args[i]);\n    }\n  }\n\n  Filter.prototype = {\n    transform: function(value, toModelDirection, filterRegistry, model,\n                        observer) {\n      var fn = filterRegistry[this.name];\n      var context = model;\n      if (fn) {\n        context = undefined;\n      } else {\n        fn = context[this.name];\n        if (!fn) {\n          console.error('Cannot find filter: ' + this.name);\n          return;\n        }\n      }\n\n      // If toModelDirection is falsey, then the \"normal\" (dom-bound) direction\n      // is used. Otherwise, it looks for a 'toModel' property function on the\n      // object.\n      if (toModelDirection) {\n        fn = fn.toModel;\n      } else if (typeof fn.toDOM == 'function') {\n        fn = fn.toDOM;\n      }\n\n      if (typeof fn != 'function') {\n        console.error('No ' + (toModelDirection ? 'toModel' : 'toDOM') +\n                      ' found on' + this.name);\n        return;\n      }\n\n      var args = [value];\n      for (var i = 0; i < this.args.length; i++) {\n        args[i + 1] = getFn(this.args[i])(model, observer);\n      }\n\n      return fn.apply(context, args);\n    }\n  };\n\n  function notImplemented() { throw Error('Not Implemented'); }\n\n  var unaryOperators = {\n    '+': function(v) { return +v; },\n    '-': function(v) { return -v; },\n    '!': function(v) { return !v; }\n  };\n\n  var binaryOperators = {\n    '+': function(l, r) { return l+r; },\n    '-': function(l, r) { return l-r; },\n    '*': function(l, r) { return l*r; },\n    '/': function(l, r) { return l/r; },\n    '%': function(l, r) { return l%r; },\n    '<': function(l, r) { return l<r; },\n    '>': function(l, r) { return l>r; },\n    '<=': function(l, r) { return l<=r; },\n    '>=': function(l, r) { return l>=r; },\n    '==': function(l, r) { return l==r; },\n    '!=': function(l, r) { return l!=r; },\n    '===': function(l, r) { return l===r; },\n    '!==': function(l, r) { return l!==r; },\n    '&&': function(l, r) { return l&&r; },\n    '||': function(l, r) { return l||r; },\n  };\n\n  function getFn(arg) {\n    return typeof arg == 'function' ? arg : arg.valueFn();\n  }\n\n  function ASTDelegate() {\n    this.expression = null;\n    this.filters = [];\n    this.deps = {};\n    this.currentPath = undefined;\n    this.scopeIdent = undefined;\n    this.indexIdent = undefined;\n    this.dynamicDeps = false;\n  }\n\n  ASTDelegate.prototype = {\n    createUnaryExpression: function(op, argument) {\n      if (!unaryOperators[op])\n        throw Error('Disallowed operator: ' + op);\n\n      argument = getFn(argument);\n\n      return function(model, observer) {\n        return unaryOperators[op](argument(model, observer));\n      };\n    },\n\n    createBinaryExpression: function(op, left, right) {\n      if (!binaryOperators[op])\n        throw Error('Disallowed operator: ' + op);\n\n      left = getFn(left);\n      right = getFn(right);\n\n      return function(model, observer) {\n        return binaryOperators[op](left(model, observer),\n                                   right(model, observer));\n      };\n    },\n\n    createConditionalExpression: function(test, consequent, alternate) {\n      test = getFn(test);\n      consequent = getFn(consequent);\n      alternate = getFn(alternate);\n\n      return function(model, observer) {\n        return test(model, observer) ?\n            consequent(model, observer) : alternate(model, observer);\n      }\n    },\n\n    createIdentifier: function(name) {\n      var ident = new IdentPath(name);\n      ident.type = 'Identifier';\n      return ident;\n    },\n\n    createMemberExpression: function(accessor, object, property) {\n      var ex = new MemberExpression(object, property, accessor);\n      if (ex.dynamicDeps)\n        this.dynamicDeps = true;\n      return ex;\n    },\n\n    createLiteral: function(token) {\n      return new Literal(token.value);\n    },\n\n    createArrayExpression: function(elements) {\n      for (var i = 0; i < elements.length; i++)\n        elements[i] = getFn(elements[i]);\n\n      return function(model, observer) {\n        var arr = []\n        for (var i = 0; i < elements.length; i++)\n          arr.push(elements[i](model, observer));\n        return arr;\n      }\n    },\n\n    createProperty: function(kind, key, value) {\n      return {\n        key: key instanceof IdentPath ? key.name : key.value,\n        value: value\n      };\n    },\n\n    createObjectExpression: function(properties) {\n      for (var i = 0; i < properties.length; i++)\n        properties[i].value = getFn(properties[i].value);\n\n      return function(model, observer) {\n        var obj = {};\n        for (var i = 0; i < properties.length; i++)\n          obj[properties[i].key] = properties[i].value(model, observer);\n        return obj;\n      }\n    },\n\n    createFilter: function(name, args) {\n      this.filters.push(new Filter(name, args));\n    },\n\n    createAsExpression: function(expression, scopeIdent) {\n      this.expression = expression;\n      this.scopeIdent = scopeIdent;\n    },\n\n    createInExpression: function(scopeIdent, indexIdent, expression) {\n      this.expression = expression;\n      this.scopeIdent = scopeIdent;\n      this.indexIdent = indexIdent;\n    },\n\n    createTopLevel: function(expression) {\n      this.expression = expression;\n    },\n\n    createThisExpression: notImplemented\n  }\n\n  function ConstantObservable(value) {\n    this.value_ = value;\n  }\n\n  ConstantObservable.prototype = {\n    open: function() { return this.value_; },\n    discardChanges: function() { return this.value_; },\n    deliver: function() {},\n    close: function() {},\n  }\n\n  function Expression(delegate) {\n    this.scopeIdent = delegate.scopeIdent;\n    this.indexIdent = delegate.indexIdent;\n\n    if (!delegate.expression)\n      throw Error('No expression found.');\n\n    this.expression = delegate.expression;\n    getFn(this.expression); // forces enumeration of path dependencies\n\n    this.filters = delegate.filters;\n    this.dynamicDeps = delegate.dynamicDeps;\n  }\n\n  Expression.prototype = {\n    getBinding: function(model, filterRegistry, oneTime) {\n      if (oneTime)\n        return this.getValue(model, undefined, filterRegistry);\n\n      var observer = new CompoundObserver();\n      this.getValue(model, observer, filterRegistry);  // captures deps.\n      var self = this;\n\n      function valueFn() {\n        if (self.dynamicDeps)\n          observer.startReset();\n\n        var value = self.getValue(model,\n                                  self.dynamicDeps ? observer : undefined,\n                                  filterRegistry);\n        if (self.dynamicDeps)\n          observer.finishReset();\n\n        return value;\n      }\n\n      function setValueFn(newValue) {\n        self.setValue(model, newValue, filterRegistry);\n        return newValue;\n      }\n\n      return new ObserverTransform(observer, valueFn, setValueFn, true);\n    },\n\n    getValue: function(model, observer, filterRegistry) {\n      var value = getFn(this.expression)(model, observer);\n      for (var i = 0; i < this.filters.length; i++) {\n        value = this.filters[i].transform(value, false, filterRegistry, model,\n                                          observer);\n      }\n\n      return value;\n    },\n\n    setValue: function(model, newValue, filterRegistry) {\n      var count = this.filters ? this.filters.length : 0;\n      while (count-- > 0) {\n        newValue = this.filters[count].transform(newValue, true, filterRegistry,\n                                                 model);\n      }\n\n      if (this.expression.setValue)\n        return this.expression.setValue(model, newValue);\n    }\n  }\n\n  /**\n   * Converts a style property name to a css property name. For example:\n   * \"WebkitUserSelect\" to \"-webkit-user-select\"\n   */\n  function convertStylePropertyName(name) {\n    return String(name).replace(/[A-Z]/g, function(c) {\n      return '-' + c.toLowerCase();\n    });\n  }\n\n  function isEventHandler(name) {\n    return name[0] === 'o' &&\n           name[1] === 'n' &&\n           name[2] === '-';\n  }\n\n  var mixedCaseEventTypes = {};\n  [\n    'webkitAnimationStart',\n    'webkitAnimationEnd',\n    'webkitTransitionEnd',\n    'DOMFocusOut',\n    'DOMFocusIn',\n    'DOMMouseScroll'\n  ].forEach(function(e) {\n    mixedCaseEventTypes[e.toLowerCase()] = e;\n  });\n\n  var parentScopeName = '@' + Math.random().toString(36).slice(2);\n\n  // Single ident paths must bind directly to the appropriate scope object.\n  // I.e. Pushed values in two-bindings need to be assigned to the actual model\n  // object.\n  function findScope(model, prop) {\n    while (model[parentScopeName] &&\n           !Object.prototype.hasOwnProperty.call(model, prop)) {\n      model = model[parentScopeName];\n    }\n\n    return model;\n  }\n\n  function resolveEventReceiver(model, path, node) {\n    if (path.length == 0)\n      return undefined;\n\n    if (path.length == 1)\n      return findScope(model, path[0]);\n\n    for (var i = 0; model != null && i < path.length - 1; i++) {\n      model = model[path[i]];\n    }\n\n    return model;\n  }\n\n  function prepareEventBinding(path, name, polymerExpressions) {\n    var eventType = name.substring(3);\n    eventType = mixedCaseEventTypes[eventType] || eventType;\n\n    return function(model, node, oneTime) {\n      var fn, receiver, handler;\n      if (typeof polymerExpressions.resolveEventHandler == 'function') {\n        handler = function(e) {\n          fn = fn || polymerExpressions.resolveEventHandler(model, path, node);\n          fn(e, e.detail, e.currentTarget);\n\n          if (Platform && typeof Platform.flush == 'function')\n            Platform.flush();\n        };\n      } else {\n        handler = function(e) {\n          fn = fn || path.getValueFrom(model);\n          receiver = receiver || resolveEventReceiver(model, path, node);\n\n          fn.apply(receiver, [e, e.detail, e.currentTarget]);\n\n          if (Platform && typeof Platform.flush == 'function')\n            Platform.flush();\n        };\n      }\n\n      node.addEventListener(eventType, handler);\n\n      if (oneTime)\n        return;\n\n      function bindingValue() {\n        return '{{ ' + path + ' }}';\n      }\n\n      return {\n        open: bindingValue,\n        discardChanges: bindingValue,\n        close: function() {\n          node.removeEventListener(eventType, handler);\n        }\n      };\n    }\n  }\n\n  function PolymerExpressions() {}\n\n  PolymerExpressions.prototype = {\n    // \"built-in\" filters\n    styleObject: function(value) {\n      var parts = [];\n      for (var key in value) {\n        parts.push(convertStylePropertyName(key) + ': ' + value[key]);\n      }\n      return parts.join('; ');\n    },\n\n    tokenList: function(value) {\n      var tokens = [];\n      for (var key in value) {\n        if (value[key])\n          tokens.push(key);\n      }\n      return tokens.join(' ');\n    },\n\n    // binding delegate API\n    prepareInstancePositionChanged: function(template) {\n      var indexIdent = template.polymerExpressionIndexIdent_;\n      if (!indexIdent)\n        return;\n\n      return function(templateInstance, index) {\n        templateInstance.model[indexIdent] = index;\n      };\n    },\n\n    prepareBinding: function(pathString, name, node) {\n      var path = Path.get(pathString);\n      if (isEventHandler(name)) {\n        if (!path.valid) {\n          console.error('on-* bindings must be simple path expressions');\n          return;\n        }\n\n        return prepareEventBinding(path, name, this);\n      }\n\n      if (path.valid) {\n        if (path.length == 1) {\n          return function(model, node, oneTime) {\n            if (oneTime)\n              return path.getValueFrom(model);\n\n            var scope = findScope(model, path[0]);\n            return new PathObserver(scope, path);\n          }\n        }\n\n        return; // bail out early if pathString is simple path.\n      }\n\n      return prepareBinding(pathString, name, node, this);\n    },\n\n    prepareInstanceModel: function(template) {\n      var scopeName = template.polymerExpressionScopeIdent_;\n      if (!scopeName)\n        return;\n\n      var parentScope = template.templateInstance ?\n          template.templateInstance.model :\n          template.model;\n\n      var indexName = template.polymerExpressionIndexIdent_;\n\n      return function(model) {\n        var scope = Object.create(parentScope);\n        scope[scopeName] = model;\n        scope[indexName] = undefined;\n        scope[parentScopeName] = parentScope;\n        return scope;\n      };\n    }\n  };\n\n  global.PolymerExpressions = PolymerExpressions;\n  if (global.exposeGetExpression)\n    global.getExpression_ = getExpression;\n\n  global.PolymerExpressions.prepareEventBinding = prepareEventBinding;\n})(this);\n","/*\n * Copyright 2013 The Polymer Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n(function(scope) {\n\n// inject style sheet\nvar style = document.createElement('style');\nstyle.textContent = 'template {display: none !important;} /* injected by platform.js */';\nvar head = document.querySelector('head');\nhead.insertBefore(style, head.firstChild);\n\n// flush (with logging)\nvar flushing;\nfunction flush() {\n  if (!flushing) {\n    flushing = true;\n    scope.endOfMicrotask(function() {\n      flushing = false;\n      logFlags.data && console.group('Platform.flush()');\n      scope.performMicrotaskCheckpoint();\n      logFlags.data && console.groupEnd();\n    });\n  }\n};\n\n// polling dirty checker\nvar FLUSH_POLL_INTERVAL = 125;\nwindow.addEventListener('WebComponentsReady', function() {\n  flush();\n  // flush periodically if platform does not have object observe.\n  if (!Observer.hasObjectObserve) {\n    scope.flushPoll = setInterval(flush, FLUSH_POLL_INTERVAL);\n  }\n});\n\nif (window.CustomElements && !CustomElements.useNative) {\n  var originalImportNode = Document.prototype.importNode;\n  Document.prototype.importNode = function(node, deep) {\n    var imported = originalImportNode.call(this, node, deep);\n    CustomElements.upgradeAll(imported);\n    return imported;\n  }\n}\n\n// exports\nscope.flush = flush;\n\n})(window.Platform);\n\n"]}
\ No newline at end of file
diff --git a/pkg/custom_element/lib/polyfill.dart b/pkg/web_components/lib/polyfill.dart
similarity index 68%
rename from pkg/custom_element/lib/polyfill.dart
rename to pkg/web_components/lib/polyfill.dart
index 413d7d6..a141c4d 100644
--- a/pkg/custom_element/lib/polyfill.dart
+++ b/pkg/web_components/lib/polyfill.dart
@@ -3,7 +3,7 @@
 // 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;
+library web_components.polyfill;
 
 import 'dart:async';
 import 'dart:html';
@@ -17,6 +17,7 @@
  * while parsing the HTML document, but the custom element polyfill cannot,
  * so it completes this future once all elements are upgraded.
  */
+// TODO(jmesserly): rename to webComponentsReady to match the event?
 Future customElementsReady = () {
   if (_isReady) return new Future.value();
 
@@ -44,20 +45,18 @@
 }
 
 /**
- * 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]).
+ * *Note* this API is primarily intended for tests. In other code it is better
+ * to write it in a style that works with or without the polyfill, rather than
+ * using this method.
  *
- * 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.
+ * Synchronously trigger evaluation of pending lifecycle events, which otherwise
+ * need to wait for a [MutationObserver] to signal the changes in the polyfill.
+ * This method can be used to resolve differences in timing between native and
+ * polyfilled custom elements.
  */
-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;
+void customElementsTakeRecords() {
+  var customElements = js.context['CustomElements'];
+  if (customElements != null) {
+    customElements.callMethod('takeRecords');
   }
-  return new Future.value();
 }
diff --git a/pkg/web_components/pubspec.yaml b/pkg/web_components/pubspec.yaml
new file mode 100644
index 0000000..0f761ec
--- /dev/null
+++ b/pkg/web_components/pubspec.yaml
@@ -0,0 +1,11 @@
+name: web_components
+version: 0.3.0
+author: Polymer.dart Authors <web-ui-dev@dartlang.org>
+homepage: https://www.dartlang.org/polymer-dart/
+description: >
+  Custom Elements let authors define their own elements. Authors associate code
+  with custom tag names, and then use those custom tag names as they would any
+  standard tag. Shadow DOM is designed to provide encapsulation for custom
+  elements, by hiding DOM subtrees under shadow roots.
+environment:
+  sdk: ">=1.2.0-dev.4.0 <2.0.0"
diff --git a/runtime/bin/file_system_watcher_macos.cc b/runtime/bin/file_system_watcher_macos.cc
index 2fa80a2..30322c8 100644
--- a/runtime/bin/file_system_watcher_macos.cc
+++ b/runtime/bin/file_system_watcher_macos.cc
@@ -55,46 +55,39 @@
  public:
   class Node {
    public:
-    Node(FSEventsWatcher* watcher, intptr_t base_path_length, int read_fd,
+    Node(FSEventsWatcher* watcher, char* base_path, int read_fd,
          int write_fd, bool recursive)
         : watcher_(watcher),
           ready_(false),
-          base_path_length_(base_path_length),
+          base_path_length_(strlen(base_path)),
+          path_ref_(CFStringCreateWithCString(
+              NULL, base_path, kCFStringEncodingUTF8)),
           read_fd_(read_fd),
           write_fd_(write_fd),
           recursive_(recursive),
-          ref_(NULL) {}
+          ref_(NULL) {
+      Start();
+    }
 
     ~Node() {
+      Stop();
       close(write_fd_);
+      CFRelease(path_ref_);
     }
 
     void set_ref(FSEventStreamRef ref) {
       ref_ = ref;
     }
 
-    static void StartCallback(CFRunLoopTimerRef timer, void* info) {
-      Node* node = reinterpret_cast<Node*>(info);
-      FSEventStreamScheduleWithRunLoop(
-          node->ref_,
-          node->watcher_->run_loop_,
-          kCFRunLoopDefaultMode);
-      FSEventStreamStart(node->ref_);
-      FSEventStreamFlushSync(node->ref_);
-      node->watcher_->monitor_.Enter();
-      node->ready_ = true;
-      node->watcher_->monitor_.Notify();
-      node->watcher_->monitor_.Exit();
-    }
-
     void Start() {
-      ASSERT(!ready_);
+      // Schedule StartCallback to be executed in the RunLoop.
       CFRunLoopTimerContext context;
       memset(&context, 0, sizeof(context));
       context.info = this;
       CFRunLoopTimerRef timer = CFRunLoopTimerCreate(
-          NULL, 0, 0, 0, 0, StartCallback, &context);
+          NULL, 0, 0, 0, 0, Node::StartCallback, &context);
       CFRunLoopAddTimer(watcher_->run_loop_, timer, kCFRunLoopCommonModes);
+      CFRelease(timer);
       watcher_->monitor_.Enter();
       while (!ready_) {
         watcher_->monitor_.Wait(Monitor::kNoTimeout);
@@ -102,8 +95,62 @@
       watcher_->monitor_.Exit();
     }
 
+    static void StartCallback(CFRunLoopTimerRef timer, void* info) {
+      Node* node = reinterpret_cast<Node*>(info);
+      ASSERT(Thread::Compare(node->watcher_->threadId_,
+                             Thread::GetCurrentThreadId()));
+      FSEventStreamContext context;
+      memset(&context, 0, sizeof(context));
+      context.info = reinterpret_cast<void*>(node);
+      CFArrayRef array = CFArrayCreate(
+          NULL, reinterpret_cast<const void**>(&node->path_ref_), 1, NULL);
+      FSEventStreamRef ref = FSEventStreamCreate(
+          NULL,
+          Callback,
+          &context,
+          array,
+          kFSEventStreamEventIdSinceNow,
+          0.10,
+          kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents);
+      CFRelease(array);
+
+      node->set_ref(ref);
+
+      FSEventStreamScheduleWithRunLoop(
+          node->ref_,
+          node->watcher_->run_loop_,
+          kCFRunLoopDefaultMode);
+
+      FSEventStreamStart(node->ref_);
+      FSEventStreamFlushSync(node->ref_);
+
+      node->watcher_->monitor_.Enter();
+      node->ready_ = true;
+      node->watcher_->monitor_.Notify();
+      node->watcher_->monitor_.Exit();
+    }
+
+    void Stop() {
+      // Schedule StopCallback to be executed in the RunLoop.
+      ASSERT(ready_);
+      CFRunLoopTimerContext context;
+      memset(&context, 0, sizeof(context));
+      context.info = this;
+      CFRunLoopTimerRef timer = CFRunLoopTimerCreate(
+          NULL, 0, 0, 0, 0, StopCallback, &context);
+      CFRunLoopAddTimer(watcher_->run_loop_, timer, kCFRunLoopCommonModes);
+      CFRelease(timer);
+      watcher_->monitor_.Enter();
+      while (ready_) {
+        watcher_->monitor_.Wait(Monitor::kNoTimeout);
+      }
+      watcher_->monitor_.Exit();
+    }
+
     static void StopCallback(CFRunLoopTimerRef timer, void* info) {
       Node* node = reinterpret_cast<Node*>(info);
+      ASSERT(Thread::Compare(node->watcher_->threadId_,
+                             Thread::GetCurrentThreadId()));
       FSEventStreamStop(node->ref_);
       FSEventStreamInvalidate(node->ref_);
       FSEventStreamRelease(node->ref_);
@@ -113,21 +160,7 @@
       node->watcher_->monitor_.Exit();
     }
 
-    void Stop() {
-      ASSERT(ready_);
-      CFRunLoopTimerContext context;
-      memset(&context, 0, sizeof(context));
-      context.info = this;
-      CFRunLoopTimerRef timer = CFRunLoopTimerCreate(
-          NULL, 0, 0, 0, 0, StopCallback, &context);
-      CFRunLoopAddTimer(watcher_->run_loop_, timer, kCFRunLoopCommonModes);
-      watcher_->monitor_.Enter();
-      while (ready_) {
-        watcher_->monitor_.Wait(Monitor::kNoTimeout);
-      }
-      watcher_->monitor_.Exit();
-    }
-
+    FSEventsWatcher* watcher() const { return watcher_; }
     bool ready() const { return ready_; }
     intptr_t base_path_length() const { return base_path_length_; }
     int read_fd() const { return read_fd_; }
@@ -138,31 +171,33 @@
     FSEventsWatcher* watcher_;
     bool ready_;
     intptr_t base_path_length_;
+    CFStringRef path_ref_;
     int read_fd_;
     int write_fd_;
     bool recursive_;
     FSEventStreamRef ref_;
   };
 
+
   FSEventsWatcher() : run_loop_(0) {
+    Start();
+  }
+
+  void Start() {
     Thread::Start(Run, reinterpret_cast<uword>(this));
-  }
-
-  ~FSEventsWatcher() {
-    CFRunLoopStop(run_loop_);
-  }
-
-  Monitor& monitor() { return monitor_; }
-
-  bool has_run_loop() const { return run_loop_ != NULL; }
-
-  static void TimerCallback(CFRunLoopTimerRef timer, void* context) {
-    // Dummy callback to keep RunLoop alive.
+    monitor_.Enter();
+    while (run_loop_ == NULL) {
+      monitor_.Wait(Monitor::kNoTimeout);
+    }
+    monitor_.Exit();
   }
 
   static void Run(uword arg) {
     FSEventsWatcher* watcher = reinterpret_cast<FSEventsWatcher*>(arg);
+    // Only checked in debug mode.
+    watcher->threadId_ = Thread::GetCurrentThreadId();
     watcher->run_loop_ = CFRunLoopGetCurrent();
+    CFRetain(watcher->run_loop_);
 
     // Notify, as the run-loop is set.
     watcher->monitor().Enter();
@@ -177,10 +212,51 @@
         0,
         TimerCallback,
         NULL);
-
     CFRunLoopAddTimer(watcher->run_loop_, timer, kCFRunLoopCommonModes);
+    CFRelease(timer);
 
     CFRunLoopRun();
+
+    CFRelease(watcher->run_loop_);
+    watcher->monitor_.Enter();
+    watcher->run_loop_ = NULL;
+    watcher->monitor_.Notify();
+    watcher->monitor_.Exit();
+  }
+
+  void Stop() {
+    // Schedule StopCallback to be executed in the RunLoop.
+    CFRunLoopTimerContext context;
+    memset(&context, 0, sizeof(context));
+    context.info = this;
+    CFRunLoopTimerRef timer = CFRunLoopTimerCreate(
+        NULL, 0, 0, 0, 0, StopCallback, &context);
+    CFRunLoopAddTimer(run_loop_, timer, kCFRunLoopCommonModes);
+    CFRelease(timer);
+    monitor_.Enter();
+    while (run_loop_ != NULL) {
+      monitor_.Wait(Monitor::kNoTimeout);
+    }
+    monitor_.Exit();
+  }
+
+  static void StopCallback(CFRunLoopTimerRef timer, void* info) {
+    FSEventsWatcher* watcher = reinterpret_cast<FSEventsWatcher*>(info);
+    ASSERT(Thread::Compare(watcher->threadId_,
+                           Thread::GetCurrentThreadId()));
+    CFRunLoopStop(watcher->run_loop_);
+  }
+
+  ~FSEventsWatcher() {
+    Stop();
+  }
+
+  Monitor& monitor() { return monitor_; }
+
+  bool has_run_loop() const { return run_loop_ != NULL; }
+
+  static void TimerCallback(CFRunLoopTimerRef timer, void* context) {
+    // Dummy callback to keep RunLoop alive.
   }
 
   Node* AddPath(const char* path, int events, bool recursive) {
@@ -191,29 +267,8 @@
 
     char base_path[PATH_MAX];
     realpath(path, base_path);
-    CFStringRef path_ref = CFStringCreateWithCString(
-        NULL, base_path, kCFStringEncodingUTF8);
 
-    Node* node = new Node(this, strlen(base_path), fds[0], fds[1], recursive);
-
-    FSEventStreamContext context;
-    context.version = 0;
-    context.info = reinterpret_cast<void*>(node);
-    context.retain = NULL;
-    context.release = NULL;
-    context.copyDescription = NULL;
-    FSEventStreamRef ref = FSEventStreamCreate(
-        NULL,
-        Callback,
-        &context,
-        CFArrayCreate(NULL, reinterpret_cast<const void**>(&path_ref), 1, NULL),
-        kFSEventStreamEventIdSinceNow,
-        0.10,
-        kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents);
-
-    node->set_ref(ref);
-
-    return node;
+    return new Node(this, base_path, fds[0], fds[1], recursive);
   }
 
  private:
@@ -224,6 +279,8 @@
                        const FSEventStreamEventFlags event_flags[],
                        const FSEventStreamEventId event_ids[]) {
     Node* node = reinterpret_cast<Node*>(client);
+    ASSERT(Thread::Compare(node->watcher()->threadId_,
+                           Thread::GetCurrentThreadId()));
     // `ready` is set on same thread as this callback is invoked, so we don't
     // need to lock here.
     if (!node->ready()) return;
@@ -243,6 +300,7 @@
 
   Monitor monitor_;
   CFRunLoopRef run_loop_;
+  ThreadId threadId_;
 };
 
 
@@ -253,19 +311,12 @@
 
 
 intptr_t FileSystemWatcher::Init() {
-  FSEventsWatcher* watcher = new FSEventsWatcher();
-  watcher->monitor().Enter();
-  while (!watcher->has_run_loop()) {
-    watcher->monitor().Wait(Monitor::kNoTimeout);
-  }
-  watcher->monitor().Exit();
-  return reinterpret_cast<intptr_t>(watcher);
+  return reinterpret_cast<intptr_t>(new FSEventsWatcher());
 }
 
 
 void FileSystemWatcher::Close(intptr_t id) {
-  FSEventsWatcher* watcher = reinterpret_cast<FSEventsWatcher*>(id);
-  delete watcher;
+  delete reinterpret_cast<FSEventsWatcher*>(id);
 }
 
 
@@ -274,18 +325,13 @@
                                       int events,
                                       bool recursive) {
   FSEventsWatcher* watcher = reinterpret_cast<FSEventsWatcher*>(id);
-  FSEventsWatcher::Node* node = watcher->AddPath(path, events, recursive);
-  node->Start();
-  return reinterpret_cast<intptr_t>(node);
+  return reinterpret_cast<intptr_t>(watcher->AddPath(path, events, recursive));
 }
 
 
 void FileSystemWatcher::UnwatchPath(intptr_t id, intptr_t path_id) {
   USE(id);
-  FSEventsWatcher::Node* node =
-      reinterpret_cast<FSEventsWatcher::Node*>(path_id);
-  node->Stop();
-  delete node;
+  delete reinterpret_cast<FSEventsWatcher::Node*>(path_id);
 }
 
 
diff --git a/runtime/bin/process_patch.dart b/runtime/bin/process_patch.dart
index 78cae4f..02a5e86 100644
--- a/runtime/bin/process_patch.dart
+++ b/runtime/bin/process_patch.dart
@@ -114,7 +114,7 @@
     }
   }
 
-  /* patch */ static int _setSignalHandler(int signal)
+  /* patch */ static _setSignalHandler(int signal)
       native "Process_SetSignalHandler";
   /* patch */ static int _clearSignalHandler(int signal)
       native "Process_ClearSignalHandler";
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index 9076848..56f04d1 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -253,7 +253,7 @@
   bool isClosing = false;
   bool isClosedRead = false;
   bool isClosedWrite = false;
-  Completer closeCompleter = new Completer();
+  Completer closeCompleter = new Completer.sync();
 
   // Handlers and receive port for socket events from the event handler.
   int eventMask = 0;
@@ -571,7 +571,7 @@
         if (i == DESTROYED_EVENT) {
           assert(!isClosed);
           isClosed = true;
-          closeCompleter.complete(this);
+          closeCompleter.complete();
           disconnectFromEventHandler();
           if (handler != null) handler();
           continue;
@@ -625,7 +625,6 @@
     activateHandlers();
   }
 
-  Future<_NativeSocket> get closeFuture => closeCompleter.future;
 
   void activateHandlers() {
     if (canActivateEvents && !isClosing && !isClosed) {
@@ -643,12 +642,12 @@
     }
   }
 
-  Future<_NativeSocket> close() {
+  Future close() {
     if (!isClosing && !isClosed) {
       sendToEventHandler(1 << CLOSE_COMMAND);
       isClosing = true;
     }
-    return closeFuture;
+    return closeCompleter.future;
   }
 
   void shutdown(SocketDirection direction) {
@@ -867,7 +866,6 @@
         onCancel: _onSubscriptionStateChange,
         onPause: _onPauseStateChange,
         onResume: _onPauseStateChange);
-    _socket.closeFuture.then((_) => _controller.close());
     _socket.setHandlers(
       read: zone.bindCallback(() {
         var socket = _socket.accept();
@@ -876,7 +874,8 @@
       error: zone.bindUnaryCallback((e) {
         _controller.addError(e);
         _controller.close();
-      })
+      }),
+      destroyed: _controller.close
     );
   }
 
@@ -909,7 +908,7 @@
     if (_controller.hasListener) {
       _resume();
     } else {
-      close();
+      _socket.close();
     }
   }
 
@@ -945,7 +944,6 @@
         onCancel: _onSubscriptionStateChange,
         onPause: _onPauseStateChange,
         onResume: _onPauseStateChange);
-    _socket.closeFuture.then((_) => _controller.close());
     _socket.setHandlers(
       read: () => _controller.add(RawSocketEvent.READ),
       write: () {
@@ -955,10 +953,13 @@
         _controller.add(RawSocketEvent.WRITE);
       },
       closed: () => _controller.add(RawSocketEvent.READ_CLOSED),
-      destroyed: () => _controller.add(RawSocketEvent.CLOSED),
+      destroyed: () {
+        _controller.add(RawSocketEvent.CLOSED);
+        _controller.close();
+      },
       error: zone.bindUnaryCallback((e) {
         _controller.addError(e);
-        close();
+        _socket.close();
       })
     );
   }
@@ -1064,7 +1065,7 @@
     if (_controller.hasListener) {
       _resume();
     } else {
-      close();
+      _socket.close();
     }
   }
 }
@@ -1427,7 +1428,6 @@
         onCancel: _onSubscriptionStateChange,
         onPause: _onPauseStateChange,
         onResume: _onPauseStateChange);
-    _socket.closeFuture.then((_) => _controller.close());
     _socket.setHandlers(
       read: () => _controller.add(RawSocketEvent.READ),
       write: () {
@@ -1437,10 +1437,13 @@
         _controller.add(RawSocketEvent.WRITE);
       },
       closed: () => _controller.add(RawSocketEvent.READ_CLOSED),
-      destroyed: () => _controller.add(RawSocketEvent.CLOSED),
+      destroyed: () {
+        _controller.add(RawSocketEvent.CLOSED);
+        _controller.close();
+      },
       error: zone.bindUnaryCallback((e) {
         _controller.addError(e);
-        close();
+        _socket.close();
       })
     );
   }
@@ -1541,7 +1544,7 @@
     if (_controller.hasListener) {
       _resume();
     } else {
-      close();
+      _socket.close();
     }
   }
 }
diff --git a/runtime/lib/array.cc b/runtime/lib/array.cc
index 532eee2..81c41a9 100644
--- a/runtime/lib/array.cc
+++ b/runtime/lib/array.cc
@@ -13,8 +13,8 @@
 namespace dart {
 
 DEFINE_NATIVE_ENTRY(List_allocate, 2) {
-  const AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::CheckedHandle(isolate, arguments->NativeArgAt(0));
+  const TypeArguments& type_arguments =
+      TypeArguments::CheckedHandle(isolate, arguments->NativeArgAt(0));
   const Instance& length = Instance::CheckedHandle(
       isolate, arguments->NativeArgAt(1));
   if (!length.IsSmi()) {
diff --git a/runtime/lib/double.cc b/runtime/lib/double.cc
index 1cadbdb..a4cac7d 100644
--- a/runtime/lib/double.cc
+++ b/runtime/lib/double.cc
@@ -19,8 +19,7 @@
 DECLARE_FLAG(bool, trace_intrinsified_natives);
 
 DEFINE_NATIVE_ENTRY(Double_doubleFromInteger, 2) {
-  ASSERT(AbstractTypeArguments::CheckedHandle(
-      arguments->NativeArgAt(0)).IsNull());
+  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
   const Integer& value = Integer::CheckedHandle(arguments->NativeArgAt(1));
   if (FLAG_trace_intrinsified_natives) {
     OS::Print("Double_doubleFromInteger %s\n", value.ToCString());
diff --git a/runtime/lib/growable_array.cc b/runtime/lib/growable_array.cc
index 34f60a0..5cbf585 100644
--- a/runtime/lib/growable_array.cc
+++ b/runtime/lib/growable_array.cc
@@ -13,8 +13,8 @@
 namespace dart {
 
 DEFINE_NATIVE_ENTRY(GrowableList_allocate, 2) {
-  const AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::CheckedHandle(arguments->NativeArgAt(0));
+  const TypeArguments& type_arguments =
+      TypeArguments::CheckedHandle(arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Array, data, arguments->NativeArgAt(1));
   if ((data.Length() <= 0)) {
     const Integer& index = Integer::Handle(Integer::New(data.Length()));
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 71fa51f..083ea66 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -61,8 +61,7 @@
 
 
 DEFINE_NATIVE_ENTRY(RawReceivePortImpl_factory, 1) {
-  ASSERT(AbstractTypeArguments::CheckedHandle(
-      arguments->NativeArgAt(0)).IsNull());
+  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
   Dart_Port port_id =
       PortMap::CreatePort(arguments->isolate()->message_handler());
   const Object& port = Object::Handle(ReceivePortCreate(port_id));
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 9f5c763..a6641b3 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -856,8 +856,8 @@
   ASSERT(instantiator.IsFinalized());
   ASSERT(!instantiator.IsMalformed());
 
-  const AbstractTypeArguments& type_args =
-      AbstractTypeArguments::Handle(instantiator.arguments());
+  const TypeArguments& type_args =
+      TypeArguments::Handle(instantiator.arguments());
   Error& bound_error = Error::Handle();
   AbstractType& result =
       AbstractType::Handle(type.InstantiateFrom(type_args, &bound_error));
@@ -1258,8 +1258,7 @@
   const Array& result = Array::Handle(Array::New(num_params));
   AbstractType& arg_type = AbstractType::Handle();
   Instance& type_mirror = Instance::Handle();
-  const AbstractTypeArguments& args =
-      AbstractTypeArguments::Handle(type.arguments());
+  const TypeArguments& args = TypeArguments::Handle(type.arguments());
 
   // Handle argument lists that have been optimized away, because either no
   // arguments have been provided, or all arguments are dynamic. Return a list
@@ -1750,8 +1749,7 @@
   }
 
   ASSERT(!type.IsNull());
-  AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::Handle(type.arguments());
+  TypeArguments& type_arguments = TypeArguments::Handle(type.arguments());
   if (!type.IsInstantiated()) {
     // Must have been a declaration type.
     AbstractType& rare_type = AbstractType::Handle(klass.RareType());
@@ -1775,6 +1773,7 @@
         ThrowInvokeError(bound_error);
         UNREACHABLE();
       }
+      redirect_type ^= redirect_type.Canonicalize();
     }
 
     type = redirect_type.raw();
@@ -2037,8 +2036,21 @@
 DEFINE_NATIVE_ENTRY(MethodMirror_source, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
   const Function& func = Function::Handle(ref.GetFunctionReferent());
+  if (func.IsImplicitConstructor() || func.IsSignatureFunction()) {
+    // We may need to handle more cases when the restrictions on mixins are
+    // relaxed. In particular we might start associating some source with the
+    // forwarding constructors when it becomes possible to specify a particular
+    // constructor from the mixin to use.
+    return Instance::null();
+  }
   const Script& script = Script::Handle(func.script());
   const TokenStream& stream = TokenStream::Handle(script.tokens());
+  if (!script.HasSource()) {
+    // When source is not available, avoid printing the whole token stream and
+    // doing expensive position calculations.
+    return stream.GenerateSource(func.token_pos(), func.end_token_pos() + 1);
+  }
+
   const TokenStream::Iterator tkit(stream, func.end_token_pos());
   intptr_t from_line;
   intptr_t from_col;
@@ -2059,7 +2071,10 @@
        String::Handle(func.name()).Equals("<anonymous closure>"))) {  // Case 3.
     last_tok_len = 0;
   }
-  return script.GetSnippet(from_line, from_col, to_line, to_col + last_tok_len);
+  const Instance& result = Instance::Handle(
+      script.GetSnippet(from_line, from_col, to_line, to_col + last_tok_len));
+  ASSERT(!result.IsNull());
+  return result.raw();
 }
 
 
@@ -2095,4 +2110,17 @@
   return InstantiateType(type, instantiator);
 }
 
+DEFINE_NATIVE_ENTRY(TypeMirror_subtypeTest, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, a, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, b, arguments->NativeArgAt(1));
+  return Bool::Get(a.IsSubtypeOf(b, NULL)).raw();
+}
+
+DEFINE_NATIVE_ENTRY(TypeMirror_moreSpecificTest, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, a, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, b, arguments->NativeArgAt(1));
+  return Bool::Get(a.IsMoreSpecificThan(b, NULL)).raw();
+}
+
+
 }  // namespace dart
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 8f5a1a2..f527df7 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -109,6 +109,12 @@
 List _metadata(reflectee)
     native 'DeclarationMirror_metadata';
 
+bool _subtypeTest(Type a, Type b)
+    native 'TypeMirror_subtypeTest';
+
+bool _moreSpecificTest(Type a, Type b)
+    native 'TypeMirror_moreSpecificTest';
+
 class _LocalMirrorSystem extends MirrorSystem {
   final Map<Uri, LibraryMirror> libraries;
   final IsolateMirror isolate;
@@ -851,6 +857,31 @@
 
   int get hashCode => simpleName.hashCode;
 
+  bool isSubtypeOf(TypeMirror other) {
+    if (other == currentMirrorSystem().dynamicType) return true;
+    if (other == currentMirrorSystem().voidType) return false;
+    return _subtypeTest(_reflectedType, other._reflectedType);
+  }
+
+  bool isAssignableTo(TypeMirror other) {
+    if (other == currentMirrorSystem().dynamicType) return true;
+    if (other == currentMirrorSystem().voidType) return false;
+    return _moreSpecificTest(_reflectedType, other._reflectedType)
+        || _moreSpecificTest(other._reflectedType, _reflectedType);
+  }
+
+  bool isSubclassOf(ClassMirror other) {
+    if (other is! ClassMirror) throw new ArgumentError(other);
+    ClassMirror otherDeclaration = other.originalDeclaration;
+    ClassMirror c = this;
+    while (c != null) {
+      c = c.originalDeclaration;
+      if (c == otherDeclaration) return true;
+      c = c.superclass;
+    }
+    return false;
+  }
+
   static _library(reflectee)
       native "ClassMirror_library";
 
@@ -1023,7 +1054,8 @@
   }
 
   bool get hasReflectedType => false;
-  Type get reflectedType => throw new UnsupportedError() ;
+  Type get reflectedType => throw new UnsupportedError();
+  Type get _reflectedType => _reflectee;
 
   List<TypeVariableMirror> get typeVariables => emptyList;
   List<TypeMirror> get typeArguments => emptyList;
@@ -1040,6 +1072,19 @@
   }
   int get hashCode => simpleName.hashCode;
 
+  bool isSubtypeOf(TypeMirror other) {
+    if (other == currentMirrorSystem().dynamicType) return true;
+    if (other == currentMirrorSystem().voidType) return false;
+    return _subtypeTest(_reflectedType, other._reflectedType);
+  }
+
+  bool isAssignableTo(TypeMirror other) {
+    if (other == currentMirrorSystem().dynamicType) return true;
+    if (other == currentMirrorSystem().voidType) return false;
+    return _moreSpecificTest(_reflectedType, other._reflectedType)
+        || _moreSpecificTest(other._reflectedType, _reflectedType);
+  }
+
   static DeclarationMirror _TypeVariableMirror_owner(reflectee)
       native "TypeVariableMirror_owner";
 
@@ -1127,6 +1172,19 @@
 
   String toString() => "TypedefMirror on '${_n(simpleName)}'";
 
+  bool isSubtypeOf(TypeMirror other) {
+    if (other == currentMirrorSystem().dynamicType) return true;
+    if (other == currentMirrorSystem().voidType) return false;
+    return _subtypeTest(_reflectedType, other._reflectedType);
+  }
+
+  bool isAssignableTo(TypeMirror other) {
+    if (other == currentMirrorSystem().dynamicType) return true;
+    if (other == currentMirrorSystem().voidType) return false;
+    return _moreSpecificTest(_reflectedType, other._reflectedType)
+        || _moreSpecificTest(other._reflectedType, _reflectedType);
+  }
+
   static _nativeReferent(reflectedType)
       native "TypedefMirror_referent";
 
@@ -1359,7 +1417,6 @@
   String get source {
     if (_source == null) {
       _source = _MethodMirror_source(_reflectee);
-      assert(_source != null);
     }
     return _source;
   }
@@ -1532,6 +1589,14 @@
   int get hashCode => simpleName.hashCode;
 
   String toString() => "TypeMirror on '${_n(simpleName)}'";
+
+  bool isSubtypeOf(TypeMirror other) {
+    return simpleName == #dynamic || other is _SpecialTypeMirror;
+  }
+
+  bool isAssignableTo(TypeMirror other) {
+    return simpleName == #dynamic || other is _SpecialTypeMirror;
+  }
 }
 
 class _Mirrors {
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 30a9e17..3836838 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -114,8 +114,8 @@
   // Instantiator at position 1 is not used. It is passed along so that the call
   // can be easily converted to an optimized implementation. Instantiator is
   // used to populate the subtype cache.
-  const AbstractTypeArguments& instantiator_type_arguments =
-      AbstractTypeArguments::CheckedHandle(arguments->NativeArgAt(2));
+  const TypeArguments& instantiator_type_arguments =
+      TypeArguments::CheckedHandle(arguments->NativeArgAt(2));
   const AbstractType& type =
       AbstractType::CheckedHandle(arguments->NativeArgAt(3));
   const Bool& negate = Bool::CheckedHandle(arguments->NativeArgAt(4));
@@ -159,8 +159,8 @@
   // Instantiator at position 1 is not used. It is passed along so that the call
   // can be easily converted to an optimized implementation. Instantiator is
   // used to populate the subtype cache.
-  const AbstractTypeArguments& instantiator_type_arguments =
-      AbstractTypeArguments::CheckedHandle(arguments->NativeArgAt(2));
+  const TypeArguments& instantiator_type_arguments =
+      TypeArguments::CheckedHandle(arguments->NativeArgAt(2));
   const AbstractType& type =
       AbstractType::CheckedHandle(arguments->NativeArgAt(3));
   ASSERT(type.IsFinalized());
diff --git a/runtime/lib/regexp.cc b/runtime/lib/regexp.cc
index 9ac59da..4152923 100644
--- a/runtime/lib/regexp.cc
+++ b/runtime/lib/regexp.cc
@@ -13,8 +13,7 @@
 namespace dart {
 
 DEFINE_NATIVE_ENTRY(JSSyntaxRegExp_factory, 4) {
-  ASSERT(AbstractTypeArguments::CheckedHandle(
-      arguments->NativeArgAt(0)).IsNull());
+  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(String, pattern, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(
       Instance, handle_multi_line, arguments->NativeArgAt(2));
diff --git a/runtime/lib/simd128.cc b/runtime/lib/simd128.cc
index 5485953..e216555 100644
--- a/runtime/lib/simd128.cc
+++ b/runtime/lib/simd128.cc
@@ -24,8 +24,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Float32x4_fromDoubles, 5) {
-  ASSERT(AbstractTypeArguments::CheckedHandle(
-      arguments->NativeArgAt(0)).IsNull());
+  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(Double, x, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Double, y, arguments->NativeArgAt(2));
   GET_NON_NULL_NATIVE_ARGUMENT(Double, z, arguments->NativeArgAt(3));
@@ -39,8 +38,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Float32x4_splat, 2) {
-  ASSERT(AbstractTypeArguments::CheckedHandle(
-      arguments->NativeArgAt(0)).IsNull());
+  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(Double, v, arguments->NativeArgAt(1));
   float _v = v.value();
   return Float32x4::New(_v, _v, _v, _v);
@@ -48,8 +46,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Float32x4_zero, 1) {
-  ASSERT(AbstractTypeArguments::CheckedHandle(
-      arguments->NativeArgAt(0)).IsNull());
+  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
   return Float32x4::New(0.0f, 0.0f, 0.0f, 0.0f);
 }
 
@@ -408,8 +405,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Int32x4_fromInts, 5) {
-  ASSERT(AbstractTypeArguments::CheckedHandle(
-      arguments->NativeArgAt(0)).IsNull());
+  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, x, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, y, arguments->NativeArgAt(2));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, z, arguments->NativeArgAt(3));
@@ -423,8 +419,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Int32x4_fromBools, 5) {
-  ASSERT(AbstractTypeArguments::CheckedHandle(
-      arguments->NativeArgAt(0)).IsNull());
+  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(Bool, x, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Bool, y, arguments->NativeArgAt(2));
   GET_NON_NULL_NATIVE_ARGUMENT(Bool, z, arguments->NativeArgAt(3));
@@ -717,8 +712,7 @@
 
 
 DEFINE_NATIVE_ENTRY(Float64x2_fromDoubles, 3) {
-  ASSERT(AbstractTypeArguments::CheckedHandle(
-      arguments->NativeArgAt(0)).IsNull());
+  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(Double, x, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Double, y, arguments->NativeArgAt(2));
   return Float64x2::New(x.value(), y.value());
@@ -726,23 +720,20 @@
 
 
 DEFINE_NATIVE_ENTRY(Float64x2_splat, 2) {
-  ASSERT(AbstractTypeArguments::CheckedHandle(
-      arguments->NativeArgAt(0)).IsNull());
+  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(Double, v, arguments->NativeArgAt(1));
   return Float64x2::New(v.value(), v.value());
 }
 
 
 DEFINE_NATIVE_ENTRY(Float64x2_zero, 1) {
-  ASSERT(AbstractTypeArguments::CheckedHandle(
-      arguments->NativeArgAt(0)).IsNull());
+  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
   return Float64x2::New(0.0, 0.0);
 }
 
 
 DEFINE_NATIVE_ENTRY(Float64x2_fromFloat32x4, 2) {
-  ASSERT(AbstractTypeArguments::CheckedHandle(
-      arguments->NativeArgAt(0)).IsNull());
+  ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
   GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, v, arguments->NativeArgAt(1));
   double _x = v.x();
   double _y = v.y();
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 41bfa56..e275f20 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -5,6 +5,7 @@
 # These tests are expected to crash on all platforms.
 cc/ArrayNew_Overflow_Crash: Crash
 cc/AllocGeneric_Overflow: Crash
+cc/CodeImmutability: Crash
 
 cc/SNPrint_BadArgs: Skip
 
diff --git a/runtime/tools/create_resources.py b/runtime/tools/create_resources.py
index ab8371d..255ef92 100644
--- a/runtime/tools/create_resources.py
+++ b/runtime/tools/create_resources.py
@@ -26,7 +26,7 @@
     resource_url = '/%s' % resource_file_name
     result += '// %s\n' % resource_file
     result += 'const char '
-    resource_name = re.sub(r'(/|\.|-)', '_', resource_file_name) + '_'
+    resource_name = re.sub(r'(/|\.|-|\\)', '_', resource_file_name) + '_'
     result += resource_name
     result += '[] = {\n   '
     fileHandle = open(resource_file, 'rb')
diff --git a/runtime/vm/assembler.cc b/runtime/vm/assembler.cc
index 5a8f846..ff08c9a 100644
--- a/runtime/vm/assembler.cc
+++ b/runtime/vm/assembler.cc
@@ -149,12 +149,25 @@
     pointer_offsets_->Add(position);
   }
 
+  virtual bool IsPointerOffset() const { return true; }
+
  private:
   ZoneGrowableArray<intptr_t>* pointer_offsets_;
   const Object& object_;
 };
 
 
+intptr_t AssemblerBuffer::CountPointerOffsets() const {
+  intptr_t count = 0;
+  AssemblerFixup* current = fixup_;
+  while (current != NULL) {
+    if (current->IsPointerOffset()) ++count;
+    current = current->previous_;
+  }
+  return count;
+}
+
+
 void AssemblerBuffer::EmitObject(const Object& object) {
   // Since we are going to store the handle as part of the fixup information
   // the handle needs to be a zone handle.
diff --git a/runtime/vm/assembler.h b/runtime/vm/assembler.h
index c08f923..043ea56 100644
--- a/runtime/vm/assembler.h
+++ b/runtime/vm/assembler.h
@@ -53,6 +53,8 @@
  public:
   virtual void Process(const MemoryRegion& region, intptr_t position) = 0;
 
+  virtual bool IsPointerOffset() const = 0;
+
   // It would be ideal if the destructor method could be made private,
   // but the g++ compiler complains when this is subclassed.
   virtual ~AssemblerFixup() { UNREACHABLE(); }
@@ -118,6 +120,10 @@
     fixup_ = fixup;
   }
 
+  // Count the fixups that produce a pointer offset, without processing
+  // the fixups.
+  intptr_t CountPointerOffsets() const;
+
   // Get the size of the emitted code.
   intptr_t Size() const { return cursor_ - contents_; }
   uword contents() const { return contents_; }
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index 18697a8..7f9933d 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -1798,6 +1798,8 @@
     ASSERT((movt == Instr::kNopInstruction) &&
            (bx == Instr::kNopInstruction));
   }
+
+  virtual bool IsPointerOffset() const { return false; }
 };
 
 
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index 997aea0..87046cc 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -313,6 +313,11 @@
   // Misc. functionality
   intptr_t CodeSize() const { return buffer_.Size(); }
   intptr_t prologue_offset() const { return prologue_offset_; }
+
+  // Count the fixups that produce a pointer offset, without processing
+  // the fixups.  On ARM there are no pointers in code.
+  intptr_t CountPointerOffsets() const { return 0; }
+
   const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const {
     ASSERT(buffer_.pointer_offsets().length() == 0);  // No pointers in code.
     return buffer_.pointer_offsets();
diff --git a/runtime/vm/assembler_ia32.cc b/runtime/vm/assembler_ia32.cc
index 111b136..67b62df 100644
--- a/runtime/vm/assembler_ia32.cc
+++ b/runtime/vm/assembler_ia32.cc
@@ -80,6 +80,8 @@
     int32_t delta = region.start() + position + sizeof(int32_t);
     region.Store<int32_t>(position, pointer - delta);
   }
+
+  virtual bool IsPointerOffset() const { return false; }
 };
 
 
diff --git a/runtime/vm/assembler_ia32.h b/runtime/vm/assembler_ia32.h
index 346f5b6..cfff9a9 100644
--- a/runtime/vm/assembler_ia32.h
+++ b/runtime/vm/assembler_ia32.h
@@ -720,6 +720,12 @@
 
   intptr_t CodeSize() const { return buffer_.Size(); }
   intptr_t prologue_offset() const { return prologue_offset_; }
+
+  // Count the fixups that produce a pointer offset, without processing
+  // the fixups.
+  intptr_t CountPointerOffsets() const {
+    return buffer_.CountPointerOffsets();
+  }
   const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const {
     return buffer_.pointer_offsets();
   }
diff --git a/runtime/vm/assembler_mips.cc b/runtime/vm/assembler_mips.cc
index 7406be6..85f6a645 100644
--- a/runtime/vm/assembler_mips.cc
+++ b/runtime/vm/assembler_mips.cc
@@ -106,6 +106,8 @@
     // the far branch with a near one, and so these instructions should be NOPs.
     ASSERT((high == Instr::kNopInstruction) && (low == Instr::kNopInstruction));
   }
+
+  virtual bool IsPointerOffset() const { return false; }
 };
 
 
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index d7931b0..d80baee 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -163,6 +163,13 @@
   // Misc. functionality
   intptr_t CodeSize() const { return buffer_.Size(); }
   intptr_t prologue_offset() const { return prologue_offset_; }
+
+  // Count the fixups that produce a pointer offset, without processing
+  // the fixups.
+  intptr_t CountPointerOffsets() const {
+    return buffer_.CountPointerOffsets();
+  }
+
   const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const {
     return buffer_.pointer_offsets();
   }
diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h
index 6d419a6..1fb9c2e 100644
--- a/runtime/vm/assembler_x64.h
+++ b/runtime/vm/assembler_x64.h
@@ -770,6 +770,13 @@
 
   intptr_t CodeSize() const { return buffer_.Size(); }
   intptr_t prologue_offset() const { return prologue_offset_; }
+
+  // Count the fixups that produce a pointer offset, without processing
+  // the fixups.
+  intptr_t CountPointerOffsets() const {
+    return buffer_.CountPointerOffsets();
+  }
+
   const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const {
     return buffer_.pointer_offsets();
   }
diff --git a/runtime/vm/ast.h b/runtime/vm/ast.h
index f2de67b..b2e87e8 100644
--- a/runtime/vm/ast.h
+++ b/runtime/vm/ast.h
@@ -299,8 +299,8 @@
     ASSERT(!type_.IsNull());
     ASSERT(type_.IsFinalized());
     // Type may be uninstantiated when creating a generic list literal.
-    ASSERT((type_.arguments() == AbstractTypeArguments::null()) ||
-           ((AbstractTypeArguments::Handle(type_.arguments()).Length() == 1)));
+    ASSERT((type_.arguments() == TypeArguments::null()) ||
+           ((TypeArguments::Handle(type_.arguments()).Length() == 1)));
   }
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(ArrayNode);
@@ -1551,7 +1551,7 @@
 class ConstructorCallNode : public AstNode {
  public:
   ConstructorCallNode(intptr_t token_pos,
-                      const AbstractTypeArguments& type_arguments,
+                      const TypeArguments& type_arguments,
                       const Function& constructor,
                       ArgumentListNode* arguments)
       : AstNode(token_pos),
@@ -1563,7 +1563,7 @@
     ASSERT(arguments_ != NULL);
   }
 
-  const AbstractTypeArguments& type_arguments() const {
+  const TypeArguments& type_arguments() const {
     return type_arguments_;
   }
   const Function& constructor() const { return constructor_; }
@@ -1576,7 +1576,7 @@
   DECLARE_COMMON_NODE_FUNCTIONS(ConstructorCallNode);
 
  private:
-  const AbstractTypeArguments& type_arguments_;
+  const TypeArguments& type_arguments_;
   const Function& constructor_;
   ArgumentListNode* arguments_;
 
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index 62c04de..94d8baf 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -482,4 +482,24 @@
   benchmark->set_score(elapsed_time);
 }
 
+
+BENCHMARK(EnterExitIsolate) {
+  const char* kScriptChars =
+      "import 'dart:core';\n"
+      "\n";
+  const intptr_t kLoopCount = 1000000;
+  TestCase::LoadTestScript(kScriptChars, NULL);
+  Api::CheckIsolateState(Isolate::Current());
+  Dart_Isolate isolate = Dart_CurrentIsolate();
+  Timer timer(true, "Enter and Exit isolate");
+  timer.Start();
+  for (intptr_t i = 0; i < kLoopCount; i++) {
+    Dart_ExitIsolate();
+    Dart_EnterIsolate(isolate);
+  }
+  timer.Stop();
+  int64_t elapsed_time = timer.TotalElapsedTime();
+  benchmark->set_score(elapsed_time);
+}
+
 }  // namespace dart
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 0c8faca..c5e5b85 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -297,6 +297,8 @@
   V(ClosureMirror_find_in_context, 2)                                          \
   V(ClosureMirror_function, 1)                                                 \
   V(ClosureMirror_apply, 2)                                                    \
+  V(TypeMirror_subtypeTest, 2)                                                 \
+  V(TypeMirror_moreSpecificTest, 2)                                            \
   V(ClassMirror_library, 1)                                                    \
   V(ClassMirror_supertype, 1)                                                  \
   V(ClassMirror_supertype_instantiated, 1)                                     \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 7221924..5f6ded3 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -402,8 +402,7 @@
     // If the target type refers to type parameters, substitute them with the
     // type arguments of the redirection type.
     if (!target_type.IsInstantiated()) {
-      const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(
-          type.arguments());
+      const TypeArguments& type_args = TypeArguments::Handle(type.arguments());
       Error& bound_error = Error::Handle();
       target_type ^= target_type.InstantiateFrom(type_args, &bound_error);
       if (bound_error.IsNull()) {
@@ -461,8 +460,7 @@
   }
 
   // Resolve type arguments, if any.
-  const AbstractTypeArguments& arguments =
-      AbstractTypeArguments::Handle(type.arguments());
+  const TypeArguments& arguments = TypeArguments::Handle(type.arguments());
   if (!arguments.IsNull()) {
     const intptr_t num_arguments = arguments.Length();
     AbstractType& type_argument = AbstractType::Handle();
@@ -531,7 +529,7 @@
 // same time. Canonicalization happens when pending types are processed.
 void ClassFinalizer::FinalizeTypeArguments(
     const Class& cls,
-    const AbstractTypeArguments& arguments,
+    const TypeArguments& arguments,
     intptr_t num_uninitialized_arguments,
     Error* bound_error,
     GrowableObjectArray* pending_types) {
@@ -552,7 +550,7 @@
           cls, super_type, kFinalize, pending_types);
       cls.set_super_type(super_type);
     }
-    AbstractTypeArguments& super_type_args = AbstractTypeArguments::Handle(
+    TypeArguments& super_type_args = TypeArguments::Handle(
         super_type.arguments());
     // Offset of super type's type parameters in cls' type argument vector.
     const intptr_t super_offset = num_super_type_args - num_super_type_params;
@@ -594,10 +592,9 @@
 // Replace a type argument that cannot be checked at compile time by a
 // BoundedType, thereby postponing the bound check to run time.
 // Return a bound error if a type argument is not within bound at compile time.
-void ClassFinalizer::CheckTypeArgumentBounds(
-    const Class& cls,
-    const AbstractTypeArguments& arguments,
-    Error* bound_error) {
+void ClassFinalizer::CheckTypeArgumentBounds(const Class& cls,
+                                             const TypeArguments& arguments,
+                                             Error* bound_error) {
   if (!cls.is_type_finalized()) {
     FinalizeUpperBounds(cls);
   }
@@ -690,8 +687,7 @@
 
 void ClassFinalizer::CheckTypeBounds(const Class& cls, const Type& type) {
   ASSERT(type.IsFinalized());
-  AbstractTypeArguments& arguments =
-      AbstractTypeArguments::Handle(type.arguments());
+  TypeArguments& arguments = TypeArguments::Handle(type.arguments());
   if (arguments.IsNull()) {
     return;
   }
@@ -830,8 +826,8 @@
   // Check the number of parsed type arguments, if any.
   // Specifying no type arguments indicates a raw type, which is not an error.
   // However, type parameter bounds are checked below, even for a raw type.
-  AbstractTypeArguments& arguments =
-      AbstractTypeArguments::Handle(parameterized_type.arguments());
+  TypeArguments& arguments =
+      TypeArguments::Handle(parameterized_type.arguments());
   if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) {
     // Wrong number of type arguments. The type is mapped to the raw type.
     if (FLAG_error_on_bad_type) {
@@ -844,7 +840,7 @@
     }
     // Make the type raw and continue without reporting any error.
     // A static warning should have been reported.
-    arguments = AbstractTypeArguments::null();
+    arguments = TypeArguments::null();
     parameterized_type.set_arguments(arguments);
   }
 
@@ -963,7 +959,7 @@
   if (FLAG_trace_type_finalization) {
     OS::Print("Done finalizing type '%s' with %" Pd " type args: %s\n",
               String::Handle(parameterized_type.Name()).ToCString(),
-              parameterized_type.arguments() == AbstractTypeArguments::null() ?
+              parameterized_type.arguments() == TypeArguments::null() ?
                   0 : num_type_arguments,
               parameterized_type.ToCString());
   }
@@ -1050,8 +1046,8 @@
   const intptr_t num_type_params = cls.NumTypeParameters();
   TypeParameter& type_param = TypeParameter::Handle();
   AbstractType& bound = AbstractType::Handle();
-  const AbstractTypeArguments& type_params =
-      AbstractTypeArguments::Handle(cls.type_parameters());
+  const TypeArguments& type_params =
+      TypeArguments::Handle(cls.type_parameters());
   ASSERT((type_params.IsNull() && (num_type_params == 0)) ||
          (type_params.Length() == num_type_params));
   // In a first pass, resolve all bounds. This guarantees that finalization
@@ -1069,8 +1065,8 @@
   const intptr_t num_type_params = cls.NumTypeParameters();
   TypeParameter& type_param = TypeParameter::Handle();
   AbstractType& bound = AbstractType::Handle();
-  const AbstractTypeArguments& type_params =
-      AbstractTypeArguments::Handle(cls.type_parameters());
+  const TypeArguments& type_params =
+      TypeArguments::Handle(cls.type_parameters());
   ASSERT((type_params.IsNull() && (num_type_params == 0)) ||
          (type_params.Length() == num_type_params));
   for (intptr_t i = 0; i < num_type_params; i++) {
@@ -1191,7 +1187,7 @@
       if (!error.IsNull() ||
           (!type.IsDynamicType() &&
            !const_value.IsInstanceOf(type,
-                                     AbstractTypeArguments::Handle(),
+                                     Object::null_type_arguments(),
                                      &error))) {
         if (FLAG_error_on_bad_type) {
           const AbstractType& const_value_type = AbstractType::Handle(
@@ -1386,7 +1382,7 @@
 // CloneMixinAppTypeParameters decorates class S&M with type parameters T` and
 // T, and use them as type arguments in S<T`> and M<T>.
 void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) {
-  ASSERT(mixin_app_class.type_parameters() == AbstractTypeArguments::null());
+  ASSERT(mixin_app_class.type_parameters() == TypeArguments::null());
   Isolate* isolate = Isolate::Current();
   const AbstractType& super_type = AbstractType::Handle(isolate,
       mixin_app_class.super_type());
@@ -1664,7 +1660,7 @@
     // the mixin class typedef.
     const Type& generic_mixin_type = Type::Handle(isolate,
         Type::New(Class::Handle(isolate, aliased_mixin_type.type_class()),
-                  Object::null_abstract_type_arguments(),
+                  Object::null_type_arguments(),
                   aliased_mixin_type.token_pos()));
     inserted_class.set_mixin(generic_mixin_type);
     // The interface will be set in CloneMixinAppTypeParameters.
@@ -1714,8 +1710,8 @@
   ASSERT(inserted_class.NumTypeParameters() ==
          (num_super_type_params + num_aliased_mixin_type_params));
   // The aliased_mixin_type may be raw.
-  const AbstractTypeArguments& mixin_class_super_type_args =
-      AbstractTypeArguments::Handle(isolate,
+  const TypeArguments& mixin_class_super_type_args =
+      TypeArguments::Handle(isolate,
           AbstractType::Handle(isolate, mixin_class.super_type()).arguments());
   TypeArguments& new_mixin_type_args = TypeArguments::Handle(isolate);
   if ((num_aliased_mixin_type_params > 0) &&
@@ -2224,8 +2220,7 @@
         !IsAliasCycleFree(type_class, visited)) {
       return false;
     }
-    const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(
-        type.arguments());
+    const TypeArguments& type_args = TypeArguments::Handle(type.arguments());
     if (!type_args.IsNull()) {
       AbstractType& type_arg = AbstractType::Handle();
       for (intptr_t i = 0; i < type_args.Length(); i++) {
@@ -2261,8 +2256,8 @@
   // Check the bounds of this signature type.
   const intptr_t num_type_params = cls.NumTypeParameters();
   TypeParameter& type_param = TypeParameter::Handle();
-  const AbstractTypeArguments& type_params =
-      AbstractTypeArguments::Handle(cls.type_parameters());
+  const TypeArguments& type_params =
+      TypeArguments::Handle(cls.type_parameters());
   ASSERT((type_params.IsNull() && (num_type_params == 0)) ||
          (type_params.Length() == num_type_params));
   for (intptr_t i = 0; i < num_type_params; i++) {
@@ -2329,8 +2324,7 @@
     const GrowableObjectArray& collected_args) {
   ASSERT(type.HasResolvedTypeClass());
   Class& type_class = Class::Handle(type.type_class());
-  AbstractTypeArguments& type_args =
-      AbstractTypeArguments::Handle(type.arguments());
+  TypeArguments& type_args = TypeArguments::Handle(type.arguments());
   const intptr_t num_type_parameters = type_class.NumTypeParameters();
   const intptr_t num_type_arguments =
       type_args.IsNull() ? 0 : type_args.Length();
@@ -2444,7 +2438,7 @@
       mixin_app_class.set_super_type(mixin_super_type);
       mixin_type_class = mixin_type.type_class();
       generic_mixin_type = Type::New(mixin_type_class,
-                                     Object::null_abstract_type_arguments(),
+                                     Object::null_type_arguments(),
                                      mixin_type.token_pos());
       mixin_app_class.set_mixin(generic_mixin_type);
       mixin_app_class.set_is_synthesized_class();
@@ -2462,7 +2456,7 @@
     // the next mixin application class. It is however too early to provide the
     // correct super type arguments. We use the raw type for now.
     mixin_super_type = Type::New(mixin_app_class,
-                                 Object::null_abstract_type_arguments(),
+                                 Object::null_type_arguments(),
                                  mixin_type.token_pos());
   }
   AbstractType& type_arg = AbstractType::Handle();
@@ -2755,7 +2749,7 @@
   // Make the type raw, since it may not be possible to
   // properly finalize its type arguments.
   type.set_type_class(Class::Handle(Object::dynamic_class()));
-  type.set_arguments(Object::null_abstract_type_arguments());
+  type.set_arguments(Object::null_type_arguments());
   if (!type.IsFinalized()) {
     type.SetIsFinalized();
     // Do not canonicalize malformed types, since they may not be resolved.
diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h
index a62a3ed..9e1d8bd 100644
--- a/runtime/vm/class_finalizer.h
+++ b/runtime/vm/class_finalizer.h
@@ -11,17 +11,17 @@
 namespace dart {
 
 class AbstractType;
-class MixinAppType;
-class AbstractTypeArguments;
 class Class;
 class Error;
 class Function;
 class GrowableObjectArray;
+class MixinAppType;
 class RawAbstractType;
 class RawClass;
 class RawType;
 class Script;
 class Type;
+class TypeArguments;
 class UnresolvedClass;
 
 // Traverses all pending, unfinalized classes, validates and marks them as
@@ -141,13 +141,13 @@
   static void FinalizeTypeParameters(const Class& cls,
                                      GrowableObjectArray* pending_types = NULL);
   static void FinalizeTypeArguments(const Class& cls,
-                                    const AbstractTypeArguments& arguments,
+                                    const TypeArguments& arguments,
                                     intptr_t num_uninitialized_arguments,
                                     Error* bound_error,
                                     GrowableObjectArray* pending_types);
   static void CheckTypeBounds(const Class& cls, const Type& type);
   static void CheckTypeArgumentBounds(const Class& cls,
-                                      const AbstractTypeArguments& arguments,
+                                      const TypeArguments& arguments,
                                       Error* bound_error);
   static void ResolveUpperBounds(const Class& cls);
   static void FinalizeUpperBounds(const Class& cls);
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 511daa5..cc90af3 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -91,8 +91,8 @@
   const Smi& length = Smi::CheckedHandle(arguments.ArgAt(0));
   const Array& array = Array::Handle(Array::New(length.Value()));
   arguments.SetReturn(array);
-  AbstractTypeArguments& element_type =
-      AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
+  TypeArguments& element_type =
+      TypeArguments::CheckedHandle(arguments.ArgAt(1));
   // An Array is raw or takes one type argument. However, its type argument
   // vector may be longer than 1 due to a type optimization reusing the type
   // argument vector of the instantiator.
@@ -102,6 +102,15 @@
 }
 
 
+// Helper returning the token position of the Dart caller.
+static intptr_t GetCallerLocation() {
+  DartFrameIterator iterator;
+  StackFrame* caller_frame = iterator.NextFrame();
+  ASSERT(caller_frame != NULL);
+  return caller_frame->GetTokenPos();
+}
+
+
 // Allocate a new object.
 // Arg0: class of the object that needs to be allocated.
 // Arg1: type arguments of the object that needs to be allocated.
@@ -116,8 +125,8 @@
     ASSERT(Instance::CheckedHandle(arguments.ArgAt(1)).IsNull());
     return;
   }
-  AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
+  TypeArguments& type_arguments =
+      TypeArguments::CheckedHandle(arguments.ArgAt(1));
   // If no instantiator is provided, set the type arguments and return.
   if (Object::Handle(arguments.ArgAt(2)).IsSmi()) {
     ASSERT(Smi::CheckedHandle(arguments.ArgAt(2)).Value() ==
@@ -134,61 +143,17 @@
   // A still uninstantiated type argument vector must have the correct length.
   ASSERT(!type_arguments.IsInstantiated() &&
          (type_arguments.Length() == cls.NumTypeArguments()));
-  const AbstractTypeArguments& instantiator =
-      AbstractTypeArguments::CheckedHandle(arguments.ArgAt(2));
+  const TypeArguments& instantiator =
+      TypeArguments::CheckedHandle(arguments.ArgAt(2));
   ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
   // 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 = InstantiatedTypeArguments::New(type_arguments, instantiator);
-  instance.SetTypeArguments(type_arguments);
-}
-
-
-// Helper returning the token position of the Dart caller.
-static intptr_t GetCallerLocation() {
-  DartFrameIterator iterator;
-  StackFrame* caller_frame = iterator.NextFrame();
-  ASSERT(caller_frame != NULL);
-  return caller_frame->GetTokenPos();
-}
-
-
-// Allocate a new object of a generic type and check that the instantiated type
-// arguments are within the declared bounds or throw a dynamic type error.
-// Arg0: class of the object that needs to be allocated.
-// Arg1: type arguments of the object that needs to be allocated.
-// Arg2: type arguments of the instantiator or kNoInstantiator.
-// Return value: newly allocated object.
-DEFINE_RUNTIME_ENTRY(AllocateObjectWithBoundsCheck, 3) {
-  ASSERT(FLAG_enable_type_checks);
-  const Class& cls = Class::CheckedHandle(arguments.ArgAt(0));
-  const Instance& instance = Instance::Handle(Instance::New(cls));
-  arguments.SetReturn(instance);
-  ASSERT(cls.NumTypeArguments() > 0);
-  AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
-  if (Object::Handle(arguments.ArgAt(2)).IsSmi()) {
-    ASSERT(Smi::CheckedHandle(arguments.ArgAt(2)).Value() ==
-           StubCode::kNoInstantiator);
-    // Unless null (for a raw type), the type argument vector may be longer than
-    // necessary due to a type optimization reusing the type argument vector of
-    // the instantiator.
-    ASSERT(type_arguments.IsNull() ||
-           (type_arguments.IsInstantiated() &&
-            (type_arguments.Length() >= cls.NumTypeArguments())));
-  } else {
-    // A still uninstantiated type argument vector must have the correct length.
-    ASSERT(!type_arguments.IsInstantiated() &&
-           (type_arguments.Length() == cls.NumTypeArguments()));
-    const AbstractTypeArguments& instantiator =
-        AbstractTypeArguments::CheckedHandle(arguments.ArgAt(2));
-    ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
+  if (FLAG_enable_type_checks) {
     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, &bound_error);
+    type_arguments =
+        type_arguments.InstantiateAndCanonicalizeFrom(instantiator,
+                                                      &bound_error);
     if (!bound_error.IsNull()) {
       // Throw a dynamic type error.
       const intptr_t location = GetCallerLocation();
@@ -199,6 +164,9 @@
           Symbols::Empty(), bound_error_message);
       UNREACHABLE();
     }
+  } else {
+    type_arguments =
+        type_arguments.InstantiateAndCanonicalizeFrom(instantiator, NULL);
   }
   ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated());
   instance.SetTypeArguments(type_arguments);
@@ -211,8 +179,8 @@
 // Return value: instantiated type.
 DEFINE_RUNTIME_ENTRY(InstantiateType, 2) {
   AbstractType& type = AbstractType::CheckedHandle(arguments.ArgAt(0));
-  const AbstractTypeArguments& instantiator =
-      AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
+  const TypeArguments& instantiator =
+      TypeArguments::CheckedHandle(arguments.ArgAt(1));
   ASSERT(!type.IsNull() && !type.IsInstantiated());
   ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
   Error& bound_error = Error::Handle();
@@ -242,16 +210,17 @@
 // Arg1: instantiator type arguments.
 // Return value: instantiated type arguments.
 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) {
-  AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::CheckedHandle(arguments.ArgAt(0));
-  const AbstractTypeArguments& instantiator =
-      AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
+  TypeArguments& type_arguments =
+      TypeArguments::CheckedHandle(arguments.ArgAt(0));
+  const TypeArguments& instantiator =
+      TypeArguments::CheckedHandle(arguments.ArgAt(1));
   ASSERT(!type_arguments.IsNull() && !type_arguments.IsInstantiated());
   ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
   // 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 = InstantiatedTypeArguments::New(type_arguments, instantiator);
+  type_arguments =
+      type_arguments.InstantiateAndCanonicalizeFrom(instantiator, NULL);
   ASSERT(type_arguments.IsInstantiated());
   arguments.SetReturn(type_arguments);
 }
@@ -268,8 +237,8 @@
 DEFINE_RUNTIME_ENTRY(AllocateClosure, 2) {
   const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
   ASSERT(function.IsClosureFunction() && !function.IsImplicitClosureFunction());
-  const AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
+  const TypeArguments& type_arguments =
+      TypeArguments::CheckedHandle(arguments.ArgAt(1));
   ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated());
   // The current context was saved in the Isolate structure when entering the
   // runtime.
@@ -290,8 +259,8 @@
   const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
   ASSERT(function.IsImplicitInstanceClosureFunction());
   const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(1));
-  const AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::CheckedHandle(arguments.ArgAt(2));
+  const TypeArguments& type_arguments =
+      TypeArguments::CheckedHandle(arguments.ArgAt(2));
   ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated());
   Context& context = Context::Handle();
   context = Context::New(1);
@@ -331,7 +300,7 @@
     const char* message,
     const Instance& instance,
     const AbstractType& type,
-    const AbstractTypeArguments& instantiator_type_arguments,
+    const TypeArguments& instantiator_type_arguments,
     const Bool& result) {
   DartFrameIterator iterator;
   StackFrame* caller_frame = iterator.NextFrame();
@@ -370,51 +339,6 @@
 }
 
 
-// Converts InstantiatedTypeArguments to TypeArguments and stores it
-// into the instance. The assembly code can handle only type arguments of
-// class TypeArguments. Because of the overhead, do it only when needed.
-// Return true if type arguments have been replaced, false otherwise.
-static bool OptimizeTypeArguments(const Instance& instance) {
-  const Class& type_class = Class::ZoneHandle(instance.clazz());
-  if (type_class.NumTypeArguments() == 0) {
-    return false;
-  }
-  AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::Handle(instance.GetTypeArguments());
-  if (type_arguments.IsNull()) {
-    return false;
-  }
-  bool replaced = false;
-  if (type_arguments.IsInstantiatedTypeArguments()) {
-    AbstractTypeArguments& uninstantiated = AbstractTypeArguments::Handle();
-    AbstractTypeArguments& instantiator = AbstractTypeArguments::Handle();
-    do {
-      const InstantiatedTypeArguments& instantiated_type_arguments =
-          InstantiatedTypeArguments::Cast(type_arguments);
-      uninstantiated =
-          instantiated_type_arguments.uninstantiated_type_arguments();
-      instantiator = instantiated_type_arguments.instantiator_type_arguments();
-      Error& bound_error = Error::Handle();
-      type_arguments = uninstantiated.InstantiateFrom(instantiator,
-                                                      &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();
-    instance.SetTypeArguments(new_type_arguments);
-    replaced = true;
-  } else if (!type_arguments.IsCanonical()) {
-    AbstractTypeArguments& new_type_arguments = AbstractTypeArguments::Handle();
-    new_type_arguments = type_arguments.Canonicalize();
-    instance.SetTypeArguments(new_type_arguments);
-    replaced = true;
-  }
-  ASSERT(AbstractTypeArguments::Handle(
-      instance.GetTypeArguments()).IsTypeArguments());
-  return replaced;
-}
-
-
 // This updates the type test cache, an array containing 4-value elements
 // (instance class, instance type arguments, instantiator type arguments and
 // test_result). It can be applied to classes with type arguments in which
@@ -426,7 +350,7 @@
     const Instance& instance,
     const AbstractType& type,
     const Instance& instantiator,
-    const AbstractTypeArguments& incoming_instantiator_type_arguments,
+    const TypeArguments& instantiator_type_arguments,
     const Bool& result,
     const SubtypeTestCache& new_cache) {
   // Since the test is expensive, don't do it unless necessary.
@@ -438,37 +362,35 @@
     }
     return;
   }
-  // Instantiator type arguments may be canonicalized later.
-  AbstractTypeArguments& instantiator_type_arguments =
-      AbstractTypeArguments::Handle(incoming_instantiator_type_arguments.raw());
-  AbstractTypeArguments& instance_type_arguments =
-      AbstractTypeArguments::Handle();
+  if (instance.IsSmi()) {
+    if (FLAG_trace_type_checks) {
+      OS::Print("UpdateTypeTestCache: instance is Smi\n");
+    }
+    return;
+  }
+  TypeArguments& instance_type_arguments =
+      TypeArguments::Handle();
   const Class& instance_class = Class::Handle(instance.clazz());
 
-  // Canonicalize type arguments.
-  bool type_arguments_replaced = false;
   if (instance_class.NumTypeArguments() > 0) {
-    // Canonicalize type arguments.
-    type_arguments_replaced = OptimizeTypeArguments(instance);
     instance_type_arguments = instance.GetTypeArguments();
   }
-  if (!instantiator.IsNull()) {
-    if (OptimizeTypeArguments(instantiator)) {
-      type_arguments_replaced = true;
-    }
-    instantiator_type_arguments = instantiator.GetTypeArguments();
-  }
 
-  intptr_t last_instance_class_id = -1;
-  AbstractTypeArguments& last_instance_type_arguments =
-      AbstractTypeArguments::Handle();
-  AbstractTypeArguments& last_instantiator_type_arguments =
-      AbstractTypeArguments::Handle();
-  Bool& last_result = Bool::Handle();
   const intptr_t len = new_cache.NumberOfChecks();
   if (len >= FLAG_max_subtype_cache_entries) {
     return;
   }
+#if defined(DEBUG)
+  ASSERT(instance_type_arguments.IsNull() ||
+         instance_type_arguments.IsCanonical());
+  ASSERT(instantiator_type_arguments.IsNull() ||
+         instantiator_type_arguments.IsCanonical());
+  intptr_t last_instance_class_id = -1;
+  TypeArguments& last_instance_type_arguments =
+      TypeArguments::Handle();
+  TypeArguments& last_instantiator_type_arguments =
+      TypeArguments::Handle();
+  Bool& last_result = Bool::Handle();
   for (intptr_t i = 0; i < len; ++i) {
     new_cache.GetCheck(
         i,
@@ -480,28 +402,18 @@
         (last_instance_type_arguments.raw() == instance_type_arguments.raw()) &&
         (last_instantiator_type_arguments.raw() ==
          instantiator_type_arguments.raw())) {
-      if (FLAG_trace_type_checks) {
-        OS::PrintErr("%" Pd " ", i);
-        if (type_arguments_replaced) {
-          PrintTypeCheck("Duplicate cache entry (canonical.)", instance, type,
-              instantiator_type_arguments, result);
-        } else {
-          PrintTypeCheck("WARNING Duplicate cache entry", instance, type,
-              instantiator_type_arguments, result);
-        }
-      }
-      // Can occur if we have canonicalized arguments.
-      // TODO(srdjan): Investigate why this assert can fail.
-      // ASSERT(type_arguments_replaced);
+      OS::PrintErr("  Error in test cache %p ix: %" Pd ",", new_cache.raw(), i);
+      PrintTypeCheck(" duplicate cache entry", instance, type,
+          instantiator_type_arguments, result);
+      UNREACHABLE();
       return;
     }
   }
-  if (!instantiator_type_arguments.IsInstantiatedTypeArguments()) {
-    new_cache.AddCheck(instance_class.id(),
-                       instance_type_arguments,
-                       instantiator_type_arguments,
-                       result);
-  }
+#endif
+  new_cache.AddCheck(instance_class.id(),
+                     instance_type_arguments,
+                     instantiator_type_arguments,
+                     result);
   if (FLAG_trace_type_checks) {
     AbstractType& test_type = AbstractType::Handle(type.raw());
     if (!test_type.IsInstantiated()) {
@@ -550,8 +462,8 @@
   const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0));
   const AbstractType& type = AbstractType::CheckedHandle(arguments.ArgAt(1));
   const Instance& instantiator = Instance::CheckedHandle(arguments.ArgAt(2));
-  const AbstractTypeArguments& instantiator_type_arguments =
-      AbstractTypeArguments::CheckedHandle(arguments.ArgAt(3));
+  const TypeArguments& instantiator_type_arguments =
+      TypeArguments::CheckedHandle(arguments.ArgAt(3));
   const SubtypeTestCache& cache =
       SubtypeTestCache::CheckedHandle(arguments.ArgAt(4));
   ASSERT(type.IsFinalized());
@@ -598,8 +510,8 @@
       AbstractType::CheckedHandle(arguments.ArgAt(1));
   const Instance& dst_instantiator =
       Instance::CheckedHandle(arguments.ArgAt(2));
-  const AbstractTypeArguments& instantiator_type_arguments =
-      AbstractTypeArguments::CheckedHandle(arguments.ArgAt(3));
+  const TypeArguments& instantiator_type_arguments =
+      TypeArguments::CheckedHandle(arguments.ArgAt(3));
   const String& dst_name = String::CheckedHandle(arguments.ArgAt(4));
   const SubtypeTestCache& cache =
       SubtypeTestCache::CheckedHandle(arguments.ArgAt(5));
@@ -754,9 +666,14 @@
   // target.
   ASSERT(target_code.EntryPoint() !=
          CodePatcher::GetStaticCallTargetAt(caller_frame->pc(), caller_code));
-  CodePatcher::PatchStaticCallAt(caller_frame->pc(), caller_code,
-                                 target_code.EntryPoint());
-  caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code);
+  const Instructions& instrs =
+      Instructions::Handle(caller_code.instructions());
+  {
+    WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size());
+    CodePatcher::PatchStaticCallAt(caller_frame->pc(), caller_code,
+                                   target_code.EntryPoint());
+    caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code);
+  }
   if (FLAG_trace_patching) {
     OS::PrintErr("PatchStaticCall: patching from %#" Px " to '%s' %#" Px "\n",
         caller_frame->pc(),
@@ -1451,9 +1368,13 @@
   ASSERT(target_function.raw() == target_code.function());
 
   const Code& current_target_code = Code::Handle(target_function.CurrentCode());
-  CodePatcher::PatchStaticCallAt(frame->pc(), caller_code,
-                                 current_target_code.EntryPoint());
-  caller_code.SetStaticCallTargetCodeAt(frame->pc(), current_target_code);
+  const Instructions& instrs = Instructions::Handle(caller_code.instructions());
+  {
+    WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size());
+    CodePatcher::PatchStaticCallAt(frame->pc(), caller_code,
+                                   current_target_code.EntryPoint());
+    caller_code.SetStaticCallTargetCodeAt(frame->pc(), current_target_code);
+  }
   if (FLAG_trace_patching) {
     OS::PrintErr("FixCallersTarget: patching from %#" Px " to '%s' %#" Px "\n",
         frame->pc(),
@@ -1493,7 +1414,12 @@
   // is not a performance issue).
   uword lazy_deopt_jump = optimized_code.GetLazyDeoptPc();
   ASSERT(lazy_deopt_jump != 0);
-  CodePatcher::InsertCallAt(pc, lazy_deopt_jump);
+  const Instructions& instrs =
+      Instructions::Handle(optimized_code.instructions());
+  {
+    WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size());
+    CodePatcher::InsertCallAt(pc, lazy_deopt_jump);
+  }
   if (FLAG_trace_patching) {
     const String& name = String::Handle(function.name());
     OS::PrintErr("InsertCallAt: %" Px " to %" Px " for %s\n", pc,
diff --git a/runtime/vm/code_generator.h b/runtime/vm/code_generator.h
index 3931588..47c2d58 100644
--- a/runtime/vm/code_generator.h
+++ b/runtime/vm/code_generator.h
@@ -21,7 +21,6 @@
 DECLARE_RUNTIME_ENTRY(AllocateImplicitInstanceClosure);
 DECLARE_RUNTIME_ENTRY(AllocateContext);
 DECLARE_RUNTIME_ENTRY(AllocateObject);
-DECLARE_RUNTIME_ENTRY(AllocateObjectWithBoundsCheck);
 DECLARE_RUNTIME_ENTRY(BreakpointRuntimeHandler);
 DECLARE_RUNTIME_ENTRY(SingleStepHandler);
 DECLARE_RUNTIME_ENTRY(CloneContext);
@@ -72,6 +71,7 @@
   V(UnaryOp)                                                                   \
   V(UnboxInteger)                                                              \
   V(CheckClass)                                                                \
+  V(HoistedCheckClass)                                                         \
   V(CheckSmi)                                                                  \
   V(CheckArrayBound)                                                           \
   V(AtCall)                                                                    \
diff --git a/runtime/vm/code_patcher.cc b/runtime/vm/code_patcher.cc
index 283a706..f2b325d 100644
--- a/runtime/vm/code_patcher.cc
+++ b/runtime/vm/code_patcher.cc
@@ -6,9 +6,37 @@
 #include "vm/cpu.h"
 #include "vm/instructions.h"
 #include "vm/object.h"
+#include "vm/virtual_memory.h"
 
 namespace dart {
 
+DEFINE_FLAG(bool, write_protect_code, false, "Write protect jitted code");
+
+
+WritableInstructionsScope::WritableInstructionsScope(uword address,
+                                                     intptr_t size)
+    : address_(address), size_(size) {
+  if (FLAG_write_protect_code) {
+    bool status =
+        VirtualMemory::Protect(reinterpret_cast<void*>(address),
+                               size,
+                               VirtualMemory::kReadWrite);
+    ASSERT(status);
+  }
+}
+
+
+WritableInstructionsScope::~WritableInstructionsScope() {
+  if (FLAG_write_protect_code) {
+    bool status =
+        VirtualMemory::Protect(reinterpret_cast<void*>(address_),
+                               size_,
+                               VirtualMemory::kReadExecute);
+    ASSERT(status);
+  }
+}
+
+
 static void SwapCode(intptr_t num_bytes, char* code, char* buffer) {
   uword code_address = reinterpret_cast<uword>(code);
   for (intptr_t i = 0; i < num_bytes; i++) {
@@ -36,10 +64,15 @@
   JumpPattern jmp_patch(patch_buffer, code);
   ASSERT(jmp_patch.IsValid());
   const uword jump_target = jmp_patch.TargetAddress();
-  SwapCode(jmp_patch.pattern_length_in_bytes(),
-           reinterpret_cast<char*>(patch_addr),
-           reinterpret_cast<char*>(patch_buffer));
-  jmp_entry.SetTargetAddress(jump_target);
+  intptr_t length = jmp_patch.pattern_length_in_bytes();
+  {
+    WritableInstructionsScope writable_code(patch_addr, length);
+    WritableInstructionsScope writable_buffer(patch_buffer, length);
+    SwapCode(jmp_patch.pattern_length_in_bytes(),
+             reinterpret_cast<char*>(patch_addr),
+             reinterpret_cast<char*>(patch_buffer));
+    jmp_entry.SetTargetAddress(jump_target);
+  }
 }
 
 
@@ -57,11 +90,16 @@
   // 'patch_buffer' contains original entry code.
   JumpPattern jmp_patch(patch_buffer, code);
   ASSERT(!jmp_patch.IsValid());
-  SwapCode(jmp_patch.pattern_length_in_bytes(),
-           reinterpret_cast<char*>(patch_addr),
-           reinterpret_cast<char*>(patch_buffer));
-  ASSERT(jmp_patch.IsValid());
-  jmp_patch.SetTargetAddress(jump_target);
+  intptr_t length = jmp_patch.pattern_length_in_bytes();
+  {
+    WritableInstructionsScope writable_code(patch_addr, length);
+    WritableInstructionsScope writable_buffer(patch_buffer, length);
+    SwapCode(jmp_patch.pattern_length_in_bytes(),
+             reinterpret_cast<char*>(patch_addr),
+             reinterpret_cast<char*>(patch_buffer));
+    ASSERT(jmp_patch.IsValid());
+    jmp_patch.SetTargetAddress(jump_target);
+  }
 }
 
 
diff --git a/runtime/vm/code_patcher.h b/runtime/vm/code_patcher.h
index 0a7410f..10ab117 100644
--- a/runtime/vm/code_patcher.h
+++ b/runtime/vm/code_patcher.h
@@ -22,6 +22,22 @@
 class RawObject;
 class String;
 
+
+// Stack-allocated class to create a scope where the specified region
+// [address, addresss + size] has write access enabled. This is used
+// when patching generated code. Access is reset to read-execute in
+// the destructor of this scope.
+class WritableInstructionsScope : public ValueObject {
+ public:
+  WritableInstructionsScope(uword address, intptr_t size);
+  ~WritableInstructionsScope();
+
+ private:
+  const uword address_;
+  const intptr_t size_;
+};
+
+
 class CodePatcher : public AllStatic {
  public:
   // Dart static calls have a distinct, machine-dependent code pattern.
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index e8a5b4f..6f65346 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -48,8 +48,6 @@
     "Attempt to sink temporary allocations to side exits");
 DEFINE_FLAG(int, deoptimization_counter_threshold, 16,
     "How many times we allow deoptimization before we disallow optimization.");
-DEFINE_FLAG(int, deoptimization_counter_licm_threshold, 8,
-    "How many times we allow deoptimization before we disable LICM.");
 DEFINE_FLAG(bool, print_flow_graph, false, "Print the IR flow graph.");
 DEFINE_FLAG(bool, print_flow_graph_optimized, false,
             "Print the IR flow graph when optimizing.");
@@ -442,9 +440,7 @@
         optimizer.TryOptimizePatterns();
         DEBUG_ASSERT(flow_graph->VerifyUseLists());
 
-        if (FLAG_loop_invariant_code_motion &&
-            (function.deoptimization_counter() <
-             FLAG_deoptimization_counter_licm_threshold)) {
+        if (FLAG_loop_invariant_code_motion) {
           LICM licm(flow_graph);
           licm.Optimize();
           DEBUG_ASSERT(flow_graph->VerifyUseLists());
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 5cbfefa..3639ffa 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -98,6 +98,7 @@
   FreeListElement::InitOnce();
   Api::InitOnce();
   CodeObservers::InitOnce();
+  ThreadInterrupter::InitOnce();
   Profiler::InitOnce();
 #if defined(USING_SIMULATOR)
   Simulator::InitOnce();
@@ -130,6 +131,7 @@
     }
 #endif
     PremarkingVisitor premarker(vm_isolate_);
+    vm_isolate_->heap()->WriteProtect(false);
     vm_isolate_->heap()->IterateOldObjects(&premarker);
     vm_isolate_->heap()->WriteProtect(true);
   }
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 754f0d6..17c7f33 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1338,7 +1338,7 @@
   CHECK_CALLBACK_STATE(isolate);
   Error& malformed_type_error = Error::Handle(isolate);
   *value = instance.IsInstanceOf(type_obj,
-                                 Object::null_abstract_type_arguments(),
+                                 Object::null_type_arguments(),
                                  &malformed_type_error);
   ASSERT(malformed_type_error.IsNull());  // Type was created from a class.
   return Api::Success();
@@ -2945,8 +2945,8 @@
   Type& type_obj = Type::Handle();
   type_obj ^= unchecked_type.raw();
   Class& cls = Class::Handle(isolate, type_obj.type_class());
-  AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::Handle(isolate, type_obj.arguments());
+  TypeArguments& type_arguments =
+      TypeArguments::Handle(isolate, type_obj.arguments());
 
   const String& base_constructor_name = String::Handle(isolate, cls.Name());
 
@@ -2999,6 +2999,7 @@
       if (!bound_error.IsNull()) {
         return Api::NewHandle(isolate, bound_error.raw());
       }
+      redirect_type ^= redirect_type.Canonicalize();
     }
 
     type_obj = redirect_type.raw();
@@ -3160,8 +3161,8 @@
   strings.SetAt(1, Symbols::Dot());
   strings.SetAt(2, constructor_name);
   const String& dot_name = String::Handle(isolate, String::ConcatAll(strings));
-  const AbstractTypeArguments& type_arguments =
-    AbstractTypeArguments::Handle(isolate, type_obj.arguments());
+  const TypeArguments& type_arguments =
+    TypeArguments::Handle(isolate, type_obj.arguments());
   const Function& constructor =
     Function::Handle(isolate, cls.LookupFunctionAllowPrivate(dot_name));
   const int extra_args = 2;
diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc
index 70d5720..123d535 100644
--- a/runtime/vm/dart_api_message.cc
+++ b/runtime/vm/dart_api_message.cc
@@ -487,6 +487,7 @@
       AddBackRef(object_id, value, kIsDeserialized);
       Dart_CObject* length = ReadObjectImpl();
       ASSERT(length->type == Dart_CObject_kInt32);
+      // The instantiations_ field is only written to a full snapshot.
       for (int i = 0; i < length->value.as_int32; i++) {
         Dart_CObject* type = ReadObjectImpl();
         if (type != &dynamic_type_marker) {
diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc
index 6dada00..58e7794 100644
--- a/runtime/vm/debugger_api_impl.cc
+++ b/runtime/vm/debugger_api_impl.cc
@@ -608,8 +608,8 @@
   const Class& super_cls = Class::Handle(cls.SuperClass());
   intptr_t num_expected_type_arguments = super_cls.NumTypeArguments();
   TypeArguments& super_type_args_array = TypeArguments::Handle();
-  const AbstractTypeArguments& type_args_array =
-      AbstractTypeArguments::Handle(type.arguments());
+  const TypeArguments& type_args_array =
+      TypeArguments::Handle(type.arguments());
   if (!type_args_array.IsNull() && (num_expected_type_arguments > 0)) {
     super_type_args_array = TypeArguments::New(num_expected_type_arguments);
     AbstractType& type_arg = AbstractType::Handle();
diff --git a/runtime/vm/debugger_arm.cc b/runtime/vm/debugger_arm.cc
index 0f59fd9..cdb13e7 100644
--- a/runtime/vm/debugger_arm.cc
+++ b/runtime/vm/debugger_arm.cc
@@ -40,20 +40,24 @@
 
 void CodeBreakpoint::PatchCode() {
   ASSERT(!is_enabled_);
-  switch (breakpoint_kind_) {
-    case PcDescriptors::kIcCall:
-    case PcDescriptors::kUnoptStaticCall:
-    case PcDescriptors::kRuntimeCall:
-    case PcDescriptors::kClosureCall:
-    case PcDescriptors::kReturn: {
-      const Code& code = Code::Handle(code_);
-      saved_value_ = CodePatcher::GetStaticCallTargetAt(pc_, code);
-      CodePatcher::PatchStaticCallAt(pc_, code,
-                                     StubCode::BreakpointRuntimeEntryPoint());
-      break;
+  const Code& code = Code::Handle(code_);
+  const Instructions& instrs = Instructions::Handle(code.instructions());
+  {
+    WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size());
+    switch (breakpoint_kind_) {
+      case PcDescriptors::kIcCall:
+      case PcDescriptors::kUnoptStaticCall:
+      case PcDescriptors::kRuntimeCall:
+      case PcDescriptors::kClosureCall:
+      case PcDescriptors::kReturn: {
+        saved_value_ = CodePatcher::GetStaticCallTargetAt(pc_, code);
+        CodePatcher::PatchStaticCallAt(pc_, code,
+                                       StubCode::BreakpointRuntimeEntryPoint());
+        break;
+      }
+      default:
+        UNREACHABLE();
     }
-    default:
-      UNREACHABLE();
   }
   is_enabled_ = true;
 }
@@ -61,18 +65,22 @@
 
 void CodeBreakpoint::RestoreCode() {
   ASSERT(is_enabled_);
-  switch (breakpoint_kind_) {
-    case PcDescriptors::kIcCall:
-    case PcDescriptors::kUnoptStaticCall:
-    case PcDescriptors::kClosureCall:
-    case PcDescriptors::kRuntimeCall:
-    case PcDescriptors::kReturn: {
-      const Code& code = Code::Handle(code_);
-      CodePatcher::PatchStaticCallAt(pc_, code, saved_value_);
-      break;
+  const Code& code = Code::Handle(code_);
+  const Instructions& instrs = Instructions::Handle(code.instructions());
+  {
+    WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size());
+    switch (breakpoint_kind_) {
+      case PcDescriptors::kIcCall:
+      case PcDescriptors::kUnoptStaticCall:
+      case PcDescriptors::kClosureCall:
+      case PcDescriptors::kRuntimeCall:
+      case PcDescriptors::kReturn: {
+        CodePatcher::PatchStaticCallAt(pc_, code, saved_value_);
+        break;
+      }
+      default:
+        UNREACHABLE();
     }
-    default:
-      UNREACHABLE();
   }
   is_enabled_ = false;
 }
diff --git a/runtime/vm/debugger_ia32.cc b/runtime/vm/debugger_ia32.cc
index cbc9c0d..372a8c1 100644
--- a/runtime/vm/debugger_ia32.cc
+++ b/runtime/vm/debugger_ia32.cc
@@ -44,20 +44,24 @@
 
 void CodeBreakpoint::PatchCode() {
   ASSERT(!is_enabled_);
-  switch (breakpoint_kind_) {
-    case PcDescriptors::kIcCall:
-    case PcDescriptors::kUnoptStaticCall:
-    case PcDescriptors::kRuntimeCall:
-    case PcDescriptors::kClosureCall:
-    case PcDescriptors::kReturn: {
-      const Code& code = Code::Handle(code_);
-      saved_value_ = CodePatcher::GetStaticCallTargetAt(pc_, code);
-      CodePatcher::PatchStaticCallAt(pc_, code,
-                                     StubCode::BreakpointRuntimeEntryPoint());
-      break;
+  const Code& code = Code::Handle(code_);
+  const Instructions& instrs = Instructions::Handle(code.instructions());
+  {
+    WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size());
+    switch (breakpoint_kind_) {
+      case PcDescriptors::kIcCall:
+      case PcDescriptors::kUnoptStaticCall:
+      case PcDescriptors::kRuntimeCall:
+      case PcDescriptors::kClosureCall:
+      case PcDescriptors::kReturn: {
+        saved_value_ = CodePatcher::GetStaticCallTargetAt(pc_, code);
+        CodePatcher::PatchStaticCallAt(pc_, code,
+                                       StubCode::BreakpointRuntimeEntryPoint());
+        break;
+      }
+      default:
+        UNREACHABLE();
     }
-    default:
-      UNREACHABLE();
   }
   is_enabled_ = true;
 }
@@ -65,18 +69,22 @@
 
 void CodeBreakpoint::RestoreCode() {
   ASSERT(is_enabled_);
-  switch (breakpoint_kind_) {
-    case PcDescriptors::kIcCall:
-    case PcDescriptors::kUnoptStaticCall:
-    case PcDescriptors::kClosureCall:
-    case PcDescriptors::kRuntimeCall:
-    case PcDescriptors::kReturn: {
-      const Code& code = Code::Handle(code_);
-      CodePatcher::PatchStaticCallAt(pc_, code, saved_value_);
-      break;
+  const Code& code = Code::Handle(code_);
+  const Instructions& instrs = Instructions::Handle(code.instructions());
+  {
+    WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size());
+    switch (breakpoint_kind_) {
+      case PcDescriptors::kIcCall:
+      case PcDescriptors::kUnoptStaticCall:
+      case PcDescriptors::kClosureCall:
+      case PcDescriptors::kRuntimeCall:
+      case PcDescriptors::kReturn: {
+        CodePatcher::PatchStaticCallAt(pc_, code, saved_value_);
+        break;
+      }
+      default:
+        UNREACHABLE();
     }
-    default:
-      UNREACHABLE();
   }
   is_enabled_ = false;
 }
diff --git a/runtime/vm/debugger_mips.cc b/runtime/vm/debugger_mips.cc
index 8ac2019..54fd4cd 100644
--- a/runtime/vm/debugger_mips.cc
+++ b/runtime/vm/debugger_mips.cc
@@ -40,20 +40,24 @@
 
 void CodeBreakpoint::PatchCode() {
   ASSERT(!is_enabled_);
-  switch (breakpoint_kind_) {
-    case PcDescriptors::kIcCall:
-    case PcDescriptors::kUnoptStaticCall:
-    case PcDescriptors::kRuntimeCall:
-    case PcDescriptors::kClosureCall:
-    case PcDescriptors::kReturn: {
-      const Code& code = Code::Handle(code_);
-      saved_value_ = CodePatcher::GetStaticCallTargetAt(pc_, code);
-      CodePatcher::PatchStaticCallAt(pc_, code,
-                                     StubCode::BreakpointRuntimeEntryPoint());
-      break;
+  const Code& code = Code::Handle(code_);
+  const Instructions& instrs = Instructions::Handle(code.instructions());
+  {
+    WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size());
+    switch (breakpoint_kind_) {
+      case PcDescriptors::kIcCall:
+      case PcDescriptors::kUnoptStaticCall:
+      case PcDescriptors::kRuntimeCall:
+      case PcDescriptors::kClosureCall:
+      case PcDescriptors::kReturn: {
+        saved_value_ = CodePatcher::GetStaticCallTargetAt(pc_, code);
+        CodePatcher::PatchStaticCallAt(pc_, code,
+                                       StubCode::BreakpointRuntimeEntryPoint());
+        break;
+      }
+      default:
+        UNREACHABLE();
     }
-    default:
-      UNREACHABLE();
   }
   is_enabled_ = true;
 }
@@ -61,18 +65,22 @@
 
 void CodeBreakpoint::RestoreCode() {
   ASSERT(is_enabled_);
-  switch (breakpoint_kind_) {
-    case PcDescriptors::kIcCall:
-    case PcDescriptors::kUnoptStaticCall:
-    case PcDescriptors::kClosureCall:
-    case PcDescriptors::kRuntimeCall:
-    case PcDescriptors::kReturn: {
-      const Code& code = Code::Handle(code_);
-      CodePatcher::PatchStaticCallAt(pc_, code, saved_value_);
-      break;
+  const Code& code = Code::Handle(code_);
+  const Instructions& instrs = Instructions::Handle(code.instructions());
+  {
+    WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size());
+    switch (breakpoint_kind_) {
+      case PcDescriptors::kIcCall:
+      case PcDescriptors::kUnoptStaticCall:
+      case PcDescriptors::kClosureCall:
+      case PcDescriptors::kRuntimeCall:
+      case PcDescriptors::kReturn: {
+        CodePatcher::PatchStaticCallAt(pc_, code, saved_value_);
+        break;
+      }
+      default:
+        UNREACHABLE();
     }
-    default:
-      UNREACHABLE();
   }
   is_enabled_ = false;
 }
diff --git a/runtime/vm/debugger_x64.cc b/runtime/vm/debugger_x64.cc
index 4e26f6b..33fb63a 100644
--- a/runtime/vm/debugger_x64.cc
+++ b/runtime/vm/debugger_x64.cc
@@ -49,23 +49,28 @@
 
 void CodeBreakpoint::PatchCode() {
   ASSERT(!is_enabled_);
-  switch (breakpoint_kind_) {
-    case PcDescriptors::kIcCall:
-    case PcDescriptors::kUnoptStaticCall:
-    case PcDescriptors::kRuntimeCall:
-    case PcDescriptors::kClosureCall:
-    case PcDescriptors::kReturn: {
-      int32_t offset = CodePatcher::GetPoolOffsetAt(pc_);
-      ASSERT((offset > 0) && ((offset % 8) == 7));
-      saved_value_ = static_cast<uword>(offset);
-      const uint32_t stub_offset =
-          InstructionPattern::OffsetFromPPIndex(
-              Assembler::kBreakpointRuntimeCPIndex);
-      CodePatcher::SetPoolOffsetAt(pc_, stub_offset);
-      break;
+  const Code& code = Code::Handle(code_);
+  const Instructions& instrs = Instructions::Handle(code.instructions());
+  {
+    WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size());
+    switch (breakpoint_kind_) {
+      case PcDescriptors::kIcCall:
+      case PcDescriptors::kUnoptStaticCall:
+      case PcDescriptors::kRuntimeCall:
+      case PcDescriptors::kClosureCall:
+      case PcDescriptors::kReturn: {
+        int32_t offset = CodePatcher::GetPoolOffsetAt(pc_);
+        ASSERT((offset > 0) && ((offset % 8) == 7));
+        saved_value_ = static_cast<uword>(offset);
+        const uint32_t stub_offset =
+            InstructionPattern::OffsetFromPPIndex(
+                Assembler::kBreakpointRuntimeCPIndex);
+        CodePatcher::SetPoolOffsetAt(pc_, stub_offset);
+        break;
+      }
+      default:
+        UNREACHABLE();
     }
-    default:
-      UNREACHABLE();
   }
   is_enabled_ = true;
 }
@@ -73,17 +78,22 @@
 
 void CodeBreakpoint::RestoreCode() {
   ASSERT(is_enabled_);
-  switch (breakpoint_kind_) {
-    case PcDescriptors::kIcCall:
-    case PcDescriptors::kUnoptStaticCall:
-    case PcDescriptors::kClosureCall:
-    case PcDescriptors::kRuntimeCall:
-    case PcDescriptors::kReturn: {
-      CodePatcher::SetPoolOffsetAt(pc_, static_cast<int32_t>(saved_value_));
-      break;
+  const Code& code = Code::Handle(code_);
+  const Instructions& instrs = Instructions::Handle(code.instructions());
+  {
+    WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size());
+    switch (breakpoint_kind_) {
+      case PcDescriptors::kIcCall:
+      case PcDescriptors::kUnoptStaticCall:
+      case PcDescriptors::kClosureCall:
+      case PcDescriptors::kRuntimeCall:
+      case PcDescriptors::kReturn: {
+        CodePatcher::SetPoolOffsetAt(pc_, static_cast<int32_t>(saved_value_));
+        break;
+      }
+      default:
+        UNREACHABLE();
     }
-    default:
-      UNREACHABLE();
   }
   is_enabled_ = false;
 }
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 874c314..150e191 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -584,6 +584,9 @@
       if (!ic_data.IsNull()) {
         ic_data.set_deopt_reason(deopt_context->deopt_reason());
       }
+    } else if (deopt_context->deopt_reason() == kDeoptHoistedCheckClass) {
+      // Prevent excessive deoptimization.
+      Function::Handle(code.function()).set_allows_hoisting_check_class(false);
     }
   }
 
diff --git a/runtime/vm/disassembler_ia32.cc b/runtime/vm/disassembler_ia32.cc
index 3981beb..1a6877f 100644
--- a/runtime/vm/disassembler_ia32.cc
+++ b/runtime/vm/disassembler_ia32.cc
@@ -356,6 +356,7 @@
   uint8_t* F3Instruction(uint8_t* data);
   int F7Instruction(uint8_t* data);
   int FPUInstruction(uint8_t* data);
+  uint8_t* SSEInstruction(uint8_t prefix, uint8_t primary, uint8_t* data);
   int BitwisePDInstruction(uint8_t* data);
   int Packed660F38Instruction(uint8_t* data);
   int DecodeEnter(uint8_t* data);
@@ -1128,6 +1129,37 @@
 }
 
 
+uint8_t* X86Decoder::SSEInstruction(uint8_t prefix, uint8_t primary,
+                                    uint8_t* data) {
+  ASSERT(prefix == 0x0F);
+  int mod, regop, rm;
+  if (primary == 0x10) {
+    GetModRm(*data, &mod, &regop, &rm);
+    Print("movups ");
+    PrintXmmRegister(regop);
+    Print(",");
+    data += PrintRightOperand(data);
+  } else if (primary == 0x11) {
+    int mod, regop, rm;
+    GetModRm(*data, &mod, &regop, &rm);
+    Print("movups ");
+    data += PrintRightXmmOperand(data);
+    Print(",");
+    PrintXmmRegister(regop);
+  } else if (IsTwoXmmRegInstruction(primary)) {
+    const char* f0mnem = F0Mnem(primary);
+    int mod, regop, rm;
+    GetModRm(*data, &mod, &regop, &rm);
+    Print(f0mnem);
+    Print(" ");
+    PrintXmmRegister(regop);
+    Print(",");
+    data += PrintRightXmmOperand(data);
+  }
+  return data;
+}
+
+
 int X86Decoder::BitwisePDInstruction(uint8_t* data) {
   const char* mnem = (*data == 0x57)
       ? "xorpd"
@@ -1396,21 +1428,9 @@
               PrintCPURegister(regop);
               Print(",cl");
             }
-          } else if (f0byte == 0x10) {
-            int mod, regop, rm;
-            GetModRm(*data, &mod, &regop, &rm);
-            Print("movups ");
-            PrintXmmRegister(regop);
-            Print(",");
-            data += PrintRightOperand(data);
-          } else if (IsTwoXmmRegInstruction(f0byte)) {
-            int mod, regop, rm;
-            GetModRm(*data, &mod, &regop, &rm);
-            Print(f0mnem);
-            Print(" ");
-            PrintXmmRegister(regop);
-            Print(",");
-            data += PrintRightXmmOperand(data);
+          } else if ((f0byte == 0x10) || (f0byte == 0x11) ||
+                     IsTwoXmmRegInstruction(f0byte)) {
+            data = SSEInstruction(0x0F, f0byte, data);
           } else if (f0byte == 0x50) {
             Print("movmskps ");
             int mod, regop, rm;
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index d716b25..8eb9e54 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -2169,8 +2169,8 @@
 
 
 void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) {
-  const AbstractTypeArguments& type_args =
-      AbstractTypeArguments::ZoneHandle(node->type().arguments());
+  const TypeArguments& type_args =
+      TypeArguments::ZoneHandle(node->type().arguments());
   Value* element_type = BuildInstantiatedTypeArguments(node->token_pos(),
                                                        type_args);
   Value* num_elements =
@@ -2489,46 +2489,21 @@
 }
 
 
-Value* EffectGraphVisitor::BuildObjectAllocation(
-    ConstructorCallNode* node) {
+Value* EffectGraphVisitor::BuildObjectAllocation(ConstructorCallNode* node) {
   const Class& cls = Class::ZoneHandle(node->constructor().Owner());
   const bool requires_type_arguments = cls.NumTypeArguments() > 0;
 
-  // In checked mode, if the type arguments are uninstantiated, they may need to
-  // be checked against declared bounds at run time.
-  Definition* allocation = NULL;
-  if (FLAG_enable_type_checks &&
-      requires_type_arguments &&
-      !node->type_arguments().IsNull() &&
-      !node->type_arguments().IsInstantiated() &&
-      node->type_arguments().IsBounded()) {
-    ZoneGrowableArray<PushArgumentInstr*>* allocate_arguments =
-        new ZoneGrowableArray<PushArgumentInstr*>(4);
-    // Argument 1: Empty argument slot for return value.
-    Value* null_val = Bind(new ConstantInstr(Object::ZoneHandle()));
-    allocate_arguments->Add(PushArgument(null_val));
-    // Argument 2: Class.
-    Value* cls_val =
-        Bind(new ConstantInstr(Class::ZoneHandle(node->constructor().Owner())));
-    allocate_arguments->Add(PushArgument(cls_val));
-    // Build arguments 3 and 4.
+  ZoneGrowableArray<PushArgumentInstr*>* allocate_arguments =
+      new ZoneGrowableArray<PushArgumentInstr*>();
+  if (requires_type_arguments) {
     BuildConstructorTypeArguments(node, allocate_arguments);
-
-    // The uninstantiated type arguments cannot be verified to be within their
-    // bounds at compile time, so verify them at runtime.
-    allocation = new AllocateObjectWithBoundsCheckInstr(node);
-  } else {
-    ZoneGrowableArray<PushArgumentInstr*>* allocate_arguments =
-        new ZoneGrowableArray<PushArgumentInstr*>();
-    if (requires_type_arguments) {
-      BuildConstructorTypeArguments(node, allocate_arguments);
-    }
-
-    allocation = new AllocateObjectInstr(
-        node->token_pos(),
-        Class::ZoneHandle(node->constructor().Owner()),
-        allocate_arguments);
   }
+
+  Definition* allocation = new AllocateObjectInstr(
+      node->token_pos(),
+      Class::ZoneHandle(node->constructor().Owner()),
+      allocate_arguments);
+
   return Bind(allocation);
 }
 
@@ -2649,7 +2624,7 @@
     Value* instantiator) {
   if (instantiator_class.NumTypeParameters() == 0) {
     // The type arguments are compile time constants.
-    AbstractTypeArguments& type_arguments = AbstractTypeArguments::ZoneHandle();
+    TypeArguments& type_arguments = TypeArguments::ZoneHandle();
     // Type is temporary. Only its type arguments are preserved.
     Type& type = Type::Handle(
         Type::New(instantiator_class, type_arguments, token_pos, Heap::kNew));
@@ -2678,9 +2653,9 @@
     instantiator = BuildInstantiator();
   }
   // The instantiator is the receiver of the caller, which is not a factory.
-  // The receiver cannot be null; extract its AbstractTypeArguments object.
+  // The receiver cannot be null; extract its TypeArguments object.
   // Note that in the factory case, the instantiator is the first parameter
-  // of the factory, i.e. already an AbstractTypeArguments object.
+  // of the factory, i.e. already a TypeArguments object.
   intptr_t type_arguments_field_offset =
       instantiator_class.type_arguments_field_offset();
   ASSERT(type_arguments_field_offset != Class::kNoTypeArguments);
@@ -2694,7 +2669,7 @@
 
 Value* EffectGraphVisitor::BuildInstantiatedTypeArguments(
     intptr_t token_pos,
-    const AbstractTypeArguments& type_arguments) {
+    const TypeArguments& type_arguments) {
   if (type_arguments.IsNull() || type_arguments.IsInstantiated()) {
     return Bind(new ConstantInstr(type_arguments));
   }
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h
index b527bff..0b3cae9 100644
--- a/runtime/vm/flow_graph_builder.h
+++ b/runtime/vm/flow_graph_builder.h
@@ -16,7 +16,6 @@
 namespace dart {
 
 class AbstractType;
-class AbstractTypeArguments;
 class Array;
 class Class;
 class Field;
@@ -24,6 +23,7 @@
 class LocalVariable;
 class ParsedFunction;
 class String;
+class TypeArguments;
 
 class NestedStatement;
 class TestGraphVisitor;
@@ -334,7 +334,7 @@
   // May be called only if allocating an object of a parameterized class.
   Value* BuildInstantiatedTypeArguments(
       intptr_t token_pos,
-      const AbstractTypeArguments& type_arguments);
+      const TypeArguments& type_arguments);
 
   // Creates a possibly uninstantiated type argument vector and the type
   // argument vector of the instantiator used in
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 6b4f67d..9d20dcd 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -31,7 +31,8 @@
 DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, use_cha);
 DECLARE_FLAG(bool, use_osr);
-
+DEFINE_FLAG(bool, enable_simd_inline, true,
+    "Enable inlining of SIMD related method calls.");
 
 // Assign locations to incoming arguments, i.e., values pushed above spill slots
 // with PushArgument.  Recursively allocates from outermost to innermost
@@ -455,10 +456,25 @@
 // and FlowGraphCompiler::SlowPathEnvironmentFor.
 void FlowGraphCompiler::RecordSafepoint(LocationSummary* locs) {
   if (is_optimizing()) {
+    RegisterSet* registers = locs->live_registers();
+    ASSERT(registers != NULL);
+    const intptr_t kFpuRegisterSpillFactor =
+            kFpuRegisterSize / kWordSize;
+    const intptr_t live_registers_size = registers->CpuRegisterCount() +
+        (registers->FpuRegisterCount() * kFpuRegisterSpillFactor);
     BitmapBuilder* bitmap = locs->stack_bitmap();
     ASSERT(bitmap != NULL);
-    ASSERT(bitmap->Length() <= StackSize());
-    // Pad the bitmap out to describe all the spill slots.
+    // An instruction may have two safepoints in deferred code. The
+    // call to RecordSafepoint has the side-effect of appending the live
+    // registers to the bitmap. This is why the second call to RecordSafepoint
+    // with the same instruction (and same location summary) sees a bitmap that
+    // is larger that StackSize(). It will never be larger than StackSize() +
+    // live_registers_size.
+    ASSERT(bitmap->Length() <= (StackSize() + live_registers_size));
+    // The first safepoint will grow the bitmap to be the size of StackSize()
+    // but the second safepoint will truncate the bitmap and append the
+    // live registers to it again. The bitmap produced by both calls will
+    // be the same.
     bitmap->SetLength(StackSize());
 
     // Mark the bits in the stack map in the same order we push registers in
@@ -475,8 +491,6 @@
         //
         // FPU registers have the highest register number at the highest
         // address (i.e., first in the stackmap).
-        const intptr_t kFpuRegisterSpillFactor =
-            kFpuRegisterSize / kWordSize;
         for (intptr_t i = kNumberOfFpuRegisters - 1; i >= 0; --i) {
           FpuRegister reg = static_cast<FpuRegister>(i);
           if (regs->ContainsFpuRegister(reg)) {
@@ -1240,8 +1254,8 @@
     // arguments.
     const intptr_t num_type_params = type_class.NumTypeParameters();
     const intptr_t from_index = num_type_args - num_type_params;
-    const AbstractTypeArguments& type_arguments =
-        AbstractTypeArguments::Handle(type.arguments());
+    const TypeArguments& type_arguments =
+        TypeArguments::Handle(type.arguments());
     const bool is_raw_type = type_arguments.IsNull() ||
         type_arguments.IsRaw(from_index, num_type_params);
     return is_raw_type;
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index ffdfd75..812d62d 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -246,6 +246,7 @@
 
   static bool SupportsUnboxedMints();
   static bool SupportsSinCos();
+  static bool SupportsUnboxedFloat32x4();
 
   // Accessors.
   Assembler* assembler() const { return assembler_; }
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 21639f8..93cf6c4 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -26,6 +26,7 @@
 DECLARE_FLAG(int, reoptimization_counter_threshold);
 DECLARE_FLAG(bool, enable_type_checks);
 DECLARE_FLAG(bool, eliminate_type_checks);
+DECLARE_FLAG(bool, enable_simd_inline);
 
 
 FlowGraphCompiler::~FlowGraphCompiler() {
@@ -42,6 +43,11 @@
 }
 
 
+bool FlowGraphCompiler::SupportsUnboxedFloat32x4() {
+  return CPUFeatures::neon_supported() && FLAG_enable_simd_inline;
+}
+
+
 bool FlowGraphCompiler::SupportsSinCos() {
   return false;
 }
@@ -244,8 +250,8 @@
   const intptr_t num_type_args = type_class.NumTypeArguments();
   const intptr_t num_type_params = type_class.NumTypeParameters();
   const intptr_t from_index = num_type_args - num_type_params;
-  const AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::ZoneHandle(type.arguments());
+  const TypeArguments& type_arguments =
+      TypeArguments::ZoneHandle(type.arguments());
   const bool is_raw_type = type_arguments.IsNull() ||
       type_arguments.IsRaw(from_index, num_type_params);
   // Signature class is an instantiated parameterized type.
@@ -417,24 +423,16 @@
     // Load instantiator (or null) and instantiator type arguments on stack.
     __ ldr(R1, Address(SP, 0));  // Get instantiator type arguments.
     // R1: instantiator type arguments.
-    // Check if type argument is dynamic.
+    // Check if type arguments are null, i.e. equivalent to vector of dynamic.
     __ CompareImmediate(R1, reinterpret_cast<intptr_t>(Object::null()));
     __ b(is_instance_lbl, EQ);
-    // Can handle only type arguments that are instances of TypeArguments.
-    // (runtime checks canonicalize type arguments).
-    Label fall_through;
-    __ CompareClassId(R1, kTypeArgumentsCid, R2);
-    __ b(&fall_through, NE);
     __ ldr(R2,
         FieldAddress(R1, TypeArguments::type_at_offset(type_param.index())));
     // R2: concrete type of type.
     // Check if type argument is dynamic.
     __ CompareObject(R2, Type::ZoneHandle(Type::DynamicType()));
     __ b(is_instance_lbl, EQ);
-    __ CompareImmediate(R2, reinterpret_cast<intptr_t>(Object::null()));
-    __ b(is_instance_lbl, EQ);
-    const Type& object_type = Type::ZoneHandle(Type::ObjectType());
-    __ CompareObject(R2, object_type);
+    __ CompareObject(R2, Type::ZoneHandle(Type::ObjectType()));
     __ b(is_instance_lbl, EQ);
 
     // For Smi check quickly against int and num interfaces.
@@ -446,6 +444,7 @@
     __ CompareObject(R2, Type::ZoneHandle(Type::Number()));
     __ b(is_instance_lbl, EQ);
     // Smi must be handled in runtime.
+    Label fall_through;
     __ b(&fall_through);
 
     __ Bind(&not_smi);
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 4b7d0d2..27c34cb 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -28,6 +28,7 @@
 DECLARE_FLAG(bool, enable_type_checks);
 DECLARE_FLAG(bool, eliminate_type_checks);
 DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
+DECLARE_FLAG(bool, enable_simd_inline);
 
 
 FlowGraphCompiler::~FlowGraphCompiler() {
@@ -46,6 +47,11 @@
 }
 
 
+bool FlowGraphCompiler::SupportsUnboxedFloat32x4() {
+  return FLAG_enable_simd_inline;
+}
+
+
 bool FlowGraphCompiler::SupportsSinCos() {
   return true;
 }
@@ -253,8 +259,8 @@
   const intptr_t num_type_args = type_class.NumTypeArguments();
   const intptr_t num_type_params = type_class.NumTypeParameters();
   const intptr_t from_index = num_type_args - num_type_params;
-  const AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::ZoneHandle(type.arguments());
+  const TypeArguments& type_arguments =
+      TypeArguments::ZoneHandle(type.arguments());
   const bool is_raw_type = type_arguments.IsNull() ||
       type_arguments.IsRaw(from_index, num_type_params);
   // Signature class is an instantiated parameterized type.
@@ -430,24 +436,16 @@
     // Load instantiator (or null) and instantiator type arguments on stack.
     __ movl(EDX, Address(ESP, 0));  // Get instantiator type arguments.
     // EDX: instantiator type arguments.
-    // Check if type argument is dynamic.
+    // Check if type arguments are null, i.e. equivalent to vector of dynamic.
     __ cmpl(EDX, raw_null);
     __ j(EQUAL, is_instance_lbl);
-    // Can handle only type arguments that are instances of TypeArguments.
-    // (runtime checks canonicalize type arguments).
-    Label fall_through;
-    __ CompareClassId(EDX, kTypeArgumentsCid, EDI);
-    __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
     __ movl(EDI,
         FieldAddress(EDX, TypeArguments::type_at_offset(type_param.index())));
     // EDI: concrete type of type.
     // Check if type argument is dynamic.
     __ CompareObject(EDI, Type::ZoneHandle(Type::DynamicType()));
     __ j(EQUAL,  is_instance_lbl);
-    __ cmpl(EDI, raw_null);
-    __ j(EQUAL,  is_instance_lbl);
-    const Type& object_type = Type::ZoneHandle(Type::ObjectType());
-    __ CompareObject(EDI, object_type);
+    __ CompareObject(EDI, Type::ZoneHandle(Type::ObjectType()));
     __ j(EQUAL,  is_instance_lbl);
 
     // For Smi check quickly against int and num interfaces.
@@ -459,6 +457,7 @@
     __ CompareObject(EDI, Type::ZoneHandle(Type::Number()));
     __ j(EQUAL,  is_instance_lbl);
     // Smi must be handled in runtime.
+    Label fall_through;
     __ jmp(&fall_through);
 
     __ Bind(&not_smi);
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 56e1b58..f2fd7f8 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -42,6 +42,11 @@
 }
 
 
+bool FlowGraphCompiler::SupportsUnboxedFloat32x4() {
+  return false;
+}
+
+
 bool FlowGraphCompiler::SupportsSinCos() {
   return false;
 }
@@ -244,8 +249,8 @@
   const intptr_t num_type_args = type_class.NumTypeArguments();
   const intptr_t num_type_params = type_class.NumTypeParameters();
   const intptr_t from_index = num_type_args - num_type_params;
-  const AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::ZoneHandle(type.arguments());
+  const TypeArguments& type_arguments =
+      TypeArguments::ZoneHandle(type.arguments());
   const bool is_raw_type = type_arguments.IsNull() ||
       type_arguments.IsRaw(from_index, num_type_params);
   // Signature class is an instantiated parameterized type.
@@ -417,22 +422,15 @@
     // Load instantiator (or null) and instantiator type arguments on stack.
     __ lw(A1, Address(SP, 0));  // Get instantiator type arguments.
     // A1: instantiator type arguments.
-    // Check if type argument is dynamic.
+    // Check if type arguments are null, i.e. equivalent to vector of dynamic.
     __ LoadImmediate(T7, reinterpret_cast<int32_t>(Object::null()));
     __ beq(A1, T7, is_instance_lbl);
-    // Can handle only type arguments that are instances of TypeArguments.
-    // (runtime checks canonicalize type arguments).
-    Label fall_through;
-    __ LoadClassId(T2, A1);
-    __ BranchNotEqual(T2, kTypeArgumentsCid, &fall_through);
     __ lw(T2,
         FieldAddress(A1, TypeArguments::type_at_offset(type_param.index())));
     // R2: concrete type of type.
     // Check if type argument is dynamic.
     __ BranchEqual(T2, Type::ZoneHandle(Type::DynamicType()), is_instance_lbl);
-    __ beq(T2, T7, is_instance_lbl);
-    const Type& object_type = Type::ZoneHandle(Type::ObjectType());
-    __ BranchEqual(T2, object_type, is_instance_lbl);
+    __ BranchEqual(T2, Type::ZoneHandle(Type::ObjectType()), is_instance_lbl);
 
     // For Smi check quickly against int and num interfaces.
     Label not_smi;
@@ -440,8 +438,8 @@
     __ bne(CMPRES1, ZR, &not_smi);  // Value is Smi?
     __ BranchEqual(T2, Type::ZoneHandle(Type::IntType()), is_instance_lbl);
     __ BranchEqual(T2, Type::ZoneHandle(Type::Number()), is_instance_lbl);
-
     // Smi must be handled in runtime.
+    Label fall_through;
     __ b(&fall_through);
 
     __ Bind(&not_smi);
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 8606398..31e1fb9 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -26,6 +26,7 @@
 DECLARE_FLAG(int, reoptimization_counter_threshold);
 DECLARE_FLAG(bool, enable_type_checks);
 DECLARE_FLAG(bool, eliminate_type_checks);
+DECLARE_FLAG(bool, enable_simd_inline);
 
 
 FlowGraphCompiler::~FlowGraphCompiler() {
@@ -43,6 +44,12 @@
 }
 
 
+bool FlowGraphCompiler::SupportsUnboxedFloat32x4() {
+  return FLAG_enable_simd_inline;
+}
+
+
+
 bool FlowGraphCompiler::SupportsSinCos() {
   return true;
 }
@@ -244,8 +251,8 @@
   const intptr_t num_type_args = type_class.NumTypeArguments();
   const intptr_t num_type_params = type_class.NumTypeParameters();
   const intptr_t from_index = num_type_args - num_type_params;
-  const AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::ZoneHandle(type.arguments());
+  const TypeArguments& type_arguments =
+      TypeArguments::ZoneHandle(type.arguments());
   const bool is_raw_type = type_arguments.IsNull() ||
       type_arguments.IsRaw(from_index, num_type_params);
   // Signature class is an instantiated parameterized type.
@@ -417,22 +424,15 @@
     // Load instantiator (or null) and instantiator type arguments on stack.
     __ movq(RDX, Address(RSP, 0));  // Get instantiator type arguments.
     // RDX: instantiator type arguments.
-    // Check if type argument is dynamic.
+    // Check if type arguments are null, i.e. equivalent to vector of dynamic.
     __ CompareObject(RDX, Object::null_object(), PP);
     __ j(EQUAL, is_instance_lbl);
-    // Can handle only type arguments that are instances of TypeArguments.
-    // (runtime checks canonicalize type arguments).
-    Label fall_through;
-    __ CompareClassId(RDX, kTypeArgumentsCid);
-    __ j(NOT_EQUAL, &fall_through);
     __ movq(RDI,
         FieldAddress(RDX, TypeArguments::type_at_offset(type_param.index())));
     // RDI: Concrete type of type.
     // Check if type argument is dynamic.
     __ CompareObject(RDI, Type::ZoneHandle(Type::DynamicType()), PP);
     __ j(EQUAL,  is_instance_lbl);
-    __ CompareObject(RDI, Object::null_object(), PP);
-    __ j(EQUAL,  is_instance_lbl);
     const Type& object_type = Type::ZoneHandle(Type::ObjectType());
     __ CompareObject(RDI, object_type, PP);
     __ j(EQUAL,  is_instance_lbl);
@@ -446,6 +446,7 @@
     __ CompareObject(RDI, Type::ZoneHandle(Type::Number()), PP);
     __ j(EQUAL,  is_instance_lbl);
     // Smi must be handled in runtime.
+    Label fall_through;
     __ jmp(&fall_through);
 
     __ Bind(&not_smi);
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 2c7c516..ce258c0 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -23,6 +23,8 @@
 
 DEFINE_FLAG(bool, array_bounds_check_elimination, true,
     "Eliminate redundant bounds checks.");
+DEFINE_FLAG(int, getter_setter_ratio, 13,
+    "Ratio of getter/setter usage used for double field unboxing heuristics");
 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination.");
 DEFINE_FLAG(int, max_polymorphic_checks, 4,
     "Maximum number of polymorphic check, otherwise it is megamorphic.");
@@ -32,29 +34,20 @@
 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis.");
 DEFINE_FLAG(bool, trace_constant_propagation, false,
     "Print constant propagation and useless code elimination.");
+DEFINE_FLAG(bool, trace_load_optimization, false,
+    "Print live sets for load optimization pass.");
 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details.");
 DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress");
 DEFINE_FLAG(bool, truncating_left_shift, true,
     "Optimize left shift to truncate if possible");
 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis.");
-DEFINE_FLAG(bool, trace_load_optimization, false,
-    "Print live sets for load optimization pass.");
-DEFINE_FLAG(bool, enable_simd_inline, true,
-    "Enable inlining of SIMD related method calls.");
-DEFINE_FLAG(int, getter_setter_ratio, 13,
-    "Ratio of getter/setter usage used for double field unboxing heuristics");
 DECLARE_FLAG(bool, eliminate_type_checks);
 DECLARE_FLAG(bool, enable_type_checks);
 DECLARE_FLAG(bool, trace_type_check_elimination);
 
 
 static bool ShouldInlineSimd() {
-#if defined(TARGET_ARCH_MIPS)
-  return false;
-#elif defined(TARGET_ARCH_ARM)
-  return CPUFeatures::neon_supported() && FLAG_enable_simd_inline;
-#endif
-  return FLAG_enable_simd_inline;
+  return FlowGraphCompiler::SupportsUnboxedFloat32x4();
 }
 
 
@@ -3364,8 +3357,8 @@
     // arguments.
     const intptr_t num_type_params = type_class.NumTypeParameters();
     const intptr_t from_index = num_type_args - num_type_params;
-    const AbstractTypeArguments& type_arguments =
-        AbstractTypeArguments::Handle(type.arguments());
+    const TypeArguments& type_arguments =
+        TypeArguments::Handle(type.arguments());
     const bool is_raw_type = type_arguments.IsNull() ||
         type_arguments.IsRaw(from_index, num_type_params);
     if (!is_raw_type) {
@@ -4500,6 +4493,9 @@
 void LICM::Hoist(ForwardInstructionIterator* it,
                  BlockEntryInstr* pre_header,
                  Instruction* current) {
+  if (current->IsCheckClass()) {
+    current->AsCheckClass()->set_licm_hoisted(true);
+  }
   // TODO(fschneider): Avoid repeated deoptimization when
   // speculatively hoisting checks.
   if (FLAG_trace_optimization) {
@@ -4587,6 +4583,12 @@
 
 
 void LICM::Optimize() {
+  if (!flow_graph()->parsed_function().function().
+          allows_hoisting_check_class()) {
+    // Do not hoist any.
+    return;
+  }
+
   const ZoneGrowableArray<BlockEntryInstr*>& loop_headers =
       flow_graph()->loop_headers();
 
@@ -7123,12 +7125,6 @@
 }
 
 
-void ConstantPropagator::VisitAllocateObjectWithBoundsCheck(
-    AllocateObjectWithBoundsCheckInstr* instr) {
-  SetValue(instr, non_constant_);
-}
-
-
 void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) {
   SetValue(instr, non_constant_);
 }
@@ -7236,12 +7232,32 @@
 
 void ConstantPropagator::VisitExtractConstructorTypeArguments(
     ExtractConstructorTypeArgumentsInstr* instr) {
+  CompileType* type = instr->instantiator()->Type();
+  if (type->HasDecidableNullability()) {
+    if (!type->is_nullable()) {
+      SetValue(instr, instr->type_arguments());
+      return;
+    }
+    ASSERT(type->IsNull());
+    SetValue(instr, instr->instantiator()->definition()->constant_value());
+    return;
+  }
   SetValue(instr, non_constant_);
 }
 
 
 void ConstantPropagator::VisitExtractConstructorInstantiator(
     ExtractConstructorInstantiatorInstr* instr) {
+  CompileType* type = instr->instantiator()->Type();
+  if (type->HasDecidableNullability()) {
+    if (type->IsNull()) {
+      SetValue(instr, Smi::ZoneHandle(Smi::New(StubCode::kNoInstantiator)));
+      return;
+    }
+    ASSERT(!type->is_nullable());
+    SetValue(instr, instr->instantiator()->definition()->constant_value());
+    return;
+  }
   SetValue(instr, non_constant_);
 }
 
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index 99a92bb..2042771 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -751,7 +751,8 @@
         value().GetClassId(),
         AbstractType::ZoneHandle(Instance::Cast(value()).GetType()));
   } else {
-    return CompileType::Dynamic();
+    // Type info for non-instance objects.
+    return CompileType::FromCid(value().GetClassId());
   }
 }
 
diff --git a/runtime/vm/freelist.cc b/runtime/vm/freelist.cc
index 54f2bdd..f187841 100644
--- a/runtime/vm/freelist.cc
+++ b/runtime/vm/freelist.cc
@@ -15,6 +15,8 @@
 
 
 FreeListElement* FreeListElement::AsElement(uword addr, intptr_t size) {
+  // Precondition: the (page containing the) header of the element is
+  // writable.
   ASSERT(size >= kObjectAlignment);
   ASSERT(Utils::IsAligned(size, kObjectAlignment));
 
@@ -29,8 +31,9 @@
     *result->SizeAddress() = size;
   }
   result->set_next(NULL);
-
   return result;
+  // Postcondition: the (page containing the) header of the element is
+  // writable.
 }
 
 
@@ -50,10 +53,22 @@
 }
 
 
-uword FreeList::TryAllocate(intptr_t size) {
+uword FreeList::TryAllocate(intptr_t size, bool is_protected) {
+  // Precondition: is_protected is false or else all free list elements are
+  // in non-writable pages.
+
+  // Postcondition: if allocation succeeds, the allocated block is writable.
   int index = IndexForSize(size);
   if ((index != kNumLists) && free_map_.Test(index)) {
-    return reinterpret_cast<uword>(DequeueElement(index));
+    FreeListElement* element = DequeueElement(index);
+    if (is_protected) {
+      bool status =
+          VirtualMemory::Protect(reinterpret_cast<void*>(element),
+                                 size,
+                                 VirtualMemory::kReadWrite /*Execute*/);
+      ASSERT(status);
+    }
+    return reinterpret_cast<uword>(element);
   }
 
   if ((index + 1) < kNumLists) {
@@ -62,7 +77,22 @@
       // Dequeue an element from the list, split and enqueue the remainder in
       // the appropriate list.
       FreeListElement* element = DequeueElement(next_index);
-      SplitElementAfterAndEnqueue(element, size);
+      if (is_protected) {
+        // Make the allocated block and the header of the remainder element
+        // writable.  The remainder will be non-writable if necessary after
+        // the call to SplitElementAfterAndEnqueue.
+        // If the remainder size is zero, only the element itself needs to
+        // be made writable.
+        intptr_t remainder_size = element->Size() - size;
+        intptr_t region_size = size +
+            ((remainder_size > 0) ? FreeListElement::kHeaderSize : 0);
+        bool status =
+            VirtualMemory::Protect(reinterpret_cast<void*>(element),
+                                   region_size,
+                                   VirtualMemory::kReadWrite /*Execute*/);
+        ASSERT(status);
+      }
+      SplitElementAfterAndEnqueue(element, size, is_protected);
       return reinterpret_cast<uword>(element);
     }
   }
@@ -73,12 +103,53 @@
     if (current->Size() >= size) {
       // Found an element large enough to hold the requested size. Dequeue,
       // split and enqueue the remainder.
+      if (is_protected) {
+        // Make the allocated block and the header of the remainder element
+        // writable.  The remainder will be non-writable if necessary after
+        // the call to SplitElementAfterAndEnqueue.
+        intptr_t remainder_size = current->Size() - size;
+        intptr_t region_size = size +
+            ((remainder_size > 0) ? FreeListElement::kHeaderSize : 0);
+        bool status =
+            VirtualMemory::Protect(reinterpret_cast<void*>(current),
+                                   region_size,
+                                   VirtualMemory::kReadWrite /*Execute*/);
+        ASSERT(status);
+      }
       if (previous == NULL) {
         free_lists_[kNumLists] = current->next();
       } else {
+        // If the previous free list element's next field is protected, it
+        // needs to be unprotected before storing to it and reprotected
+        // after.
+        bool target_is_protected = false;
+        uword target_address = 0L;
+        if (is_protected) {
+          uword writable_start = reinterpret_cast<uword>(current);
+          uword writable_end =
+              writable_start + size + FreeListElement::kHeaderSize - 1;
+          target_address = previous->next_address();
+          target_is_protected =
+              !VirtualMemory::InSamePage(target_address, writable_start) &&
+              !VirtualMemory::InSamePage(target_address, writable_end);
+        }
+        if (target_is_protected) {
+          bool status =
+              VirtualMemory::Protect(reinterpret_cast<void*>(target_address),
+                                     kWordSize,
+                                     VirtualMemory::kReadWrite /*Execute*/);
+          ASSERT(status);
+        }
         previous->set_next(current->next());
+        if (target_is_protected) {
+          bool status =
+              VirtualMemory::Protect(reinterpret_cast<void*>(target_address),
+                                     kWordSize,
+                                     VirtualMemory::kReadExecute);
+          ASSERT(status);
+        }
       }
-      SplitElementAfterAndEnqueue(current, size);
+      SplitElementAfterAndEnqueue(current, size, is_protected);
       return reinterpret_cast<uword>(current);
     }
     previous = current;
@@ -89,9 +160,15 @@
 
 
 void FreeList::Free(uword addr, intptr_t size) {
+  // Precondition required by AsElement and EnqueueElement: the (page
+  // containing the) header of the freed block should be writable.  This is
+  // the case when called for newly allocated pages because they are
+  // allocated as writable.  It is the case when called during GC sweeping
+  // because the entire heap is writable.
   intptr_t index = IndexForSize(size);
   FreeListElement* element = FreeListElement::AsElement(addr, size);
   EnqueueElement(element, index);
+  // Postcondition: the (page containing the) header is left writable.
 }
 
 
@@ -213,14 +290,31 @@
 
 
 void FreeList::SplitElementAfterAndEnqueue(FreeListElement* element,
-                                           intptr_t size) {
+                                           intptr_t size,
+                                           bool is_protected) {
+  // Precondition required by AsElement and EnqueueElement: either
+  // element->Size() == size, or else the (page containing the) header of
+  // the remainder element starting at element + size is writable.
   intptr_t remainder_size = element->Size() - size;
   if (remainder_size == 0) return;
 
-  element = FreeListElement::AsElement(reinterpret_cast<uword>(element) + size,
-                                       remainder_size);
+  uword remainder_address = reinterpret_cast<uword>(element) + size;
+  element = FreeListElement::AsElement(remainder_address, remainder_size);
   intptr_t remainder_index = IndexForSize(remainder_size);
   EnqueueElement(element, remainder_index);
+
+  // Postcondition: when allocating in a protected page, the remainder
+  // element is no longer writable unless it is in the same page as the
+  // allocated element.  (The allocated element is still writable, and the
+  // remainder element will be protected when the allocated one is).
+  if (is_protected &&
+      !VirtualMemory::InSamePage(remainder_address - 1, remainder_address)) {
+    bool status =
+        VirtualMemory::Protect(reinterpret_cast<void*>(remainder_address),
+                               remainder_size,
+                               VirtualMemory::kReadExecute);
+    ASSERT(status);
+  }
 }
 
 }  // namespace dart
diff --git a/runtime/vm/freelist.h b/runtime/vm/freelist.h
index 8ec1ac4..9bed00e 100644
--- a/runtime/vm/freelist.h
+++ b/runtime/vm/freelist.h
@@ -19,9 +19,15 @@
 // the element at the address following the next_ field.
 class FreeListElement {
  public:
+  // Maximum header size is three words (tags, next, and size).
+  static const intptr_t kHeaderSize = 3 * kWordSize;
+
   FreeListElement* next() const {
     return next_;
   }
+  uword next_address() const {
+    return reinterpret_cast<uword>(&next_);
+  }
 
   void set_next(FreeListElement* next) {
     next_ = next;
@@ -75,7 +81,7 @@
   FreeList();
   ~FreeList();
 
-  uword TryAllocate(intptr_t size);
+  uword TryAllocate(intptr_t size, bool is_protected);
   void Free(uword addr, intptr_t size);
 
   void Reset();
@@ -92,7 +98,9 @@
   void EnqueueElement(FreeListElement* element, intptr_t index);
   FreeListElement* DequeueElement(intptr_t index);
 
-  void SplitElementAfterAndEnqueue(FreeListElement* element, intptr_t size);
+  void SplitElementAfterAndEnqueue(FreeListElement* element,
+                                   intptr_t size,
+                                   bool is_protected);
 
   void PrintSmall() const;
   void PrintLarge() const;
diff --git a/runtime/vm/freelist_test.cc b/runtime/vm/freelist_test.cc
index a64ce34..fc506d7 100644
--- a/runtime/vm/freelist_test.cc
+++ b/runtime/vm/freelist_test.cc
@@ -18,32 +18,33 @@
   // Enqueue the large blob as one free block.
   free_list->Free(blob, kBlobSize);
   // Allocate a small object. Expect it to be positioned as the first element.
-  uword small_object = free_list->TryAllocate(kSmallObjectSize);
+  uword small_object = free_list->TryAllocate(kSmallObjectSize, false);
   EXPECT_EQ(blob, small_object);
   // Freeing and allocating should give us the same memory back.
   free_list->Free(small_object, kSmallObjectSize);
-  small_object = free_list->TryAllocate(kSmallObjectSize);
+  small_object = free_list->TryAllocate(kSmallObjectSize, false);
   EXPECT_EQ(blob, small_object);
   // Splitting the remainder further with small and medium objects.
-  uword small_object2 = free_list->TryAllocate(kSmallObjectSize);
+  uword small_object2 = free_list->TryAllocate(kSmallObjectSize, false);
   EXPECT_EQ(blob + kSmallObjectSize, small_object2);
-  uword med_object = free_list->TryAllocate(kMediumObjectSize);
+  uword med_object = free_list->TryAllocate(kMediumObjectSize, false);
   EXPECT_EQ(small_object2 + kSmallObjectSize, med_object);
   // Allocate a large object.
-  uword large_object = free_list->TryAllocate(kLargeObjectSize);
+  uword large_object = free_list->TryAllocate(kLargeObjectSize, false);
   EXPECT_EQ(med_object + kMediumObjectSize, large_object);
   // Make sure that small objects can still split the remainder.
-  uword small_object3 = free_list->TryAllocate(kSmallObjectSize);
+  uword small_object3 = free_list->TryAllocate(kSmallObjectSize, false);
   EXPECT_EQ(large_object + kLargeObjectSize, small_object3);
   // Split the large object.
   free_list->Free(large_object, kLargeObjectSize);
-  uword small_object4 = free_list->TryAllocate(kSmallObjectSize);
+  uword small_object4 = free_list->TryAllocate(kSmallObjectSize, false);
   EXPECT_EQ(large_object, small_object4);
   // Get the full remainder of the large object.
-  large_object = free_list->TryAllocate(kLargeObjectSize - kSmallObjectSize);
+  large_object =
+      free_list->TryAllocate(kLargeObjectSize - kSmallObjectSize, false);
   EXPECT_EQ(small_object4 + kSmallObjectSize, large_object);
   // Get another large object from the large unallocated remainder.
-  uword large_object2 = free_list->TryAllocate(kLargeObjectSize);
+  uword large_object2 = free_list->TryAllocate(kLargeObjectSize, false);
   EXPECT_EQ(small_object3 + kSmallObjectSize, large_object2);
   // Delete the memory associated with the test.
   free(reinterpret_cast<void*>(blob));
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index 05995dd..682c75a 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -479,16 +479,6 @@
 }
 
 
-void AllocateObjectWithBoundsCheckInstr::PrintOperandsTo(
-    BufferFormatter* f) const {
-  f->Print("%s", Class::Handle(constructor().Owner()).ToCString());
-  for (intptr_t i = 0; i < InputCount(); i++) {
-    f->Print(", ");
-    InputAt(i)->PrintTo(f);
-  }
-}
-
-
 void MaterializeObjectInstr::PrintOperandsTo(BufferFormatter* f) const {
   f->Print("%s", String::Handle(cls_.Name()).ToCString());
   for (intptr_t i = 0; i < InputCount(); i++) {
diff --git a/runtime/vm/instructions_arm_test.cc b/runtime/vm/instructions_arm_test.cc
index dec458d..9970592 100644
--- a/runtime/vm/instructions_arm_test.cc
+++ b/runtime/vm/instructions_arm_test.cc
@@ -38,6 +38,13 @@
 
 
 ASSEMBLER_TEST_RUN(Jump, test) {
+  const Code& code = test->code();
+  const Instructions& instrs = Instructions::Handle(code.instructions());
+  bool status =
+      VirtualMemory::Protect(reinterpret_cast<void*>(instrs.EntryPoint()),
+                             instrs.size(),
+                             VirtualMemory::kReadWrite);
+  EXPECT(status);
   JumpPattern jump1(test->entry(), test->code());
   EXPECT_EQ(StubCode::InstanceFunctionLookupLabel().address(),
             jump1.TargetAddress());
diff --git a/runtime/vm/instructions_ia32_test.cc b/runtime/vm/instructions_ia32_test.cc
index e449e21..637f72e 100644
--- a/runtime/vm/instructions_ia32_test.cc
+++ b/runtime/vm/instructions_ia32_test.cc
@@ -7,8 +7,10 @@
 
 #include "vm/assembler.h"
 #include "vm/instructions.h"
+#include "vm/object.h"
 #include "vm/stub_code.h"
 #include "vm/unit_test.h"
+#include "vm/virtual_memory.h"
 
 namespace dart {
 
@@ -35,6 +37,13 @@
 
 
 ASSEMBLER_TEST_RUN(Jump, test) {
+  const Code& code = test->code();
+  const Instructions& instrs = Instructions::Handle(code.instructions());
+  bool status =
+      VirtualMemory::Protect(reinterpret_cast<void*>(instrs.EntryPoint()),
+                             instrs.size(),
+                             VirtualMemory::kReadWrite);
+  EXPECT(status);
   JumpPattern jump1(test->entry(), test->code());
   EXPECT_EQ(StubCode::InstanceFunctionLookupLabel().address(),
             jump1.TargetAddress());
diff --git a/runtime/vm/instructions_mips_test.cc b/runtime/vm/instructions_mips_test.cc
index 7348db8..4aff913 100644
--- a/runtime/vm/instructions_mips_test.cc
+++ b/runtime/vm/instructions_mips_test.cc
@@ -39,6 +39,13 @@
 
 
 ASSEMBLER_TEST_RUN(Jump, test) {
+  const Code& code = test->code();
+  const Instructions& instrs = Instructions::Handle(code.instructions());
+  bool status =
+      VirtualMemory::Protect(reinterpret_cast<void*>(instrs.EntryPoint()),
+                             instrs.size(),
+                             VirtualMemory::kReadWrite);
+  EXPECT(status);
   JumpPattern jump1(test->entry(), test->code());
   EXPECT_EQ(StubCode::InstanceFunctionLookupLabel().address(),
             jump1.TargetAddress());
diff --git a/runtime/vm/instructions_x64_test.cc b/runtime/vm/instructions_x64_test.cc
index c9abf0f..5cd4c8d 100644
--- a/runtime/vm/instructions_x64_test.cc
+++ b/runtime/vm/instructions_x64_test.cc
@@ -44,6 +44,13 @@
 
 ASSEMBLER_TEST_RUN(Jump, test) {
   ASSERT(prologue_code_size != -1);
+  const Code& code = test->code();
+  const Instructions& instrs = Instructions::Handle(code.instructions());
+  bool status =
+      VirtualMemory::Protect(reinterpret_cast<void*>(instrs.EntryPoint()),
+                             instrs.size(),
+                             VirtualMemory::kReadWrite);
+  EXPECT(status);
   JumpPattern jump1(test->entry() + prologue_code_size, test->code());
   jump1.IsValid();
   EXPECT_EQ(StubCode::InstanceFunctionLookupLabel().address(),
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 4ec778a..9a06cfd 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -26,7 +26,8 @@
 
 DEFINE_FLAG(bool, propagate_ic_data, true,
     "Propagate IC data from unoptimized to optimized IC calls.");
-DEFINE_FLAG(bool, unbox_double_fields, true, "Support unboxed double fields.");
+DEFINE_FLAG(bool, unbox_numeric_fields, true,
+    "Support unboxed double and float32x4 fields.");
 DECLARE_FLAG(bool, enable_type_checks);
 DECLARE_FLAG(bool, eliminate_type_checks);
 DECLARE_FLAG(bool, trace_optimization);
@@ -84,7 +85,7 @@
 CheckClassInstr::CheckClassInstr(Value* value,
                                  intptr_t deopt_id,
                                  const ICData& unary_checks)
-    : unary_checks_(unary_checks) {
+    : unary_checks_(unary_checks), licm_hoisted_(false) {
   ASSERT(unary_checks.IsZoneHandle());
   // Expected useful check data.
   ASSERT(!unary_checks_.IsNull());
@@ -138,14 +139,14 @@
 
 
 bool LoadFieldInstr::IsUnboxedLoad() const {
-  return FLAG_unbox_double_fields
+  return FLAG_unbox_numeric_fields
       && (field() != NULL)
       && field()->IsUnboxedField();
 }
 
 
 bool LoadFieldInstr::IsPotentialUnboxedLoad() const {
-  return FLAG_unbox_double_fields
+  return FLAG_unbox_numeric_fields
       && (field() != NULL)
       && field()->IsPotentialUnboxedField();
 }
@@ -157,7 +158,8 @@
     switch (cid) {
       case kDoubleCid:
         return kUnboxedDouble;
-      // TODO(johnmccutchan): Add kFloat32x4Cid here.
+      case kFloat32x4Cid:
+        return kUnboxedFloat32x4;
       default:
         UNREACHABLE();
     }
@@ -167,12 +169,12 @@
 
 
 bool StoreInstanceFieldInstr::IsUnboxedStore() const {
-  return FLAG_unbox_double_fields && field().IsUnboxedField();
+  return FLAG_unbox_numeric_fields && field().IsUnboxedField();
 }
 
 
 bool StoreInstanceFieldInstr::IsPotentialUnboxedStore() const {
-  return FLAG_unbox_double_fields && field().IsPotentialUnboxedField();
+  return FLAG_unbox_numeric_fields && field().IsPotentialUnboxedField();
 }
 
 
@@ -184,6 +186,8 @@
     switch (cid) {
       case kDoubleCid:
         return kUnboxedDouble;
+      case kFloat32x4Cid:
+        return kUnboxedFloat32x4;
       default:
         UNREACHABLE();
     }
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 1b63f7a..17272be 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -632,7 +632,6 @@
   M(CreateArray)                                                               \
   M(CreateClosure)                                                             \
   M(AllocateObject)                                                            \
-  M(AllocateObjectWithBoundsCheck)                                             \
   M(LoadField)                                                                 \
   M(StoreVMField)                                                              \
   M(LoadUntagged)                                                              \
@@ -4063,34 +4062,6 @@
 };
 
 
-class AllocateObjectWithBoundsCheckInstr : public TemplateDefinition<0> {
- public:
-  explicit AllocateObjectWithBoundsCheckInstr(ConstructorCallNode* node)
-      : ast_node_(*node) {
-  }
-
-  DECLARE_INSTRUCTION(AllocateObjectWithBoundsCheck)
-
-  virtual intptr_t ArgumentCount() const { return 4; }
-
-  const Function& constructor() const { return ast_node_.constructor(); }
-  intptr_t token_pos() const { return ast_node_.token_pos(); }
-
-  virtual void PrintOperandsTo(BufferFormatter* f) const;
-
-  virtual bool CanDeoptimize() const { return true; }
-
-  virtual EffectSet Effects() const { return EffectSet::None(); }
-
-  virtual bool MayThrow() const { return false; }
-
- private:
-  const ConstructorCallNode& ast_node_;
-
-  DISALLOW_COPY_AND_ASSIGN(AllocateObjectWithBoundsCheckInstr);
-};
-
-
 class CreateArrayInstr : public TemplateDefinition<2> {
  public:
   CreateArrayInstr(intptr_t token_pos,
@@ -4390,7 +4361,7 @@
 class InstantiateTypeArgumentsInstr : public TemplateDefinition<1> {
  public:
   InstantiateTypeArgumentsInstr(intptr_t token_pos,
-                                const AbstractTypeArguments& type_arguments,
+                                const TypeArguments& type_arguments,
                                 const Class& instantiator_class,
                                 Value* instantiator)
       : token_pos_(token_pos),
@@ -4403,7 +4374,7 @@
   DECLARE_INSTRUCTION(InstantiateTypeArguments)
 
   Value* instantiator() const { return inputs_[0]; }
-  const AbstractTypeArguments& type_arguments() const {
+  const TypeArguments& type_arguments() const {
     return type_arguments_;
   }
   const Class& instantiator_class() const { return instantiator_class_; }
@@ -4419,7 +4390,7 @@
 
  private:
   const intptr_t token_pos_;
-  const AbstractTypeArguments& type_arguments_;
+  const TypeArguments& type_arguments_;
   const Class& instantiator_class_;
 
   DISALLOW_COPY_AND_ASSIGN(InstantiateTypeArgumentsInstr);
@@ -4430,7 +4401,7 @@
  public:
   ExtractConstructorTypeArgumentsInstr(
       intptr_t token_pos,
-      const AbstractTypeArguments& type_arguments,
+      const TypeArguments& type_arguments,
       const Class& instantiator_class,
       Value* instantiator)
       : token_pos_(token_pos),
@@ -4442,7 +4413,7 @@
   DECLARE_INSTRUCTION(ExtractConstructorTypeArguments)
 
   Value* instantiator() const { return inputs_[0]; }
-  const AbstractTypeArguments& type_arguments() const {
+  const TypeArguments& type_arguments() const {
     return type_arguments_;
   }
   const Class& instantiator_class() const { return instantiator_class_; }
@@ -4458,7 +4429,7 @@
 
  private:
   const intptr_t token_pos_;
-  const AbstractTypeArguments& type_arguments_;
+  const TypeArguments& type_arguments_;
   const Class& instantiator_class_;
 
   DISALLOW_COPY_AND_ASSIGN(ExtractConstructorTypeArgumentsInstr);
@@ -4477,7 +4448,7 @@
   DECLARE_INSTRUCTION(ExtractConstructorInstantiator)
 
   Value* instantiator() const { return inputs_[0]; }
-  const AbstractTypeArguments& type_arguments() const {
+  const TypeArguments& type_arguments() const {
     return ast_node_.type_arguments();
   }
   const Function& constructor() const { return ast_node_.constructor(); }
@@ -6822,8 +6793,11 @@
 
   virtual bool MayThrow() const { return false; }
 
+  void set_licm_hoisted(bool value) { licm_hoisted_ = value; }
+
  private:
   const ICData& unary_checks_;
+  bool licm_hoisted_;
 
   DISALLOW_COPY_AND_ASSIGN(CheckClassInstr);
 };
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 977763a..55c8e2c 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -1590,6 +1590,7 @@
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
     __ Comment("StoreInstanceFieldSlowPath");
     __ Bind(entry_label());
+
     const Code& stub =
         Code::Handle(StubCode::GetAllocationStubForClass(cls_));
     const ExternalLabel label(cls_.ToCString(), stub.EntryPoint());
@@ -1652,6 +1653,7 @@
 
   if (IsUnboxedStore() && compiler->is_optimizing()) {
     DRegister value = EvenDRegisterOf(locs()->in(1).fpu_reg());
+    DRegister value_odd = OddDRegisterOf(locs()->in(1).fpu_reg());
     Register temp = locs()->temp(0).reg();
     Register temp2 = locs()->temp(1).reg();
     const intptr_t cid = field().UnboxedFieldCid();
@@ -1662,13 +1664,17 @@
         case kDoubleCid:
           cls = &compiler->double_class();
           break;
-        // TODO(johnmccutchan): Add kFloat32x4Cid here.
+        case kFloat32x4Cid:
+          cls = &compiler->float32x4_class();
+          break;
         default:
           UNREACHABLE();
       }
+
       StoreInstanceFieldSlowPath* slow_path =
           new StoreInstanceFieldSlowPath(this, *cls);
       compiler->AddSlowPathCode(slow_path);
+
       __ TryAllocate(*cls,
                      slow_path->entry_label(),
                      temp,
@@ -1683,9 +1689,16 @@
     }
     switch (cid) {
       case kDoubleCid:
-      __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag);
-      // TODO(johnmccutchan): Add kFloat32x4Cid here.
-      break;
+        __ Comment("UnboxedDoubleStoreInstanceFieldInstr");
+        __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag);
+        break;
+      case kFloat32x4Cid:
+        __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr");
+        __ StoreDToOffset(value, temp,
+            Float32x4::value_offset() - kHeapObjectTag);
+        __ StoreDToOffset(value_odd, temp,
+            Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag);
+        break;
       default:
         UNREACHABLE();
     }
@@ -1698,10 +1711,11 @@
     Register temp = locs()->temp(0).reg();
     Register temp2 = locs()->temp(1).reg();
     DRegister fpu_temp = EvenDRegisterOf(locs()->temp(2).fpu_reg());
+    DRegister fpu_temp_odd = OddDRegisterOf(locs()->temp(2).fpu_reg());
 
     Label store_pointer;
-    Label copy_double;
     Label store_double;
+    Label store_float32x4;
 
     __ LoadObject(temp, Field::ZoneHandle(field().raw()));
 
@@ -1717,40 +1731,82 @@
     __ CompareImmediate(temp2, kDoubleCid);
     __ b(&store_double, EQ);
 
+    __ ldr(temp2, FieldAddress(temp, Field::guarded_cid_offset()));
+    __ CompareImmediate(temp2, kFloat32x4Cid);
+    __ b(&store_float32x4, EQ);
+
     // Fall through.
     __ b(&store_pointer);
 
-    __ Bind(&store_double);
-
-    __ ldr(temp, FieldAddress(instance_reg, field().Offset()));
-    __ CompareImmediate(temp,
-                        reinterpret_cast<intptr_t>(Object::null()));
-    __ b(&copy_double, NE);
-
-    StoreInstanceFieldSlowPath* slow_path =
-        new StoreInstanceFieldSlowPath(this, compiler->double_class());
-    compiler->AddSlowPathCode(slow_path);
-
     if (!compiler->is_optimizing()) {
-      locs()->live_registers()->Add(locs()->in(0));
-      locs()->live_registers()->Add(locs()->in(1));
+        locs()->live_registers()->Add(locs()->in(0));
+        locs()->live_registers()->Add(locs()->in(1));
     }
 
-    __ TryAllocate(compiler->double_class(),
-                   slow_path->entry_label(),
-                   temp,
-                   temp2);
-    __ Bind(slow_path->exit_label());
-    __ MoveRegister(temp2, temp);
-    __ StoreIntoObject(instance_reg,
-                       FieldAddress(instance_reg, field().Offset()),
-                       temp2);
-    __ Bind(&copy_double);
-    __ LoadDFromOffset(fpu_temp,
-                       value_reg,
-                       Double::value_offset() - kHeapObjectTag);
-    __ StoreDToOffset(fpu_temp, temp, Double::value_offset() - kHeapObjectTag);
-    __ b(&skip_store);
+    {
+      __ Bind(&store_double);
+      Label copy_double;
+      StoreInstanceFieldSlowPath* slow_path =
+          new StoreInstanceFieldSlowPath(this, compiler->double_class());
+      compiler->AddSlowPathCode(slow_path);
+
+      __ ldr(temp, FieldAddress(instance_reg, field().Offset()));
+      __ CompareImmediate(temp,
+                          reinterpret_cast<intptr_t>(Object::null()));
+      __ b(&copy_double, NE);
+
+      __ TryAllocate(compiler->double_class(),
+                     slow_path->entry_label(),
+                     temp,
+                     temp2);
+      __ Bind(slow_path->exit_label());
+      __ MoveRegister(temp2, temp);
+      __ StoreIntoObject(instance_reg,
+                         FieldAddress(instance_reg, field().Offset()),
+                         temp2);
+      __ Bind(&copy_double);
+      __ LoadDFromOffset(fpu_temp,
+                         value_reg,
+                         Double::value_offset() - kHeapObjectTag);
+      __ StoreDToOffset(fpu_temp,
+                        temp,
+                        Double::value_offset() - kHeapObjectTag);
+      __ b(&skip_store);
+    }
+
+    {
+      __ Bind(&store_float32x4);
+      Label copy_float32x4;
+      StoreInstanceFieldSlowPath* slow_path =
+          new StoreInstanceFieldSlowPath(this, compiler->float32x4_class());
+      compiler->AddSlowPathCode(slow_path);
+
+      __ ldr(temp, FieldAddress(instance_reg, field().Offset()));
+      __ CompareImmediate(temp,
+                          reinterpret_cast<intptr_t>(Object::null()));
+      __ b(&copy_float32x4, NE);
+
+      __ TryAllocate(compiler->float32x4_class(),
+                     slow_path->entry_label(),
+                     temp,
+                     temp2);
+      __ Bind(slow_path->exit_label());
+      __ MoveRegister(temp2, temp);
+      __ StoreIntoObject(instance_reg,
+                         FieldAddress(instance_reg, field().Offset()),
+                         temp2);
+      __ Bind(&copy_float32x4);
+      __ LoadDFromOffset(fpu_temp, value_reg,
+          Float32x4::value_offset() - kHeapObjectTag);
+      __ LoadDFromOffset(fpu_temp_odd, value_reg,
+          Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag);
+      __ StoreDToOffset(fpu_temp, temp,
+          Float32x4::value_offset() - kHeapObjectTag);
+      __ StoreDToOffset(fpu_temp_odd, temp,
+          Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag);
+      __ b(&skip_store);
+    }
+
     __ Bind(&store_pointer);
   }
 
@@ -1875,25 +1931,6 @@
 }
 
 
-LocationSummary*
-AllocateObjectWithBoundsCheckInstr::MakeLocationSummary(bool opt) const {
-  return MakeCallSummary();
-}
-
-
-void AllocateObjectWithBoundsCheckInstr::EmitNativeCode(
-    FlowGraphCompiler* compiler) {
-  compiler->GenerateRuntimeCall(token_pos(),
-                                deopt_id(),
-                                kAllocateObjectWithBoundsCheckRuntimeEntry,
-                                3,
-                                locs());
-  __ Drop(3);
-  ASSERT(locs()->out().reg() == R0);
-  __ Pop(R0);  // Pop new instance.
-}
-
-
 class BoxDoubleSlowPath : public SlowPathCode {
  public:
   explicit BoxDoubleSlowPath(Instruction* instruction)
@@ -1926,6 +1963,38 @@
 };
 
 
+class BoxFloat32x4SlowPath : public SlowPathCode {
+ public:
+  explicit BoxFloat32x4SlowPath(Instruction* instruction)
+      : instruction_(instruction) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("BoxFloat32x4SlowPath");
+    __ Bind(entry_label());
+    const Class& float32x4_class = compiler->float32x4_class();
+    const Code& stub =
+        Code::Handle(StubCode::GetAllocationStubForClass(float32x4_class));
+    const ExternalLabel label(float32x4_class.ToCString(), stub.EntryPoint());
+
+    LocationSummary* locs = instruction_->locs();
+    locs->live_registers()->Remove(locs->out());
+
+    compiler->SaveLiveRegisters(locs);
+    compiler->GenerateCall(Scanner::kNoSourcePos,  // No token position.
+                           &label,
+                           PcDescriptors::kOther,
+                           locs);
+    __ mov(locs->out().reg(), ShifterOperand(R0));
+    compiler->RestoreLiveRegisters(locs);
+
+    __ b(exit_label());
+  }
+
+ private:
+  Instruction* instruction_;
+};
+
+
 LocationSummary* LoadFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
@@ -1954,15 +2023,23 @@
   Register instance_reg = locs()->in(0).reg();
   if (IsUnboxedLoad() && compiler->is_optimizing()) {
     DRegister result = EvenDRegisterOf(locs()->out().fpu_reg());
+    DRegister result_odd = OddDRegisterOf(locs()->out().fpu_reg());
     Register temp = locs()->temp(0).reg();
     __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes()));
     intptr_t cid = field()->UnboxedFieldCid();
     switch (cid) {
       case kDoubleCid:
+        __ Comment("UnboxedDoubleLoadFieldInstr");
         __ LoadDFromOffset(result, temp,
                            Double::value_offset() - kHeapObjectTag);
         break;
-      // TODO(johnmccutchan): Add Float32x4 path here.
+      case kFloat32x4Cid:
+        __ Comment("UnboxedFloat32x4LoadFieldInstr");
+        __ LoadDFromOffset(result, temp,
+            Float32x4::value_offset() - kHeapObjectTag);
+        __ LoadDFromOffset(result_odd, temp,
+            Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag);
+        break;
       default:
         UNREACHABLE();
     }
@@ -1974,9 +2051,11 @@
   if (IsPotentialUnboxedLoad()) {
     Register temp = locs()->temp(1).reg();
     DRegister value = EvenDRegisterOf(locs()->temp(0).fpu_reg());
+    DRegister value_odd = OddDRegisterOf(locs()->temp(0).fpu_reg());
 
     Label load_pointer;
     Label load_double;
+    Label load_float32x4;
 
     __ LoadObject(result_reg, Field::ZoneHandle(field()->raw()));
 
@@ -1992,31 +2071,56 @@
     __ CompareImmediate(temp, kDoubleCid);
     __ b(&load_double, EQ);
 
+    __ ldr(temp, field_cid_operand);
+    __ CompareImmediate(temp, kFloat32x4Cid);
+    __ b(&load_float32x4, EQ);
+
     // Fall through.
     __ b(&load_pointer);
 
-    __ Bind(&load_double);
-
-    BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
-    compiler->AddSlowPathCode(slow_path);
-
     if (!compiler->is_optimizing()) {
       locs()->live_registers()->Add(locs()->in(0));
     }
 
-    __ TryAllocate(compiler->double_class(),
-                   slow_path->entry_label(),
-                   result_reg,
-                   temp);
-    __ Bind(slow_path->exit_label());
-    __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes()));
-    __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag);
-    __ StoreDToOffset(value,
-                      result_reg,
-                      Double::value_offset() - kHeapObjectTag);
-    __ b(&done);
+    {
+      __ Bind(&load_double);
+      BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
+      compiler->AddSlowPathCode(slow_path);
 
-    // TODO(johnmccutchan): Add Float32x4 path here.
+      __ TryAllocate(compiler->double_class(),
+                     slow_path->entry_label(),
+                     result_reg,
+                     temp);
+      __ Bind(slow_path->exit_label());
+      __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes()));
+      __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag);
+      __ StoreDToOffset(value,
+                        result_reg,
+                        Double::value_offset() - kHeapObjectTag);
+      __ b(&done);
+    }
+
+    {
+      __ Bind(&load_float32x4);
+      BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this);
+      compiler->AddSlowPathCode(slow_path);
+
+      __ TryAllocate(compiler->float32x4_class(),
+                     slow_path->entry_label(),
+                     result_reg,
+                     temp);
+      __ Bind(slow_path->exit_label());
+      __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes()));
+      __ LoadDFromOffset(value, temp,
+          Float32x4::value_offset() - kHeapObjectTag);
+      __ LoadDFromOffset(value_odd, temp,
+          Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag);
+      __ StoreDToOffset(value, result_reg,
+          Float32x4::value_offset() - kHeapObjectTag);
+      __ StoreDToOffset(value_odd, result_reg,
+          Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag);
+      __ b(&done);
+    }
 
     __ Bind(&load_pointer);
   }
@@ -2041,8 +2145,7 @@
   Register instantiator_reg = locs()->in(0).reg();
   Register result_reg = locs()->out().reg();
 
-  // 'instantiator_reg' is the instantiator AbstractTypeArguments object
-  // (or null).
+  // 'instantiator_reg' is the instantiator TypeArguments object (or null).
   // A runtime call to instantiate the type is required.
   __ PushObject(Object::ZoneHandle());  // Make room for the result.
   __ PushObject(type());
@@ -2075,8 +2178,7 @@
   Register instantiator_reg = locs()->in(0).reg();
   Register result_reg = locs()->out().reg();
 
-  // 'instantiator_reg' is the instantiator AbstractTypeArguments object
-  // (or null).
+  // 'instantiator_reg' is the instantiator TypeArguments object (or null).
   ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
          !type_arguments().CanShareInstantiatorTypeArguments(
              instantiator_class()));
@@ -2125,8 +2227,8 @@
   Register result_reg = locs()->out().reg();
   ASSERT(instantiator_reg == result_reg);
 
-  // instantiator_reg is the instantiator type argument vector, i.e. an
-  // AbstractTypeArguments object (or null).
+  // instantiator_reg is the instantiator type argument vector,
+  // i.e. a TypeArguments object (or null).
   ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
          !type_arguments().CanShareInstantiatorTypeArguments(
              instantiator_class()));
@@ -2166,8 +2268,7 @@
   Register instantiator_reg = locs()->in(0).reg();
   ASSERT(locs()->out().reg() == instantiator_reg);
 
-  // instantiator_reg is the instantiator AbstractTypeArguments object
-  // (or null).
+  // instantiator_reg is the instantiator TypeArguments object (or null).
   ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
          !type_arguments().CanShareInstantiatorTypeArguments(
              instantiator_class()));
@@ -2916,38 +3017,6 @@
 }
 
 
-class BoxFloat32x4SlowPath : public SlowPathCode {
- public:
-  explicit BoxFloat32x4SlowPath(BoxFloat32x4Instr* instruction)
-      : instruction_(instruction) { }
-
-  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
-    __ Comment("BoxFloat32x4SlowPath");
-    __ Bind(entry_label());
-    const Class& float32x4_class = compiler->float32x4_class();
-    const Code& stub =
-        Code::Handle(StubCode::GetAllocationStubForClass(float32x4_class));
-    const ExternalLabel label(float32x4_class.ToCString(), stub.EntryPoint());
-
-    LocationSummary* locs = instruction_->locs();
-    locs->live_registers()->Remove(locs->out());
-
-    compiler->SaveLiveRegisters(locs);
-    compiler->GenerateCall(Scanner::kNoSourcePos,  // No token position.
-                           &label,
-                           PcDescriptors::kOther,
-                           locs);
-    __ mov(locs->out().reg(), ShifterOperand(R0));
-    compiler->RestoreLiveRegisters(locs);
-
-    __ b(exit_label());
-  }
-
- private:
-  BoxFloat32x4Instr* instruction_;
-};
-
-
 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
   BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this);
   compiler->AddSlowPathCode(slow_path);
@@ -4477,9 +4546,10 @@
 
 
 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const DeoptReasonId deopt_reason =
+      licm_hoisted_ ? kDeoptHoistedCheckClass : kDeoptCheckClass;
   if (IsNullCheck()) {
-    Label* deopt = compiler->AddDeoptStub(deopt_id(),
-                                          kDeoptCheckClass);
+    Label* deopt = compiler->AddDeoptStub(deopt_id(), deopt_reason);
     __ CompareImmediate(locs()->in(0).reg(),
                         reinterpret_cast<intptr_t>(Object::null()));
     __ b(deopt, EQ);
@@ -4490,8 +4560,7 @@
          (unary_checks().NumberOfChecks() > 1));
   Register value = locs()->in(0).reg();
   Register temp = locs()->temp(0).reg();
-  Label* deopt = compiler->AddDeoptStub(deopt_id(),
-                                        kDeoptCheckClass);
+  Label* deopt = compiler->AddDeoptStub(deopt_id(), deopt_reason);
   Label is_ok;
   intptr_t cix = 0;
   if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) {
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index c1b3e04..be9f97f 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -1605,7 +1605,6 @@
 
     LocationSummary* locs = instruction_->locs();
     locs->live_registers()->Remove(locs->out());
-
     compiler->SaveLiveRegisters(locs);
     compiler->GenerateCall(Scanner::kNoSourcePos,  // No token position.
                            &label,
@@ -1613,7 +1612,6 @@
                            locs);
     __ MoveRegister(locs->temp(0).reg(), EAX);
     compiler->RestoreLiveRegisters(locs);
-
     __ jmp(exit_label());
   }
 
@@ -1671,10 +1669,13 @@
         case kDoubleCid:
           cls = &compiler->double_class();
           break;
-        // TODO(johnmccutchan): Add kFloat32x4Cid here.
+        case kFloat32x4Cid:
+          cls = &compiler->float32x4_class();
+          break;
         default:
           UNREACHABLE();
       }
+
       StoreInstanceFieldSlowPath* slow_path =
           new StoreInstanceFieldSlowPath(this, *cls);
       compiler->AddSlowPathCode(slow_path);
@@ -1694,8 +1695,12 @@
     }
     switch (cid) {
       case kDoubleCid:
-      __ movsd(FieldAddress(temp, Double::value_offset()), value);
-      // TODO(johnmccutchan): Add kFloat32x4Cid here.
+        __ Comment("UnboxedDoubleStoreInstanceFieldInstr");
+        __ movsd(FieldAddress(temp, Double::value_offset()), value);
+      break;
+      case kFloat32x4Cid:
+        __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr");
+        __ movups(FieldAddress(temp, Float32x4::value_offset()), value);
       break;
       default:
         UNREACHABLE();
@@ -1710,8 +1715,8 @@
     FpuRegister fpu_temp = locs()->temp(2).fpu_reg();
 
     Label store_pointer;
-    Label copy_double;
     Label store_double;
+    Label store_float32x4;
 
     __ LoadObject(temp, Field::ZoneHandle(field().raw()));
 
@@ -1727,41 +1732,80 @@
             Immediate(kDoubleCid));
     __ j(EQUAL, &store_double);
 
+    __ cmpl(FieldAddress(temp, Field::guarded_cid_offset()),
+            Immediate(kFloat32x4Cid));
+    __ j(EQUAL, &store_float32x4);
+
     // Fall through.
     __ jmp(&store_pointer);
 
-    __ Bind(&store_double);
-
-    const Immediate& raw_null =
-        Immediate(reinterpret_cast<intptr_t>(Object::null()));
-    __ movl(temp, FieldAddress(instance_reg, field().Offset()));
-    __ cmpl(temp, raw_null);
-    __ j(NOT_EQUAL, &copy_double);
-
-    StoreInstanceFieldSlowPath* slow_path =
-        new StoreInstanceFieldSlowPath(this, compiler->double_class());
-    compiler->AddSlowPathCode(slow_path);
 
     if (!compiler->is_optimizing()) {
       locs()->live_registers()->Add(locs()->in(0));
       locs()->live_registers()->Add(locs()->in(1));
     }
 
-    __ TryAllocate(compiler->double_class(),
-                   slow_path->entry_label(),
-                   Assembler::kFarJump,
-                   temp,
-                   temp2);
-    __ Bind(slow_path->exit_label());
-    __ movl(temp2, temp);
-    __ StoreIntoObject(instance_reg,
-                       FieldAddress(instance_reg, field().Offset()),
-                       temp2);
+    {
+      __ Bind(&store_double);
+      Label copy_double;
 
-    __ Bind(&copy_double);
-    __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset()));
-    __ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp);
-    __ jmp(&skip_store);
+      StoreInstanceFieldSlowPath* slow_path =
+          new StoreInstanceFieldSlowPath(this, compiler->double_class());
+      compiler->AddSlowPathCode(slow_path);
+
+      const Immediate& raw_null =
+          Immediate(reinterpret_cast<intptr_t>(Object::null()));
+      __ movl(temp, FieldAddress(instance_reg, field().Offset()));
+      __ cmpl(temp, raw_null);
+      __ j(NOT_EQUAL, &copy_double);
+
+      __ TryAllocate(compiler->double_class(),
+                     slow_path->entry_label(),
+                     Assembler::kFarJump,
+                     temp,
+                     temp2);
+      __ Bind(slow_path->exit_label());
+      __ movl(temp2, temp);
+      __ StoreIntoObject(instance_reg,
+                         FieldAddress(instance_reg, field().Offset()),
+                         temp2);
+
+      __ Bind(&copy_double);
+      __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset()));
+      __ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp);
+      __ jmp(&skip_store);
+    }
+
+    {
+      __ Bind(&store_float32x4);
+      Label copy_float32x4;
+
+      StoreInstanceFieldSlowPath* slow_path =
+          new StoreInstanceFieldSlowPath(this, compiler->float32x4_class());
+      compiler->AddSlowPathCode(slow_path);
+
+      const Immediate& raw_null =
+          Immediate(reinterpret_cast<intptr_t>(Object::null()));
+      __ movl(temp, FieldAddress(instance_reg, field().Offset()));
+      __ cmpl(temp, raw_null);
+      __ j(NOT_EQUAL, &copy_float32x4);
+
+      __ TryAllocate(compiler->float32x4_class(),
+                     slow_path->entry_label(),
+                     Assembler::kFarJump,
+                     temp,
+                     temp2);
+      __ Bind(slow_path->exit_label());
+      __ movl(temp2, temp);
+      __ StoreIntoObject(instance_reg,
+                         FieldAddress(instance_reg, field().Offset()),
+                         temp2);
+
+      __ Bind(&copy_float32x4);
+      __ movups(fpu_temp, FieldAddress(value_reg, Float32x4::value_offset()));
+      __ movups(FieldAddress(temp, Float32x4::value_offset()), fpu_temp);
+      __ jmp(&skip_store);
+    }
     __ Bind(&store_pointer);
   }
 
@@ -1887,25 +1931,6 @@
 }
 
 
-LocationSummary*
-AllocateObjectWithBoundsCheckInstr::MakeLocationSummary(bool opt) const {
-  return MakeCallSummary();
-}
-
-
-void AllocateObjectWithBoundsCheckInstr::EmitNativeCode(
-    FlowGraphCompiler* compiler) {
-  compiler->GenerateRuntimeCall(token_pos(),
-                                deopt_id(),
-                                kAllocateObjectWithBoundsCheckRuntimeEntry,
-                                3,
-                                locs());
-  __ Drop(3);
-  ASSERT(locs()->out().reg() == EAX);
-  __ popl(EAX);  // Pop new instance.
-}
-
-
 class BoxDoubleSlowPath : public SlowPathCode {
  public:
   explicit BoxDoubleSlowPath(Instruction* instruction)
@@ -1938,6 +1963,39 @@
 };
 
 
+class BoxFloat32x4SlowPath : public SlowPathCode {
+ public:
+  explicit BoxFloat32x4SlowPath(Instruction* instruction)
+      : instruction_(instruction) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("BoxFloat32x4SlowPath");
+    __ Bind(entry_label());
+    const Class& float32x4_class = compiler->float32x4_class();
+    const Code& stub =
+        Code::Handle(StubCode::GetAllocationStubForClass(float32x4_class));
+    const ExternalLabel label(float32x4_class.ToCString(), stub.EntryPoint());
+
+    LocationSummary* locs = instruction_->locs();
+    locs->live_registers()->Remove(locs->out());
+
+    compiler->SaveLiveRegisters(locs);
+    compiler->GenerateCall(Scanner::kNoSourcePos,  // No token position.
+                           &label,
+                           PcDescriptors::kOther,
+                           locs);
+    __ MoveRegister(locs->out().reg(), EAX);
+    compiler->RestoreLiveRegisters(locs);
+
+    __ jmp(exit_label());
+  }
+
+ private:
+  Instruction* instruction_;
+};
+
+
+
 LocationSummary* LoadFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
@@ -1971,9 +2029,13 @@
     const intptr_t cid = field()->UnboxedFieldCid();
     switch (cid) {
       case kDoubleCid:
+        __ Comment("UnboxedDoubleLoadFieldInstr");
         __ movsd(result, FieldAddress(temp, Double::value_offset()));
         break;
-      // TODO(johnmccutchan): Add Float32x4 path here.
+      case kFloat32x4Cid:
+        __ Comment("UnboxedFloat32x4LoadFieldInstr");
+        __ movups(result, FieldAddress(temp, Float32x4::value_offset()));
+        break;
       default:
         UNREACHABLE();
     }
@@ -1986,8 +2048,11 @@
     Register temp = locs()->temp(1).reg();
     XmmRegister value = locs()->temp(0).fpu_reg();
 
+
     Label load_pointer;
     Label load_double;
+    Label load_float32x4;
+
     __ LoadObject(result, Field::ZoneHandle(field()->raw()));
 
     FieldAddress field_cid_operand(result, Field::guarded_cid_offset());
@@ -1999,29 +2064,50 @@
     __ cmpl(field_cid_operand, Immediate(kDoubleCid));
     __ j(EQUAL, &load_double);
 
+    __ cmpl(field_cid_operand, Immediate(kFloat32x4Cid));
+    __ j(EQUAL, &load_float32x4);
+
     // Fall through.
     __ jmp(&load_pointer);
 
-    __ Bind(&load_double);
-    BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
-    compiler->AddSlowPathCode(slow_path);
-
     if (!compiler->is_optimizing()) {
       locs()->live_registers()->Add(locs()->in(0));
     }
 
-    __ TryAllocate(compiler->double_class(),
-                   slow_path->entry_label(),
-                   Assembler::kFarJump,
-                   result,
-                   temp);
-    __ Bind(slow_path->exit_label());
-    __ movl(temp, FieldAddress(instance_reg, offset_in_bytes()));
-    __ movsd(value, FieldAddress(temp, Double::value_offset()));
-    __ movsd(FieldAddress(result, Double::value_offset()), value);
-    __ jmp(&done);
+    {
+      __ Bind(&load_double);
+      BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
+      compiler->AddSlowPathCode(slow_path);
 
-    // TODO(johnmccutchan): Add Float32x4 path here.
+      __ TryAllocate(compiler->double_class(),
+                     slow_path->entry_label(),
+                     Assembler::kFarJump,
+                     result,
+                     temp);
+      __ Bind(slow_path->exit_label());
+      __ movl(temp, FieldAddress(instance_reg, offset_in_bytes()));
+      __ movsd(value, FieldAddress(temp, Double::value_offset()));
+      __ movsd(FieldAddress(result, Double::value_offset()), value);
+      __ jmp(&done);
+    }
+
+    {
+      __ Bind(&load_float32x4);
+
+      BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this);
+      compiler->AddSlowPathCode(slow_path);
+
+      __ TryAllocate(compiler->float32x4_class(),
+                     slow_path->entry_label(),
+                     Assembler::kFarJump,
+                     result,
+                     temp);
+      __ Bind(slow_path->exit_label());
+      __ movl(temp, FieldAddress(instance_reg, offset_in_bytes()));
+      __ movups(value, FieldAddress(temp, Float32x4::value_offset()));
+      __ movups(FieldAddress(result, Float32x4::value_offset()), value);
+      __ jmp(&done);
+    }
 
     __ Bind(&load_pointer);
   }
@@ -2045,8 +2131,7 @@
   Register instantiator_reg = locs()->in(0).reg();
   Register result_reg = locs()->out().reg();
 
-  // 'instantiator_reg' is the instantiator AbstractTypeArguments object
-  // (or null).
+  // 'instantiator_reg' is the instantiator TypeArguments object (or null).
   // A runtime call to instantiate the type is required.
   __ PushObject(Object::ZoneHandle());  // Make room for the result.
   __ PushObject(type());
@@ -2079,8 +2164,7 @@
   Register instantiator_reg = locs()->in(0).reg();
   Register result_reg = locs()->out().reg();
 
-  // 'instantiator_reg' is the instantiator AbstractTypeArguments object
-  // (or null).
+  // 'instantiator_reg' is the instantiator TypeArguments object (or null).
   ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
          !type_arguments().CanShareInstantiatorTypeArguments(
              instantiator_class()));
@@ -2130,8 +2214,8 @@
   Register result_reg = locs()->out().reg();
   ASSERT(instantiator_reg == result_reg);
 
-  // instantiator_reg is the instantiator type argument vector, i.e. an
-  // AbstractTypeArguments object (or null).
+  // instantiator_reg is the instantiator type argument vector,
+  // i.e. a TypeArguments object (or null).
   ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
          !type_arguments().CanShareInstantiatorTypeArguments(
           instantiator_class()));
@@ -2172,8 +2256,7 @@
   Register instantiator_reg = locs()->in(0).reg();
   ASSERT(locs()->out().reg() == instantiator_reg);
 
-  // instantiator_reg is the instantiator AbstractTypeArguments object
-  // (or null).
+  // instantiator_reg is the instantiator TypeArguments object (or null).
   ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
          !type_arguments().CanShareInstantiatorTypeArguments(
              instantiator_class()));
@@ -2877,6 +2960,9 @@
 }
 
 
+
+
+
 LocationSummary* BoxDoubleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
@@ -2966,38 +3052,6 @@
 }
 
 
-class BoxFloat32x4SlowPath : public SlowPathCode {
- public:
-  explicit BoxFloat32x4SlowPath(BoxFloat32x4Instr* instruction)
-      : instruction_(instruction) { }
-
-  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
-    __ Comment("BoxFloat32x4SlowPath");
-    __ Bind(entry_label());
-    const Class& float32x4_class = compiler->float32x4_class();
-    const Code& stub =
-        Code::Handle(StubCode::GetAllocationStubForClass(float32x4_class));
-    const ExternalLabel label(float32x4_class.ToCString(), stub.EntryPoint());
-
-    LocationSummary* locs = instruction_->locs();
-    locs->live_registers()->Remove(locs->out());
-
-    compiler->SaveLiveRegisters(locs);
-    compiler->GenerateCall(Scanner::kNoSourcePos,  // No token position.
-                           &label,
-                           PcDescriptors::kOther,
-                           locs);
-    __ MoveRegister(locs->out().reg(), EAX);
-    compiler->RestoreLiveRegisters(locs);
-
-    __ jmp(exit_label());
-  }
-
- private:
-  BoxFloat32x4Instr* instruction_;
-};
-
-
 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
   BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this);
   compiler->AddSlowPathCode(slow_path);
@@ -4464,9 +4518,10 @@
 
 
 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const DeoptReasonId deopt_reason =
+      licm_hoisted_ ? kDeoptHoistedCheckClass : kDeoptCheckClass;
   if (IsNullCheck()) {
-    Label* deopt = compiler->AddDeoptStub(deopt_id(),
-                                          kDeoptCheckClass);
+    Label* deopt = compiler->AddDeoptStub(deopt_id(), deopt_reason);
     const Immediate& raw_null =
         Immediate(reinterpret_cast<intptr_t>(Object::null()));
     __ cmpl(locs()->in(0).reg(), raw_null);
@@ -4478,8 +4533,7 @@
          (unary_checks().NumberOfChecks() > 1));
   Register value = locs()->in(0).reg();
   Register temp = locs()->temp(0).reg();
-  Label* deopt = compiler->AddDeoptStub(deopt_id(),
-                                        kDeoptCheckClass);
+  Label* deopt = compiler->AddDeoptStub(deopt_id(), deopt_reason);
   Label is_ok;
   intptr_t cix = 0;
   if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) {
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 450c24b..df916f9 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -1740,9 +1740,11 @@
         default:
           UNREACHABLE();
       }
+
       StoreInstanceFieldSlowPath* slow_path =
           new StoreInstanceFieldSlowPath(this, *cls);
       compiler->AddSlowPathCode(slow_path);
+
       __ TryAllocate(*cls,
                      slow_path->entry_label(),
                      temp,
@@ -1772,7 +1774,6 @@
     DRegister fpu_temp = locs()->temp(2).fpu_reg();
 
     Label store_pointer;
-    Label copy_double;
     Label store_double;
 
     __ LoadObject(temp, Field::ZoneHandle(field().raw()));
@@ -1790,37 +1791,42 @@
     // Fall through.
     __ b(&store_pointer);
 
-    __ Bind(&store_double);
-
-    __ lw(temp, FieldAddress(instance_reg, field().Offset()));
-    __ BranchNotEqual(temp, reinterpret_cast<int32_t>(Object::null()),
-                      &copy_double);
-
-    StoreInstanceFieldSlowPath* slow_path =
-        new StoreInstanceFieldSlowPath(this, compiler->double_class());
-    compiler->AddSlowPathCode(slow_path);
-
     if (!compiler->is_optimizing()) {
       locs()->live_registers()->Add(locs()->in(0));
       locs()->live_registers()->Add(locs()->in(1));
     }
 
-    __ TryAllocate(compiler->double_class(),
-                   slow_path->entry_label(),
-                   temp,
-                   temp2);
-    __ Bind(slow_path->exit_label());
-    __ mov(temp2, temp);
-    __ StoreIntoObject(instance_reg,
-                       FieldAddress(instance_reg, field().Offset()),
-                       temp2);
+    {
+      __ Bind(&store_double);
+      Label copy_double;
 
-    __ Bind(&copy_double);
-    __ LoadDFromOffset(fpu_temp,
-                       value_reg,
-                       Double::value_offset() - kHeapObjectTag);
-    __ StoreDToOffset(fpu_temp, temp, Double::value_offset() - kHeapObjectTag);
-    __ b(&skip_store);
+      __ lw(temp, FieldAddress(instance_reg, field().Offset()));
+      __ BranchNotEqual(temp, reinterpret_cast<int32_t>(Object::null()),
+                        &copy_double);
+
+      StoreInstanceFieldSlowPath* slow_path =
+          new StoreInstanceFieldSlowPath(this, compiler->double_class());
+      compiler->AddSlowPathCode(slow_path);
+
+      __ TryAllocate(compiler->double_class(),
+                     slow_path->entry_label(),
+                     temp,
+                     temp2);
+      __ Bind(slow_path->exit_label());
+      __ mov(temp2, temp);
+      __ StoreIntoObject(instance_reg,
+                         FieldAddress(instance_reg, field().Offset()),
+                         temp2);
+
+      __ Bind(&copy_double);
+      __ LoadDFromOffset(fpu_temp,
+                         value_reg,
+                         Double::value_offset() - kHeapObjectTag);
+      __ StoreDToOffset(fpu_temp, temp,
+                        Double::value_offset() - kHeapObjectTag);
+      __ b(&skip_store);
+    }
+
     __ Bind(&store_pointer);
   }
 
@@ -1948,25 +1954,6 @@
 }
 
 
-LocationSummary*
-AllocateObjectWithBoundsCheckInstr::MakeLocationSummary(bool opt) const {
-  return MakeCallSummary();
-}
-
-
-void AllocateObjectWithBoundsCheckInstr::EmitNativeCode(
-    FlowGraphCompiler* compiler) {
-  compiler->GenerateRuntimeCall(token_pos(),
-                                deopt_id(),
-                                kAllocateObjectWithBoundsCheckRuntimeEntry,
-                                3,
-                                locs());
-  __ Drop(3);
-  ASSERT(locs()->out().reg() == V0);
-  __ Pop(V0);  // Pop new instance.
-}
-
-
 class BoxDoubleSlowPath : public SlowPathCode {
  public:
   explicit BoxDoubleSlowPath(Instruction* instruction)
@@ -2067,26 +2054,28 @@
     // Fall through.
     __ b(&load_pointer);
 
-    __ Bind(&load_double);
-
-    BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
-    compiler->AddSlowPathCode(slow_path);
-
     if (!compiler->is_optimizing()) {
       locs()->live_registers()->Add(locs()->in(0));
     }
 
-    __ TryAllocate(compiler->double_class(),
-                   slow_path->entry_label(),
-                   result_reg,
-                   temp);
-    __ Bind(slow_path->exit_label());
-    __ lw(temp, FieldAddress(instance_reg, offset_in_bytes()));
-    __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag);
-    __ StoreDToOffset(value,
-                      result_reg,
-                      Double::value_offset() - kHeapObjectTag);
-    __ b(&done);
+    {
+      __ Bind(&load_double);
+      BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
+      compiler->AddSlowPathCode(slow_path);
+
+      __ TryAllocate(compiler->double_class(),
+                     slow_path->entry_label(),
+                     result_reg,
+                     temp);
+      __ Bind(slow_path->exit_label());
+      __ lw(temp, FieldAddress(instance_reg, offset_in_bytes()));
+      __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag);
+      __ StoreDToOffset(value,
+                        result_reg,
+                        Double::value_offset() - kHeapObjectTag);
+      __ b(&done);
+    }
+
     __ Bind(&load_pointer);
   }
   __ lw(result_reg, Address(instance_reg, offset_in_bytes() - kHeapObjectTag));
@@ -2110,8 +2099,7 @@
   Register instantiator_reg = locs()->in(0).reg();
   Register result_reg = locs()->out().reg();
 
-  // 'instantiator_reg' is the instantiator AbstractTypeArguments object
-  // (or null).
+  // 'instantiator_reg' is the instantiator TypeArguments object (or null).
   // A runtime call to instantiate the type is required.
   __ addiu(SP, SP, Immediate(-3 * kWordSize));
   __ LoadObject(TMP, Object::ZoneHandle());
@@ -2152,8 +2140,7 @@
   Register instantiator_reg = locs()->in(0).reg();
   Register result_reg = locs()->out().reg();
 
-  // 'instantiator_reg' is the instantiator AbstractTypeArguments object
-  // (or null).
+  // 'instantiator_reg' is the instantiator TypeArguments object (or null).
   ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
          !type_arguments().CanShareInstantiatorTypeArguments(
              instantiator_class()));
@@ -2208,8 +2195,8 @@
   Register result_reg = locs()->out().reg();
   ASSERT(instantiator_reg == result_reg);
 
-  // instantiator_reg is the instantiator type argument vector, i.e. an
-  // AbstractTypeArguments object (or null).
+  // instantiator_reg is the instantiator type argument vector,
+  // i.e. a TypeArguments object (or null).
   ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
          !type_arguments().CanShareInstantiatorTypeArguments(
              instantiator_class()));
@@ -2248,8 +2235,7 @@
   Register instantiator_reg = locs()->in(0).reg();
   ASSERT(locs()->out().reg() == instantiator_reg);
 
-  // instantiator_reg is the instantiator AbstractTypeArguments object
-  // (or null).
+  // instantiator_reg is the instantiator TypeArguments object (or null).
   ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
          !type_arguments().CanShareInstantiatorTypeArguments(
              instantiator_class()));
@@ -3820,9 +3806,10 @@
 
 
 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const DeoptReasonId deopt_reason =
+      licm_hoisted_ ? kDeoptHoistedCheckClass : kDeoptCheckClass;
   if (IsNullCheck()) {
-    Label* deopt = compiler->AddDeoptStub(deopt_id(),
-                                          kDeoptCheckClass);
+    Label* deopt = compiler->AddDeoptStub(deopt_id(), deopt_reason);
     __ BranchEqual(locs()->in(0).reg(),
         reinterpret_cast<int32_t>(Object::null()), deopt);
     return;
@@ -3832,8 +3819,7 @@
          (unary_checks().NumberOfChecks() > 1));
   Register value = locs()->in(0).reg();
   Register temp = locs()->temp(0).reg();
-  Label* deopt = compiler->AddDeoptStub(deopt_id(),
-                                        kDeoptCheckClass);
+  Label* deopt = compiler->AddDeoptStub(deopt_id(), deopt_reason);
   Label is_ok;
   intptr_t cix = 0;
   if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) {
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index f47abad..ecb7ec4 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -1571,10 +1571,13 @@
         case kDoubleCid:
           cls = &compiler->double_class();
           break;
-        // TODO(johnmccutchan): Add kFloat32x4Cid here.
+        case kFloat32x4Cid:
+          cls = &compiler->float32x4_class();
+          break;
         default:
           UNREACHABLE();
       }
+
       StoreInstanceFieldSlowPath* slow_path =
           new StoreInstanceFieldSlowPath(this, *cls);
       compiler->AddSlowPathCode(slow_path);
@@ -1594,9 +1597,13 @@
     }
     switch (cid) {
       case kDoubleCid:
-      __ movsd(FieldAddress(temp, Double::value_offset()), value);
-      // TODO(johnmccutchan): Add kFloat32x4Cid here.
-      break;
+        __ Comment("UnboxedDoubleStoreInstanceFieldInstr");
+        __ movsd(FieldAddress(temp, Double::value_offset()), value);
+        break;
+      case kFloat32x4Cid:
+        __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr");
+        __ movups(FieldAddress(temp, Float32x4::value_offset()), value);
+        break;
       default:
         UNREACHABLE();
     }
@@ -1610,8 +1617,8 @@
     FpuRegister fpu_temp = locs()->temp(2).fpu_reg();
 
     Label store_pointer;
-    Label copy_double;
     Label store_double;
+    Label store_float32x4;
 
     __ LoadObject(temp, Field::ZoneHandle(field().raw()), PP);
 
@@ -1627,38 +1634,74 @@
             Immediate(kDoubleCid));
     __ j(EQUAL, &store_double);
 
+    __ cmpq(FieldAddress(temp, Field::guarded_cid_offset()),
+            Immediate(kFloat32x4Cid));
+    __ j(EQUAL, &store_float32x4);
+
     // Fall through.
     __ jmp(&store_pointer);
 
-    __ Bind(&store_double);
-
-    __ movq(temp, FieldAddress(instance_reg, field().Offset()));
-    __ CompareObject(temp, Object::null_object(), PP);
-    __ j(NOT_EQUAL, &copy_double);
-
-    StoreInstanceFieldSlowPath* slow_path =
-        new StoreInstanceFieldSlowPath(this, compiler->double_class());
-    compiler->AddSlowPathCode(slow_path);
-
     if (!compiler->is_optimizing()) {
       locs()->live_registers()->Add(locs()->in(0));
       locs()->live_registers()->Add(locs()->in(1));
     }
-    __ TryAllocate(compiler->double_class(),
-                   slow_path->entry_label(),
-                   Assembler::kFarJump,
-                   temp,
-                   PP);
-    __ Bind(slow_path->exit_label());
-    __ movq(temp2, temp);
-    __ StoreIntoObject(instance_reg,
-                       FieldAddress(instance_reg, field().Offset()),
-                       temp2);
 
-    __ Bind(&copy_double);
-    __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset()));
-    __ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp);
-    __ jmp(&skip_store);
+    {
+      __ Bind(&store_double);
+      Label copy_double;
+      StoreInstanceFieldSlowPath* slow_path =
+          new StoreInstanceFieldSlowPath(this, compiler->double_class());
+      compiler->AddSlowPathCode(slow_path);
+
+      __ movq(temp, FieldAddress(instance_reg, field().Offset()));
+      __ CompareObject(temp, Object::null_object(), PP);
+      __ j(NOT_EQUAL, &copy_double);
+
+      __ TryAllocate(compiler->double_class(),
+                     slow_path->entry_label(),
+                     Assembler::kFarJump,
+                     temp,
+                     PP);
+      __ Bind(slow_path->exit_label());
+      __ movq(temp2, temp);
+      __ StoreIntoObject(instance_reg,
+                         FieldAddress(instance_reg, field().Offset()),
+                         temp2);
+
+      __ Bind(&copy_double);
+      __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset()));
+      __ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp);
+      __ jmp(&skip_store);
+    }
+
+    {
+      __ Bind(&store_float32x4);
+      Label copy_float32x4;
+      StoreInstanceFieldSlowPath* slow_path =
+          new StoreInstanceFieldSlowPath(this, compiler->float32x4_class());
+      compiler->AddSlowPathCode(slow_path);
+
+      __ movq(temp, FieldAddress(instance_reg, field().Offset()));
+      __ CompareObject(temp, Object::null_object(), PP);
+      __ j(NOT_EQUAL, &copy_float32x4);
+
+      __ TryAllocate(compiler->float32x4_class(),
+                     slow_path->entry_label(),
+                     Assembler::kFarJump,
+                     temp,
+                     PP);
+      __ Bind(slow_path->exit_label());
+      __ movq(temp2, temp);
+      __ StoreIntoObject(instance_reg,
+                         FieldAddress(instance_reg, field().Offset()),
+                         temp2);
+
+      __ Bind(&copy_float32x4);
+      __ movups(fpu_temp, FieldAddress(value_reg, Float32x4::value_offset()));
+      __ movups(FieldAddress(temp, Float32x4::value_offset()), fpu_temp);
+      __ jmp(&skip_store);
+    }
+
     __ Bind(&store_pointer);
   }
 
@@ -1780,25 +1823,6 @@
 }
 
 
-LocationSummary*
-AllocateObjectWithBoundsCheckInstr::MakeLocationSummary(bool opt) const {
-  return MakeCallSummary();
-}
-
-
-void AllocateObjectWithBoundsCheckInstr::EmitNativeCode(
-    FlowGraphCompiler* compiler) {
-  compiler->GenerateRuntimeCall(token_pos(),
-                                deopt_id(),
-                                kAllocateObjectWithBoundsCheckRuntimeEntry,
-                                3,
-                                locs());
-  __ Drop(3);
-  ASSERT(locs()->out().reg() == RAX);
-  __ popq(RAX);  // Pop new instance.
-}
-
-
 class BoxDoubleSlowPath : public SlowPathCode {
  public:
   explicit BoxDoubleSlowPath(Instruction* instruction)
@@ -1831,6 +1855,38 @@
 };
 
 
+class BoxFloat32x4SlowPath : public SlowPathCode {
+ public:
+  explicit BoxFloat32x4SlowPath(Instruction* instruction)
+      : instruction_(instruction) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("BoxFloat32x4SlowPath");
+    __ Bind(entry_label());
+    const Class& float32x4_class = compiler->float32x4_class();
+    const Code& stub =
+        Code::Handle(StubCode::GetAllocationStubForClass(float32x4_class));
+    const ExternalLabel label(float32x4_class.ToCString(), stub.EntryPoint());
+
+    LocationSummary* locs = instruction_->locs();
+    locs->live_registers()->Remove(locs->out());
+
+    compiler->SaveLiveRegisters(locs);
+    compiler->GenerateCall(Scanner::kNoSourcePos,  // No token position.
+                           &label,
+                           PcDescriptors::kOther,
+                           locs);
+    __ MoveRegister(locs->out().reg(), RAX);
+    compiler->RestoreLiveRegisters(locs);
+
+    __ jmp(exit_label());
+  }
+
+ private:
+  Instruction* instruction_;
+};
+
+
 LocationSummary* LoadFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
@@ -1864,9 +1920,13 @@
     intptr_t cid = field()->UnboxedFieldCid();
     switch (cid) {
       case kDoubleCid:
+        __ Comment("UnboxedDoubleLoadFieldInstr");
         __ movsd(result, FieldAddress(temp, Double::value_offset()));
         break;
-      // TODO(johnmccutchan): Add Float32x4 path here.
+      case kFloat32x4Cid:
+        __ Comment("UnboxedFloat32x4LoadFieldInstr");
+        __ movups(result, FieldAddress(temp, Float32x4::value_offset()));
+        break;
       default:
         UNREACHABLE();
     }
@@ -1881,6 +1941,7 @@
 
     Label load_pointer;
     Label load_double;
+    Label load_float32x4;
 
     __ LoadObject(result, Field::ZoneHandle(field()->raw()), PP);
 
@@ -1892,30 +1953,49 @@
             Immediate(kDoubleCid));
     __ j(EQUAL, &load_double);
 
+    __ cmpq(FieldAddress(result, Field::guarded_cid_offset()),
+            Immediate(kFloat32x4Cid));
+    __ j(EQUAL, &load_float32x4);
+
     // Fall through.
     __ jmp(&load_pointer);
 
-    __ Bind(&load_double);
-
-    BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
-    compiler->AddSlowPathCode(slow_path);
-
     if (!compiler->is_optimizing()) {
       locs()->live_registers()->Add(locs()->in(0));
     }
 
-    __ TryAllocate(compiler->double_class(),
-                   slow_path->entry_label(),
-                   Assembler::kFarJump,
-                   result,
-                   PP);
-    __ Bind(slow_path->exit_label());
-    __ movq(temp, FieldAddress(instance_reg, offset_in_bytes()));
-    __ movsd(value, FieldAddress(temp, Double::value_offset()));
-    __ movsd(FieldAddress(result, Double::value_offset()), value);
-    __ jmp(&done);
+    {
+      __ Bind(&load_double);
+      BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
+      compiler->AddSlowPathCode(slow_path);
 
-    // TODO(johnmccutchan): Add Float32x4 path here.
+      __ TryAllocate(compiler->double_class(),
+                     slow_path->entry_label(),
+                     Assembler::kFarJump,
+                     result,
+                     PP);
+      __ Bind(slow_path->exit_label());
+      __ movq(temp, FieldAddress(instance_reg, offset_in_bytes()));
+      __ movsd(value, FieldAddress(temp, Double::value_offset()));
+      __ movsd(FieldAddress(result, Double::value_offset()), value);
+      __ jmp(&done);
+    }
+    {
+      __ Bind(&load_float32x4);
+      BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this);
+      compiler->AddSlowPathCode(slow_path);
+
+      __ TryAllocate(compiler->float32x4_class(),
+                     slow_path->entry_label(),
+                     Assembler::kFarJump,
+                     result,
+                     PP);
+      __ Bind(slow_path->exit_label());
+      __ movq(temp, FieldAddress(instance_reg, offset_in_bytes()));
+      __ movups(value, FieldAddress(temp, Float32x4::value_offset()));
+      __ movups(FieldAddress(result, Float32x4::value_offset()), value);
+      __ jmp(&done);
+    }
 
     __ Bind(&load_pointer);
   }
@@ -1939,8 +2019,7 @@
   Register instantiator_reg = locs()->in(0).reg();
   Register result_reg = locs()->out().reg();
 
-  // 'instantiator_reg' is the instantiator AbstractTypeArguments object
-  // (or null).
+  // 'instantiator_reg' is the instantiator TypeArguments object (or null).
   // A runtime call to instantiate the type is required.
   __ PushObject(Object::ZoneHandle(), PP);  // Make room for the result.
   __ PushObject(type(), PP);
@@ -1973,8 +2052,7 @@
   Register instantiator_reg = locs()->in(0).reg();
   Register result_reg = locs()->out().reg();
 
-  // 'instantiator_reg' is the instantiator AbstractTypeArguments object
-  // (or null).
+  // 'instantiator_reg' is the instantiator TypeArguments object (or null).
   ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
          !type_arguments().CanShareInstantiatorTypeArguments(
              instantiator_class()));
@@ -2022,8 +2100,8 @@
   Register result_reg = locs()->out().reg();
   ASSERT(instantiator_reg == result_reg);
 
-  // instantiator_reg is the instantiator type argument vector, i.e. an
-  // AbstractTypeArguments object (or null).
+  // instantiator_reg is the instantiator type argument vector,
+  // i.e. a TypeArguments object (or null).
   ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
          !type_arguments().CanShareInstantiatorTypeArguments(
              instantiator_class()));
@@ -2063,8 +2141,7 @@
   Register instantiator_reg = locs()->in(0).reg();
   ASSERT(locs()->out().reg() == instantiator_reg);
 
-  // instantiator_reg is the instantiator AbstractTypeArguments object
-  // (or null).
+  // instantiator_reg is the instantiator TypeArguments object (or null).
   ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
          !type_arguments().CanShareInstantiatorTypeArguments(
              instantiator_class()));
@@ -2969,38 +3046,6 @@
 }
 
 
-class BoxFloat32x4SlowPath : public SlowPathCode {
- public:
-  explicit BoxFloat32x4SlowPath(BoxFloat32x4Instr* instruction)
-      : instruction_(instruction) { }
-
-  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
-    __ Comment("BoxFloat32x4SlowPath");
-    __ Bind(entry_label());
-    const Class& float32x4_class = compiler->float32x4_class();
-    const Code& stub =
-        Code::Handle(StubCode::GetAllocationStubForClass(float32x4_class));
-    const ExternalLabel label(float32x4_class.ToCString(), stub.EntryPoint());
-
-    LocationSummary* locs = instruction_->locs();
-    locs->live_registers()->Remove(locs->out());
-
-    compiler->SaveLiveRegisters(locs);
-    compiler->GenerateCall(Scanner::kNoSourcePos,  // No token position.
-                           &label,
-                           PcDescriptors::kOther,
-                           locs);
-    __ MoveRegister(locs->out().reg(), RAX);
-    compiler->RestoreLiveRegisters(locs);
-
-    __ jmp(exit_label());
-  }
-
- private:
-  BoxFloat32x4Instr* instruction_;
-};
-
-
 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
   BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this);
   compiler->AddSlowPathCode(slow_path);
@@ -4542,9 +4587,10 @@
 
 
 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const DeoptReasonId deopt_reason =
+      licm_hoisted_ ? kDeoptHoistedCheckClass : kDeoptCheckClass;
   if (IsNullCheck()) {
-    Label* deopt = compiler->AddDeoptStub(deopt_id(),
-                                          kDeoptCheckClass);
+    Label* deopt = compiler->AddDeoptStub(deopt_id(), deopt_reason);
     __ CompareObject(locs()->in(0).reg(),
                      Object::null_object(), PP);
     __ j(EQUAL, deopt);
@@ -4555,8 +4601,7 @@
          (unary_checks().NumberOfChecks() > 1));
   Register value = locs()->in(0).reg();
   Register temp = locs()->temp(0).reg();
-  Label* deopt = compiler->AddDeoptStub(deopt_id(),
-                                        kDeoptCheckClass);
+  Label* deopt = compiler->AddDeoptStub(deopt_id(), deopt_reason);
   Label is_ok;
   intptr_t cix = 0;
   if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) {
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index e1f9298..1b29a2b 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -203,9 +203,6 @@
     __ b(&checked_ok, EQ);
 
     // Check if it's dynamic.
-    // For now handle only TypeArguments and bail out if InstantiatedTypeArgs.
-    __ CompareClassId(R1, kTypeArgumentsCid, R0);
-    __ b(&fall_through, NE);
     // Get type at index 0.
     __ ldr(R0, FieldAddress(R1, TypeArguments::type_at_offset(0)));
     __ CompareObject(R0, Type::ZoneHandle(Type::DynamicType()));
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index 8b871ac..6b4b5d2 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -205,9 +205,6 @@
     __ cmpl(EBX, raw_null);
     __ j(EQUAL, &checked_ok, Assembler::kNearJump);
     // Check if it's dynamic.
-    // For now handle only TypeArguments and bail out if InstantiatedTypeArgs.
-    __ CompareClassId(EBX, kTypeArgumentsCid, EAX);
-    __ j(NOT_EQUAL, &fall_through);
     // Get type at index 0.
     __ movl(EAX, FieldAddress(EBX, TypeArguments::type_at_offset(0)));
     __ CompareObject(EAX, Type::ZoneHandle(Type::DynamicType()));
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index 9e2b668..14b3105 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -209,10 +209,6 @@
     __ beq(T1, T7, &checked_ok);
 
     // Check if it's dynamic.
-    // For now handle only TypeArguments and bail out if InstantiatedTypeArgs.
-    __ LoadClassId(CMPRES1, T1);
-    __ BranchNotEqual(CMPRES1, kTypeArgumentsCid, &fall_through);
-
     // Get type at index 0.
     __ lw(T0, FieldAddress(T1, TypeArguments::type_at_offset(0)));
     __ BranchEqual(T0, Type::ZoneHandle(Type::DynamicType()), &checked_ok);
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index abe9dda..bb493ab 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -315,6 +315,8 @@
       cha_used_(false),
       object_id_ring_(NULL),
       profiler_data_(NULL),
+      thread_state_(NULL),
+      next_(NULL),
       REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
       reusable_handles_() {
   if (FLAG_print_object_histogram && (Dart::vm_isolate() != NULL)) {
@@ -343,12 +345,23 @@
   delete spawn_state_;
 }
 
+
 void Isolate::SetCurrent(Isolate* current) {
   Isolate* old_current = Current();
-  if (old_current != current) {
+  if (old_current != NULL) {
+    old_current->set_thread_state(NULL);
     Profiler::EndExecution(old_current);
-    Thread::SetThreadLocal(isolate_key, reinterpret_cast<uword>(current));
+  }
+  Thread::SetThreadLocal(isolate_key, reinterpret_cast<uword>(current));
+  if (current != NULL) {
+    ASSERT(current->thread_state() == NULL);
+    InterruptableThreadState* thread_state =
+        ThreadInterrupter::GetCurrentThreadState();
+#if defined(DEBUG)
+    CheckForDuplicateThreadState(thread_state);
+#endif
     Profiler::BeginExecution(current);
+    current->set_thread_state(thread_state);
   }
 }
 
@@ -365,6 +378,8 @@
   isolate_key = Thread::CreateThreadLocal();
   ASSERT(isolate_key != Thread::kUnsetThreadLocalKey);
   create_callback_ = NULL;
+  isolates_list_monitor_ = new Monitor();
+  ASSERT(isolates_list_monitor_ != NULL);
 }
 
 
@@ -375,6 +390,9 @@
   // Setup for profiling.
   Profiler::InitProfilingForIsolate(result);
 
+  // Add to isolate list.
+  AddIsolateTolist(result);
+
   // TODO(5411455): For now just set the recently created isolate as
   // the current isolate.
   SetCurrent(result);
@@ -749,6 +767,7 @@
   // TODO(5411455): For now just make sure there are no current isolates
   // as we are shutting down the isolate.
   SetCurrent(NULL);
+  RemoveIsolateFromList(this);
   Profiler::ShutdownProfilingForIsolate(this);
 }
 
@@ -766,6 +785,10 @@
 Dart_IsolateInterruptCallback Isolate::vmstats_callback_ = NULL;
 Dart_ServiceIsolateCreateCalback Isolate::service_create_callback_ = NULL;
 
+Monitor* Isolate::isolates_list_monitor_ = NULL;
+Isolate* Isolate::isolates_list_head_ = NULL;
+
+
 void Isolate::VisitObjectPointers(ObjectPointerVisitor* visitor,
                                   bool visit_prologue_weak_handles,
                                   bool validate_frames) {
@@ -866,6 +889,63 @@
 }
 
 
+void Isolate::VisitIsolates(IsolateVisitor* visitor) {
+  if (visitor == NULL) {
+    return;
+  }
+  MonitorLocker ml(isolates_list_monitor_);
+  Isolate* current = isolates_list_head_;
+  while (current) {
+    visitor->VisitIsolate(current);
+    current = current->next_;
+  }
+}
+
+
+void Isolate::AddIsolateTolist(Isolate* isolate) {
+  MonitorLocker ml(isolates_list_monitor_);
+  ASSERT(isolate != NULL);
+  ASSERT(isolate->next_ == NULL);
+  isolate->next_ = isolates_list_head_;
+  isolates_list_head_ = isolate;
+}
+
+
+void Isolate::RemoveIsolateFromList(Isolate* isolate) {
+  MonitorLocker ml(isolates_list_monitor_);
+  ASSERT(isolate != NULL);
+  if (isolate == isolates_list_head_) {
+    isolates_list_head_ = isolate->next_;
+    return;
+  }
+  Isolate* previous = NULL;
+  Isolate* current = isolates_list_head_;
+  while (current) {
+    if (current == isolate) {
+      ASSERT(previous != NULL);
+      previous->next_ = current->next_;
+      return;
+    }
+    previous = current;
+    current = current->next_;
+  }
+  UNREACHABLE();
+}
+
+
+#if defined(DEBUG)
+void Isolate::CheckForDuplicateThreadState(InterruptableThreadState* state) {
+  MonitorLocker ml(isolates_list_monitor_);
+  ASSERT(state != NULL);
+  Isolate* current = isolates_list_head_;
+  while (current) {
+    ASSERT(current->thread_state() != state);
+    current = current->next_;
+  }
+}
+#endif
+
+
 template<class T>
 T* Isolate::AllocateReusableHandle() {
   T* handle = reinterpret_cast<T*>(reusable_handles_.AllocateScopedHandle());
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 8356d97..7d31166 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -36,6 +36,7 @@
 class Instance;
 class IsolateProfilerData;
 class IsolateSpawnState;
+class InterruptableThreadState;
 class LongJumpScope;
 class MessageHandler;
 class Mutex;
@@ -75,6 +76,19 @@
   V(TypeParameter)                                                             \
   V(TypeArguments)                                                             \
 
+
+class IsolateVisitor {
+ public:
+  IsolateVisitor() {}
+  virtual ~IsolateVisitor() {}
+
+  virtual void VisitIsolate(Isolate* isolate) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(IsolateVisitor);
+};
+
+
 class Isolate : public BaseIsolate {
  public:
   ~Isolate();
@@ -405,12 +419,23 @@
     profiler_data_ = profiler_data;
   }
 
-  IsolateProfilerData* profiler_data() {
+  IsolateProfilerData* profiler_data() const {
     return profiler_data_;
   }
 
   void PrintToJSONStream(JSONStream* stream);
 
+  void set_thread_state(InterruptableThreadState* state) {
+    ASSERT((thread_state_ == NULL) || (state == NULL));
+    thread_state_ = state;
+  }
+
+  InterruptableThreadState* thread_state() const {
+    return thread_state_;
+  }
+
+  static void VisitIsolates(IsolateVisitor* visitor);
+
  private:
   Isolate();
 
@@ -467,6 +492,10 @@
 
   IsolateProfilerData* profiler_data_;
   Mutex profiler_data_mutex_;
+  InterruptableThreadState* thread_state_;
+
+  // Isolate list next pointer.
+  Isolate* next_;
 
   // Reusable handles support.
 #define REUSABLE_HANDLE_FIELDS(object)                                         \
@@ -488,8 +517,16 @@
   static Dart_IsolateInterruptCallback vmstats_callback_;
   static Dart_ServiceIsolateCreateCalback service_create_callback_;
 
+  // Manage list of existing isolates.
+  static void AddIsolateTolist(Isolate* isolate);
+  static void RemoveIsolateFromList(Isolate* isolate);
+  static void CheckForDuplicateThreadState(InterruptableThreadState* state);
+  static Monitor* isolates_list_monitor_;
+  static Isolate* isolates_list_head_;
+
   friend class ReusableHandleScope;
   friend class ReusableObjectHandleScope;
+
   DISALLOW_COPY_AND_ASSIGN(Isolate);
 };
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 1de1ac0..33216e7 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -26,6 +26,7 @@
 #include "vm/double_conversion.h"
 #include "vm/exceptions.h"
 #include "vm/flow_graph_builder.h"
+#include "vm/flow_graph_compiler.h"
 #include "vm/growable_array.h"
 #include "vm/heap.h"
 #include "vm/intermediate_language.h"
@@ -69,6 +70,7 @@
 DECLARE_FLAG(bool, trace_deoptimization_verbose);
 DECLARE_FLAG(bool, verbose_stacktrace);
 DECLARE_FLAG(charp, coverage_dir);
+DECLARE_FLAG(bool, write_protect_code);
 
 static const char* kGetterPrefix = "get:";
 static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix);
@@ -89,7 +91,7 @@
 Array* Object::null_array_ = NULL;
 String* Object::null_string_ = NULL;
 Instance* Object::null_instance_ = NULL;
-AbstractTypeArguments* Object::null_abstract_type_arguments_ = NULL;
+TypeArguments* Object::null_type_arguments_ = NULL;
 Array* Object::empty_array_ = NULL;
 PcDescriptors* Object::empty_descriptors_ = NULL;
 Instance* Object::sentinel_ = NULL;
@@ -111,8 +113,6 @@
 RawClass* Object::unresolved_class_class_ =
     reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::type_arguments_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
-RawClass* Object::instantiated_type_arguments_class_ =
-    reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::patch_class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::function_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::closure_data_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -447,7 +447,7 @@
   null_array_ = Array::ReadOnlyHandle();
   null_string_ = String::ReadOnlyHandle();
   null_instance_ = Instance::ReadOnlyHandle();
-  null_abstract_type_arguments_ = AbstractTypeArguments::ReadOnlyHandle();
+  null_type_arguments_ = TypeArguments::ReadOnlyHandle();
   empty_array_ = Array::ReadOnlyHandle();
   empty_descriptors_ = PcDescriptors::ReadOnlyHandle();
   sentinel_ = Instance::ReadOnlyHandle();
@@ -475,7 +475,7 @@
   *null_array_ = Array::null();
   *null_string_ = String::null();
   *null_instance_ = Instance::null();
-  *null_abstract_type_arguments_ = AbstractTypeArguments::null();
+  *null_type_arguments_ = TypeArguments::null();
 
   // Initialize the empty array handle to null_ in order to be able to check
   // if the empty array was allocated (RAW_NULL is not available).
@@ -547,9 +547,6 @@
   cls = Class::New<TypeArguments>();
   type_arguments_class_ = cls.raw();
 
-  cls = Class::New<InstantiatedTypeArguments>();
-  instantiated_type_arguments_class_ = cls.raw();
-
   cls = Class::New<PatchClass>();
   patch_class_class_ = cls.raw();
 
@@ -719,8 +716,8 @@
   ASSERT(null_string_->IsString());
   ASSERT(!null_instance_->IsSmi());
   ASSERT(null_instance_->IsInstance());
-  ASSERT(!null_abstract_type_arguments_->IsSmi());
-  ASSERT(null_abstract_type_arguments_->IsAbstractTypeArguments());
+  ASSERT(!null_type_arguments_->IsSmi());
+  ASSERT(null_type_arguments_->IsTypeArguments());
   ASSERT(!empty_array_->IsSmi());
   ASSERT(empty_array_->IsArray());
   ASSERT(!sentinel_->IsSmi());
@@ -756,7 +753,6 @@
   SET_CLASS_NAME(void, Void);
   SET_CLASS_NAME(unresolved_class, UnresolvedClass);
   SET_CLASS_NAME(type_arguments, TypeArguments);
-  SET_CLASS_NAME(instantiated_type_arguments, InstantiatedTypeArguments);
   SET_CLASS_NAME(patch_class, PatchClass);
   SET_CLASS_NAME(function, Function);
   SET_CLASS_NAME(closure_data, ClosureData);
@@ -1627,7 +1623,7 @@
 RawAbstractType* Class::RareType() const {
   const Type& type = Type::Handle(Type::New(
       *this,
-      Object::null_abstract_type_arguments(),
+      Object::null_type_arguments(),
       Scanner::kNoSourcePos));
   return ClassFinalizer::FinalizeType(*this,
                                       type,
@@ -2034,8 +2030,8 @@
   ASSERT(!IsMixinApplication() || is_mixin_type_applied());
   const AbstractType& sup_type = AbstractType::Handle(isolate, super_type());
   ASSERT(sup_type.IsResolved());
-  const AbstractTypeArguments& sup_type_args =
-      AbstractTypeArguments::Handle(isolate, sup_type.arguments());
+  const TypeArguments& sup_type_args =
+      TypeArguments::Handle(isolate, sup_type.arguments());
   if (sup_type_args.IsNull()) {
     // The super type is raw or the super class is non generic.
     // In either case, overlapping is not possible.
@@ -2049,8 +2045,8 @@
   // finalized, but the last num_sup_type_args type arguments will not be
   // modified by finalization, only shifted to higher indices in the vector.
   // They may however get wrapped in a BoundedType, which we skip.
-  const AbstractTypeArguments& type_params =
-      AbstractTypeArguments::Handle(isolate, type_parameters());
+  const TypeArguments& type_params =
+      TypeArguments::Handle(isolate, type_parameters());
   // Determine the maximum overlap of a prefix of the vector consisting of the
   // type parameters of this class with a suffix of the vector consisting of the
   // type arguments of the super type of this class.
@@ -2941,8 +2937,6 @@
       return Symbols::UnresolvedClass().raw();
     case kTypeArgumentsCid:
       return Symbols::TypeArguments().raw();
-    case kInstantiatedTypeArgumentsCid:
-      return Symbols::InstantiatedTypeArguments().raw();
     case kPatchClassCid:
       return Symbols::PatchClass().raw();
     case kFunctionCid:
@@ -3237,13 +3231,12 @@
 // type T by class 'other' parameterized with 'other_type_arguments'.
 // This class and class 'other' do not need to be finalized, however, they must
 // be resolved as well as their interfaces.
-bool Class::TypeTestNonRecursive(
-    const Class& cls,
-    Class::TypeTestKind test_kind,
-    const AbstractTypeArguments& type_arguments,
-    const Class& other,
-    const AbstractTypeArguments& other_type_arguments,
-    Error* bound_error) {
+bool Class::TypeTestNonRecursive(const Class& cls,
+                                 Class::TypeTestKind test_kind,
+                                 const TypeArguments& type_arguments,
+                                 const Class& other,
+                                 const TypeArguments& other_type_arguments,
+                                 Error* bound_error) {
   // Use the thsi object as if it was the receiver of this method, but instead
   // of recursing reset it to the super class and loop.
   Class& thsi = Class::Handle(cls.raw());
@@ -3343,7 +3336,7 @@
     Array& interfaces = Array::Handle(thsi.interfaces());
     AbstractType& interface = AbstractType::Handle();
     Class& interface_class = Class::Handle();
-    AbstractTypeArguments& interface_args = AbstractTypeArguments::Handle();
+    TypeArguments& interface_args = TypeArguments::Handle();
     Error& error = Error::Handle();
     for (intptr_t i = 0; i < interfaces.Length(); i++) {
       interface ^= interfaces.At(i);
@@ -3407,11 +3400,10 @@
 // type T by class 'other' parameterized with 'other_type_arguments'.
 // This class and class 'other' do not need to be finalized, however, they must
 // be resolved as well as their interfaces.
-bool Class::TypeTest(
-                     TypeTestKind test_kind,
-                     const AbstractTypeArguments& type_arguments,
+bool Class::TypeTest(TypeTestKind test_kind,
+                     const TypeArguments& type_arguments,
                      const Class& other,
-                     const AbstractTypeArguments& other_type_arguments,
+                     const TypeArguments& other_type_arguments,
                      Error* bound_error) const {
   return TypeTestNonRecursive(*this,
                               test_kind,
@@ -3854,63 +3846,6 @@
 }
 
 
-intptr_t AbstractTypeArguments::Length() const  {
-  // AbstractTypeArguments is an abstract class.
-  UNREACHABLE();
-  return -1;
-}
-
-
-RawAbstractType* AbstractTypeArguments::TypeAt(intptr_t index) const {
-  // AbstractTypeArguments is an abstract class.
-  UNREACHABLE();
-  return NULL;
-}
-
-
-void AbstractTypeArguments::SetTypeAt(intptr_t index,
-                                      const AbstractType& value) const {
-  // AbstractTypeArguments is an abstract class.
-  UNREACHABLE();
-}
-
-
-bool AbstractTypeArguments::IsResolved() const {
-  // AbstractTypeArguments is an abstract class.
-  UNREACHABLE();
-  return false;
-}
-
-
-bool AbstractTypeArguments::IsInstantiated(GrowableObjectArray* trail) const {
-  // AbstractTypeArguments is an abstract class.
-  UNREACHABLE();
-  return false;
-}
-
-
-bool AbstractTypeArguments::IsUninstantiatedIdentity() const {
-  // AbstractTypeArguments is an abstract class.
-  UNREACHABLE();
-  return false;
-}
-
-
-bool AbstractTypeArguments::CanShareInstantiatorTypeArguments(
-      const Class& instantiator_class) const {
-  // AbstractTypeArguments is an abstract class.
-  UNREACHABLE();
-  return false;
-}
-
-
-bool AbstractTypeArguments::IsBounded() const {
-  // AbstractTypeArguments is an abstract class.
-  UNREACHABLE();
-  return false;
-}
-
-
 static intptr_t FinalizeHash(uword hash) {
   hash += hash << 3;
   hash ^= hash >> 11;
@@ -3919,7 +3854,7 @@
 }
 
 
-intptr_t AbstractTypeArguments::Hash() const {
+intptr_t TypeArguments::Hash() const {
   if (IsNull()) return 0;
   uword result = 0;
   const intptr_t num_types = Length();
@@ -3934,10 +3869,9 @@
 }
 
 
-RawString* AbstractTypeArguments::SubvectorName(
-    intptr_t from_index,
-    intptr_t len,
-    NameVisibility name_visibility) const {
+RawString* TypeArguments::SubvectorName(intptr_t from_index,
+                                        intptr_t len,
+                                        NameVisibility name_visibility) const {
   ASSERT(from_index + len <= Length());
   String& name = String::Handle();
   const intptr_t num_strings = 2*len + 1;  // "<""T"", ""T"">".
@@ -3960,8 +3894,8 @@
 }
 
 
-bool AbstractTypeArguments::IsEquivalent(const AbstractTypeArguments& other,
-                                         GrowableObjectArray* trail) const {
+bool TypeArguments::IsEquivalent(const TypeArguments& other,
+                                 GrowableObjectArray* trail) const {
   if (this->raw() == other.raw()) {
     return true;
   }
@@ -3985,19 +3919,9 @@
 }
 
 
-RawAbstractTypeArguments* AbstractTypeArguments::InstantiateFrom(
-    const AbstractTypeArguments& instantiator_type_arguments,
-    Error* bound_error,
-    GrowableObjectArray* trail) const {
-  // AbstractTypeArguments is an abstract class.
-  UNREACHABLE();
-  return NULL;
-}
-
-
-bool AbstractTypeArguments::IsDynamicTypes(bool raw_instantiated,
-                                           intptr_t from_index,
-                                           intptr_t len) const {
+bool TypeArguments::IsDynamicTypes(bool raw_instantiated,
+                                   intptr_t from_index,
+                                   intptr_t len) const {
   ASSERT(Length() >= (from_index + len));
   AbstractType& type = AbstractType::Handle();
   Class& type_class = Class::Handle();
@@ -4021,11 +3945,11 @@
 }
 
 
-bool AbstractTypeArguments::TypeTest(TypeTestKind test_kind,
-                                     const AbstractTypeArguments& other,
-                                     intptr_t from_index,
-                                     intptr_t len,
-                                     Error* bound_error) const {
+bool TypeArguments::TypeTest(TypeTestKind test_kind,
+                             const TypeArguments& other,
+                             intptr_t from_index,
+                             intptr_t len,
+                             Error* bound_error) const {
   ASSERT(Length() >= (from_index + len));
   ASSERT(!other.IsNull());
   ASSERT(other.Length() >= (from_index + len));
@@ -4044,20 +3968,18 @@
 }
 
 
-const char* AbstractTypeArguments::ToCString() const {
-  // AbstractTypeArguments is an abstract class, valid only for representing
-  // null.
-  if (IsNull()) {
-    return "NULL AbstractTypeArguments";
-  }
-  UNREACHABLE();
-  return "AbstractTypeArguments";
+void TypeArguments::PrintToJSONStream(JSONStream* stream, bool ref) const {
+  JSONObject jsobj(stream);
 }
 
 
-void AbstractTypeArguments::PrintToJSONStream(JSONStream* stream,
-                                              bool ref) const {
-  JSONObject jsobj(stream);
+RawArray* TypeArguments::instantiations() const {
+  return raw_ptr()->instantiations_;
+}
+
+void TypeArguments::set_instantiations(const Array& value) const {
+  ASSERT(!value.IsNull());
+  StorePointer(&raw_ptr()->instantiations_, value.raw());
 }
 
 
@@ -4072,6 +3994,12 @@
 }
 
 
+void TypeArguments::set_type_at(intptr_t index,
+                                const AbstractType& value) const {
+  StorePointer(TypeAddr(index), value.raw());
+}
+
+
 void TypeArguments::SetTypeAt(intptr_t index, const AbstractType& value) const {
   const AbstractType& type_arg = AbstractType::Handle(TypeAt(index));
   if (type_arg.IsTypeRef()) {
@@ -4079,7 +4007,7 @@
       TypeRef::Cast(type_arg).set_type(value);
     }
   } else {
-    StorePointer(TypeAddr(index), value.raw());
+    set_type_at(index, value);
   }
 }
 
@@ -4192,7 +4120,7 @@
   }
   AbstractType& super_type = AbstractType::Handle(
       instantiator_class.super_type());
-  const AbstractTypeArguments& super_type_args = AbstractTypeArguments::Handle(
+  const TypeArguments& super_type_args = TypeArguments::Handle(
       super_type.arguments());
   if (super_type_args.IsNull()) {
     return false;
@@ -4240,7 +4168,7 @@
       }
       continue;
     }
-    const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(
+    const TypeArguments& type_args = TypeArguments::Handle(
         Type::Cast(type).arguments());
     if (!type_args.IsNull() && type_args.IsBounded()) {
       return true;
@@ -4250,8 +4178,8 @@
 }
 
 
-RawAbstractTypeArguments* TypeArguments::InstantiateFrom(
-    const AbstractTypeArguments& instantiator_type_arguments,
+RawTypeArguments* TypeArguments::InstantiateFrom(
+    const TypeArguments& instantiator_type_arguments,
     Error* bound_error,
     GrowableObjectArray* trail) const {
   ASSERT(!IsInstantiated());
@@ -4277,6 +4205,52 @@
 }
 
 
+RawTypeArguments* TypeArguments::InstantiateAndCanonicalizeFrom(
+    const TypeArguments& instantiator_type_arguments,
+    Error* bound_error) const {
+  ASSERT(!IsInstantiated());
+  ASSERT(instantiator_type_arguments.IsNull() ||
+         instantiator_type_arguments.IsCanonical());
+  // Lookup instantiator and, if found, return paired instantiated result.
+  Array& prior_instantiations = Array::Handle(instantiations());
+  ASSERT(!prior_instantiations.IsNull() && prior_instantiations.IsArray());
+  intptr_t length = prior_instantiations.Length();
+  intptr_t index = 0;
+  while (index < length) {
+    if (prior_instantiations.At(index) == instantiator_type_arguments.raw()) {
+      return TypeArguments::RawCast(prior_instantiations.At(index + 1));
+    }
+    if (prior_instantiations.At(index) == Smi::New(StubCode::kNoInstantiator)) {
+      break;
+    }
+    index += 2;
+  }
+  // Cache lookup failed. Instantiate the type arguments.
+  TypeArguments& result = TypeArguments::Handle();
+  result = InstantiateFrom(instantiator_type_arguments, bound_error);
+  if ((bound_error != NULL) && !bound_error->IsNull()) {
+    return result.raw();
+  }
+  // Instantiation did not result in bound error. Canonicalize type arguments.
+  result = result.Canonicalize();
+  // Add instantiator and result to instantiations array.
+  if ((index + 2) > length) {
+    // Grow the instantiations array.
+    length = (length == 0) ? 2 : length + 4;
+    prior_instantiations =
+        Array::Grow(prior_instantiations, length, Heap::kOld);
+    set_instantiations(prior_instantiations);
+  }
+  prior_instantiations.SetAt(index, instantiator_type_arguments);
+  prior_instantiations.SetAt(index + 1, result);
+  if ((index + 2) < length) {
+    prior_instantiations.SetAt(index + 2,
+        Smi::Handle(Smi::New(StubCode::kNoInstantiator)));
+  }
+  return result.raw();
+}
+
+
 RawTypeArguments* TypeArguments::New(intptr_t len, Heap::Space space) {
   if (len < 0 || len > kMaxElements) {
     // This should be caught before we reach here.
@@ -4292,6 +4266,7 @@
     // Length must be set before we start storing into the array.
     result.SetLength(len);
   }
+  result.set_instantiations(Object::empty_array());
   return result.raw();
 }
 
@@ -4383,8 +4358,8 @@
 }
 
 
-RawAbstractTypeArguments* TypeArguments::CloneUnfinalized() const {
-  if (IsFinalized()) {
+RawTypeArguments* TypeArguments::CloneUnfinalized() const {
+  if (IsNull() || IsFinalized()) {
     return raw();
   }
   AbstractType& type = AbstractType::Handle();
@@ -4400,7 +4375,7 @@
 }
 
 
-RawAbstractTypeArguments* TypeArguments::Canonicalize(
+RawTypeArguments* TypeArguments::Canonicalize(
     GrowableObjectArray* trail) const {
   if (IsNull() || IsCanonical()) {
     ASSERT(IsOld());
@@ -4438,6 +4413,7 @@
   ASSERT(result.Equals(*this));
   ASSERT(!result.IsNull());
   ASSERT(result.IsTypeArguments());
+  ASSERT(result.IsCanonical());
   return result.raw();
 }
 
@@ -4460,113 +4436,6 @@
 }
 
 
-void TypeArguments::PrintToJSONStream(JSONStream* stream, bool ref) const {
-  JSONObject jsobj(stream);
-}
-
-
-intptr_t InstantiatedTypeArguments::Length() const {
-  return AbstractTypeArguments::Handle(
-      uninstantiated_type_arguments()).Length();
-}
-
-
-RawAbstractType* InstantiatedTypeArguments::TypeAt(intptr_t index) const {
-  AbstractType& type = AbstractType::Handle(AbstractTypeArguments::Handle(
-      uninstantiated_type_arguments()).TypeAt(index));
-  if (!type.IsInstantiated()) {
-    const AbstractTypeArguments& instantiator_type_args =
-        AbstractTypeArguments::Handle(instantiator_type_arguments());
-    Error& bound_error = Error::Handle();
-    type = type.InstantiateFrom(instantiator_type_args, &bound_error);
-    // InstantiatedTypeArguments cannot include unchecked bounds.
-    // In the presence of unchecked bounds, no InstantiatedTypeArguments are
-    // allocated, but the type arguments are instantiated individually and their
-    // bounds are checked.
-    ASSERT(bound_error.IsNull());
-  }
-  return type.raw();
-}
-
-
-void InstantiatedTypeArguments::SetTypeAt(intptr_t index,
-                                          const AbstractType& value) const {
-  // We only replace individual argument types during resolution at compile
-  // time, when no type parameters are instantiated yet.
-  UNREACHABLE();
-}
-
-
-RawAbstractTypeArguments* InstantiatedTypeArguments::Canonicalize(
-    GrowableObjectArray* trail) const {
-  const intptr_t num_types = Length();
-  const TypeArguments& type_args = TypeArguments::Handle(
-      TypeArguments::New(num_types, Heap::kOld));
-  AbstractType& type = AbstractType::Handle();
-  for (intptr_t i = 0; i < num_types; i++) {
-    type = TypeAt(i);
-    type_args.SetTypeAt(i, type);
-  }
-  return type_args.Canonicalize(trail);
-}
-
-
-void InstantiatedTypeArguments::set_uninstantiated_type_arguments(
-    const AbstractTypeArguments& value) const {
-  StorePointer(&raw_ptr()->uninstantiated_type_arguments_, value.raw());
-}
-
-
-void InstantiatedTypeArguments::set_instantiator_type_arguments(
-    const AbstractTypeArguments& value) const {
-  StorePointer(&raw_ptr()->instantiator_type_arguments_, value.raw());
-}
-
-
-RawInstantiatedTypeArguments* InstantiatedTypeArguments::New() {
-  ASSERT(Object::instantiated_type_arguments_class() != Class::null());
-  RawObject* raw = Object::Allocate(InstantiatedTypeArguments::kClassId,
-                                    InstantiatedTypeArguments::InstanceSize(),
-                                    Heap::kNew);
-  return reinterpret_cast<RawInstantiatedTypeArguments*>(raw);
-}
-
-
-RawInstantiatedTypeArguments* InstantiatedTypeArguments::New(
-    const AbstractTypeArguments& uninstantiated_type_arguments,
-    const AbstractTypeArguments& instantiator_type_arguments) {
-  const InstantiatedTypeArguments& result =
-      InstantiatedTypeArguments::Handle(InstantiatedTypeArguments::New());
-  result.set_uninstantiated_type_arguments(uninstantiated_type_arguments);
-  result.set_instantiator_type_arguments(instantiator_type_arguments);
-  return result.raw();
-}
-
-
-const char* InstantiatedTypeArguments::ToCString() const {
-  if (IsNull()) {
-    return "NULL InstantiatedTypeArguments";
-  }
-  const char* format = "InstantiatedTypeArguments: [%s] instantiator: [%s]";
-  const char* arg_cstr =
-      AbstractTypeArguments::Handle(
-          uninstantiated_type_arguments()).ToCString();
-  const char* instantiator_cstr =
-      AbstractTypeArguments::Handle(instantiator_type_arguments()).ToCString();
-  intptr_t len =
-      OS::SNPrint(NULL, 0, format, arg_cstr, instantiator_cstr) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
-  OS::SNPrint(chars, len, format, arg_cstr, instantiator_cstr);
-  return chars;
-}
-
-
-void InstantiatedTypeArguments::PrintToJSONStream(JSONStream* stream,
-                                                  bool ref) const {
-  JSONObject jsobj(stream);
-}
-
-
 const char* PatchClass::ToCString() const {
   const char* kFormat = "PatchClass for %s";
   const Class& cls = Class::Handle(patched_class());
@@ -5145,11 +5014,18 @@
   set_is_optimizable(value);
 }
 
+
 void Function::set_is_optimizable(bool value) const {
   set_kind_tag(OptimizableBit::update(value, raw_ptr()->kind_tag_));
 }
 
 
+void Function::set_allows_hoisting_check_class(bool value) const {
+  set_kind_tag(
+      AllowsHoistingCheckClassBit::update(value, raw_ptr()->kind_tag_));
+}
+
+
 void Function::set_is_native(bool value) const {
   set_kind_tag(NativeBit::update(value, raw_ptr()->kind_tag_));
 }
@@ -5417,8 +5293,8 @@
   ASSERT((bound_error != NULL) && bound_error->IsNull());
   // Check that this function's signature type is a subtype of the other
   // function's signature type.
-  if (!TypeTest(kIsSubtypeOf, Object::null_abstract_type_arguments(),
-                other, Object::null_abstract_type_arguments(), bound_error)) {
+  if (!TypeTest(kIsSubtypeOf, Object::null_type_arguments(),
+                other, Object::null_type_arguments(), bound_error)) {
     // For more informative error reporting, use the location of the other
     // function here, since the caller will use the location of this function.
     *bound_error = LanguageError::NewFormatted(
@@ -5457,9 +5333,9 @@
     TypeTestKind test_kind,
     intptr_t parameter_position,
     intptr_t other_parameter_position,
-    const AbstractTypeArguments& type_arguments,
+    const TypeArguments& type_arguments,
     const Function& other,
-    const AbstractTypeArguments& other_type_arguments,
+    const TypeArguments& other_type_arguments,
     Error* bound_error) const {
   AbstractType& other_param_type =
       AbstractType::Handle(other.ParameterTypeAt(other_parameter_position));
@@ -5496,9 +5372,9 @@
 
 
 bool Function::TypeTest(TypeTestKind test_kind,
-                        const AbstractTypeArguments& type_arguments,
+                        const TypeArguments& type_arguments,
                         const Function& other,
-                        const AbstractTypeArguments& other_type_arguments,
+                        const TypeArguments& other_type_arguments,
                         Error* bound_error) const {
   const intptr_t num_fixed_params = num_fixed_parameters();
   const intptr_t num_opt_pos_params = NumOptionalPositionalParameters();
@@ -5663,6 +5539,7 @@
   result.set_optimized_call_site_count(0);
   result.set_is_optimizable(is_native ? false : true);
   result.set_is_inlinable(true);
+  result.set_allows_hoisting_check_class(true);
   if (kind == RawFunction::kClosureFunction) {
     const ClosureData& data = ClosureData::Handle(ClosureData::New());
     result.set_data(data);
@@ -5809,7 +5686,7 @@
 void Function::BuildSignatureParameters(
     bool instantiate,
     NameVisibility name_visibility,
-    const AbstractTypeArguments& instantiator,
+    const TypeArguments& instantiator,
     const GrowableObjectArray& pieces) const {
   AbstractType& param_type = AbstractType::Handle();
   const intptr_t num_params = NumParameters();
@@ -5883,10 +5760,9 @@
 }
 
 
-RawString* Function::BuildSignature(
-    bool instantiate,
-    NameVisibility name_visibility,
-    const AbstractTypeArguments& instantiator) const {
+RawString* Function::BuildSignature(bool instantiate,
+                                    NameVisibility name_visibility,
+                                    const TypeArguments& instantiator) const {
   const GrowableObjectArray& pieces =
       GrowableObjectArray::Handle(GrowableObjectArray::New());
   String& name = String::Handle();
@@ -6456,9 +6332,11 @@
 
 
 bool Field::IsUnboxedField() const {
-  // TODO(johnmccutchan): Add kFloat32x4Cid here.
+  bool valid_class = (guarded_cid() == kDoubleCid) ||
+                     (FlowGraphCompiler::SupportsUnboxedFloat32x4() &&
+                      (guarded_cid() == kFloat32x4Cid));
   return is_unboxing_candidate() && !is_final() && !is_nullable() &&
-         ((guarded_cid() == kDoubleCid));
+         valid_class;
 }
 
 
@@ -6798,9 +6676,13 @@
   StorePointer(&raw_ptr()->private_key_, value.raw());
 }
 
-
 RawString* TokenStream::GenerateSource() const {
-  Iterator iterator(*this, 0, Iterator::kAllTokens);
+  return GenerateSource(0, kMaxElements);
+}
+
+RawString* TokenStream::GenerateSource(intptr_t start_pos,
+                                       intptr_t end_pos) const {
+  Iterator iterator(*this, start_pos, Iterator::kAllTokens);
   const ExternalTypedData& data = ExternalTypedData::Handle(GetStream());
   const GrowableObjectArray& literals =
       GrowableObjectArray::Handle(GrowableObjectArray::New(data.Length()));
@@ -6815,7 +6697,7 @@
   // Current indentation level.
   int indent = 0;
 
-  while (curr != Token::kEOS) {
+  while ((curr != Token::kEOS) && (iterator.CurrentPosition() < end_pos)) {
     // Remember current values for this token.
     obj = iterator.CurrentToken();
     literal = iterator.MakeLiteralToken(obj);
@@ -6845,12 +6727,12 @@
       }
     } else if (curr == Token::kINTERPOL_VAR) {
       literals.Add(Symbols::Dollar());
-      if (literal.CharAt(0) == Scanner::kPrivateIdentifierStart) {
+      if (literal.CharAt(0) == Library::kPrivateIdentifierStart) {
         literal = String::SubString(literal, 0, literal.Length() - private_len);
       }
       literals.Add(literal);
     } else if (curr == Token::kIDENT) {
-      if (literal.CharAt(0) == Scanner::kPrivateIdentifierStart) {
+      if (literal.CharAt(0) == Library::kPrivateIdentifierStart) {
         literal = String::SubString(literal, 0, literal.Length() - private_len);
       }
       literals.Add(literal);
@@ -7973,6 +7855,7 @@
   if (!FLAG_use_lib_cache) {
     return;
   }
+  ASSERT(!Field::IsGetterName(name) && !Field::IsSetterName(name));
   const Array& cache = Array::Handle(resolved_names());
   // let N = cache.Length();
   // The entry cache[N-1] is used as a counter
@@ -8560,7 +8443,6 @@
   const Library& result = Library::Handle(Library::New());
   result.StorePointer(&result.raw_ptr()->name_, Symbols::Empty().raw());
   result.StorePointer(&result.raw_ptr()->url_, url.raw());
-  result.raw_ptr()->private_key_ = Scanner::AllocatePrivateKey(result);
   result.raw_ptr()->resolved_names_ = Object::empty_array().raw();
   result.raw_ptr()->dictionary_ = Object::empty_array().raw();
   result.StorePointer(&result.raw_ptr()->metadata_,
@@ -8579,6 +8461,7 @@
   result.InitResolvedNamesCache(kInitialNameCacheSize);
   result.InitClassDictionary();
   result.InitImportList();
+  result.AllocatePrivateKey();
   if (import_core_lib) {
     const Library& core_lib = Library::Handle(Library::CoreLibrary());
     ASSERT(!core_lib.IsNull());
@@ -8675,6 +8558,20 @@
 }
 
 
+bool Library::IsPrivate(const String& name) {
+  if (ShouldBePrivate(name)) return true;
+  // Factory names: List._fromLiteral.
+  for (intptr_t i = 1; i < name.Length() - 1; i++) {
+    if (name.CharAt(i) == '.') {
+      if (name.CharAt(i + 1) == '_') {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+
 bool Library::IsKeyUsed(intptr_t key) {
   intptr_t lib_key;
   const GrowableObjectArray& libs = GrowableObjectArray::Handle(
@@ -8693,17 +8590,16 @@
 }
 
 
-bool Library::IsPrivate(const String& name) {
-  if (ShouldBePrivate(name)) return true;
-  // Factory names: List._fromLiteral.
-  for (intptr_t i = 1; i < name.Length() - 1; i++) {
-    if (name.CharAt(i) == '.') {
-      if (name.CharAt(i + 1) == '_') {
-        return true;
-      }
-    }
+void Library::AllocatePrivateKey() const {
+  const String& url = String::Handle(this->url());
+  intptr_t key_value = url.Hash();
+  while (Library::IsKeyUsed(key_value)) {
+    key_value++;
   }
-  return false;
+  char private_key[32];
+  OS::SNPrint(private_key, sizeof(private_key),
+              "%c%#" Px "", kPrivateKeySeparator, key_value);
+  StorePointer(&raw_ptr()->private_key_, String::New(private_key, Heap::kOld));
 }
 
 
@@ -8717,7 +8613,7 @@
 RawClass* Library::LookupCoreClass(const String& class_name) {
   const Library& core_lib = Library::Handle(Library::CoreLibrary());
   String& name = String::Handle(class_name.raw());
-  if (class_name.CharAt(0) == Scanner::kPrivateIdentifierStart) {
+  if (class_name.CharAt(0) == kPrivateIdentifierStart) {
     // Private identifiers are mangled on a per library basis.
     name = String::Concat(name, String::Handle(core_lib.private_key()));
     name = Symbols::New(name);
@@ -10265,7 +10161,7 @@
     result ^= raw;
     result.set_pointer_offsets_length(pointer_offsets_length);
     result.set_is_optimized(false);
-    result.set_is_alive(true);
+    result.set_is_alive(false);
     result.set_comments(Comments::New(0));
     result.set_pc_descriptors(Object::empty_descriptors());
   }
@@ -10278,7 +10174,11 @@
                             bool optimized) {
   ASSERT(assembler != NULL);
 
-  // Allocate the Instructions object.
+  // Allocate the Code and Instructions objects.  Code is allocated first
+  // because a GC during allocation of the code will leave the instruction
+  // pages read-only.
+  intptr_t pointer_offset_count = assembler->CountPointerOffsets();
+  Code& code = Code::ZoneHandle(Code::New(pointer_offset_count));
   Instructions& instrs =
       Instructions::ZoneHandle(Instructions::New(assembler->CodeSize()));
 
@@ -10295,17 +10195,15 @@
                            instrs.size(),
                            optimized);
 
-  const ZoneGrowableArray<intptr_t>& pointer_offsets =
-      assembler->GetPointerOffsets();
-
-  // Allocate the code object.
-  Code& code = Code::ZoneHandle(Code::New(pointer_offsets.length()));
   {
     NoGCScope no_gc;
+    const ZoneGrowableArray<intptr_t>& pointer_offsets =
+        assembler->GetPointerOffsets();
+    ASSERT(pointer_offsets.length() == pointer_offset_count);
+    ASSERT(code.pointer_offsets_length() == pointer_offsets.length());
 
     // Set pointer offsets list in Code object and resolve all handles in
     // the instruction stream to raw objects.
-    ASSERT(code.pointer_offsets_length() == pointer_offsets.length());
     for (intptr_t i = 0; i < pointer_offsets.length(); i++) {
       intptr_t offset_in_instrs = pointer_offsets[i];
       code.SetPointerOffsetAt(i, offset_in_instrs);
@@ -10316,6 +10214,7 @@
     // Hook up Code and Instructions objects.
     instrs.set_code(code.raw());
     code.set_instructions(instrs.raw());
+    code.set_is_alive(true);
 
     // Set object pool in Instructions object.
     const GrowableObjectArray& object_pool = assembler->object_pool();
@@ -10327,6 +10226,13 @@
       // GrowableObjectArray in new space.
       instrs.set_object_pool(Array::MakeArray(object_pool));
     }
+    bool status =
+        VirtualMemory::Protect(reinterpret_cast<void*>(instrs.raw_ptr()),
+                               instrs.raw()->Size(),
+                               FLAG_write_protect_code
+                                   ? VirtualMemory::kReadExecute
+                                   : VirtualMemory::kReadWriteExecute);
+    ASSERT(status);
   }
   return code.raw();
 }
@@ -11337,8 +11243,8 @@
 
 void SubtypeTestCache::AddCheck(
     intptr_t instance_class_id,
-    const AbstractTypeArguments& instance_type_arguments,
-    const AbstractTypeArguments& instantiator_type_arguments,
+    const TypeArguments& instance_type_arguments,
+    const TypeArguments& instantiator_type_arguments,
     const Bool& test_result) const {
   intptr_t old_num = NumberOfChecks();
   Array& data = Array::Handle(cache());
@@ -11355,12 +11261,11 @@
 }
 
 
-void SubtypeTestCache::GetCheck(
-    intptr_t ix,
-    intptr_t* instance_class_id,
-    AbstractTypeArguments* instance_type_arguments,
-    AbstractTypeArguments* instantiator_type_arguments,
-    Bool* test_result) const {
+void SubtypeTestCache::GetCheck(intptr_t ix,
+                                intptr_t* instance_class_id,
+                                TypeArguments* instance_type_arguments,
+                                TypeArguments* instantiator_type_arguments,
+                                Bool* test_result) const {
   Array& data = Array::Handle(cache());
   intptr_t data_pos = ix * kTestEntryLength;
   *instance_class_id =
@@ -11915,7 +11820,7 @@
   const Class& cls = Class::Handle(clazz());
   Type& type = Type::Handle(cls.CanonicalType());
   if (type.IsNull()) {
-    AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle();
+    TypeArguments& type_arguments = TypeArguments::Handle();
     if (cls.NumTypeArguments() > 0) {
       type_arguments = GetTypeArguments();
     }
@@ -11927,17 +11832,18 @@
 }
 
 
-RawAbstractTypeArguments* Instance::GetTypeArguments() const {
+RawTypeArguments* Instance::GetTypeArguments() const {
   const Class& cls = Class::Handle(clazz());
   intptr_t field_offset = cls.type_arguments_field_offset();
   ASSERT(field_offset != Class::kNoTypeArguments);
-  AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle();
+  TypeArguments& type_arguments = TypeArguments::Handle();
   type_arguments ^= *FieldAddrAtOffset(field_offset);
   return type_arguments.raw();
 }
 
 
-void Instance::SetTypeArguments(const AbstractTypeArguments& value) const {
+void Instance::SetTypeArguments(const TypeArguments& value) const {
+  ASSERT(value.IsNull() || value.IsCanonical());
   const Class& cls = Class::Handle(clazz());
   intptr_t field_offset = cls.type_arguments_field_offset();
   ASSERT(field_offset != Class::kNoTypeArguments);
@@ -11946,7 +11852,7 @@
 
 
 bool Instance::IsInstanceOf(const AbstractType& other,
-                            const AbstractTypeArguments& other_instantiator,
+                            const TypeArguments& other_instantiator,
                             Error* bound_error) const {
   ASSERT(other.IsFinalized());
   ASSERT(!other.IsDynamicType());
@@ -11957,14 +11863,11 @@
   }
   Isolate* isolate = Isolate::Current();
   const Class& cls = Class::Handle(isolate, clazz());
-  AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::Handle(isolate);
+  TypeArguments& type_arguments =
+      TypeArguments::Handle(isolate);
   if (cls.NumTypeArguments() > 0) {
     type_arguments = GetTypeArguments();
-    if (!type_arguments.IsNull() && !type_arguments.IsCanonical()) {
-      type_arguments = type_arguments.Canonicalize();
-      SetTypeArguments(type_arguments);
-    }
+    ASSERT(type_arguments.IsNull() || type_arguments.IsCanonical());
     // The number of type arguments in the instance must be greater or equal to
     // the number of type arguments expected by the instance class.
     // A discrepancy is allowed for closures, which borrow the type argument
@@ -11977,8 +11880,7 @@
            (type_arguments.Length() >= cls.NumTypeArguments()));
   }
   Class& other_class = Class::Handle(isolate);
-  AbstractTypeArguments& other_type_arguments =
-      AbstractTypeArguments::Handle(isolate);
+  TypeArguments& other_type_arguments = TypeArguments::Handle(isolate);
   // Note that we may encounter a bound error in checked mode.
   if (!other.IsInstantiated()) {
     const AbstractType& instantiated_other = AbstractType::Handle(
@@ -12105,7 +12007,7 @@
     }
     const char* kFormat = "Instance of '%s'";
     const Class& cls = Class::Handle(clazz());
-    AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle();
+    TypeArguments& type_arguments = TypeArguments::Handle();
     const intptr_t num_type_arguments = cls.NumTypeArguments();
     if (num_type_arguments > 0) {
       type_arguments = GetTypeArguments();
@@ -12213,7 +12115,7 @@
 }
 
 
-RawAbstractTypeArguments* AbstractType::arguments() const  {
+RawTypeArguments* AbstractType::arguments() const  {
   // AbstractType is an abstract class.
   UNREACHABLE();
   return NULL;
@@ -12291,7 +12193,7 @@
 
 
 RawAbstractType* AbstractType::InstantiateFrom(
-    const AbstractTypeArguments& instantiator_type_arguments,
+    const TypeArguments& instantiator_type_arguments,
     Error* bound_error,
     GrowableObjectArray* trail) const {
   // AbstractType is an abstract class.
@@ -12332,7 +12234,7 @@
     } else if (bound.IsType()) {
       const Class& cls = Class::Handle(Type::Cast(bound).type_class());
       bound_name = cls.Name();
-      if (Type::Cast(bound).arguments() != AbstractTypeArguments::null()) {
+      if (Type::Cast(bound).arguments() != TypeArguments::null()) {
         bound_name = String::Concat(bound_name, Symbols::OptimizedOut());
       }
     } else {
@@ -12346,8 +12248,7 @@
   }
   // If the type is still being finalized, we may be reporting an error about
   // a malformed type, so proceed with caution.
-  const AbstractTypeArguments& args =
-      AbstractTypeArguments::Handle(arguments());
+  const TypeArguments& args = TypeArguments::Handle(arguments());
   const intptr_t num_args = args.IsNull() ? 0 : args.Length();
   String& class_name = String::Handle();
   intptr_t first_type_param_index;
@@ -12556,9 +12457,9 @@
   }
   const Class& cls = Class::Handle(type_class());
   return cls.TypeTest(test_kind,
-                      AbstractTypeArguments::Handle(arguments()),
+                      TypeArguments::Handle(arguments()),
                       Class::Handle(other.type_class()),
-                      AbstractTypeArguments::Handle(other.arguments()),
+                      TypeArguments::Handle(other.arguments()),
                       bound_error);
 }
 
@@ -12749,8 +12650,7 @@
   if (!HasResolvedTypeClass()) {
     return false;
   }
-  const AbstractTypeArguments& args =
-      AbstractTypeArguments::Handle(arguments());
+  const TypeArguments& args = TypeArguments::Handle(arguments());
   return args.IsNull() || args.IsResolved();
 }
 
@@ -12788,7 +12688,7 @@
 }
 
 
-RawAbstractTypeArguments* Type::arguments() const {
+RawTypeArguments* Type::arguments() const {
   return raw_ptr()->arguments_;
 }
 
@@ -12800,14 +12700,13 @@
   if (raw_ptr()->type_state_ == RawType::kFinalizedUninstantiated) {
     return false;
   }
-  const AbstractTypeArguments& args =
-      AbstractTypeArguments::Handle(arguments());
+  const TypeArguments& args = TypeArguments::Handle(arguments());
   return args.IsNull() || args.IsInstantiated(trail);
 }
 
 
 RawAbstractType* Type::InstantiateFrom(
-    const AbstractTypeArguments& instantiator_type_arguments,
+    const TypeArguments& instantiator_type_arguments,
     Error* bound_error,
     GrowableObjectArray* trail) const {
   ASSERT(IsFinalized() || IsBeingFinalized());
@@ -12816,8 +12715,7 @@
   if (IsMalformed()) {
     return raw();
   }
-  AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::Handle(arguments());
+  TypeArguments& type_arguments = TypeArguments::Handle(arguments());
   type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments,
                                                   bound_error,
                                                   trail);
@@ -12831,6 +12729,7 @@
   ASSERT(type_arguments.IsNull() ||
          (type_arguments.Length() == cls.NumTypeArguments()));
   instantiated_type.SetIsFinalized();
+  // Canonicalization is not part of instantiation.
   return instantiated_type.raw();
 }
 
@@ -12873,9 +12772,8 @@
   }
   const intptr_t num_type_args = cls.NumTypeArguments();
   const intptr_t from_index = num_type_args - num_type_params;
-  const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(
-      arguments());
-  const AbstractTypeArguments& other_type_args = AbstractTypeArguments::Handle(
+  const TypeArguments& type_args = TypeArguments::Handle(arguments());
+  const TypeArguments& other_type_args = TypeArguments::Handle(
       other_type.arguments());
   if (type_args.IsNull()) {
     return other_type_args.IsRaw(from_index, num_type_params);
@@ -12905,7 +12803,7 @@
   }
   ASSERT(!IsMalformed());  // Malformed types are finalized.
   ASSERT(!IsBeingFinalized());  // Cloning must occur prior to finalization.
-  AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(arguments());
+  TypeArguments& type_args = TypeArguments::Handle(arguments());
   type_args = type_args.CloneUnfinalized();
   const Class& type_cls = Class::Handle(type_class());
   return Type::New(type_cls, type_args, token_pos());
@@ -12915,7 +12813,7 @@
 RawAbstractType* Type::Canonicalize(GrowableObjectArray* trail) const {
   ASSERT(IsFinalized());
   if (IsCanonical() || IsMalformed()) {
-    ASSERT(IsMalformed() || AbstractTypeArguments::Handle(arguments()).IsOld());
+    ASSERT(IsMalformed() || TypeArguments::Handle(arguments()).IsOld());
     return this->raw();
   }
   Isolate* isolate = Isolate::Current();
@@ -12960,8 +12858,7 @@
     index++;
   }
   // Canonicalize the type arguments.
-  AbstractTypeArguments& type_args =
-      AbstractTypeArguments::Handle(isolate, arguments());
+  TypeArguments& type_args = TypeArguments::Handle(isolate, arguments());
   // In case the type is first canonicalized at runtime, its type argument
   // vector may be longer than necessary. This is not an issue.
   ASSERT(type_args.IsNull() || (type_args.Length() >= cls.NumTypeArguments()));
@@ -13014,7 +12911,7 @@
   uword result = 1;
   if (IsMalformed()) return result;
   result += Class::Handle(type_class()).id();
-  result += AbstractTypeArguments::Handle(arguments()).Hash();
+  result += TypeArguments::Handle(arguments()).Hash();
   return FinalizeHash(result);
 }
 
@@ -13025,7 +12922,7 @@
 }
 
 
-void Type::set_arguments(const AbstractTypeArguments& value) const {
+void Type::set_arguments(const TypeArguments& value) const {
   StorePointer(&raw_ptr()->arguments_, value.raw());
 }
 
@@ -13040,7 +12937,7 @@
 
 
 RawType* Type::New(const Object& clazz,
-                   const AbstractTypeArguments& arguments,
+                   const TypeArguments& arguments,
                    intptr_t token_pos,
                    Heap::Space space) {
   const Type& result = Type::Handle(Type::New(space));
@@ -13069,8 +12966,7 @@
 
 const char* Type::ToCString() const {
   if (IsResolved()) {
-    const AbstractTypeArguments& type_arguments =
-        AbstractTypeArguments::Handle(arguments());
+    const TypeArguments& type_arguments = TypeArguments::Handle(arguments());
     const char* class_name;
     if (HasResolvedTypeClass()) {
       class_name = String::Handle(
@@ -13086,8 +12982,7 @@
       return chars;
     } else {
       const char* format = "Type: class '%s', args:[%s]";
-      const char* args_cstr =
-          AbstractTypeArguments::Handle(arguments()).ToCString();
+      const char* args_cstr = TypeArguments::Handle(arguments()).ToCString();
       intptr_t len = OS::SNPrint(NULL, 0, format, class_name, args_cstr) + 1;
       char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
       OS::SNPrint(chars, len, format, class_name, args_cstr);
@@ -13125,7 +13020,7 @@
 
 
 RawAbstractType* TypeRef::InstantiateFrom(
-    const AbstractTypeArguments& instantiator_type_arguments,
+    const TypeArguments& instantiator_type_arguments,
     Error* bound_error,
     GrowableObjectArray* trail) const {
   TypeRef& instantiated_type_ref = TypeRef::Handle();
@@ -13259,7 +13154,7 @@
   const char* type_cstr = String::Handle(Class::Handle(AbstractType::Handle(
       type()).type_class()).Name()).ToCString();
   const char* args_cstr = (AbstractType::Handle(
-      type()).arguments() == AbstractTypeArguments::null()) ? "" : "<...>";
+      type()).arguments() == TypeArguments::null()) ? "" : "<...>";
   intptr_t len = OS::SNPrint(NULL, 0, format, type_cstr, args_cstr) + 1;
   char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, format, type_cstr, args_cstr);
@@ -13328,7 +13223,7 @@
 
 
 RawAbstractType* TypeParameter::InstantiateFrom(
-    const AbstractTypeArguments& instantiator_type_arguments,
+    const TypeArguments& instantiator_type_arguments,
     Error* bound_error,
     GrowableObjectArray* trail) const {
   ASSERT(IsFinalized());
@@ -13553,7 +13448,7 @@
 
 
 RawAbstractType* BoundedType::InstantiateFrom(
-    const AbstractTypeArguments& instantiator_type_arguments,
+    const TypeArguments& instantiator_type_arguments,
     Error* bound_error,
     GrowableObjectArray* trail) const {
   ASSERT(IsFinalized());
@@ -15621,7 +15516,7 @@
     int32_t ch = T1::CharAt(str1, pos);
     pos++;
 
-    if (ch == Scanner::kPrivateKeySeparator) {
+    if (ch == Library::kPrivateKeySeparator) {
       // Consume a private key separator.
       while ((pos < len) && (T1::CharAt(str1, pos) != '.')) {
         pos++;
@@ -16231,9 +16126,8 @@
   }
 
   // Both arrays must have the same type arguments.
-  const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(
-      GetTypeArguments());
-  const AbstractTypeArguments& other_type_args = AbstractTypeArguments::Handle(
+  const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
+  const TypeArguments& other_type_args = TypeArguments::Handle(
       other.GetTypeArguments());
   if (!type_args.Equals(other_type_args)) {
     return false;
@@ -16310,8 +16204,7 @@
   intptr_t len = 0;
   if (!source.IsNull()) {
     len = source.Length();
-    result.SetTypeArguments(
-        AbstractTypeArguments::Handle(source.GetTypeArguments()));
+    result.SetTypeArguments(TypeArguments::Handle(source.GetTypeArguments()));
   }
   ASSERT(new_length >= len);  // Cannot copy 'source' into new array.
   ASSERT(new_length != len);  // Unnecessary copying of array.
@@ -16455,9 +16348,8 @@
   }
 
   // Both arrays must have the same type arguments.
-  const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(
-      GetTypeArguments());
-  const AbstractTypeArguments& other_type_args = AbstractTypeArguments::Handle(
+  const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
+  const TypeArguments& other_type_args = TypeArguments::Handle(
       other.GetTypeArguments());
   if (!type_args.Equals(other_type_args)) {
     return false;
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 37dfc34..ab2c0f7 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -358,9 +358,9 @@
     ASSERT(null_instance_ != NULL);
     return *null_instance_;
   }
-  static const AbstractTypeArguments& null_abstract_type_arguments() {
-    ASSERT(null_abstract_type_arguments_ != NULL);
-    return *null_abstract_type_arguments_;
+  static const TypeArguments& null_type_arguments() {
+    ASSERT(null_type_arguments_ != NULL);
+    return *null_type_arguments_;
   }
 
   static const Array& empty_array() {
@@ -427,9 +427,6 @@
   static RawType* void_type() { return void_type_; }
   static RawClass* unresolved_class_class() { return unresolved_class_class_; }
   static RawClass* type_arguments_class() { return type_arguments_class_; }
-  static RawClass* instantiated_type_arguments_class() {
-      return instantiated_type_arguments_class_;
-  }
   static RawClass* patch_class_class() { return patch_class_class_; }
   static RawClass* function_class() { return function_class_; }
   static RawClass* closure_data_class() { return closure_data_class_; }
@@ -580,9 +577,7 @@
   static RawType* dynamic_type_;  // Class of the 'dynamic' type.
   static RawType* void_type_;  // Class of the 'void' type.
   static RawClass* unresolved_class_class_;  // Class of UnresolvedClass.
-  // Class of the TypeArguments vm object.
-  static RawClass* type_arguments_class_;
-  static RawClass* instantiated_type_arguments_class_;  // Class of Inst..ments.
+  static RawClass* type_arguments_class_;  // Class of TypeArguments vm object.
   static RawClass* patch_class_class_;  // Class of the PatchClass vm object.
   static RawClass* function_class_;  // Class of the Function vm object.
   static RawClass* closure_data_class_;  // Class of ClosureData vm obj.
@@ -617,7 +612,7 @@
   static Array* null_array_;
   static String* null_string_;
   static Instance* null_instance_;
-  static AbstractTypeArguments* null_abstract_type_arguments_;
+  static TypeArguments* null_type_arguments_;
   static Array* empty_array_;
   static PcDescriptors* empty_descriptors_;
   static Instance* sentinel_;
@@ -857,9 +852,9 @@
   bool IsCanonicalSignatureClass() const;
 
   // Check the subtype relationship.
-  bool IsSubtypeOf(const AbstractTypeArguments& type_arguments,
+  bool IsSubtypeOf(const TypeArguments& type_arguments,
                    const Class& other,
-                   const AbstractTypeArguments& other_type_arguments,
+                   const TypeArguments& other_type_arguments,
                    Error* bound_error) const {
     return TypeTest(kIsSubtypeOf,
                     type_arguments,
@@ -869,9 +864,9 @@
   }
 
   // Check the 'more specific' relationship.
-  bool IsMoreSpecificThan(const AbstractTypeArguments& type_arguments,
+  bool IsMoreSpecificThan(const TypeArguments& type_arguments,
                           const Class& other,
-                          const AbstractTypeArguments& other_type_arguments,
+                          const TypeArguments& other_type_arguments,
                           Error* bound_error) const {
     return TypeTest(kIsMoreSpecificThan,
                     type_arguments,
@@ -1171,17 +1166,17 @@
 
   // Check the subtype or 'more specific' relationship.
   bool TypeTest(TypeTestKind test_kind,
-                const AbstractTypeArguments& type_arguments,
+                const TypeArguments& type_arguments,
                 const Class& other,
-                const AbstractTypeArguments& other_type_arguments,
+                const TypeArguments& other_type_arguments,
                 Error* bound_error) const;
 
   static bool TypeTestNonRecursive(
       const Class& cls,
       TypeTestKind test_kind,
-      const AbstractTypeArguments& type_arguments,
+      const TypeArguments& type_arguments,
       const Class& other,
-      const AbstractTypeArguments& other_type_arguments,
+      const TypeArguments& other_type_arguments,
       Error* bound_error);
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Class, Object);
@@ -1224,44 +1219,24 @@
 };
 
 
-// AbstractTypeArguments is an abstract superclass.
-// Subclasses of AbstractTypeArguments are TypeArguments and
-// InstantiatedTypeArguments.
-class AbstractTypeArguments : public Object {
+// A TypeArguments is an array of AbstractType.
+class TypeArguments : public Object {
  public:
-  // Returns true if all types of this vector are finalized.
-  virtual bool IsFinalized() const { return true; }
-
-  // Return 'this' if this type argument vector is instantiated, i.e. if it does
-  // not refer to type parameters. Otherwise, return a new type argument vector
-  // where each reference to a type parameter is replaced with the corresponding
-  // type of the instantiator type argument vector.
-  // If bound_error is not NULL, it may be set to reflect a bound error.
-  virtual RawAbstractTypeArguments* InstantiateFrom(
-      const AbstractTypeArguments& instantiator_type_arguments,
-      Error* bound_error,
-      GrowableObjectArray* trail = NULL) const;
-
-  // Do not clone InstantiatedTypeArguments or null vectors, since they are
-  // considered finalized.
-  virtual RawAbstractTypeArguments* CloneUnfinalized() const {
-    return this->raw();
+  intptr_t Length() const;
+  RawAbstractType* TypeAt(intptr_t index) const;
+  static intptr_t type_at_offset(intptr_t index) {
+    return OFFSET_OF(RawTypeArguments, types_) + index * kWordSize;
   }
-
-  // Null vectors are canonical.
-  virtual RawAbstractTypeArguments* Canonicalize(
-      GrowableObjectArray* trail = NULL) const {
-    return this->raw();
-  }
+  void SetTypeAt(intptr_t index, const AbstractType& value) const;
 
   // The name of this type argument vector, e.g. "<T, dynamic, List<T>, Smi>".
-  virtual RawString* Name() const {
+  RawString* Name() const {
     return SubvectorName(0, Length(), kInternalName);
   }
 
   // The name of this type argument vector, e.g. "<T, dynamic, List<T>, int>".
   // Names of internal classes are mapped to their public interfaces.
-  virtual RawString* UserVisibleName() const {
+  RawString* UserVisibleName() const {
     return SubvectorName(0, Length(), kUserVisibleName);
   }
 
@@ -1281,7 +1256,7 @@
 
   // Check the subtype relationship, considering only a subvector of length
   // 'len' starting at 'from_index'.
-  bool IsSubtypeOf(const AbstractTypeArguments& other,
+  bool IsSubtypeOf(const TypeArguments& other,
                    intptr_t from_index,
                    intptr_t len,
                    Error* bound_error) const {
@@ -1290,7 +1265,7 @@
 
   // Check the 'more specific' relationship, considering only a subvector of
   // length 'len' starting at 'from_index'.
-  bool IsMoreSpecificThan(const AbstractTypeArguments& other,
+  bool IsMoreSpecificThan(const TypeArguments& other,
                           intptr_t from_index,
                           intptr_t len,
                           Error* bound_error) const {
@@ -1298,82 +1273,49 @@
   }
 
   // Check if the vectors are equal.
-  bool Equals(const AbstractTypeArguments& other) const {
+  bool Equals(const TypeArguments& other) const {
     return IsEquivalent(other);
   }
 
-  bool IsEquivalent(const AbstractTypeArguments& other,
+  bool IsEquivalent(const TypeArguments& other,
                     GrowableObjectArray* trail = NULL) const;
 
-  // UNREACHABLEs as AbstractTypeArguments is an abstract class.
-  virtual intptr_t Length() const;
-  virtual RawAbstractType* TypeAt(intptr_t index) const;
-  virtual void SetTypeAt(intptr_t index, const AbstractType& value) const;
-  virtual bool IsResolved() const;
-  virtual bool IsInstantiated(GrowableObjectArray* trail = NULL) const;
-  virtual bool IsUninstantiatedIdentity() const;
-  virtual bool CanShareInstantiatorTypeArguments(
-      const Class& instantiator_class) const;
-  virtual bool IsBounded() const;
+  bool IsResolved() const;
+  bool IsInstantiated(GrowableObjectArray* trail = NULL) const;
+  bool IsUninstantiatedIdentity() const;
+  bool CanShareInstantiatorTypeArguments(const Class& instantiator_class) const;
 
-  virtual intptr_t Hash() const;
+  // Returns true if all types of this vector are finalized.
+  bool IsFinalized() const;
+  bool IsBounded() const;
 
- private:
-  // Check if the subvector of length 'len' starting at 'from_index' of this
-  // type argument vector consists solely of DynamicType.
-  // If raw_instantiated is true, consider each type parameter to be first
-  // instantiated from a vector of dynamic types.
-  bool IsDynamicTypes(bool raw_instantiated,
-                      intptr_t from_index,
-                      intptr_t len) const;
+  // Clone this type argument vector and clone all unfinalized type arguments.
+  // Finalized type arguments are shared.
+  RawTypeArguments* CloneUnfinalized() const;
 
-  // Check the subtype or 'more specific' relationship, considering only a
-  // subvector of length 'len' starting at 'from_index'.
-  bool TypeTest(TypeTestKind test_kind,
-                const AbstractTypeArguments& other,
-                intptr_t from_index,
-                intptr_t len,
-                Error* bound_error) const;
-
-  // Return the internal or public name of a subvector of this type argument
-  // vector, e.g. "<T, dynamic, List<T>, int>".
-  RawString* SubvectorName(intptr_t from_index,
-                           intptr_t len,
-                           NameVisibility name_visibility) const;
-
- protected:
-  HEAP_OBJECT_IMPLEMENTATION(AbstractTypeArguments, Object);
-  friend class AbstractType;
-  friend class Class;
-};
-
-
-// A TypeArguments is an array of AbstractType.
-class TypeArguments : public AbstractTypeArguments {
- public:
-  virtual intptr_t Length() const;
-  virtual RawAbstractType* TypeAt(intptr_t index) const;
-  static intptr_t type_at_offset(intptr_t index) {
-    return OFFSET_OF(RawTypeArguments, types_) + index * kWordSize;
-  }
-  virtual void SetTypeAt(intptr_t index, const AbstractType& value) const;
-  virtual bool IsResolved() const;
-  virtual bool IsInstantiated(GrowableObjectArray* trail = NULL) const;
-  virtual bool IsUninstantiatedIdentity() const;
-  virtual bool CanShareInstantiatorTypeArguments(
-      const Class& instantiator_class) const;
-  virtual bool IsFinalized() const;
-  virtual bool IsBounded() const;
-  virtual RawAbstractTypeArguments* CloneUnfinalized() const;
   // Canonicalize only if instantiated, otherwise returns 'this'.
-  virtual RawAbstractTypeArguments* Canonicalize(
-      GrowableObjectArray* trail = NULL) const;
+  RawTypeArguments* Canonicalize(GrowableObjectArray* trail = NULL) const;
 
-  virtual RawAbstractTypeArguments* InstantiateFrom(
-      const AbstractTypeArguments& instantiator_type_arguments,
+  // Return 'this' if this type argument vector is instantiated, i.e. if it does
+  // not refer to type parameters. Otherwise, return a new type argument vector
+  // where each reference to a type parameter is replaced with the corresponding
+  // type of the instantiator type argument vector.
+  // If bound_error is not NULL, it may be set to reflect a bound error.
+  RawTypeArguments* InstantiateFrom(
+      const TypeArguments& instantiator_type_arguments,
       Error* bound_error,
       GrowableObjectArray* trail = NULL) const;
 
+  // Runtime instantiation with canonicalization. Not to be used during type
+  // finalization at compile time.
+  RawTypeArguments* InstantiateAndCanonicalizeFrom(
+      const TypeArguments& instantiator_type_arguments,
+      Error* bound_error) const;
+
+  static intptr_t instantiations_offset() {
+    return OFFSET_OF(RawTypeArguments, instantiations_);
+  }
+
   static const intptr_t kBytesPerElement = kWordSize;
   static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
 
@@ -1387,90 +1329,49 @@
   }
 
   static intptr_t InstanceSize(intptr_t len) {
-    // Ensure that the types_ is not adding to the object length.
-    ASSERT(sizeof(RawTypeArguments) == (sizeof(RawObject) + (1 * kWordSize)));
+    // Ensure that the types_ is not adding to the object size, which includes
+    // 2 fields: instantiations_ and length_.
+    ASSERT(sizeof(RawTypeArguments) == (sizeof(RawObject) + (2 * kWordSize)));
     ASSERT(0 <= len && len <= kMaxElements);
     return RoundedAllocationSize(
         sizeof(RawTypeArguments) + (len * kBytesPerElement));
   }
 
+  intptr_t Hash() const;
+
   static RawTypeArguments* New(intptr_t len, Heap::Space space = Heap::kOld);
 
  private:
+  // Check if the subvector of length 'len' starting at 'from_index' of this
+  // type argument vector consists solely of DynamicType.
+  // If raw_instantiated is true, consider each type parameter to be first
+  // instantiated from a vector of dynamic types.
+  bool IsDynamicTypes(bool raw_instantiated,
+                      intptr_t from_index,
+                      intptr_t len) const;
+
+  // Check the subtype or 'more specific' relationship, considering only a
+  // subvector of length 'len' starting at 'from_index'.
+  bool TypeTest(TypeTestKind test_kind,
+                const TypeArguments& other,
+                intptr_t from_index,
+                intptr_t len,
+                Error* bound_error) const;
+
+  // Return the internal or public name of a subvector of this type argument
+  // vector, e.g. "<T, dynamic, List<T>, int>".
+  RawString* SubvectorName(intptr_t from_index,
+                           intptr_t len,
+                           NameVisibility name_visibility) const;
+
+  RawArray* instantiations() const;
+  void set_instantiations(const Array& value) const;
+  void set_type_at(intptr_t index, const AbstractType& value) const;
   RawAbstractType** TypeAddr(intptr_t index) const;
   void SetLength(intptr_t value) const;
 
-  FINAL_HEAP_OBJECT_IMPLEMENTATION(TypeArguments, AbstractTypeArguments);
-  friend class Class;
-};
-
-
-// An instance of InstantiatedTypeArguments is never encountered at compile
-// time, but only at run time, when type parameters can be matched to actual
-// types.
-// An instance of InstantiatedTypeArguments consists of a pair of
-// AbstractTypeArguments objects. The first type argument vector is
-// uninstantiated, because it contains type expressions referring to at least
-// one TypeParameter object, i.e. to a type that is not known at compile time.
-// The second type argument vector is the instantiator, because each type
-// parameter with index i in the first vector can be substituted (or
-// "instantiated") with the type at index i in the second type argument vector.
-class InstantiatedTypeArguments : public AbstractTypeArguments {
- public:
-  virtual intptr_t Length() const;
-  virtual RawAbstractType* TypeAt(intptr_t index) const;
-  virtual void SetTypeAt(intptr_t index, const AbstractType& value) const;
-  virtual bool IsResolved() const { return true; }
-  virtual bool IsInstantiated(GrowableObjectArray* trail = NULL) const {
-    return true;
-  }
-  virtual bool IsUninstantiatedIdentity() const {
-    UNREACHABLE();
-    return false;
-  }
-  virtual bool CanShareInstantiatorTypeArguments(
-      const Class& instantiator_class) const {
-    UNREACHABLE();
-    return false;
-  }
-  virtual bool IsBounded() const { return false; }  // Bounds were checked.
-  virtual RawAbstractTypeArguments* Canonicalize(
-      GrowableObjectArray* trail = NULL) const;
-
-  RawAbstractTypeArguments* uninstantiated_type_arguments() const {
-    return raw_ptr()->uninstantiated_type_arguments_;
-  }
-  static intptr_t uninstantiated_type_arguments_offset() {
-    return OFFSET_OF(RawInstantiatedTypeArguments,
-                     uninstantiated_type_arguments_);
-  }
-
-  RawAbstractTypeArguments* instantiator_type_arguments() const {
-    return raw_ptr()->instantiator_type_arguments_;
-  }
-  static intptr_t instantiator_type_arguments_offset() {
-    return OFFSET_OF(RawInstantiatedTypeArguments,
-                     instantiator_type_arguments_);
-  }
-
-  static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(RawInstantiatedTypeArguments));
-  }
-
-  static RawInstantiatedTypeArguments* New(
-      const AbstractTypeArguments& uninstantiated_type_arguments,
-      const AbstractTypeArguments& instantiator_type_arguments);
-
- private:
-  void set_uninstantiated_type_arguments(
-      const AbstractTypeArguments& value) const;
-  void set_instantiator_type_arguments(
-      const AbstractTypeArguments& value) const;
-
-  static RawInstantiatedTypeArguments* New();
-
-  FINAL_HEAP_OBJECT_IMPLEMENTATION(InstantiatedTypeArguments,
-                                   AbstractTypeArguments);
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(TypeArguments, Object);
+  friend class AbstractType;
   friend class Class;
 };
 
@@ -1531,9 +1432,8 @@
   // signature of the given function, where all generic types (e.g. '<T, R>' in
   // 'C<T, R>(T, {b: B, c: C}) => R') are instantiated using the given
   // instantiator type argument vector of a C instance (e.g. '<A, D>').
-  RawString* InstantiatedSignatureFrom(
-      const AbstractTypeArguments& instantiator,
-      NameVisibility name_visibility) const {
+  RawString* InstantiatedSignatureFrom(const TypeArguments& instantiator,
+                                       NameVisibility name_visibility) const {
     const bool instantiate = true;
     return BuildSignature(instantiate, name_visibility, instantiator);
   }
@@ -1823,6 +1723,11 @@
   }
   void set_is_redirecting(bool value) const;
 
+  bool allows_hoisting_check_class() const {
+    return AllowsHoistingCheckClassBit::decode(raw_ptr()->kind_tag_);
+  }
+  void set_allows_hoisting_check_class(bool value) const;
+
   bool HasOptimizedCode() const;
 
   // Returns true if the argument counts are valid for calling this function.
@@ -1852,9 +1757,9 @@
 
   // Returns true if the type of this function is a subtype of the type of
   // the other function.
-  bool IsSubtypeOf(const AbstractTypeArguments& type_arguments,
+  bool IsSubtypeOf(const TypeArguments& type_arguments,
                    const Function& other,
-                   const AbstractTypeArguments& other_type_arguments,
+                   const TypeArguments& other_type_arguments,
                    Error* bound_error) const {
     return TypeTest(kIsSubtypeOf,
                     type_arguments,
@@ -1865,9 +1770,9 @@
 
   // Returns true if the type of this function is more specific than the type of
   // the other function.
-  bool IsMoreSpecificThan(const AbstractTypeArguments& type_arguments,
+  bool IsMoreSpecificThan(const TypeArguments& type_arguments,
                           const Function& other,
-                          const AbstractTypeArguments& other_type_arguments,
+                          const TypeArguments& other_type_arguments,
                           Error* bound_error) const {
     return TypeTest(kIsMoreSpecificThan,
                     type_arguments,
@@ -1993,6 +1898,7 @@
     kNativeBit = 12,
     kRedirectingBit = 13,
     kExternalBit = 14,
+    kAllowsHoistingCheckClassBit = 15,
   };
   class KindBits :
     public BitField<RawFunction::Kind, kKindTagBit, kKindTagSize> {};  // NOLINT
@@ -2007,6 +1913,8 @@
   class NativeBit : public BitField<bool, kNativeBit, 1> {};
   class ExternalBit : public BitField<bool, kExternalBit, 1> {};
   class RedirectingBit : public BitField<bool, kRedirectingBit, 1> {};
+  class AllowsHoistingCheckClassBit :
+      public BitField<bool, kAllowsHoistingCheckClassBit, 1> {};  // NOLINT
 
   void set_name(const String& value) const;
   void set_kind(RawFunction::Kind value) const;
@@ -2031,17 +1939,17 @@
 
   void BuildSignatureParameters(bool instantiate,
                                 NameVisibility name_visibility,
-                                const AbstractTypeArguments& instantiator,
+                                const TypeArguments& instantiator,
                                 const GrowableObjectArray& pieces) const;
   RawString* BuildSignature(bool instantiate,
                             NameVisibility name_visibility,
-                            const AbstractTypeArguments& instantiator) const;
+                            const TypeArguments& instantiator) const;
 
   // Check the subtype or 'more specific' relationship.
   bool TypeTest(TypeTestKind test_kind,
-                const AbstractTypeArguments& type_arguments,
+                const TypeArguments& type_arguments,
                 const Function& other,
-                const AbstractTypeArguments& other_type_arguments,
+                const TypeArguments& other_type_arguments,
                 Error* bound_error) const;
 
   // Checks the type of the formal parameter at the given position for
@@ -2050,9 +1958,9 @@
   bool TestParameterType(TypeTestKind test_kind,
                          intptr_t parameter_position,
                          intptr_t other_parameter_position,
-                         const AbstractTypeArguments& type_arguments,
+                         const TypeArguments& type_arguments,
                          const Function& other,
-                         const AbstractTypeArguments& other_type_arguments,
+                         const TypeArguments& other_type_arguments,
                          Error* bound_error) const;
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Function, Object);
@@ -2367,6 +2275,7 @@
   void SetStream(const ExternalTypedData& stream) const;
 
   RawString* GenerateSource() const;
+  RawString* GenerateSource(intptr_t start, intptr_t end) const;
   intptr_t ComputeSourcePosition(intptr_t tok_pos) const;
 
   RawString* PrivateKey() const;
@@ -2680,7 +2589,6 @@
 
   static RawLibrary* LookupLibrary(const String& url);
   static RawLibrary* GetLibrary(intptr_t index);
-  static bool IsKeyUsed(intptr_t key);
 
   static void InitCoreLibrary(Isolate* isolate);
   static void InitNativeWrappersLibrary(Isolate* isolate);
@@ -2715,6 +2623,13 @@
                                   const char* class_name,
                                   const char* function_name);
 
+  // Character used to indicate a private identifier.
+  static const char kPrivateIdentifierStart  = '_';
+
+  // Character used to separate private identifiers from
+  // the library-specific key.
+  static const char kPrivateKeySeparator = '@';
+
  private:
   static const int kInitialImportsCapacity = 4;
   static const int kImportsCapacityIncrement = 8;
@@ -2746,6 +2661,9 @@
                                       bool import_core_lib);
   RawObject* LookupEntry(const String& name, intptr_t *index) const;
 
+  static bool IsKeyUsed(intptr_t key);
+  void AllocatePrivateKey() const;
+
   RawString* MakeMetadataName(const Object& obj) const;
   RawField* GetMetadataField(const String& metaname) const;
   void AddMetadata(const Class& cls,
@@ -3834,13 +3752,13 @@
 
   intptr_t NumberOfChecks() const;
   void AddCheck(intptr_t class_id,
-                const AbstractTypeArguments& instance_type_arguments,
-                const AbstractTypeArguments& instantiator_type_arguments,
+                const TypeArguments& instance_type_arguments,
+                const TypeArguments& instantiator_type_arguments,
                 const Bool& test_result) const;
   void GetCheck(intptr_t ix,
                 intptr_t* class_id,
-                AbstractTypeArguments* instance_type_arguments,
-                AbstractTypeArguments* instantiator_type_arguments,
+                TypeArguments* instance_type_arguments,
+                TypeArguments* instantiator_type_arguments,
                 Bool* test_result) const;
 
   static RawSubtypeTestCache* New();
@@ -4043,12 +3961,12 @@
 
   RawType* GetType() const;
 
-  virtual RawAbstractTypeArguments* GetTypeArguments() const;
-  virtual void SetTypeArguments(const AbstractTypeArguments& value) const;
+  virtual RawTypeArguments* GetTypeArguments() const;
+  virtual void SetTypeArguments(const TypeArguments& value) const;
 
   // Check if the type of this instance is a subtype of the given type.
   bool IsInstanceOf(const AbstractType& type,
-                    const AbstractTypeArguments& type_instantiator,
+                    const TypeArguments& type_instantiator,
                     Error* bound_error) const;
 
   // Check whether this instance is identical to the argument according to the
@@ -4135,7 +4053,7 @@
   virtual bool HasResolvedTypeClass() const;
   virtual RawClass* type_class() const;
   virtual RawUnresolvedClass* unresolved_class() const;
-  virtual RawAbstractTypeArguments* arguments() const;
+  virtual RawTypeArguments* arguments() const;
   virtual intptr_t token_pos() const;
   virtual bool IsInstantiated(GrowableObjectArray* trail = NULL) const;
   virtual bool Equals(const Instance& other) const {
@@ -4148,7 +4066,7 @@
   // Return a new type, or return 'this' if it is already instantiated.
   // If bound_error is not NULL, it may be set to reflect a bound error.
   virtual RawAbstractType* InstantiateFrom(
-      const AbstractTypeArguments& instantiator_type_arguments,
+      const TypeArguments& instantiator_type_arguments,
       Error* bound_error,
       GrowableObjectArray* trail = NULL) const;
 
@@ -4247,9 +4165,9 @@
 
  protected:
   HEAP_OBJECT_IMPLEMENTATION(AbstractType, Instance);
-  friend class AbstractTypeArguments;
   friend class Class;
   friend class Function;
+  friend class TypeArguments;
 };
 
 
@@ -4286,14 +4204,14 @@
   virtual RawClass* type_class() const;
   void set_type_class(const Object& value) const;
   virtual RawUnresolvedClass* unresolved_class() const;
-  virtual RawAbstractTypeArguments* arguments() const;
-  void set_arguments(const AbstractTypeArguments& value) const;
+  virtual RawTypeArguments* arguments() const;
+  void set_arguments(const TypeArguments& value) const;
   virtual intptr_t token_pos() const { return raw_ptr()->token_pos_; }
   virtual bool IsInstantiated(GrowableObjectArray* trail = NULL) const;
   virtual bool IsEquivalent(const Instance& other,
                             GrowableObjectArray* trail = NULL) const;
   virtual RawAbstractType* InstantiateFrom(
-      const AbstractTypeArguments& instantiator_type_arguments,
+      const TypeArguments& instantiator_type_arguments,
       Error* malformed_error,
       GrowableObjectArray* trail = NULL) const;
   virtual RawAbstractType* CloneUnfinalized() const;
@@ -4355,7 +4273,7 @@
   static RawType* NewNonParameterizedType(const Class& type_class);
 
   static RawType* New(const Object& clazz,
-                      const AbstractTypeArguments& arguments,
+                      const TypeArguments& arguments,
                       intptr_t token_pos,
                       Heap::Space space = Heap::kOld);
 
@@ -4367,6 +4285,7 @@
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Type, AbstractType);
   friend class Class;
+  friend class TypeArguments;
 };
 
 
@@ -4397,7 +4316,7 @@
   virtual RawClass* type_class() const {
     return AbstractType::Handle(type()).type_class();
   }
-  virtual RawAbstractTypeArguments* arguments() const {
+  virtual RawTypeArguments* arguments() const {
     return AbstractType::Handle(type()).arguments();
   }
   virtual intptr_t token_pos() const {
@@ -4407,7 +4326,7 @@
   virtual bool IsEquivalent(const Instance& other,
                             GrowableObjectArray* trail = NULL) const;
   virtual RawAbstractType* InstantiateFrom(
-      const AbstractTypeArguments& instantiator_type_arguments,
+      const TypeArguments& instantiator_type_arguments,
       Error* bound_error,
       GrowableObjectArray* trail = NULL) const;
   virtual RawAbstractType* Canonicalize(
@@ -4495,7 +4414,7 @@
   virtual bool IsEquivalent(const Instance& other,
                             GrowableObjectArray* trail = NULL) const;
   virtual RawAbstractType* InstantiateFrom(
-      const AbstractTypeArguments& instantiator_type_arguments,
+      const TypeArguments& instantiator_type_arguments,
       Error* bound_error,
       GrowableObjectArray* trail = NULL) const;
   virtual RawAbstractType* CloneUnfinalized() const;
@@ -4557,7 +4476,7 @@
   virtual RawUnresolvedClass* unresolved_class() const {
     return AbstractType::Handle(type()).unresolved_class();
   }
-  virtual RawAbstractTypeArguments* arguments() const {
+  virtual RawTypeArguments* arguments() const {
     return AbstractType::Handle(type()).arguments();
   }
   RawAbstractType* type() const { return raw_ptr()->type_; }
@@ -4578,7 +4497,7 @@
   virtual bool IsEquivalent(const Instance& other,
                             GrowableObjectArray* trail = NULL) const;
   virtual RawAbstractType* InstantiateFrom(
-      const AbstractTypeArguments& instantiator_type_arguments,
+      const TypeArguments& instantiator_type_arguments,
       Error* bound_error,
       GrowableObjectArray* trail = NULL) const;
   virtual RawAbstractType* CloneUnfinalized() const;
@@ -5665,10 +5584,10 @@
     return raw()->GetClassId() == kImmutableArrayCid;
   }
 
-  virtual RawAbstractTypeArguments* GetTypeArguments() const {
+  virtual RawTypeArguments* GetTypeArguments() const {
     return raw_ptr()->type_arguments_;
   }
-  virtual void SetTypeArguments(const AbstractTypeArguments& value) const {
+  virtual void SetTypeArguments(const TypeArguments& value) const {
     // An Array is raw or takes one type argument. However, its type argument
     // vector may be longer than 1 due to a type optimization reusing the type
     // argument vector of the instantiator.
@@ -5823,10 +5742,10 @@
   void Grow(intptr_t new_capacity, Heap::Space space = Heap::kNew) const;
   RawObject* RemoveLast() const;
 
-  virtual RawAbstractTypeArguments* GetTypeArguments() const {
+  virtual RawTypeArguments* GetTypeArguments() const {
     return raw_ptr()->type_arguments_;
   }
-  virtual void SetTypeArguments(const AbstractTypeArguments& value) const {
+  virtual void SetTypeArguments(const TypeArguments& value) const {
     // A GrowableObjectArray is raw or takes one type argument. However, its
     // type argument vector may be longer than 1 due to a type optimization
     // reusing the type argument vector of the instantiator.
@@ -6321,11 +6240,11 @@
     return static_cast<intptr_t>(kContextOffset * kWordSize);
   }
 
-  static RawAbstractTypeArguments* GetTypeArguments(const Instance& closure) {
+  static RawTypeArguments* GetTypeArguments(const Instance& closure) {
     return *TypeArgumentsAddr(closure);
   }
   static void SetTypeArguments(const Instance& closure,
-                               const AbstractTypeArguments& value) {
+                               const TypeArguments& value) {
     closure.StorePointer(TypeArgumentsAddr(closure), value.raw());
   }
   static intptr_t type_arguments_offset() {
@@ -6350,9 +6269,9 @@
   static const int kContextOffset = 3;
   static const int kNumFields = 3;
 
-  static RawAbstractTypeArguments** TypeArgumentsAddr(const Instance& obj) {
+  static RawTypeArguments** TypeArgumentsAddr(const Instance& obj) {
     ASSERT(obj.IsClosure());
-    return reinterpret_cast<RawAbstractTypeArguments**>(
+    return reinterpret_cast<RawTypeArguments**>(
         reinterpret_cast<intptr_t>(obj.raw_ptr()) + type_arguments_offset());
   }
   static RawFunction** FunctionAddr(const Instance& obj) {
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index ced3d4f..49b9444 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -17,6 +17,8 @@
 
 namespace dart {
 
+DECLARE_FLAG(bool, write_protect_code);
+
 static RawLibrary* CreateDummyLibrary(const String& library_name) {
   return Library::New(library_name);
 }
@@ -2464,6 +2466,36 @@
 }
 
 
+// Test for immutability of generated instructions. The test crashes with a
+// segmentation fault when writing into it.
+TEST_CASE(CodeImmutability) {
+  extern void GenerateIncrement(Assembler* assembler);
+  Assembler _assembler_;
+  GenerateIncrement(&_assembler_);
+  Code& code = Code::Handle(Code::FinalizeCode(
+      *CreateFunction("Test_Code"), &_assembler_));
+  Instructions& instructions = Instructions::Handle(code.instructions());
+  uword entry_point = instructions.EntryPoint();
+  // Try writing into the generated code, expected to crash.
+  *(reinterpret_cast<char*>(entry_point) + 1) = 1;
+  intptr_t retval = 0;
+#if defined(USING_SIMULATOR)
+  retval = bit_copy<intptr_t, int64_t>(Simulator::Current()->Call(
+      static_cast<int32_t>(entry_point), 0, 0, 0, 0));
+#else
+  typedef intptr_t (*IncrementCode)();
+  retval = reinterpret_cast<IncrementCode>(entry_point)();
+#endif
+  EXPECT_EQ(3, retval);
+  EXPECT_EQ(instructions.raw(), Instructions::FromEntryPoint(entry_point));
+  if (!FLAG_write_protect_code) {
+    // Since this test is expected to crash, crash if write protection of code
+    // is switched off.
+    OS::DebugBreak();
+  }
+}
+
+
 // Test for Embedded String object in the instructions.
 TEST_CASE(EmbedStringInCode) {
   extern void GenerateEmbedStringInCode(Assembler* assembler, const char* str);
@@ -2747,8 +2779,8 @@
   cache.AddCheck(empty_class.id(), targ_0, targ_1, Bool::True());
   EXPECT_EQ(1, cache.NumberOfChecks());
   intptr_t test_class_id = -1;
-  AbstractTypeArguments& test_targ_0 = AbstractTypeArguments::Handle();
-  AbstractTypeArguments& test_targ_1 = AbstractTypeArguments::Handle();
+  TypeArguments& test_targ_0 = TypeArguments::Handle();
+  TypeArguments& test_targ_1 = TypeArguments::Handle();
   Bool& test_result = Bool::Handle();
   cache.GetCheck(0, &test_class_id, &test_targ_0, &test_targ_1, &test_result);
   EXPECT_EQ(empty_class.id(), test_class_id);
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc
index d5fc8ec..3081414 100644
--- a/runtime/vm/pages.cc
+++ b/runtime/vm/pages.cc
@@ -31,6 +31,7 @@
             "Emit a log message when pointers to unused code are dropped.");
 DEFINE_FLAG(bool, always_drop_code, false,
             "Always try to drop code if the function's usage counter is >= 0");
+DECLARE_FLAG(bool, write_protect_code);
 
 HeapPage* HeapPage::Initialize(VirtualMemory* memory, PageType type) {
   ASSERT(memory->size() > VirtualMemory::PageSize());
@@ -109,13 +110,10 @@
       prot = VirtualMemory::kReadOnly;
     }
   } else {
-    if (executable_) {
-      prot = VirtualMemory::kReadWriteExecute;
-    } else {
-      prot = VirtualMemory::kReadWrite;
-    }
+    prot = VirtualMemory::kReadWrite;
   }
-  memory_->Protect(prot);
+  bool status = memory_->Protect(prot);
+  ASSERT(status);
 }
 
 
@@ -155,7 +153,15 @@
   if (pages_ == NULL) {
     pages_ = page;
   } else {
+    const bool is_protected = (pages_tail_->type() == HeapPage::kExecutable)
+        && FLAG_write_protect_code;
+    if (is_protected) {
+      pages_tail_->WriteProtect(false);
+    }
     pages_tail_->set_next(page);
+    if (is_protected) {
+      pages_tail_->WriteProtect(true);
+    }
   }
   pages_tail_ = page;
   capacity_in_words_ += kPageSizeInWords;
@@ -221,7 +227,9 @@
   ASSERT(Utils::IsAligned(size, kObjectAlignment));
   uword result = 0;
   if (size < kAllocatablePageSize) {
-    result = freelist_[type].TryAllocate(size);
+    const bool is_protected = (type == HeapPage::kExecutable)
+        && FLAG_write_protect_code;
+    result = freelist_[type].TryAllocate(size, is_protected);
     if ((result == 0) &&
         (page_space_controller_.CanGrowPageSpace(size) ||
          growth_policy == kForceGrowth) &&
@@ -447,6 +455,24 @@
 
   const int64_t start = OS::GetCurrentTimeMicros();
 
+  if (FLAG_write_protect_code) {
+    // Make code pages writable.
+    HeapPage* current_page = pages_;
+    while (current_page != NULL) {
+      if (current_page->type() == HeapPage::kExecutable) {
+        current_page->WriteProtect(false);
+      }
+      current_page = current_page->next();
+    }
+    current_page = large_pages_;
+    while (current_page != NULL) {
+      if (current_page->type() == HeapPage::kExecutable) {
+        current_page->WriteProtect(false);
+      }
+      current_page = current_page->next();
+    }
+  }
+
   // Mark all reachable old-gen objects.
   bool collect_code = FLAG_collect_code && ShouldCollectCode();
   GCMarker marker(heap_);
@@ -496,6 +522,24 @@
     page = next_page;
   }
 
+  if (FLAG_write_protect_code) {
+    // Make code pages read-only.
+    HeapPage* current_page = pages_;
+    while (current_page != NULL) {
+      if (current_page->type() == HeapPage::kExecutable) {
+        current_page->WriteProtect(true);
+      }
+      current_page = current_page->next();
+    }
+    current_page = large_pages_;
+    while (current_page != NULL) {
+      if (current_page->type() == HeapPage::kExecutable) {
+        current_page->WriteProtect(true);
+      }
+      current_page = current_page->next();
+    }
+  }
+
   // Record data and print if requested.
   intptr_t used_before_in_words = used_in_words_;
   used_in_words_ = used_in_words;
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index c376a74..67aaf47 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -2838,7 +2838,7 @@
     ASSERT(current_class().raw() == func.Owner());
     params.AddReceiver(ReceiverType(current_class()), func.token_pos());
   } else if (func.IsFactory()) {
-    // The first parameter of a factory is the AbstractTypeArguments vector of
+    // The first parameter of a factory is the TypeArguments vector of
     // the type of the instance to be allocated.
     params.AddFinalParameter(
         TokenPos(),
@@ -3106,7 +3106,7 @@
   const intptr_t formal_param_pos = TokenPos();
   method->params.Clear();
   // Static functions do not have a receiver.
-  // The first parameter of a factory is the AbstractTypeArguments vector of
+  // The first parameter of a factory is the TypeArguments vector of
   // the type of the instance to be allocated.
   if (!method->has_static || method->IsConstructor()) {
     method->params.AddReceiver(ReceiverType(current_class()), formal_param_pos);
@@ -4447,7 +4447,7 @@
 }
 
 
-RawAbstractTypeArguments* Parser::ParseTypeArguments(
+RawTypeArguments* Parser::ParseTypeArguments(
     ClassFinalizer::FinalizationKind finalization) {
   TRACE_PARSER("ParseTypeArguments");
   if (CurrentToken() == Token::kLT) {
@@ -5726,8 +5726,8 @@
   // Since the signature type is cached by the signature class, it may have
   // been finalized already.
   Type& signature_type = Type::Handle(signature_class.SignatureType());
-  AbstractTypeArguments& signature_type_arguments =
-      AbstractTypeArguments::Handle(signature_type.arguments());
+  TypeArguments& signature_type_arguments =
+      TypeArguments::Handle(signature_type.arguments());
 
   if (!signature_type.IsFinalized()) {
     signature_type ^= ClassFinalizer::FinalizeType(
@@ -5841,7 +5841,7 @@
   // of int, double, String, or bool, then preset the field with the value and
   // perform the type check (in checked mode only) at finalization time.
   if (type.IsTypeParameter() ||
-      (type.arguments() != AbstractTypeArguments::null())) {
+      (type.arguments() != TypeArguments::null())) {
     // Type parameters are always resolved eagerly by the parser and never
     // resolved later by the class finalizer. Therefore, we know here that if
     // 'type' is not a type parameter (an unresolved type will not get resolved
@@ -8702,7 +8702,7 @@
           }
           // A type parameter cannot be parameterized, so make the type
           // malformed if type arguments have previously been parsed.
-          if (!AbstractTypeArguments::Handle(type->arguments()).IsNull()) {
+          if (!TypeArguments::Handle(type->arguments()).IsNull()) {
             *type = ClassFinalizer::NewFinalizedMalformedType(
                 Error::Handle(),  // No previous error.
                 script_,
@@ -8745,8 +8745,8 @@
     }
   }
   // Resolve type arguments, if any.
-  const AbstractTypeArguments& arguments =
-      AbstractTypeArguments::Handle(type->arguments());
+  const TypeArguments& arguments = TypeArguments::Handle(type->arguments());
+      TypeArguments::Handle(type->arguments());
   if (!arguments.IsNull()) {
     const intptr_t num_arguments = arguments.Length();
     for (intptr_t i = 0; i < num_arguments; i++) {
@@ -8924,7 +8924,7 @@
 
 RawObject* Parser::EvaluateConstConstructorCall(
     const Class& type_class,
-    const AbstractTypeArguments& type_arguments,
+    const TypeArguments& type_arguments,
     const Function& constructor,
     ArgumentListNode* arguments) {
   // Factories have one extra argument: the type arguments.
@@ -8940,7 +8940,7 @@
         ErrorMsg("type must be constant in const constructor");
       }
       instance.SetTypeArguments(
-          AbstractTypeArguments::Handle(type_arguments.Canonicalize()));
+          TypeArguments::Handle(type_arguments.Canonicalize()));
     }
     arg_values.SetAt(0, instance);
     arg_values.SetAt(1, Smi::Handle(Smi::New(Function::kCtorPhaseAll)));
@@ -9334,7 +9334,7 @@
                                       *type_name.ident,
                                       type_name.ident_pos);
   }
-  AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle(
+  TypeArguments& type_arguments = TypeArguments::Handle(
       isolate(), ParseTypeArguments(finalization));
   if (finalization == ClassFinalizer::kIgnore) {
     return Type::DynamicType();
@@ -9353,11 +9353,12 @@
 
 void Parser::CheckConstructorCallTypeArguments(
     intptr_t pos, Function& constructor,
-    const AbstractTypeArguments& type_arguments) {
+    const TypeArguments& type_arguments) {
   if (!type_arguments.IsNull()) {
     const Class& constructor_class = Class::Handle(constructor.Owner());
     ASSERT(!constructor_class.IsNull());
     ASSERT(constructor_class.is_finalized());
+    ASSERT(type_arguments.IsCanonical());
     // Do not report the expected vs. actual number of type arguments, because
     // the type argument vector is flattened and raw types are allowed.
     if (type_arguments.Length() != constructor_class.NumTypeArguments()) {
@@ -9373,7 +9374,7 @@
 // as one token of type Token::kINDEX.
 AstNode* Parser::ParseListLiteral(intptr_t type_pos,
                                   bool is_const,
-                                  const AbstractTypeArguments& type_arguments) {
+                                  const TypeArguments& type_arguments) {
   TRACE_PARSER("ParseListLiteral");
   ASSERT(type_pos >= 0);
   ASSERT(CurrentToken() == Token::kLBRACK || CurrentToken() == Token::kINDEX);
@@ -9382,8 +9383,8 @@
   ConsumeToken();
 
   AbstractType& element_type = Type::ZoneHandle(Type::DynamicType());
-  AbstractTypeArguments& list_type_arguments =
-      AbstractTypeArguments::ZoneHandle(type_arguments.raw());
+  TypeArguments& list_type_arguments =
+      TypeArguments::ZoneHandle(type_arguments.raw());
   // If no type argument vector is provided, leave it as null, which is
   // equivalent to using dynamic as the type argument for the element type.
   if (!list_type_arguments.IsNull()) {
@@ -9394,7 +9395,7 @@
       ASSERT(!element_type.IsMalformed());  // Would be mapped to dynamic.
       ASSERT(!element_type.IsMalbounded());  // No declared bound in List.
       if (element_type.IsDynamicType()) {
-        list_type_arguments = AbstractTypeArguments::null();
+        list_type_arguments = TypeArguments::null();
       } else if (is_const && !element_type.IsInstantiated()) {
         ErrorMsg(type_pos,
                  "the type argument of a constant list literal cannot include "
@@ -9407,7 +9408,7 @@
                  "the element type");
       }
       // Ignore type arguments.
-      list_type_arguments = AbstractTypeArguments::null();
+      list_type_arguments = TypeArguments::null();
     }
   }
   ASSERT(list_type_arguments.IsNull() || (list_type_arguments.Length() == 1));
@@ -9449,7 +9450,7 @@
     Array& const_list =
         Array::ZoneHandle(Array::New(element_list.length(), Heap::kOld));
     const_list.SetTypeArguments(
-        AbstractTypeArguments::Handle(list_type_arguments.Canonicalize()));
+        TypeArguments::Handle(list_type_arguments.Canonicalize()));
     Error& malformed_error = Error::Handle();
     for (int i = 0; i < element_list.length(); i++) {
       AstNode* elem = element_list[i];
@@ -9492,8 +9493,8 @@
       // Make sure that the instantiator is captured.
       CaptureInstantiator();
     }
-    AbstractTypeArguments& factory_type_args =
-        AbstractTypeArguments::ZoneHandle(list_type_arguments.raw());
+    TypeArguments& factory_type_args =
+        TypeArguments::ZoneHandle(list_type_arguments.raw());
     // If the factory class extends other parameterized classes, adjust the
     // type argument vector.
     if (!factory_type_args.IsNull() && (factory_class.NumTypeArguments() > 1)) {
@@ -9527,7 +9528,7 @@
 
 ConstructorCallNode* Parser::CreateConstructorCallNode(
     intptr_t token_pos,
-    const AbstractTypeArguments& type_arguments,
+    const TypeArguments& type_arguments,
     const Function& constructor,
     ArgumentListNode* arguments) {
   if (!type_arguments.IsNull() && !type_arguments.IsInstantiated()) {
@@ -9567,7 +9568,7 @@
 
 AstNode* Parser::ParseMapLiteral(intptr_t type_pos,
                                  bool is_const,
-                                 const AbstractTypeArguments& type_arguments) {
+                                 const TypeArguments& type_arguments) {
   TRACE_PARSER("ParseMapLiteral");
   ASSERT(type_pos >= 0);
   ASSERT(CurrentToken() == Token::kLBRACE);
@@ -9576,8 +9577,8 @@
 
   AbstractType& key_type = Type::ZoneHandle(Type::DynamicType());
   AbstractType& value_type = Type::ZoneHandle(Type::DynamicType());
-  AbstractTypeArguments& map_type_arguments =
-      AbstractTypeArguments::ZoneHandle(type_arguments.raw());
+  TypeArguments& map_type_arguments =
+      TypeArguments::ZoneHandle(type_arguments.raw());
   // If no type argument vector is provided, leave it as null, which is
   // equivalent to using dynamic as the type argument for the both key and value
   // types.
@@ -9592,7 +9593,7 @@
       // No declared bounds in Map.
       ASSERT(!key_type.IsMalbounded() && !value_type.IsMalbounded());
       if (key_type.IsDynamicType() && value_type.IsDynamicType()) {
-        map_type_arguments = AbstractTypeArguments::null();
+        map_type_arguments = TypeArguments::null();
       } else if (is_const && !type_arguments.IsInstantiated()) {
         ErrorMsg(type_pos,
                  "the type arguments of a constant map literal cannot include "
@@ -9605,7 +9606,7 @@
                  "the key type and the value type");
       }
       // Ignore type arguments.
-      map_type_arguments = AbstractTypeArguments::null();
+      map_type_arguments = TypeArguments::null();
     }
   }
   ASSERT(map_type_arguments.IsNull() || (map_type_arguments.Length() == 2));
@@ -9688,7 +9689,7 @@
             (!arg->AsLiteralNode()->literal().IsNull() &&
              !arg->AsLiteralNode()->literal().IsInstanceOf(
                  arg_type,
-                 Object::null_abstract_type_arguments(),
+                 Object::null_type_arguments(),
                  &malformed_error))) {
           // If the failure is due to a malformed type error, display it.
           if (!malformed_error.IsNull()) {
@@ -9750,8 +9751,8 @@
       // Make sure that the instantiator is captured.
       CaptureInstantiator();
     }
-    AbstractTypeArguments& factory_type_args =
-        AbstractTypeArguments::ZoneHandle(map_type_arguments.raw());
+    TypeArguments& factory_type_args =
+        TypeArguments::ZoneHandle(map_type_arguments.raw());
     // If the factory class extends other parameterized classes, adjust the
     // type argument vector.
     if (!factory_type_args.IsNull() && (factory_class.NumTypeArguments() > 2)) {
@@ -9790,7 +9791,7 @@
     ConsumeToken();
   }
   const intptr_t type_pos = TokenPos();
-  AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle(
+  TypeArguments& type_arguments = TypeArguments::Handle(
       ParseTypeArguments(ClassFinalizer::kCanonicalize));
   // Malformed type arguments are mapped to dynamic, so we will not encounter
   // them here.
@@ -9923,8 +9924,8 @@
   // Resolve the type and optional identifier to a constructor or factory.
   Class& type_class = Class::Handle(type.type_class());
   String& type_class_name = String::Handle(type_class.Name());
-  AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::ZoneHandle(type.arguments());
+  TypeArguments& type_arguments =
+      TypeArguments::ZoneHandle(type.arguments());
 
   // A constructor has an implicit 'this' parameter (instance to construct)
   // and a factory has an implicit 'this' parameter (type_arguments).
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 1bb7ec4..6595632 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -284,10 +284,9 @@
   void SkipQualIdent();
   void SkipFunctionPreamble();
 
-  void CheckConstructorCallTypeArguments(
-    intptr_t pos,
-    Function& constructor,
-    const AbstractTypeArguments& type_arguments);
+  void CheckConstructorCallTypeArguments(intptr_t pos,
+                                         Function& constructor,
+                                         const TypeArguments& type_arguments);
 
   // A null script means no source and a negative token_pos means no position.
   static RawString* FormatMessage(const Script& script,
@@ -320,11 +319,10 @@
   const Instance& EvaluateConstExpr(intptr_t expr_pos, AstNode* expr);
   AstNode* RunStaticFieldInitializer(const Field& field,
                                      intptr_t field_ref_pos);
-  RawObject* EvaluateConstConstructorCall(
-      const Class& type_class,
-      const AbstractTypeArguments& type_arguments,
-      const Function& constructor,
-      ArgumentListNode* arguments);
+  RawObject* EvaluateConstConstructorCall(const Class& type_class,
+                                          const TypeArguments& type_arguments,
+                                          const Function& constructor,
+                                          ArgumentListNode* arguments);
   AstNode* FoldConstExpr(intptr_t expr_pos, AstNode* expr);
 
   // Support for parsing of scripts.
@@ -360,7 +358,7 @@
                             AbstractType* type);
   RawAbstractType* ParseType(ClassFinalizer::FinalizationKind finalization);
   void ParseTypeParameters(const Class& cls);
-  RawAbstractTypeArguments* ParseTypeArguments(
+  RawTypeArguments* ParseTypeArguments(
       ClassFinalizer::FinalizationKind finalization);
   void ParseQualIdent(QualIdent* qual_ident);
   void ParseMethodOrConstructor(ClassDesc* members, MemberDesc* method);
@@ -552,10 +550,10 @@
   AstNode* ParseSymbolLiteral();
   AstNode* ParseListLiteral(intptr_t type_pos,
                             bool is_const,
-                            const AbstractTypeArguments& type_arguments);
+                            const TypeArguments& type_arguments);
   AstNode* ParseMapLiteral(intptr_t type_pos,
                            bool is_const,
-                           const AbstractTypeArguments& type_arguments);
+                           const TypeArguments& type_arguments);
   AstNode* ParseNewOperator(Token::Kind op_kind);
 
   // An implicit argument, if non-null, is prepended to the returned list.
@@ -644,7 +642,7 @@
 
   ConstructorCallNode* CreateConstructorCallNode(
       intptr_t token_pos,
-      const AbstractTypeArguments& type_arguments,
+      const TypeArguments& type_arguments,
       const Function& constructor,
       ArgumentListNode* arguments);
 
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 8b39ec9..6c6b19d 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -50,6 +50,7 @@
   } else if (FLAG_profile_depth > kMaximumDepth) {
     FLAG_profile_depth = kMaximumDepth;
   }
+  // We must always initialize the Sample, even when the profiler is disabled.
   Sample::InitOnce();
   if (!FLAG_profile) {
     return;
@@ -57,8 +58,8 @@
   ASSERT(!initialized_);
   sample_buffer_ = new SampleBuffer();
   NativeSymbolResolver::InitOnce();
-  ThreadInterrupter::InitOnce();
   ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period);
+  ThreadInterrupter::Startup();
   initialized_ = true;
 }
 
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index f9df8e5..631472f 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -329,14 +329,6 @@
 }
 
 
-intptr_t RawAbstractTypeArguments::VisitAbstractTypeArgumentsPointers(
-    RawAbstractTypeArguments* raw_obj, ObjectPointerVisitor* visitor) {
-  // RawAbstractTypeArguments is an abstract class.
-  UNREACHABLE();
-  return 0;
-}
-
-
 intptr_t RawTypeArguments::VisitTypeArgumentsPointers(
     RawTypeArguments* raw_obj, ObjectPointerVisitor* visitor) {
   intptr_t length = Smi::Value(raw_obj->ptr()->length_);
@@ -345,13 +337,6 @@
 }
 
 
-intptr_t RawInstantiatedTypeArguments::VisitInstantiatedTypeArgumentsPointers(
-    RawInstantiatedTypeArguments* raw_obj, ObjectPointerVisitor* visitor) {
-  visitor->VisitPointers(raw_obj->from(), raw_obj->to());
-  return InstantiatedTypeArguments::InstanceSize();
-}
-
-
 intptr_t RawPatchClass::VisitPatchClassPointers(RawPatchClass* raw_obj,
                                                 ObjectPointerVisitor* visitor) {
   visitor->VisitPointers(raw_obj->from(), raw_obj->to());
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index ef3368c..83e88f4 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -16,9 +16,7 @@
 #define CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(V)                           \
   V(Class)                                                                     \
   V(UnresolvedClass)                                                           \
-  V(AbstractTypeArguments)                                                     \
-    V(TypeArguments)                                                           \
-    V(InstantiatedTypeArguments)                                               \
+  V(TypeArguments)                                                             \
   V(PatchClass)                                                                \
   V(Function)                                                                  \
   V(ClosureData)                                                               \
@@ -537,19 +535,18 @@
 };
 
 
-class RawAbstractTypeArguments : public RawObject {
- private:
-  RAW_HEAP_OBJECT_IMPLEMENTATION(AbstractTypeArguments);
-};
-
-
-class RawTypeArguments : public RawAbstractTypeArguments {
+class RawTypeArguments : public RawObject {
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(TypeArguments);
 
   RawObject** from() {
-    return reinterpret_cast<RawObject**>(&ptr()->length_);
+    return reinterpret_cast<RawObject**>(&ptr()->instantiations_);
   }
+  // The instantiations_ array remains empty for instantiated type arguments.
+  RawArray* instantiations_;  // Array of paired canonical vectors:
+                              // Even index: instantiator.
+                              // Odd index: instantiated (without bound error).
+  // Instantiations leading to bound errors do not get cached.
   RawSmi* length_;
 
   // Variable length data follows here.
@@ -562,22 +559,6 @@
 };
 
 
-class RawInstantiatedTypeArguments : public RawAbstractTypeArguments {
- private:
-  RAW_HEAP_OBJECT_IMPLEMENTATION(InstantiatedTypeArguments);
-
-  RawObject** from() {
-    return reinterpret_cast<RawObject**>(
-        &ptr()->uninstantiated_type_arguments_);
-  }
-  RawAbstractTypeArguments* uninstantiated_type_arguments_;
-  RawAbstractTypeArguments* instantiator_type_arguments_;
-  RawObject** to() {
-    return reinterpret_cast<RawObject**>(&ptr()->instantiator_type_arguments_);
-  }
-};
-
-
 class RawPatchClass : public RawObject {
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(PatchClass);
@@ -1174,7 +1155,7 @@
     return reinterpret_cast<RawObject**>(&ptr()->type_class_);
   }
   RawObject* type_class_;  // Either resolved class or unresolved class.
-  RawAbstractTypeArguments* arguments_;
+  RawTypeArguments* arguments_;
   RawLanguageError* error_;  // Error object if type is malformed or malbounded.
   RawObject** to() {
     return reinterpret_cast<RawObject**>(&ptr()->error_);
@@ -1385,7 +1366,7 @@
   RawObject** from() {
     return reinterpret_cast<RawObject**>(&ptr()->type_arguments_);
   }
-  RawAbstractTypeArguments* type_arguments_;
+  RawTypeArguments* type_arguments_;
   RawSmi* length_;
   // Variable length data follows here.
   RawObject** data() {
@@ -1417,7 +1398,7 @@
   RawObject** from() {
     return reinterpret_cast<RawObject**>(&ptr()->type_arguments_);
   }
-  RawAbstractTypeArguments* type_arguments_;
+  RawTypeArguments* type_arguments_;
   RawSmi* length_;
   RawArray* data_;
   RawObject** to() {
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index e46625b..433bce8 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -435,23 +435,6 @@
 }
 
 
-RawAbstractTypeArguments* AbstractTypeArguments::ReadFrom(
-    SnapshotReader* reader,
-    intptr_t object_id,
-    intptr_t tags,
-    Snapshot::Kind kind) {
-  UNREACHABLE();  // AbstractTypeArguments is an abstract class.
-  return TypeArguments::null();
-}
-
-
-void RawAbstractTypeArguments::WriteTo(SnapshotWriter* writer,
-                                       intptr_t object_id,
-                                       Snapshot::Kind kind) {
-  UNREACHABLE();  // AbstractTypeArguments is an abstract class.
-}
-
-
 RawTypeArguments* TypeArguments::ReadFrom(SnapshotReader* reader,
                                           intptr_t object_id,
                                           intptr_t tags,
@@ -465,10 +448,19 @@
       reader->isolate(), NEW_OBJECT_WITH_LEN_SPACE(TypeArguments, len, kind));
   reader->AddBackRef(object_id, &type_arguments, kIsDeserialized);
 
-  // Now set all the object fields.
+  // Set the instantiations field, which is only read from a full snapshot.
+  if (kind == Snapshot::kFull) {
+    *reader->ArrayHandle() ^= reader->ReadObjectImpl();
+    type_arguments.set_instantiations(*reader->ArrayHandle());
+  } else {
+    // TODO(regis): Change to Object::zero_array() once supported.
+    type_arguments.set_instantiations(Object::empty_array());
+  }
+
+  // Now set all the type fields.
   for (intptr_t i = 0; i < len; i++) {
     *reader->TypeHandle() ^= reader->ReadObjectImpl();
-    type_arguments.SetTypeAt(i, *reader->TypeHandle());
+    type_arguments.set_type_at(i, *reader->TypeHandle());
   }
 
   // If object needs to be a canonical object, Canonicalize it.
@@ -510,6 +502,11 @@
   // Write out the length field.
   writer->Write<RawObject*>(ptr()->length_);
 
+  // Write out the instantiations field, but only in a full snapshot.
+  if (kind == Snapshot::kFull) {
+    writer->WriteObjectImpl(ptr()->instantiations_);
+  }
+
   // Write out the individual types.
   intptr_t len = Smi::Value(ptr()->length_);
   for (intptr_t i = 0; i < len; i++) {
@@ -518,57 +515,6 @@
 }
 
 
-RawInstantiatedTypeArguments* InstantiatedTypeArguments::ReadFrom(
-    SnapshotReader* reader,
-    intptr_t object_id,
-    intptr_t tags,
-    Snapshot::Kind kind) {
-  ASSERT(reader != NULL);
-  ASSERT(kind == Snapshot::kMessage);
-
-  // Allocate instantiated types object.
-  InstantiatedTypeArguments& instantiated_type_arguments =
-      InstantiatedTypeArguments::ZoneHandle(reader->isolate(),
-                                            InstantiatedTypeArguments::New());
-  reader->AddBackRef(object_id, &instantiated_type_arguments, kIsDeserialized);
-
-  // Set the object tags.
-  instantiated_type_arguments.set_tags(tags);
-
-  // Set all the object fields.
-  // TODO(5411462): Need to assert No GC can happen here, even though
-  // allocations may happen.
-  intptr_t num_flds = (instantiated_type_arguments.raw()->to() -
-                       instantiated_type_arguments.raw()->from());
-  for (intptr_t i = 0; i <= num_flds; i++) {
-    (*reader->ObjectHandle()) = reader->ReadObjectRef();
-    instantiated_type_arguments.StorePointer(
-        (instantiated_type_arguments.raw()->from() + i),
-        reader->ObjectHandle()->raw());
-  }
-  return instantiated_type_arguments.raw();
-}
-
-
-void RawInstantiatedTypeArguments::WriteTo(SnapshotWriter* writer,
-                                           intptr_t object_id,
-                                           Snapshot::Kind kind) {
-  ASSERT(writer != NULL);
-  ASSERT(kind == Snapshot::kMessage);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteVMIsolateObject(kInstantiatedTypeArgumentsCid);
-  writer->WriteIntptrValue(writer->GetObjectTags(this));
-
-  // Write out all the object pointer fields.
-  SnapshotWriterVisitor visitor(writer);
-  visitor.VisitPointers(from(), to());
-}
-
-
 RawPatchClass* PatchClass::ReadFrom(SnapshotReader* reader,
                                     intptr_t object_id,
                                     intptr_t tags,
@@ -2181,8 +2127,8 @@
   Array& contents = Array::Handle();
   contents ^= reader->ReadObjectImpl();
   array.SetData(contents);
-  const AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::Handle(contents.GetTypeArguments());
+  const TypeArguments& type_arguments =
+      TypeArguments::Handle(contents.GetTypeArguments());
   array.SetTypeArguments(type_arguments);
   return array.raw();
 }
diff --git a/runtime/vm/scanner.cc b/runtime/vm/scanner.cc
index 0a1763d..7e1dfbe 100644
--- a/runtime/vm/scanner.cc
+++ b/runtime/vm/scanner.cc
@@ -312,7 +312,7 @@
   current_token_.kind = Token::kIDENT;
   String& literal =
       String::ZoneHandle(Symbols::New(source_, ident_pos, ident_length));
-  if (ident_char0 == kPrivateIdentifierStart) {
+  if (ident_char0 == Library::kPrivateIdentifierStart) {
     // Private identifiers are mangled on a per library basis.
     literal = String::Concat(literal, private_key_);
     literal = Symbols::New(literal);
@@ -932,20 +932,6 @@
 }
 
 
-RawString* Scanner::AllocatePrivateKey(const Library& library) {
-  const String& url = String::Handle(library.url());
-  intptr_t key_value = url.Hash();
-  while (Library::IsKeyUsed(key_value)) {
-    key_value++;
-  }
-  char private_key[32];
-  OS::SNPrint(private_key, sizeof(private_key),
-              "%c%#" Px "", kPrivateKeySeparator, key_value);
-  const String& result = String::Handle(String::New(private_key, Heap::kOld));
-  return result.raw();
-}
-
-
 void Scanner::InitOnce() {
   ASSERT(Isolate::Current() == Dart::vm_isolate());
   for (int i = 0; i < Token::numKeywords; i++) {
diff --git a/runtime/vm/scanner.h b/runtime/vm/scanner.h
index 22ce56a2..3e1407c 100644
--- a/runtime/vm/scanner.h
+++ b/runtime/vm/scanner.h
@@ -44,12 +44,6 @@
   // Dummy token index reflecting an unknown source position.
   static const intptr_t kNoSourcePos = 0;
 
-  // Character used to indicate a private identifier.
-  static const char kPrivateIdentifierStart  = '_';
-
-  // Character used to separate the private identifier from the key.
-  static const char kPrivateKeySeparator = '@';
-
   typedef ZoneGrowableArray<TokenDescriptor> GrowableTokenStream;
 
   // Initializes scanner to scan string source.
@@ -80,9 +74,6 @@
 
   static void InitOnce();
 
-  // Allocated a private key which is used for name mangling.
-  static RawString* AllocatePrivateKey(const Library& library);
-
   // Return true if str is an identifier.
   static bool IsIdent(const String& str);
 
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index c3cf071..7499d0f 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -148,18 +148,18 @@
     : BaseReader(buffer, size),
       kind_(kind),
       isolate_(isolate),
-      cls_(Class::Handle()),
-      obj_(Object::Handle()),
-      array_(Array::Handle()),
-      field_(Field::Handle()),
-      str_(String::Handle()),
-      library_(Library::Handle()),
-      type_(AbstractType::Handle()),
-      type_arguments_(AbstractTypeArguments::Handle()),
-      tokens_(Array::Handle()),
-      stream_(TokenStream::Handle()),
-      data_(ExternalTypedData::Handle()),
-      error_(UnhandledException::Handle()),
+      cls_(Class::Handle(isolate)),
+      obj_(Object::Handle(isolate)),
+      array_(Array::Handle(isolate)),
+      field_(Field::Handle(isolate)),
+      str_(String::Handle(isolate)),
+      library_(Library::Handle(isolate)),
+      type_(AbstractType::Handle(isolate)),
+      type_arguments_(TypeArguments::Handle(isolate)),
+      tokens_(Array::Handle(isolate)),
+      stream_(TokenStream::Handle(isolate)),
+      data_(ExternalTypedData::Handle(isolate)),
+      error_(UnhandledException::Handle(isolate)),
       backward_references_((kind == Snapshot::kFull) ?
                            kNumInitialReferencesInFullSnapshot :
                            kNumInitialReferences) {
@@ -723,6 +723,15 @@
     ErrorHandle()->set_exception(exception);
     Isolate::Current()->long_jump_base()->Jump(1, *ErrorHandle());
   }
+#if defined(DEBUG)
+  // Zap the uninitialized memory area.
+  uword current = address;
+  uword end = address + size;
+  while (current < end) {
+    *reinterpret_cast<intptr_t*>(current) = kZapUninitializedWord;
+    current += kWordSize;
+  }
+#endif  // defined(DBEUG)
   // Make sure to initialize the last word, as this can be left untouched in
   // case the object deserialized has an alignment tail.
   *reinterpret_cast<RawObject**>(address + size - kWordSize) = Object::null();
@@ -1361,7 +1370,7 @@
                                   intptr_t array_kind,
                                   intptr_t tags,
                                   RawSmi* length,
-                                  RawAbstractTypeArguments* type_arguments,
+                                  RawTypeArguments* type_arguments,
                                   RawObject* data[]) {
   intptr_t len = Smi::Value(length);
 
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 9aa5bc3..3f88f74 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -19,7 +19,6 @@
 
 // Forward declarations.
 class AbstractType;
-class AbstractTypeArguments;
 class Array;
 class Class;
 class ClassTable;
@@ -30,7 +29,6 @@
 class Library;
 class Object;
 class ObjectStore;
-class RawAbstractTypeArguments;
 class RawApiError;
 class RawArray;
 class RawBigint;
@@ -69,6 +67,7 @@
 class RawUnresolvedClass;
 class String;
 class TokenStream;
+class TypeArguments;
 class UnhandledException;
 
 // Serialized object header encoding is as follows:
@@ -222,9 +221,10 @@
   ObjectStore* object_store() const { return isolate_->object_store(); }
   ClassTable* class_table() const { return isolate_->class_table(); }
   Object* ObjectHandle() { return &obj_; }
+  Array* ArrayHandle() { return &array_; }
   String* StringHandle() { return &str_; }
   AbstractType* TypeHandle() { return &type_; }
-  AbstractTypeArguments* TypeArgumentsHandle() { return &type_arguments_; }
+  TypeArguments* TypeArgumentsHandle() { return &type_arguments_; }
   Array* TokensHandle() { return &tokens_; }
   TokenStream* StreamHandle() { return &stream_; }
   ExternalTypedData* DataHandle() { return &data_; }
@@ -330,7 +330,7 @@
   String& str_;  // Temporary String handle.
   Library& library_;  // Temporary library handle.
   AbstractType& type_;  // Temporary type handle.
-  AbstractTypeArguments& type_arguments_;  // Temporary type argument handle.
+  TypeArguments& type_arguments_;  // Temporary type argument handle.
   Array& tokens_;  // Temporary tokens handle.
   TokenStream& stream_;  // Temporary token stream handle.
   ExternalTypedData& data_;  // Temporary stream data handle.
@@ -350,7 +350,6 @@
   friend class Function;
   friend class GrowableObjectArray;
   friend class ImmutableArray;
-  friend class InstantiatedTypeArguments;
   friend class JSRegExp;
   friend class LanguageError;
   friend class Library;
@@ -510,7 +509,7 @@
                     intptr_t array_kind,
                     intptr_t tags,
                     RawSmi* length,
-                    RawAbstractTypeArguments* type_arguments,
+                    RawTypeArguments* type_arguments,
                     RawObject* data[]);
   void CheckIfSerializable(RawClass* cls);
   void SetWriteException(Exceptions::ExceptionType type, const char* msg);
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 365d9e0..a46d72a 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -473,7 +473,6 @@
   MessageWriter writer(&buffer, &malloc_allocator);
   writer.WriteObject(Object::class_class());
   writer.WriteObject(Object::type_arguments_class());
-  writer.WriteObject(Object::instantiated_type_arguments_class());
   writer.WriteObject(Object::function_class());
   writer.WriteObject(Object::field_class());
   writer.WriteObject(Object::token_stream_class());
@@ -492,7 +491,6 @@
                         Isolate::Current());
   EXPECT(Object::class_class() == reader.ReadObject());
   EXPECT(Object::type_arguments_class() == reader.ReadObject());
-  EXPECT(Object::instantiated_type_arguments_class() == reader.ReadObject());
   EXPECT(Object::function_class() == reader.ReadObject());
   EXPECT(Object::field_class() == reader.ReadObject());
   EXPECT(Object::token_stream_class() == reader.ReadObject());
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index c65ccc7..c64f1d7 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -23,8 +23,8 @@
 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects.");
 DEFINE_FLAG(bool, use_slow_path, false,
     "Set to true for debugging & verifying the slow paths.");
-DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, trace_optimized_ic_calls);
+DECLARE_FLAG(int, optimization_counter_threshold);
 
 
 // Input parameters:
@@ -1111,24 +1111,50 @@
   const int kInlineInstanceSize = 12;
   const intptr_t instance_size = cls.instance_size();
   ASSERT(instance_size > 0);
-  const intptr_t type_args_size = InstantiatedTypeArguments::InstanceSize();
-  if (FLAG_inline_alloc &&
-      Heap::IsAllocatableInNewSpace(instance_size + type_args_size)) {
-    Label slow_case;
+  Label slow_case_with_type_arguments;
+  if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size)) {
+    Label slow_case_reload_type_arguments;
+    if (is_cls_parameterized) {
+      // Instantiation of the type arguments vector is only required if an
+      // instantiator is provided (not kNoInstantiator, but may be null).
+      __ ldm(IA, SP, (1 << R0) | (1 << R1));
+      // R1: type arguments, instantiated or not.
+      // R0: instantiator type arguments or kNoInstantiator.
+      Label type_arguments_ready;
+      __ CompareImmediate(R0, Smi::RawValue(StubCode::kNoInstantiator));
+      __ b(&type_arguments_ready, EQ);
+      // Lookup instantiator R0 in instantiations array of type arguments R1
+      // and, if found, use cached instantiated type arguments.
+      __ ldr(R2, FieldAddress(R1, TypeArguments::instantiations_offset()));
+      __ ldr(R3, FieldAddress(R2, Array::length_offset()));
+      __ AddImmediate(R2, Array::data_offset() - kHeapObjectTag);
+      __ add(R3, R2, ShifterOperand(R3, LSL, 1));  // R3 is Smi.
+      Label loop, found;
+      __ Bind(&loop);
+      __ cmp(R2, ShifterOperand(R3));
+      __ b(&slow_case_reload_type_arguments, CS);  // Unsigned higher or equal.
+      __ ldr(R1, Address(R2, 0 * kWordSize));  // Cached instantiator.
+      __ cmp(R1, ShifterOperand(R0));
+      __ b(&found, EQ);
+      __ CompareImmediate(R1, Smi::RawValue(StubCode::kNoInstantiator));
+      __ b(&slow_case_reload_type_arguments, EQ);
+      __ AddImmediate(R2, 2 * kWordSize);
+      __ b(&loop);
+      __ Bind(&found);
+      __ ldr(R1, Address(R2, 1 * kWordSize));  // Cached instantiated args.
+      __ LoadImmediate(R0, Smi::RawValue(StubCode::kNoInstantiator));
+      __ Bind(&type_arguments_ready);
+      // R1: instantiated type arguments.
+      // R0: kNoInstantiator.
+    }
+    // Allocate the object and update top to point to
+    // next object start and initialize the allocated object.
+    // R1: instantiated type arguments (if is_cls_parameterized).
+    // R0: kNoInstantiator (if is_cls_parameterized).
     Heap* heap = Isolate::Current()->heap();
     __ LoadImmediate(R5, heap->TopAddress());
     __ ldr(R2, Address(R5, 0));
     __ AddImmediate(R3, R2, instance_size);
-    if (is_cls_parameterized) {
-      __ ldm(IA, SP, (1 << R0) | (1 << R1));
-      __ mov(R4, ShifterOperand(R3));
-      // A new InstantiatedTypeArguments object only needs to be allocated if
-      // the instantiator is provided (not kNoInstantiator, but may be null).
-      __ CompareImmediate(R0, Smi::RawValue(StubCode::kNoInstantiator));
-      __ AddImmediate(R3, type_args_size, NE);
-      // R4: potential new object end and, if R4 != R3, potential new
-      // InstantiatedTypeArguments object start.
-    }
     // Check if the allocation fits into the remaining space.
     // R2: potential new object start.
     // R3: potential next object start.
@@ -1136,48 +1162,13 @@
     __ ldr(IP, Address(IP, 0));
     __ cmp(R3, ShifterOperand(IP));
     if (FLAG_use_slow_path) {
-      __ b(&slow_case);
+      __ b(&slow_case_with_type_arguments);
     } else {
-      __ b(&slow_case, CS);  // Branch if unsigned higher or equal.
+      __ b(&slow_case_with_type_arguments, CS);  // Unsigned higher or equal.
     }
-
-    // Successfully allocated the object(s), now update top to point to
-    // next object start and initialize the object.
     __ str(R3, Address(R5, 0));
     __ UpdateAllocationStats(cls.id(), R5);
 
-    if (is_cls_parameterized) {
-      // Initialize the type arguments field in the object.
-      // R2: new object start.
-      // R4: potential new object end and, if R4 != R3, potential new
-      // InstantiatedTypeArguments object start.
-      // R3: next object start.
-      Label type_arguments_ready;
-      __ cmp(R4, ShifterOperand(R3));
-      __ b(&type_arguments_ready, EQ);
-      // Initialize InstantiatedTypeArguments object at R4.
-      __ str(R1, Address(R4,
-          InstantiatedTypeArguments::uninstantiated_type_arguments_offset()));
-      __ str(R0, Address(R4,
-          InstantiatedTypeArguments::instantiator_type_arguments_offset()));
-      const Class& ita_cls =
-          Class::ZoneHandle(Object::instantiated_type_arguments_class());
-      // Set the tags.
-      uword tags = 0;
-      tags = RawObject::SizeTag::update(type_args_size, tags);
-      tags = RawObject::ClassIdTag::update(ita_cls.id(), tags);
-      __ LoadImmediate(R0, tags);
-      __ str(R0, Address(R4, Instance::tags_offset()));
-      // Set the new InstantiatedTypeArguments object (R4) as the type
-      // arguments (R1) of the new object (R2).
-      __ add(R1, R4, ShifterOperand(kHeapObjectTag));
-      // Set R3 to new object end.
-      __ mov(R3, ShifterOperand(R4));
-      __ Bind(&type_arguments_ready);
-      // R2: new object.
-      // R1: new object type arguments.
-    }
-
     // R2: new object start.
     // R3: next object start.
     // R1: new object type arguments (if is_cls_parameterized).
@@ -1234,11 +1225,15 @@
     // R0: new object.
     __ Ret();
 
-    __ Bind(&slow_case);
+    __ Bind(&slow_case_reload_type_arguments);
   }
   if (is_cls_parameterized) {
     __ ldm(IA, SP, (1 << R0) | (1 << R1));
   }
+  __ Bind(&slow_case_with_type_arguments);
+  // If is_cls_parameterized:
+  // R1: new object type arguments (instantiated or not).
+  // R0: instantiator type arguments or kNoInstantiator.
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   __ EnterStubFrame(true);  // Uses pool pointer to pass cls to runtime.
@@ -1881,6 +1876,7 @@
     __ LoadClass(R3, R0, R4);
     // Compute instance type arguments into R4.
     Label has_no_type_arguments;
+    __ LoadImmediate(R4, reinterpret_cast<intptr_t>(Object::null()));
     __ ldr(R5, FieldAddress(R3,
         Class::type_arguments_field_offset_in_words_offset()));
     __ CompareImmediate(R5, Class::kNoTypeArguments);
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 909bd8f..a40851a4 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -25,8 +25,9 @@
 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects.");
 DEFINE_FLAG(bool, use_slow_path, false,
     "Set to true for debugging & verifying the slow paths.");
-DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, trace_optimized_ic_calls);
+DECLARE_FLAG(int, optimization_counter_threshold);
+
 
 // Input parameters:
 //   ESP : points to return address.
@@ -1118,83 +1119,66 @@
   // kInlineInstanceSize is a constant used as a threshold for determining
   // when the object initialization should be done as a loop or as
   // straight line code.
-  const int kInlineInstanceSize = 12;
+  const int kInlineInstanceSize = 12;  // In words.
   const intptr_t instance_size = cls.instance_size();
   ASSERT(instance_size > 0);
-  const intptr_t type_args_size = InstantiatedTypeArguments::InstanceSize();
-  if (FLAG_inline_alloc &&
-      Heap::IsAllocatableInNewSpace(instance_size + type_args_size)) {
-    Label slow_case;
+  Label slow_case_with_type_arguments;
+  if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size)) {
+    Label slow_case_reload_type_arguments;
+    if (is_cls_parameterized) {
+      // Instantiation of the type arguments vector is only required if an
+      // instantiator is provided (not kNoInstantiator, but may be null).
+      __ movl(EDX, Address(ESP, kObjectTypeArgumentsOffset));
+      __ movl(EDI, Address(ESP, kInstantiatorTypeArgumentsOffset));
+      Label type_arguments_ready;
+      __ cmpl(EDI, Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
+      __ j(EQUAL, &type_arguments_ready, Assembler::kNearJump);
+      // Lookup instantiator EDI in instantiations array of type arguments EDX
+      // and, if found, use cached instantiated type arguments.
+      __ movl(EAX, FieldAddress(EDX, TypeArguments::instantiations_offset()));
+      __ movl(EBX, FieldAddress(EAX, Array::length_offset()));
+      __ leal(EAX, FieldAddress(EAX, Array::data_offset()));
+      __ leal(EBX, Address(EAX, EBX, TIMES_2, 0));  // EBX is smi.
+      Label loop, found;
+      __ Bind(&loop);
+      __ cmpl(EAX, EBX);
+      __ j(ABOVE_EQUAL, &slow_case_reload_type_arguments);
+      __ movl(EDX, Address(EAX, 0 * kWordSize));  // Cached instantiator.
+      __ cmpl(EDX, EDI);
+      __ j(EQUAL, &found, Assembler::kNearJump);
+      __ cmpl(EDX, Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
+      __ j(EQUAL, &slow_case_reload_type_arguments);
+      __ addl(EAX, Immediate(2 * kWordSize));
+      __ jmp(&loop, Assembler::kNearJump);
+      __ Bind(&found);
+      __ movl(EDX, Address(EAX, 1 * kWordSize));  // Cached instantiated args.
+      __ movl(EDI, Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
+      __ Bind(&type_arguments_ready);
+      // EDX: instantiated type arguments.
+      // EDI: kNoInstantiator.
+    }
+    // Allocate the object and update top to point to
+    // next object start and initialize the allocated object.
+    // EDX: instantiated type arguments (if is_cls_parameterized).
+    // EDI: kNoInstantiator (if is_cls_parameterized).
     Heap* heap = Isolate::Current()->heap();
     __ movl(EAX, Address::Absolute(heap->TopAddress()));
     __ leal(EBX, Address(EAX, instance_size));
-    if (is_cls_parameterized) {
-      __ movl(ECX, EBX);
-      // A new InstantiatedTypeArguments object only needs to be allocated if
-      // the instantiator is provided (not kNoInstantiator, but may be null).
-      Label no_instantiator;
-      __ cmpl(Address(ESP, kInstantiatorTypeArgumentsOffset),
-              Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
-      __ j(EQUAL, &no_instantiator, Assembler::kNearJump);
-      __ addl(EBX, Immediate(type_args_size));
-      __ Bind(&no_instantiator);
-      // ECX: potential new object end and, if ECX != EBX, potential new
-      // InstantiatedTypeArguments object start.
-    }
     // Check if the allocation fits into the remaining space.
     // EAX: potential new object start.
     // EBX: potential next object start.
     __ cmpl(EBX, Address::Absolute(heap->EndAddress()));
     if (FLAG_use_slow_path) {
-      __ jmp(&slow_case);
+      __ jmp(&slow_case_with_type_arguments);
     } else {
-      __ j(ABOVE_EQUAL, &slow_case);
+      __ j(ABOVE_EQUAL, &slow_case_with_type_arguments);
     }
-
-    // Successfully allocated the object(s), now update top to point to
-    // next object start and initialize the object.
     __ movl(Address::Absolute(heap->TopAddress()), EBX);
-    __ UpdateAllocationStats(cls.id(), EDI);
-
-    if (is_cls_parameterized) {
-      // Initialize the type arguments field in the object.
-      // EAX: new object start.
-      // ECX: potential new object end and, if ECX != EBX, potential new
-      // InstantiatedTypeArguments object start.
-      // EBX: next object start.
-      Label type_arguments_ready;
-      __ movl(EDI, Address(ESP, kObjectTypeArgumentsOffset));
-      __ cmpl(ECX, EBX);
-      __ j(EQUAL, &type_arguments_ready, Assembler::kNearJump);
-      // Initialize InstantiatedTypeArguments object at ECX.
-      __ movl(Address(ECX,
-          InstantiatedTypeArguments::uninstantiated_type_arguments_offset()),
-              EDI);
-      __ movl(EDX, Address(ESP, kInstantiatorTypeArgumentsOffset));
-      __ movl(Address(ECX,
-          InstantiatedTypeArguments::instantiator_type_arguments_offset()),
-              EDX);
-      const Class& ita_cls =
-          Class::ZoneHandle(Object::instantiated_type_arguments_class());
-      // Set the tags.
-      uword tags = 0;
-      tags = RawObject::SizeTag::update(type_args_size, tags);
-      tags = RawObject::ClassIdTag::update(ita_cls.id(), tags);
-      __ movl(Address(ECX, Instance::tags_offset()), Immediate(tags));
-      // Set the new InstantiatedTypeArguments object (ECX) as the type
-      // arguments (EDI) of the new object (EAX).
-      __ movl(EDI, ECX);
-      __ addl(EDI, Immediate(kHeapObjectTag));
-      // Set EBX to new object end.
-      __ movl(EBX, ECX);
-      __ Bind(&type_arguments_ready);
-      // EAX: new object.
-      // EDI: new object type arguments.
-    }
+    __ UpdateAllocationStats(cls.id(), ECX);
 
     // EAX: new object start.
     // EBX: next object start.
-    // EDI: new object type arguments (if is_cls_parameterized).
+    // EDX: new object type arguments (if is_cls_parameterized).
     // Set the tags.
     uword tags = 0;
     tags = RawObject::SizeTag::update(instance_size, tags);
@@ -1208,7 +1192,7 @@
 
     // EAX: new object start.
     // EBX: next object start.
-    // EDI: new object type arguments (if is_cls_parameterized).
+    // EDX: new object type arguments (if is_cls_parameterized).
     // First try inlining the initialization without a loop.
     if (instance_size < (kInlineInstanceSize * kWordSize)) {
       // Check if the object contains any non-header fields.
@@ -1224,7 +1208,7 @@
       // EAX: new object.
       // EBX: next object start.
       // ECX: next word to be initialized.
-      // EDI: new object type arguments (if is_cls_parameterized).
+      // EDX: new object type arguments (if is_cls_parameterized).
       Label init_loop;
       Label done;
       __ Bind(&init_loop);
@@ -1236,29 +1220,33 @@
       __ Bind(&done);
     }
     if (is_cls_parameterized) {
-      // EDI: new object type arguments.
+      // EDX: new object type arguments.
       // Set the type arguments in the new object.
-      __ movl(Address(EAX, cls.type_arguments_field_offset()), EDI);
+      __ movl(Address(EAX, cls.type_arguments_field_offset()), EDX);
     }
     // Done allocating and initializing the instance.
     // EAX: new object.
     __ addl(EAX, Immediate(kHeapObjectTag));
     __ ret();
 
-    __ Bind(&slow_case);
+    __ Bind(&slow_case_reload_type_arguments);
   }
   if (is_cls_parameterized) {
-    __ movl(EAX, Address(ESP, kObjectTypeArgumentsOffset));
-    __ movl(EDX, Address(ESP, kInstantiatorTypeArgumentsOffset));
+    __ movl(EDX, Address(ESP, kObjectTypeArgumentsOffset));
+    __ movl(EDI, Address(ESP, kInstantiatorTypeArgumentsOffset));
   }
+  __ Bind(&slow_case_with_type_arguments);
+  // If is_cls_parameterized:
+  // EDX: new object type arguments (instantiated or not).
+  // EDI: instantiator type arguments or kNoInstantiator.
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   __ EnterStubFrame();
   __ pushl(raw_null);  // Setup space on stack for return value.
   __ PushObject(cls);  // Push class of object to be allocated.
   if (is_cls_parameterized) {
-    __ pushl(EAX);  // Push type arguments of object to be allocated.
-    __ pushl(EDX);  // Push type arguments of instantiator.
+    __ pushl(EDX);  // Push type arguments of object to be allocated.
+    __ pushl(EDI);  // Push type arguments of instantiator.
   } else {
     __ pushl(raw_null);  // Push null type arguments.
     __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index 6751b8e..45b8144 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -23,8 +23,8 @@
 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects.");
 DEFINE_FLAG(bool, use_slow_path, false,
     "Set to true for debugging & verifying the slow paths.");
-DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, trace_optimized_ic_calls);
+DECLARE_FLAG(int, optimization_counter_threshold);
 
 
 // Input parameters:
@@ -1302,74 +1302,66 @@
   const int kInlineInstanceSize = 12;
   const intptr_t instance_size = cls.instance_size();
   ASSERT(instance_size > 0);
-  const intptr_t type_args_size = InstantiatedTypeArguments::InstanceSize();
-  if (FLAG_inline_alloc &&
-      Heap::IsAllocatableInNewSpace(instance_size + type_args_size)) {
-    Label slow_case;
+  Label slow_case_with_type_arguments;
+  if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size)) {
+    Label slow_case_reload_type_arguments;
+    if (is_cls_parameterized) {
+      // Instantiation of the type arguments vector is only required if an
+      // instantiator is provided (not kNoInstantiator, but may be null).
+      __ lw(T1, Address(SP, 1 * kWordSize));
+      __ lw(T0, Address(SP, 0 * kWordSize));
+      // R1: type arguments, instantiated or not.
+      // R0: instantiator type arguments or kNoInstantiator.
+      Label type_arguments_ready;
+      __ BranchEqual(T0, Smi::RawValue(StubCode::kNoInstantiator),
+                     &type_arguments_ready);
+      // Lookup instantiator EDI in instantiations array of type arguments EDX
+      // and, if found, use cached instantiated type arguments.
+      __ lw(T2, FieldAddress(T1, TypeArguments::instantiations_offset()));
+      __ lw(T3, FieldAddress(T2, Array::length_offset()));
+      __ AddImmediate(T2, Array::data_offset() - kHeapObjectTag);
+      __ sll(TMP, T3, 1);  // T3 is Smi.
+      __ addu(T3, T2, TMP);
+      Label loop, found;
+      __ Bind(&loop);
+      __ BranchUnsignedGreaterEqual(T2, T3, &slow_case_reload_type_arguments);
+      __ lw(T1, Address(T2, 0 * kWordSize));  // Cached instantiator.
+      __ beq(T1, T0, &found);
+      __ BranchEqual(T1, Smi::RawValue(StubCode::kNoInstantiator),
+                     &slow_case_reload_type_arguments);
+      __ b(&loop);
+      __ delay_slot()->addiu(T2, T2, Immediate(2 * kWordSize));
+      __ Bind(&found);
+      __ lw(T1, Address(T2, 1 * kWordSize));  // Cached instantiated args.
+      __ LoadImmediate(T0, Smi::RawValue(StubCode::kNoInstantiator));
+      __ Bind(&type_arguments_ready);
+      // T0: instantiated type arguments.
+      // T1: kNoInstantiator.
+    }
+    // Allocate the object and update top to point to
+    // next object start and initialize the allocated object.
+    // T0: instantiated type arguments (if is_cls_parameterized).
+    // T1: kNoInstantiator (if is_cls_parameterized).
     Heap* heap = Isolate::Current()->heap();
     __ LoadImmediate(T5, heap->TopAddress());
     __ lw(T2, Address(T5));
     __ LoadImmediate(T4, instance_size);
     __ addu(T3, T2, T4);
-    if (is_cls_parameterized) {
-      Label no_instantiator;
-      __ lw(T1, Address(SP, 1 * kWordSize));
-      __ lw(T0, Address(SP, 0 * kWordSize));
-      // A new InstantiatedTypeArguments object only needs to be allocated if
-      // the instantiator is provided (not kNoInstantiator, but may be null).
-      __ BranchEqual(T0, Smi::RawValue(StubCode::kNoInstantiator),
-                     &no_instantiator);
-      __ delay_slot()->mov(T4, T3);
-      __ AddImmediate(T3, type_args_size);
-      __ Bind(&no_instantiator);
-      // T4: potential new object end and, if T4 != T3, potential new
-      // InstantiatedTypeArguments object start.
-    }
     // Check if the allocation fits into the remaining space.
     // T2: potential new object start.
     // T3: potential next object start.
     __ LoadImmediate(TMP, heap->EndAddress());
     __ lw(CMPRES1, Address(TMP));
     if (FLAG_use_slow_path) {
-      __ b(&slow_case);
+      __ b(&slow_case_with_type_arguments);
     } else {
-      __ BranchUnsignedGreaterEqual(T3, CMPRES1, &slow_case);
+      __ BranchUnsignedGreaterEqual(T3, CMPRES1,
+                                    &slow_case_with_type_arguments);
     }
-
     // Successfully allocated the object(s), now update top to point to
     // next object start and initialize the object.
     __ sw(T3, Address(T5));
-
-    if (is_cls_parameterized) {
-      // Initialize the type arguments field in the object.
-      // T2: new object start.
-      // T4: potential new object end and, if T4 != T3, potential new
-      // InstantiatedTypeArguments object start.
-      // T3: next object start.
-      Label type_arguments_ready;
-      __ beq(T4, T3, &type_arguments_ready);
-      // Initialize InstantiatedTypeArguments object at T4.
-      __ sw(T1, Address(T4,
-          InstantiatedTypeArguments::uninstantiated_type_arguments_offset()));
-      __ sw(T0, Address(T4,
-          InstantiatedTypeArguments::instantiator_type_arguments_offset()));
-      const Class& ita_cls =
-          Class::ZoneHandle(Object::instantiated_type_arguments_class());
-      // Set the tags.
-      uword tags = 0;
-      tags = RawObject::SizeTag::update(type_args_size, tags);
-      tags = RawObject::ClassIdTag::update(ita_cls.id(), tags);
-      __ LoadImmediate(T0, tags);
-      __ sw(T0, Address(T4, Instance::tags_offset()));
-      // Set the new InstantiatedTypeArguments object (T4) as the type
-      // arguments (T1) of the new object (T2).
-      __ addiu(T1, T4, Immediate(kHeapObjectTag));
-      // Set T3 to new object end.
-      __ mov(T3, T4);
-      __ Bind(&type_arguments_ready);
-      // T2: new object.
-      // T1: new object type arguments.
-    }
+    __ UpdateAllocationStats(cls.id(), T5);
 
     // T2: new object start.
     // T3: next object start.
@@ -1417,18 +1409,21 @@
       // Set the type arguments in the new object.
       __ sw(T1, Address(T2, cls.type_arguments_field_offset()));
     }
-    __ UpdateAllocationStats(cls.id(), T5);
     // Done allocating and initializing the instance.
     // T2: new object still missing its heap tag.
     __ Ret();
     __ delay_slot()->addiu(V0, T2, Immediate(kHeapObjectTag));
 
-    __ Bind(&slow_case);
+    __ Bind(&slow_case_reload_type_arguments);
   }
   if (is_cls_parameterized) {
     __ lw(T1, Address(SP, 1 * kWordSize));
     __ lw(T0, Address(SP, 0 * kWordSize));
   }
+  __ Bind(&slow_case_with_type_arguments);
+  // If is_cls_parameterized:
+  // T1: new object type arguments (instantiated or not).
+  // T0: instantiator type arguments or kNoInstantiator.
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   __ EnterStubFrame(true);  // Uses pool pointer to pass cls to runtime.
@@ -2145,8 +2140,9 @@
   if (n > 1) {
     // Get instance type arguments.
     __ LoadClass(T0, A0);
-    // Compute instance type arguments into R4.
+    // Compute instance type arguments into T1.
     Label has_no_type_arguments;
+    __ LoadImmediate(T1, reinterpret_cast<intptr_t>(Object::null()));
     __ lw(T2, FieldAddress(T0,
         Class::type_arguments_field_offset_in_words_offset()));
     __ BranchEqual(T2, Class::kNoTypeArguments, &has_no_type_arguments);
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index bfec063..5066097 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -25,8 +25,8 @@
 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects.");
 DEFINE_FLAG(bool, use_slow_path, false,
     "Set to true for debugging & verifying the slow paths.");
-DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, trace_optimized_ic_calls);
+DECLARE_FLAG(int, optimization_counter_threshold);
 
 
 // Input parameters:
@@ -1114,84 +1114,67 @@
   const int kInlineInstanceSize = 12;  // In words.
   const intptr_t instance_size = cls.instance_size();
   ASSERT(instance_size > 0);
-  const intptr_t type_args_size = InstantiatedTypeArguments::InstanceSize();
   __ LoadObject(R12, Object::null_object(), PP);
-  if (FLAG_inline_alloc &&
-      Heap::IsAllocatableInNewSpace(instance_size + type_args_size)) {
-    Label slow_case;
-    Heap* heap = Isolate::Current()->heap();
-    __ movq(RAX, Immediate(heap->TopAddress()));
-    __ movq(RAX, Address(RAX, 0));
-    __ leaq(RBX, Address(RAX, instance_size));
+  Label slow_case_with_type_arguments;
+  if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size)) {
+    Label slow_case_reload_type_arguments;
     if (is_cls_parameterized) {
-      __ movq(RCX, RBX);
-      // A new InstantiatedTypeArguments object only needs to be allocated if
-      // the instantiator is provided (not kNoInstantiator, but may be null).
-      Label no_instantiator;
-      __ cmpq(Address(RSP, kInstantiatorTypeArgumentsOffset),
-              Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
-      __ j(EQUAL, &no_instantiator, Assembler::kNearJump);
-      __ addq(RBX, Immediate(type_args_size));
-      __ Bind(&no_instantiator);
-      // RCX: potential new object end and, if RCX != RBX, potential new
-      // InstantiatedTypeArguments object start.
+      // Instantiation of the type arguments vector is only required if an
+      // instantiator is provided (not kNoInstantiator, but may be null).
+      __ movq(RDX, Address(RSP, kObjectTypeArgumentsOffset));
+      __ movq(RDI, Address(RSP, kInstantiatorTypeArgumentsOffset));
+      Label type_arguments_ready;
+      __ cmpq(RDI, Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
+      __ j(EQUAL, &type_arguments_ready, Assembler::kNearJump);
+      // Lookup instantiator RDI in instantiations array of type arguments RDX
+      // and, if found, use cached instantiated type arguments.
+      __ movq(RAX, FieldAddress(RDX, TypeArguments::instantiations_offset()));
+      __ movq(RBX, FieldAddress(RAX, Array::length_offset()));
+      __ leaq(RAX, FieldAddress(RAX, Array::data_offset()));
+      __ leaq(RBX, Address(RAX, RBX, TIMES_4, 0));  // RBX is smi.
+      Label loop, found;
+      __ Bind(&loop);
+      __ cmpq(RAX, RBX);
+      __ j(ABOVE_EQUAL, &slow_case_reload_type_arguments);
+      __ movq(RDX, Address(RAX, 0 * kWordSize));  // Cached instantiator.
+      __ cmpq(RDX, RDI);
+      __ j(EQUAL, &found, Assembler::kNearJump);
+      __ cmpq(RDX, Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
+      __ j(EQUAL, &slow_case_reload_type_arguments);
+      __ addq(RAX, Immediate(2 * kWordSize));
+      __ jmp(&loop, Assembler::kNearJump);
+      __ Bind(&found);
+      __ movq(RDX, Address(RAX, 1 * kWordSize));  // Cached instantiated args.
+      __ movq(RDI, Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
+      __ Bind(&type_arguments_ready);
+      // RDX: instantiated type arguments.
+      // RDI: kNoInstantiator.
     }
+    // Allocate the object and update top to point to
+    // next object start and initialize the allocated object.
+    // RDX: instantiated type arguments (if is_cls_parameterized).
+    // RDI: kNoInstantiator (if is_cls_parameterized).
+    Heap* heap = Isolate::Current()->heap();
+    __ movq(RCX, Immediate(heap->TopAddress()));
+    __ movq(RAX, Address(RCX, 0));
+    __ leaq(RBX, Address(RAX, instance_size));
     // Check if the allocation fits into the remaining space.
     // RAX: potential new object start.
     // RBX: potential next object start.
-    __ movq(RDI, Immediate(heap->EndAddress()));
-    __ cmpq(RBX, Address(RDI, 0));
+    // RCX: heap top address.
+    __ movq(R13, Immediate(heap->EndAddress()));
+    __ cmpq(RBX, Address(R13, 0));
     if (FLAG_use_slow_path) {
-      __ jmp(&slow_case);
+      __ jmp(&slow_case_with_type_arguments);
     } else {
-      __ j(ABOVE_EQUAL, &slow_case);
+      __ j(ABOVE_EQUAL, &slow_case_with_type_arguments);
     }
-
-    // Successfully allocated the object(s), now update top to point to
-    // next object start and initialize the object.
-    __ movq(RDI, Immediate(heap->TopAddress()));
-    __ movq(Address(RDI, 0), RBX);
+    __ movq(Address(RCX, 0), RBX);
     __ UpdateAllocationStats(cls.id());
 
-    if (is_cls_parameterized) {
-      // Initialize the type arguments field in the object.
-      // RAX: new object start.
-      // RCX: potential new object end and, if RCX != RBX, potential new
-      // InstantiatedTypeArguments object start.
-      // RBX: next object start.
-      Label type_arguments_ready;
-      __ movq(RDI, Address(RSP, kObjectTypeArgumentsOffset));
-      __ cmpq(RCX, RBX);
-      __ j(EQUAL, &type_arguments_ready, Assembler::kNearJump);
-      // Initialize InstantiatedTypeArguments object at RCX.
-      __ movq(Address(RCX,
-          InstantiatedTypeArguments::uninstantiated_type_arguments_offset()),
-              RDI);
-      __ movq(RDX, Address(RSP, kInstantiatorTypeArgumentsOffset));
-      __ movq(Address(RCX,
-          InstantiatedTypeArguments::instantiator_type_arguments_offset()),
-              RDX);
-      const Class& ita_cls =
-          Class::ZoneHandle(Object::instantiated_type_arguments_class());
-      // Set the tags.
-      uword tags = 0;
-      tags = RawObject::SizeTag::update(type_args_size, tags);
-      tags = RawObject::ClassIdTag::update(ita_cls.id(), tags);
-      __ movq(Address(RCX, Instance::tags_offset()), Immediate(tags));
-      // Set the new InstantiatedTypeArguments object (RCX) as the type
-      // arguments (RDI) of the new object (RAX).
-      __ movq(RDI, RCX);
-      __ addq(RDI, Immediate(kHeapObjectTag));
-      // Set RBX to new object end.
-      __ movq(RBX, RCX);
-      __ Bind(&type_arguments_ready);
-      // RAX: new object.
-      // RDI: new object type arguments.
-    }
-
     // RAX: new object start.
     // RBX: next object start.
-    // RDI: new object type arguments (if is_cls_parameterized).
+    // RDX: new object type arguments (if is_cls_parameterized).
     // Set the tags.
     uword tags = 0;
     tags = RawObject::SizeTag::update(instance_size, tags);
@@ -1202,7 +1185,8 @@
     // Initialize the remaining words of the object.
     // RAX: new object start.
     // RBX: next object start.
-    // RDI: new object type arguments (if is_cls_parameterized).
+    // RDX: new object type arguments (if is_cls_parameterized).
+    // R12: raw null.
     // First try inlining the initialization without a loop.
     if (instance_size < (kInlineInstanceSize * kWordSize)) {
       // Check if the object contains any non-header fields.
@@ -1218,7 +1202,7 @@
       // RAX: new object.
       // RBX: next object start.
       // RCX: next word to be initialized.
-      // RDI: new object type arguments (if is_cls_parameterized).
+      // RDX: new object type arguments (if is_cls_parameterized).
       Label init_loop;
       Label done;
       __ Bind(&init_loop);
@@ -1230,28 +1214,32 @@
       __ Bind(&done);
     }
     if (is_cls_parameterized) {
-      // RDI: new object type arguments.
+      // RDX: new object type arguments.
       // Set the type arguments in the new object.
-      __ movq(Address(RAX, cls.type_arguments_field_offset()), RDI);
+      __ movq(Address(RAX, cls.type_arguments_field_offset()), RDX);
     }
     // Done allocating and initializing the instance.
     // RAX: new object.
     __ addq(RAX, Immediate(kHeapObjectTag));
     __ ret();
 
-    __ Bind(&slow_case);
+    __ Bind(&slow_case_reload_type_arguments);
   }
   if (is_cls_parameterized) {
-    __ movq(RAX, Address(RSP, kObjectTypeArgumentsOffset));
-    __ movq(RDX, Address(RSP, kInstantiatorTypeArgumentsOffset));
+    __ movq(RDX, Address(RSP, kObjectTypeArgumentsOffset));
+    __ movq(RDI, Address(RSP, kInstantiatorTypeArgumentsOffset));
   }
+  __ Bind(&slow_case_with_type_arguments);
+  // If is_cls_parameterized:
+  // RDX: new object type arguments (instantiated or not).
+  // RDI: instantiator type arguments or kNoInstantiator.
   // Create a stub frame.
   __ EnterStubFrame(true);  // Uses PP to access class object.
   __ pushq(R12);  // Setup space on stack for return value.
   __ PushObject(cls, PP);  // Push class of object to be allocated.
   if (is_cls_parameterized) {
-    __ pushq(RAX);  // Push type arguments of object to be allocated.
-    __ pushq(RDX);  // Push type arguments of instantiator.
+    __ pushq(RDX);  // Push type arguments of object to be allocated.
+    __ pushq(RDI);  // Push type arguments of instantiator.
   } else {
     __ pushq(R12);  // Push null type arguments.
     __ pushq(Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
@@ -1634,7 +1622,7 @@
   Label is_compiled;
   __ movq(RCX, FieldAddress(RAX, Function::code_offset()));
   if (FLAG_collect_code) {
-    // If code might be GC'd, then EBX might be null. If it is, recompile.
+    // If code might be GC'd, then RBX might be null. If it is, recompile.
     __ CompareObject(RCX, Object::null_object(), PP);
     __ j(NOT_EQUAL, &is_compiled, Assembler::kNearJump);
     __ EnterStubFrame();
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 8052a1a..4a7d2b0 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -80,7 +80,6 @@
   V(BoundedType, "_BoundedType")                                               \
   V(MixinAppType, "_MixinAppType")                                             \
   V(TypeArguments, "TypeArguments")                                            \
-  V(InstantiatedTypeArguments, "InstantiatedTypeArguments")                    \
   V(PatchClass, "PatchClass")                                                  \
   V(Function, "Function")                                                      \
   V(FunctionImpl, "_FunctionImpl")                                             \
diff --git a/runtime/vm/thread_interrupter.cc b/runtime/vm/thread_interrupter.cc
index 2d44208..d2858f7 100644
--- a/runtime/vm/thread_interrupter.cc
+++ b/runtime/vm/thread_interrupter.cc
@@ -52,19 +52,21 @@
 intptr_t ThreadInterrupter::interrupt_period_ = 1000;
 ThreadLocalKey ThreadInterrupter::thread_state_key_ =
     Thread::kUnsetThreadLocalKey;
-ThreadInterrupter::ThreadState** ThreadInterrupter::threads_ = NULL;
-intptr_t ThreadInterrupter::threads_capacity_ = 0;
-intptr_t ThreadInterrupter::threads_size_ = 0;
 
 
 void ThreadInterrupter::InitOnce() {
   ASSERT(!initialized_);
-  initialized_ = true;
   ASSERT(thread_state_key_ == Thread::kUnsetThreadLocalKey);
   thread_state_key_ = Thread::CreateThreadLocal();
   ASSERT(thread_state_key_ != Thread::kUnsetThreadLocalKey);
   monitor_ = new Monitor();
-  ResizeThreads(16);
+  ASSERT(monitor_ != NULL);
+  initialized_ = true;
+}
+
+
+void ThreadInterrupter::Startup() {
+  ASSERT(initialized_);
   if (FLAG_trace_thread_interrupter) {
     OS::Print("ThreadInterrupter starting up.\n");
   }
@@ -92,15 +94,9 @@
   if (FLAG_trace_thread_interrupter) {
     OS::Print("ThreadInterrupter shutting down.\n");
   }
-  intptr_t size_at_shutdown = 0;
   {
     MonitorLocker ml(monitor_);
     shutdown_ = true;
-    size_at_shutdown = threads_size_;
-    threads_size_ = 0;
-    threads_capacity_ = 0;
-    free(threads_);
-    threads_ = NULL;
   }
   {
     MonitorLocker shutdown_ml(monitor_);
@@ -110,7 +106,7 @@
   }
   interrupter_thread_id_ = Thread::kInvalidThreadId;
   if (FLAG_trace_thread_interrupter) {
-    OS::Print("ThreadInterrupter shut down (%" Pd ").\n", size_at_shutdown);
+    OS::Print("ThreadInterrupter shut down.\n");
   }
 }
 
@@ -121,27 +117,22 @@
   }
   ASSERT(initialized_);
   ASSERT(period > 0);
-  {
-    MonitorLocker ml(monitor_);
-    interrupt_period_ = period;
-  }
+  interrupt_period_ = period;
 }
 
 
 // Register the currently running thread for interrupts. If the current thread
 // is already registered, callback and data will be updated.
-void ThreadInterrupter::Register(ThreadInterruptCallback callback, void* data) {
+InterruptableThreadState* ThreadInterrupter::Register(
+    ThreadInterruptCallback callback, void* data) {
   if (shutdown_) {
-    return;
+    return NULL;
   }
   ASSERT(initialized_);
-  {
-    MonitorLocker ml(monitor_);
-    _EnsureThreadStateCreated();
-    // Set callback and data.
-    UpdateStateObject(callback, data);
-    _Enable();
-  }
+  InterruptableThreadState* state = _EnsureThreadStateCreated();
+  // Set callback and data.
+  UpdateStateObject(callback, data);
+  return state;
 }
 
 
@@ -151,44 +142,14 @@
     return;
   }
   ASSERT(initialized_);
-  {
-    MonitorLocker ml(monitor_);
-    _EnsureThreadStateCreated();
-    // Clear callback and data.
-    UpdateStateObject(NULL, NULL);
-    _Disable();
-  }
+  _EnsureThreadStateCreated();
+  // Clear callback and data.
+  UpdateStateObject(NULL, NULL);
 }
 
 
-void ThreadInterrupter::Enable() {
-  if (shutdown_) {
-    return;
-  }
-  ASSERT(initialized_);
-  {
-    MonitorLocker ml(monitor_);
-    _EnsureThreadStateCreated();
-    _Enable();
-  }
-}
-
-
-void ThreadInterrupter::Disable() {
-  if (shutdown_) {
-    return;
-  }
-  ASSERT(initialized_);
-  {
-    MonitorLocker ml(monitor_);
-    _EnsureThreadStateCreated();
-    _Disable();
-  }
-}
-
-
-void ThreadInterrupter::_EnsureThreadStateCreated() {
-  ThreadState* state = CurrentThreadState();
+InterruptableThreadState* ThreadInterrupter::_EnsureThreadStateCreated() {
+  InterruptableThreadState* state = CurrentThreadState();
   if (state == NULL) {
     // Create thread state object lazily.
     ThreadId current_thread = Thread::GetCurrentThreadId();
@@ -197,56 +158,21 @@
       OS::Print("ThreadInterrupter Tracking %p\n",
                 reinterpret_cast<void*>(tid));
     }
-    state = new ThreadState();
+    // Note: We currently do not free a thread's InterruptableThreadState.
+    state = new InterruptableThreadState();
+    ASSERT(state != NULL);
     state->callback = NULL;
     state->data = NULL;
     state->id = current_thread;
     SetCurrentThreadState(state);
   }
+  return state;
 }
 
 
-void ThreadInterrupter::_Enable() {
-  // Must be called with monitor_ locked.
-  ThreadId current_thread = Thread::GetCurrentThreadId();
-  if (Thread::Compare(current_thread, interrupter_thread_id_)) {
-    return;
-  }
-  intptr_t i = FindThreadIndex(current_thread);
-  if (i >= 0) {
-    return;
-  }
-  AddThread(current_thread);
-  if (FLAG_trace_thread_interrupter) {
-    intptr_t tid = Thread::ThreadIdToIntPtr(current_thread);
-    OS::Print("ThreadInterrupter Added %p\n", reinterpret_cast<void*>(tid));
-  }
-}
-
-void ThreadInterrupter::_Disable() {
-  // Must be called with monitor_ locked.
-  ThreadId current_thread = Thread::GetCurrentThreadId();
-  if (Thread::Compare(current_thread, interrupter_thread_id_)) {
-    return;
-  }
-  intptr_t index = FindThreadIndex(current_thread);
-  if (index < 0) {
-    // Not registered.
-    return;
-  }
-  ThreadState* state = RemoveThread(index);
-  ASSERT(state != NULL);
-  ASSERT(state == ThreadInterrupter::CurrentThreadState());
-  if (FLAG_trace_thread_interrupter) {
-    intptr_t tid = Thread::ThreadIdToIntPtr(current_thread);
-    OS::Print("ThreadInterrupter Removed %p\n", reinterpret_cast<void*>(tid));
-  }
-}
-
 void ThreadInterrupter::UpdateStateObject(ThreadInterruptCallback callback,
                                           void* data) {
-  // Must be called with monitor_ locked.
-  ThreadState* state = CurrentThreadState();
+  InterruptableThreadState* state = CurrentThreadState();
   ThreadId current_thread = Thread::GetCurrentThreadId();
   ASSERT(state != NULL);
   ASSERT(Thread::Compare(state->id, Thread::GetCurrentThreadId()));
@@ -267,92 +193,43 @@
 }
 
 
-ThreadInterrupter::ThreadState* ThreadInterrupter::CurrentThreadState() {
-  ThreadState* state = reinterpret_cast<ThreadState*>(
+InterruptableThreadState* ThreadInterrupter::GetCurrentThreadState() {
+  return _EnsureThreadStateCreated();
+}
+
+
+InterruptableThreadState* ThreadInterrupter::CurrentThreadState() {
+  InterruptableThreadState* state = reinterpret_cast<InterruptableThreadState*>(
       Thread::GetThreadLocal(thread_state_key_));
   return state;
 }
 
 
-void ThreadInterrupter::SetCurrentThreadState(ThreadState* state) {
+void ThreadInterrupter::SetCurrentThreadState(InterruptableThreadState* state) {
   Thread::SetThreadLocal(thread_state_key_, reinterpret_cast<uword>(state));
 }
 
 
-void ThreadInterrupter::ResizeThreads(intptr_t new_capacity) {
-  // Must be called with monitor_ locked.
-  ASSERT(new_capacity < kMaxThreads);
-  ASSERT(new_capacity > threads_capacity_);
-  ThreadState* state = NULL;
-  threads_ = reinterpret_cast<ThreadState**>(
-      realloc(threads_, sizeof(state) * new_capacity));
-  for (intptr_t i = threads_capacity_; i < new_capacity; i++) {
-    threads_[i] = NULL;
-  }
-  threads_capacity_ = new_capacity;
-}
-
-
-void ThreadInterrupter::AddThread(ThreadId id) {
-  // Must be called with monitor_ locked.
-  if (threads_ == NULL) {
-    // We are shutting down.
-    return;
-  }
-  ThreadState* state = CurrentThreadState();
-  if (state->callback == NULL) {
-    // No callback.
-    return;
-  }
-  if (threads_size_ == threads_capacity_) {
-    ResizeThreads(threads_capacity_ == 0 ? 16 : threads_capacity_ * 2);
-  }
-  threads_[threads_size_] = state;
-  threads_size_++;
-}
-
-
-intptr_t ThreadInterrupter::FindThreadIndex(ThreadId id) {
-  // Must be called with monitor_ locked.
-  if (threads_ == NULL) {
-    // We are shutting down.
-    return -1;
-  }
-  for (intptr_t i = 0; i < threads_size_; i++) {
-    if (threads_[i]->id == id) {
-      return i;
-    }
-  }
-  return -1;
-}
-
-
-ThreadInterrupter::ThreadState* ThreadInterrupter::RemoveThread(intptr_t i) {
-  // Must be called with monitor_ locked.
-  if (threads_ == NULL) {
-    // We are shutting down.
-    return NULL;
-  }
-  ASSERT(i < threads_size_);
-  ThreadState* state = threads_[i];
-  ASSERT(state != NULL);
-  intptr_t last = threads_size_ - 1;
-  if (i != last) {
-    threads_[i] = threads_[last];
-  }
-  // Mark last as NULL.
-  threads_[last] = NULL;
-  // Pop.
-  threads_size_--;
-  return state;
-}
-
-
 void ThreadInterruptNoOp(const InterruptedThreadState& state, void* data) {
   // NoOp.
 }
 
 
+class ThreadInterrupterVisitIsolates : public IsolateVisitor {
+ public:
+  ThreadInterrupterVisitIsolates() { }
+  void VisitIsolate(Isolate* isolate) {
+    ASSERT(isolate != NULL);
+    InterruptableThreadState* state = isolate->thread_state();
+    if (state == NULL) {
+      return;
+    }
+    ASSERT(state->id != Thread::kInvalidThreadId);
+    ThreadInterrupter::InterruptThread(state);
+  }
+};
+
+
 void ThreadInterrupter::ThreadMain(uword parameters) {
   ASSERT(initialized_);
   InstallSignalHandler();
@@ -367,11 +244,11 @@
     startup_ml.Notify();
   }
   {
-    MonitorLocker ml(monitor_);
+    MonitorLocker wait_ml(monitor_);
+    ThreadInterrupterVisitIsolates visitor;
     while (!shutdown_) {
-      int64_t current_time = OS::GetCurrentTimeMicros();
-      InterruptThreads(current_time);
-      ml.WaitMicros(interrupt_period_);
+      Isolate::VisitIsolates(&visitor);
+      wait_ml.WaitMicros(interrupt_period_);
     }
   }
   if (FLAG_trace_thread_interrupter) {
diff --git a/runtime/vm/thread_interrupter.h b/runtime/vm/thread_interrupter.h
index 3a31683..30bc4a8 100644
--- a/runtime/vm/thread_interrupter.h
+++ b/runtime/vm/thread_interrupter.h
@@ -30,9 +30,19 @@
 typedef void (*ThreadInterruptCallback)(const InterruptedThreadState& state,
                                         void* data);
 
+// State stored per registered thread.
+class InterruptableThreadState {
+ public:
+  ThreadId id;
+  ThreadInterruptCallback callback;
+  void* data;
+};
+
 class ThreadInterrupter : public AllStatic {
  public:
   static void InitOnce();
+
+  static void Startup();
   static void Shutdown();
 
   // Delay between interrupts.
@@ -40,14 +50,16 @@
 
   // Register the currently running thread for interrupts. If the current thread
   // is already registered, callback and data will be updated.
-  static void Register(ThreadInterruptCallback callback, void* data);
+  static InterruptableThreadState* Register(ThreadInterruptCallback callback,
+                                            void* data);
   // Unregister the currently running thread for interrupts.
   static void Unregister();
 
-  // Enable interrupts for this thread. Does not alter callback.
-  static void Enable();
-  // Disable interrupts for this thread. Does not alter callback.
-  static void Disable();
+  // Get the current thread state. Will create a thread state if one hasn't
+  // been allocated.
+  static InterruptableThreadState* GetCurrentThreadState();
+  // Get the current thread state. Will not create one if one doesn't exist.
+  static InterruptableThreadState* CurrentThreadState();
 
  private:
   static const intptr_t kMaxThreads = 4096;
@@ -58,38 +70,18 @@
   static Monitor* monitor_;
   static intptr_t interrupt_period_;
   static ThreadLocalKey thread_state_key_;
-  // State stored per registered thread.
-  struct ThreadState {
-    ThreadId id;
-    ThreadInterruptCallback callback;
-    void* data;
-  };
 
+  static InterruptableThreadState* _EnsureThreadStateCreated();
   static void UpdateStateObject(ThreadInterruptCallback callback, void* data);
-  static ThreadState* CurrentThreadState();
-  static void SetCurrentThreadState(ThreadState* state);
 
-  // Registered thread table.
-  static ThreadState** threads_;
-  static intptr_t threads_capacity_;
-  static intptr_t threads_size_;
-  static void _EnsureThreadStateCreated();
-  static void _Enable();
-  static void _Disable();
-  static void ResizeThreads(intptr_t new_capacity);
-  static void AddThread(ThreadId id);
-  static intptr_t FindThreadIndex(ThreadId id);
-  static ThreadState* RemoveThread(intptr_t i);
+  static void SetCurrentThreadState(InterruptableThreadState* state);
 
-  friend class ThreadInterrupterAndroid;
-  friend class ThreadInterrupterMacOS;
-  friend class ThreadInterrupterLinux;
-  friend class ThreadInterrupterWin;
-
-  static void InterruptThreads(int64_t current_time);
+  static void InterruptThread(InterruptableThreadState* thread_state);
   static void ThreadMain(uword parameters);
 
   static void InstallSignalHandler();
+
+  friend class ThreadInterrupterVisitIsolates;
 };
 
 void ThreadInterruptNoOp(const InterruptedThreadState& state, void* data);
diff --git a/runtime/vm/thread_interrupter_android.cc b/runtime/vm/thread_interrupter_android.cc
index a5a4f8a..31af136 100644
--- a/runtime/vm/thread_interrupter_android.cc
+++ b/runtime/vm/thread_interrupter_android.cc
@@ -20,8 +20,7 @@
     if (signal != SIGPROF) {
       return;
     }
-    ThreadInterrupter::ThreadState* state =
-        ThreadInterrupter::CurrentThreadState();
+    InterruptableThreadState* state = ThreadInterrupter::CurrentThreadState();
     if ((state == NULL) || (state->callback == NULL)) {
       // No interrupter state or callback.
       return;
@@ -31,16 +30,12 @@
 };
 
 
-void ThreadInterrupter::InterruptThreads(int64_t current_time) {
-  for (intptr_t i = 0; i < threads_size_; i++) {
-    ThreadState* state = threads_[i];
-    ASSERT(state->id != Thread::kInvalidThreadId);
-    if (FLAG_trace_thread_interrupter) {
-      OS::Print("ThreadInterrupter interrupting %p\n",
-                reinterpret_cast<void*>(state->id));
-    }
-    pthread_kill(state->id, SIGPROF);
+void ThreadInterrupter::InterruptThread(InterruptableThreadState* state) {
+  if (FLAG_trace_thread_interrupter) {
+    OS::Print("ThreadInterrupter interrupting %p\n",
+              reinterpret_cast<void*>(state->id));
   }
+  pthread_kill(state->id, SIGPROF);
 }
 
 
diff --git a/runtime/vm/thread_interrupter_linux.cc b/runtime/vm/thread_interrupter_linux.cc
index ee6b4a7..f898fcc 100644
--- a/runtime/vm/thread_interrupter_linux.cc
+++ b/runtime/vm/thread_interrupter_linux.cc
@@ -20,8 +20,7 @@
     if (signal != SIGPROF) {
       return;
     }
-    ThreadInterrupter::ThreadState* state =
-        ThreadInterrupter::CurrentThreadState();
+    InterruptableThreadState* state = ThreadInterrupter::CurrentThreadState();
     if ((state == NULL) || (state->callback == NULL)) {
       // No interrupter state or callback.
       return;
@@ -40,16 +39,12 @@
 };
 
 
-void ThreadInterrupter::InterruptThreads(int64_t current_time) {
-  for (intptr_t i = 0; i < threads_size_; i++) {
-    ThreadState* state = threads_[i];
-    ASSERT(state->id != Thread::kInvalidThreadId);
-    if (FLAG_trace_thread_interrupter) {
-      OS::Print("ThreadInterrupter interrupting %p\n",
-                reinterpret_cast<void*>(state->id));
-    }
-    pthread_kill(state->id, SIGPROF);
+void ThreadInterrupter::InterruptThread(InterruptableThreadState* state) {
+  if (FLAG_trace_thread_interrupter) {
+    OS::Print("ThreadInterrupter interrupting %p\n",
+              reinterpret_cast<void*>(state->id));
   }
+  pthread_kill(state->id, SIGPROF);
 }
 
 
diff --git a/runtime/vm/thread_interrupter_macos.cc b/runtime/vm/thread_interrupter_macos.cc
index f9deca5..c26eab2 100644
--- a/runtime/vm/thread_interrupter_macos.cc
+++ b/runtime/vm/thread_interrupter_macos.cc
@@ -20,14 +20,12 @@
     if (signal != SIGPROF) {
       return;
     }
-    ThreadInterrupter::ThreadState* state =
-        ThreadInterrupter::CurrentThreadState();
+    InterruptableThreadState* state = ThreadInterrupter::CurrentThreadState();
     if ((state == NULL) || (state->callback == NULL)) {
       // No interrupter state or callback.
       return;
     }
     ASSERT(Thread::Compare(state->id, Thread::GetCurrentThreadId()));
-
     // Extract thread state.
     ucontext_t* context = reinterpret_cast<ucontext_t*>(context_);
     mcontext_t mcontext = context->uc_mcontext;
@@ -41,15 +39,11 @@
 };
 
 
-void ThreadInterrupter::InterruptThreads(int64_t current_time) {
-  for (intptr_t i = 0; i < threads_size_; i++) {
-    ThreadState* state = threads_[i];
-    ASSERT(state->id != Thread::kInvalidThreadId);
-    if (FLAG_trace_thread_interrupter) {
-      OS::Print("ThreadInterrupter interrupting %p\n", state->id);
-    }
-    pthread_kill(state->id, SIGPROF);
+void ThreadInterrupter::InterruptThread(InterruptableThreadState* state) {
+  if (FLAG_trace_thread_interrupter) {
+    OS::Print("ThreadInterrupter interrupting %p\n", state->id);
   }
+  pthread_kill(state->id, SIGPROF);
 }
 
 
diff --git a/runtime/vm/thread_interrupter_win.cc b/runtime/vm/thread_interrupter_win.cc
index c933cbb..4058da3 100644
--- a/runtime/vm/thread_interrupter_win.cc
+++ b/runtime/vm/thread_interrupter_win.cc
@@ -38,7 +38,7 @@
   }
 
 
-  static void Interrupt(ThreadInterrupter::ThreadState* state) {
+  static void Interrupt(InterruptableThreadState* state) {
     ASSERT(GetCurrentThread() != state->id);
     DWORD result = SuspendThread(state->id);
     if (result == kThreadError) {
@@ -70,19 +70,15 @@
 };
 
 
-void ThreadInterrupter::InterruptThreads(int64_t current_time) {
-  for (intptr_t i = 0; i < threads_size_; i++) {
-    ThreadState* state = threads_[i];
-    ASSERT(state->id != Thread::kInvalidThreadId);
-    if (FLAG_trace_thread_interrupter) {
-      OS::Print("ThreadInterrupter suspending %p\n",
-                reinterpret_cast<void*>(state->id));
-    }
-    ThreadInterrupterWin::Interrupt(state);
-    if (FLAG_trace_thread_interrupter) {
-      OS::Print("ThreadInterrupter resuming %p\n",
-                reinterpret_cast<void*>(state->id));
-    }
+void ThreadInterrupter::InterruptThread(InterruptableThreadState* state) {
+  if (FLAG_trace_thread_interrupter) {
+    OS::Print("ThreadInterrupter suspending %p\n",
+              reinterpret_cast<void*>(state->id));
+  }
+  ThreadInterrupterWin::Interrupt(state);
+  if (FLAG_trace_thread_interrupter) {
+    OS::Print("ThreadInterrupter resuming %p\n",
+              reinterpret_cast<void*>(state->id));
   }
 }
 
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index 0c0c912..d13cd22 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -35,7 +35,8 @@
 UNIT_TEST_CASE(Monitor) {
   // This unit test case needs a running isolate.
   Isolate* isolate = Isolate::Init(NULL);
-  // Profiler interrupts interfere with this test.
+  // Thread interrupter interferes with this test, disable interrupts.
+  isolate->set_thread_state(NULL);
   Profiler::EndExecution(isolate);
   Monitor* monitor = new Monitor();
   monitor->Enter();
diff --git a/runtime/vm/virtual_memory.cc b/runtime/vm/virtual_memory.cc
index 8accabd..4c78c09 100644
--- a/runtime/vm/virtual_memory.cc
+++ b/runtime/vm/virtual_memory.cc
@@ -9,6 +9,12 @@
 
 namespace dart {
 
+bool VirtualMemory::InSamePage(uword address0, uword address1) {
+  return (Utils::RoundDown(address0, PageSize()) ==
+          Utils::RoundDown(address1, PageSize()));
+}
+
+
 VirtualMemory* VirtualMemory::ReserveAligned(intptr_t size,
                                              intptr_t alignment) {
   ASSERT((size & (PageSize() - 1)) == 0);
diff --git a/runtime/vm/virtual_memory.h b/runtime/vm/virtual_memory.h
index 2bc0f78..09eeb7e 100644
--- a/runtime/vm/virtual_memory.h
+++ b/runtime/vm/virtual_memory.h
@@ -41,7 +41,10 @@
   }
 
   // Changes the protection of the virtual memory area.
-  bool Protect(Protection mode);
+  static bool Protect(void* address, intptr_t size, Protection mode);
+  bool Protect(Protection mode) {
+    return Protect(address(), size(), mode);
+  }
 
   // Reserves a virtual memory segment with size. If a segment of the requested
   // size cannot be allocated NULL is returned.
@@ -57,6 +60,8 @@
     return page_size_;
   }
 
+  static bool InSamePage(uword address0, uword address1);
+
  private:
   // Truncate this virtual memory segment.
   void Truncate(uword new_start, intptr_t size);
diff --git a/runtime/vm/virtual_memory_android.cc b/runtime/vm/virtual_memory_android.cc
index 966644d..d4d4a21 100644
--- a/runtime/vm/virtual_memory_android.cc
+++ b/runtime/vm/virtual_memory_android.cc
@@ -76,7 +76,10 @@
 }
 
 
-bool VirtualMemory::Protect(Protection mode) {
+bool VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
+  uword start_address = reinterpret_cast<uword>(address);
+  uword end_address = start_address + size;
+  uword page_address = Utils::RoundDown(start_address, PageSize());
   int prot = 0;
   switch (mode) {
     case kNoAccess:
@@ -95,7 +98,9 @@
       prot = PROT_READ | PROT_WRITE | PROT_EXEC;
       break;
   }
-  return (mprotect(address(), size(), prot) == 0);
+  return (mprotect(reinterpret_cast<void*>(page_address),
+                   end_address - page_address,
+                   prot) == 0);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/virtual_memory_linux.cc b/runtime/vm/virtual_memory_linux.cc
index 7a0d02b..35f5524 100644
--- a/runtime/vm/virtual_memory_linux.cc
+++ b/runtime/vm/virtual_memory_linux.cc
@@ -76,7 +76,10 @@
 }
 
 
-bool VirtualMemory::Protect(Protection mode) {
+bool VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
+  uword start_address = reinterpret_cast<uword>(address);
+  uword end_address = start_address + size;
+  uword page_address = Utils::RoundDown(start_address, PageSize());
   int prot = 0;
   switch (mode) {
     case kNoAccess:
@@ -95,9 +98,12 @@
       prot = PROT_READ | PROT_WRITE | PROT_EXEC;
       break;
   }
-  return (mprotect(address(), size(), prot) == 0);
+  return (mprotect(reinterpret_cast<void*>(page_address),
+                   end_address - page_address,
+                   prot) == 0);
 }
 
+
 }  // namespace dart
 
 #endif  // defined(TARGET_OS_LINUX)
diff --git a/runtime/vm/virtual_memory_macos.cc b/runtime/vm/virtual_memory_macos.cc
index c99a349..e74acab 100644
--- a/runtime/vm/virtual_memory_macos.cc
+++ b/runtime/vm/virtual_memory_macos.cc
@@ -76,7 +76,10 @@
 }
 
 
-bool VirtualMemory::Protect(Protection mode) {
+bool VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
+  uword start_address = reinterpret_cast<uword>(address);
+  uword end_address = start_address + size;
+  uword page_address = Utils::RoundDown(start_address, PageSize());
   int prot = 0;
   switch (mode) {
     case kNoAccess:
@@ -95,7 +98,9 @@
       prot = PROT_READ | PROT_WRITE | PROT_EXEC;
       break;
   }
-  return (mprotect(address(), size(), prot) == 0);
+  return (mprotect(reinterpret_cast<void*>(page_address),
+                   end_address - page_address,
+                   prot) == 0);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/virtual_memory_win.cc b/runtime/vm/virtual_memory_win.cc
index d1a9277..a9caf8f 100644
--- a/runtime/vm/virtual_memory_win.cc
+++ b/runtime/vm/virtual_memory_win.cc
@@ -8,6 +8,7 @@
 #include "vm/virtual_memory.h"
 
 #include "platform/assert.h"
+#include "vm/os.h"
 
 namespace dart {
 
@@ -63,7 +64,10 @@
 }
 
 
-bool VirtualMemory::Protect(Protection mode) {
+bool VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
+  uword start_address = reinterpret_cast<uword>(address);
+  uword end_address = start_address + size;
+  uword page_address = Utils::RoundDown(start_address, PageSize());
   DWORD prot = 0;
   switch (mode) {
     case kNoAccess:
@@ -83,7 +87,11 @@
       break;
   }
   DWORD old_prot = 0;
-  return VirtualProtect(address(), size(), prot, &old_prot);
+  bool result = VirtualProtect(reinterpret_cast<void*>(page_address),
+                        end_address - page_address,
+                        prot,
+                        &old_prot);
+  return result;
 }
 
 }  // namespace dart
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index 2551bf8..e115907 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -1471,6 +1471,7 @@
   Uri translateResolvedUri(LibraryElement importingLibrary,
                            Uri resolvedUri, Node node) {
     unimplemented('Compiler.translateResolvedUri');
+    return null;
   }
 
   /**
@@ -1480,10 +1481,12 @@
    */
   Future<Script> readScript(Uri readableUri, [Element element, Node node]) {
     unimplemented('Compiler.readScript');
+    return null;
   }
 
   String get legDirectory {
     unimplemented('Compiler.legDirectory');
+    return null;
   }
 
   // TODO(karlklose): split into findHelperFunction and findHelperClass and
diff --git a/sdk/lib/_internal/compiler/implementation/constant_system_dart.dart b/sdk/lib/_internal/compiler/implementation/constant_system_dart.dart
index 64b6003..cf86e65 100644
--- a/sdk/lib/_internal/compiler/implementation/constant_system_dart.dart
+++ b/sdk/lib/_internal/compiler/implementation/constant_system_dart.dart
@@ -241,13 +241,12 @@
 abstract class RelationalNumOperation implements BinaryOperation {
   const RelationalNumOperation();
   Constant fold(Constant left, Constant right) {
-    if (left.isNum() && right.isNum()) {
-      NumConstant leftNum = left;
-      NumConstant rightNum = right;
-      bool foldedValue = foldNums(leftNum.value, rightNum.value);
-      assert(foldedValue != null);
-      return DART_CONSTANT_SYSTEM.createBool(foldedValue);
-    }
+    if (!left.isNum() || !right.isNum()) return null;
+    NumConstant leftNum = left;
+    NumConstant rightNum = right;
+    bool foldedValue = foldNums(leftNum.value, rightNum.value);
+    assert(foldedValue != null);
+    return DART_CONSTANT_SYSTEM.createBool(foldedValue);
   }
 
   bool foldNums(num left, num right);
diff --git a/sdk/lib/_internal/compiler/implementation/constants.dart b/sdk/lib/_internal/compiler/implementation/constants.dart
index 272fd6a..b5f7a1a 100644
--- a/sdk/lib/_internal/compiler/implementation/constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/constants.dart
@@ -75,9 +75,8 @@
     return new DartString.literal(element.name);
   }
 
-  DartType computeType(Compiler compiler) {
-    return compiler.functionClass.computeType(compiler);
-  }
+  // TODO(johnniwinther): remove computeType.
+  DartType computeType(Compiler compiler) => element.computeType(compiler);
 
   ti.TypeMask computeMask(Compiler compiler) {
     return compiler.typesTask.functionType;
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/emitter.dart
index c58319e..0e33c0c 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/emitter.dart
@@ -4,7 +4,7 @@
 
 part of dart_backend;
 
-String emitCode(
+void emitCode(
       Unparser unparser,
       Map<LibraryElement, String> imports,
       Iterable<Node> topLevelNodes,
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/utils.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/utils.dart
index 14a2cc9..190b292 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/utils.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/utils.dart
@@ -25,105 +25,107 @@
     return clone;
   }
 
-  visitBlock(Block node) => new Block(visit(node.statements));
+  Node visitBlock(Block node) => new Block(visit(node.statements));
 
-  visitBreakStatement(BreakStatement node) => new BreakStatement(
+  Node visitBreakStatement(BreakStatement node) => new BreakStatement(
       visit(node.target), node.keywordToken, node.semicolonToken);
 
-  visitCascade(Cascade node) => new Cascade(visit(node.expression));
+  Node visitCascade(Cascade node) => new Cascade(visit(node.expression));
 
-  visitCascadeReceiver(CascadeReceiver node) => new CascadeReceiver(
+  Node visitCascadeReceiver(CascadeReceiver node) => new CascadeReceiver(
       visit(node.expression), node.cascadeOperator);
 
-  visitCaseMatch(CaseMatch node) => new CaseMatch(
+  Node visitCaseMatch(CaseMatch node) => new CaseMatch(
       node.caseKeyword, visit(node.expression), node.colonToken);
 
-  visitCatchBlock(CatchBlock node) => new CatchBlock(
+  Node visitCatchBlock(CatchBlock node) => new CatchBlock(
       visit(node.type), visit(node.formals), visit(node.block),
       node.onKeyword, node.catchKeyword);
 
-  visitClassNode(ClassNode node) => new ClassNode(
+  Node visitClassNode(ClassNode node) => new ClassNode(
       visit(node.modifiers), visit(node.name), visit(node.typeParameters),
       visit(node.superclass), visit(node.interfaces),
       node.beginToken, node.extendsKeyword, visit(node.body), node.endToken);
 
-  visitConditional(Conditional node) => new Conditional(
+  Node visitConditional(Conditional node) => new Conditional(
       visit(node.condition), visit(node.thenExpression),
       visit(node.elseExpression), node.questionToken, node.colonToken);
 
-  visitContinueStatement(ContinueStatement node) => new ContinueStatement(
+  Node visitContinueStatement(ContinueStatement node) => new ContinueStatement(
       visit(node.target), node.keywordToken, node.semicolonToken);
 
-  visitDoWhile(DoWhile node) => new DoWhile(
+  Node visitDoWhile(DoWhile node) => new DoWhile(
       visit(node.body), visit(node.condition),
       node.doKeyword, node.whileKeyword, node.endToken);
 
-  visitEmptyStatement(EmptyStatement node) => new EmptyStatement(
+  Node visitEmptyStatement(EmptyStatement node) => new EmptyStatement(
       node.semicolonToken);
 
-  visitExpressionStatement(ExpressionStatement node) => new ExpressionStatement(
+  Node visitExpressionStatement(ExpressionStatement node) => new ExpressionStatement(
       visit(node.expression), node.endToken);
 
-  visitFor(For node) => new For(
+  Node visitFor(For node) => new For(
       visit(node.initializer), visit(node.conditionStatement),
       visit(node.update), visit(node.body), node.forToken);
 
-  visitForIn(ForIn node) => new ForIn(
+  Node visitForIn(ForIn node) => new ForIn(
       visit(node.declaredIdentifier), visit(node.expression), visit(node.body),
       node.forToken, node.inToken);
 
-  visitFunctionDeclaration(FunctionDeclaration node) => new FunctionDeclaration(
+  Node visitFunctionDeclaration(FunctionDeclaration node) => new FunctionDeclaration(
       visit(node.function));
 
-  rewriteFunctionExpression(FunctionExpression node, Statement body) =>
+  Node rewriteFunctionExpression(FunctionExpression node, Statement body) =>
       new FunctionExpression(
           visit(node.name), visit(node.parameters), body,
           visit(node.returnType), visit(node.modifiers),
           visit(node.initializers), node.getOrSet);
 
-  visitFunctionExpression(FunctionExpression node) =>
+  Node visitFunctionExpression(FunctionExpression node) =>
       rewriteFunctionExpression(node, visit(node.body));
 
-  visitIdentifier(Identifier node) => new Identifier(node.token);
+  Node visitIdentifier(Identifier node) => new Identifier(node.token);
 
-  visitIf(If node) => new If(
+  Node visitIf(If node) => new If(
       visit(node.condition), visit(node.thenPart), visit(node.elsePart),
       node.ifToken, node.elseToken);
 
-  visitLabel(Label node) => new Label(visit(node.identifier), node.colonToken);
+  Node visitLabel(Label node) =>
+      new Label(visit(node.identifier), node.colonToken);
 
-  visitLabeledStatement(LabeledStatement node) => new LabeledStatement(
+  Node visitLabeledStatement(LabeledStatement node) => new LabeledStatement(
       visit(node.labels), visit(node.statement));
 
-  visitLiteralBool(LiteralBool node) => new LiteralBool(
+  Node visitLiteralBool(LiteralBool node) => new LiteralBool(
       node.token, node.handler);
 
-  visitLiteralDouble(LiteralDouble node) => new LiteralDouble(
+  Node visitLiteralDouble(LiteralDouble node) => new LiteralDouble(
       node.token, node.handler);
 
-  visitLiteralInt(LiteralInt node) => new LiteralInt(node.token, node.handler);
+  Node visitLiteralInt(LiteralInt node) =>
+      new LiteralInt(node.token, node.handler);
 
-  visitLiteralList(LiteralList node) => new LiteralList(
+  Node visitLiteralList(LiteralList node) => new LiteralList(
       visit(node.typeArguments), visit(node.elements), node.constKeyword);
 
-  visitLiteralMap(LiteralMap node) => new LiteralMap(
+  Node visitLiteralMap(LiteralMap node) => new LiteralMap(
       visit(node.typeArguments), visit(node.entries), node.constKeyword);
 
-  visitLiteralMapEntry(LiteralMapEntry node) => new LiteralMapEntry(
+  Node visitLiteralMapEntry(LiteralMapEntry node) => new LiteralMapEntry(
       visit(node.key), node.colonToken, visit(node.value));
 
-  visitLiteralNull(LiteralNull node) => new LiteralNull(node.token);
+  Node visitLiteralNull(LiteralNull node) => new LiteralNull(node.token);
 
-  visitLiteralString(LiteralString node) => new LiteralString(
+  Node visitLiteralString(LiteralString node) => new LiteralString(
       node.token, node.dartString);
 
-  visitMetadata(Metadata node) => new Metadata(
+  Node visitMetadata(Metadata node) => new Metadata(
       node.token, visit(node.expression));
 
-  visitMixinApplication(MixinApplication node) => new MixinApplication(
+  Node visitMixinApplication(MixinApplication node) => new MixinApplication(
       visit(node.superclass), visit(node.mixins));
 
-  visitNamedMixinApplication(NamedMixinApplication node) =>
+  Node visitNamedMixinApplication(NamedMixinApplication node) =>
       new NamedMixinApplication(visit(node.name),
                                 visit(node.typeParameters),
                                 visit(node.modifiers),
@@ -132,18 +134,18 @@
                                 node.classKeyword,
                                 node.endToken);
 
-  visitModifiers(Modifiers node) => new Modifiers(visit(node.nodes));
+  Node visitModifiers(Modifiers node) => new Modifiers(visit(node.nodes));
 
-  visitNamedArgument(NamedArgument node) => new NamedArgument(
+  Node visitNamedArgument(NamedArgument node) => new NamedArgument(
       visit(node.name), node.colonToken, visit(node.expression));
 
-  visitNewExpression(NewExpression node) => new NewExpression(
+  Node visitNewExpression(NewExpression node) => new NewExpression(
       node.newToken, visit(node.send));
 
-  rewriteNodeList(NodeList node, Link link) =>
+  Node rewriteNodeList(NodeList node, Link link) =>
       new NodeList(node.beginToken, link, node.endToken, node.delimiter);
 
-  visitNodeList(NodeList node) {
+  Node visitNodeList(NodeList node) {
     // Special case for classes which exist in hierarchy, but not
     // in the visitor.
     if (node is Prefix) {
@@ -161,135 +163,152 @@
     return rewriteNodeList(node, builder.toLink());
   }
 
-  visitOperator(Operator node) => new Operator(node.token);
+  Node visitOperator(Operator node) => new Operator(node.token);
 
-  visitParenthesizedExpression(ParenthesizedExpression node) =>
+  Node visitParenthesizedExpression(ParenthesizedExpression node) =>
       new ParenthesizedExpression(visit(node.expression), node.beginToken);
 
-  visitRethrow(Rethrow node) => new Rethrow(
+  Node visitRethrow(Rethrow node) => new Rethrow(
       node.throwToken, node.endToken);
 
-  visitReturn(Return node) => new Return(
+  Node visitReturn(Return node) => new Return(
       node.beginToken, node.endToken, visit(node.expression));
 
-  visitSend(Send node) => new Send(
+  Node visitSend(Send node) => new Send(
       visit(node.receiver), visit(node.selector), visit(node.argumentsNode));
 
-  visitSendSet(SendSet node) => new SendSet(
+  Node visitSendSet(SendSet node) => new SendSet(
       visit(node.receiver), visit(node.selector),
       visit(node.assignmentOperator), visit(node.argumentsNode));
 
-  visitStringInterpolation(StringInterpolation node) =>
+  Node visitStringInterpolation(StringInterpolation node) =>
       new StringInterpolation(visit(node.string), visit(node.parts));
 
-  visitStringInterpolationPart(StringInterpolationPart node) =>
+  Node visitStringInterpolationPart(StringInterpolationPart node) =>
       new StringInterpolationPart(visit(node.expression), visit(node.string));
 
-  visitStringJuxtaposition(StringJuxtaposition node) =>
+  Node visitStringJuxtaposition(StringJuxtaposition node) =>
       new StringJuxtaposition(visit(node.first), visit(node.second));
 
-  visitSwitchCase(SwitchCase node) => new SwitchCase(
+  Node visitSwitchCase(SwitchCase node) => new SwitchCase(
       visit(node.labelsAndCases), node.defaultKeyword, visit(node.statements),
       node.startToken);
 
-  visitSwitchStatement(SwitchStatement node) => new SwitchStatement(
+  Node visitSwitchStatement(SwitchStatement node) => new SwitchStatement(
       visit(node.parenthesizedExpression), visit(node.cases),
       node.switchKeyword);
 
-  visitLiteralSymbol(LiteralSymbol node) => new LiteralSymbol(
+  Node visitLiteralSymbol(LiteralSymbol node) => new LiteralSymbol(
       node.hashToken, visit(node.identifiers));
 
-  visitThrow(Throw node) => new Throw(
+  Node visitThrow(Throw node) => new Throw(
       visit(node.expression), node.throwToken, node.endToken);
 
-  visitTryStatement(TryStatement node) => new TryStatement(
+  Node visitTryStatement(TryStatement node) => new TryStatement(
       visit(node.tryBlock), visit(node.catchBlocks), visit(node.finallyBlock),
       node.tryKeyword, node.finallyKeyword);
 
-  visitTypeAnnotation(TypeAnnotation node) => new TypeAnnotation(
+  Node visitTypeAnnotation(TypeAnnotation node) => new TypeAnnotation(
       visit(node.typeName), visit(node.typeArguments));
 
-  visitTypedef(Typedef node) => new Typedef(
+  Node visitTypedef(Typedef node) => new Typedef(
       visit(node.returnType), visit(node.name), visit(node.typeParameters),
       visit(node.formals), node.typedefKeyword, node.endToken);
 
-  visitTypeVariable(TypeVariable node) => new TypeVariable(
+  Node visitTypeVariable(TypeVariable node) => new TypeVariable(
       visit(node.name), visit(node.bound));
 
-  visitVariableDefinitions(VariableDefinitions node) =>
+  Node visitVariableDefinitions(VariableDefinitions node) =>
       new VariableDefinitions.forParameter(
           visit(node.metadata), visit(node.type),
           visit(node.modifiers), visit(node.definitions));
 
-  visitWhile(While node) => new While(
+  Node visitWhile(While node) => new While(
       visit(node.condition), visit(node.body), node.whileKeyword);
 
   Node visitNode(Node node) {
     unimplemented('visitNode', node: node);
+    return null;
   }
 
   Node visitCombinator(Combinator node) {
     unimplemented('visitNode', node: node);
+    return null;
   }
 
   Node visitExport(Export node) {
     unimplemented('visitNode', node: node);
+    return null;
   }
 
   Node visitExpression(Expression node) {
     unimplemented('visitNode', node: node);
+    return null;
   }
 
   Node visitGotoStatement(GotoStatement node) {
     unimplemented('visitNode', node: node);
+    return null;
   }
 
   Node visitImport(Import node) {
     unimplemented('visitNode', node: node);
+    return null;
   }
 
   Node visitLibraryDependency(LibraryTag node) {
     unimplemented('visitNode', node: node);
+    return null;
   }
 
   Node visitLibraryName(LibraryName node) {
     unimplemented('visitNode', node: node);
+    return null;
   }
 
   Node visitLibraryTag(LibraryTag node) {
     unimplemented('visitNode', node: node);
+    return null;
   }
 
   Node visitLiteral(Literal node) {
     unimplemented('visitNode', node: node);
+    return null;
   }
 
   Node visitLoop(Loop node) {
     unimplemented('visitNode', node: node);
+    return null;
   }
 
   Node visitPart(Part node) {
     unimplemented('visitNode', node: node);
+    return null;
   }
 
   Node visitPartOf(PartOf node) {
     unimplemented('visitNode', node: node);
+    return null;
   }
 
   Node visitPostfix(Postfix node) {
     unimplemented('visitNode', node: node);
+    return null;
   }
 
   Node visitPrefix(Prefix node) {
     unimplemented('visitNode', node: node);
+    return null;
   }
 
   Node visitStatement(Statement node) {
     unimplemented('visitNode', node: node);
+    return null;
   }
 
   Node visitStringNode(StringNode node) {
     unimplemented('visitNode', node: node);
+    return null;
   }
 
   unimplemented(String message, {Node node}) {
diff --git a/sdk/lib/_internal/compiler/implementation/dart_types.dart b/sdk/lib/_internal/compiler/implementation/dart_types.dart
index ee6f15c..d41c289 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_types.dart
@@ -1546,8 +1546,9 @@
         return intersection.first;
       }
     }
-    assert(invariant(CURRENT_ELEMENT_SPANNABLE, false,
-        message: 'No least upper bound computed for $a and $b.'));
+    invariant(CURRENT_ELEMENT_SPANNABLE, false,
+        message: 'No least upper bound computed for $a and $b.');
+    return null;
   }
 
   /// Computes the least upper bound of the types in the longest prefix of [a]
diff --git a/sdk/lib/_internal/compiler/implementation/deferred_load.dart b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
index 8c0907e..b1de78e 100644
--- a/sdk/lib/_internal/compiler/implementation/deferred_load.dart
+++ b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
@@ -498,6 +498,7 @@
       if (import == _fakeMainImport) return "main";
       Link<MetadataAnnotation> metadatas = import.metadata;
       assert(metadatas != null);
+      String result;
       for (MetadataAnnotation metadata in metadatas) {
         metadata.ensureResolved(compiler);
         Element element = metadata.value.computeType(compiler).element;
@@ -505,12 +506,13 @@
             deferredLibraryClass) {
           ConstructedConstant constant = metadata.value;
           StringConstant s = constant.fields[0];
-          String result = s.value.slowToString();
-          deferNameCache[import] = result;
-          return result;
+          result = s.value.slowToString();
+          break;
         }
       }
-      assert(false);
+      assert(result != null);
+      deferNameCache[import] = result;
+      return result;
     }
 
     Set<String> usedNames = new Set<String>();
diff --git a/sdk/lib/_internal/compiler/implementation/dump_info.dart b/sdk/lib/_internal/compiler/implementation/dump_info.dart
index 5f1586e..5cc562d 100644
--- a/sdk/lib/_internal/compiler/implementation/dump_info.dart
+++ b/sdk/lib/_internal/compiler/implementation/dump_info.dart
@@ -220,6 +220,7 @@
     compiler.internalError("This element of kind ${element.kind} "
         "does not support --dump-info",
         token: element.position());
+    return null;
   }
 
   InfoNode visitLibraryElement(LibraryElement element) {
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index 8701835..6a96ee9 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -50,10 +50,12 @@
 
   Node parseNode(DiagnosticListener listener) {
     listener.internalErrorOnElement(this, 'not implemented');
+    return null;
   }
 
   DartType computeType(Compiler compiler) {
     compiler.internalError("$this.computeType.", token: position());
+    return null;
   }
 
   void addMetadata(MetadataAnnotation annotation) {
@@ -1162,6 +1164,7 @@
       }
     }
     listener.cancel('internal error: could not find $name', node: variables);
+    return null;
   }
 
   DartType computeType(Compiler compiler) {
@@ -1651,6 +1654,7 @@
 
   FunctionType computeType(Compiler compiler) {
     compiler.internalErrorOnElement(this, '$this.computeType.');
+    return null;
   }
 
   Node parseNode(DiagnosticListener listener) {
@@ -1911,6 +1915,7 @@
         return element;
       }
     }
+    return null;
   }
   /**
    * Lookup super members for the class. This will ignore constructors.
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
index 29d898b..c9646c3 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
@@ -633,7 +633,7 @@
   }
 
   T visitNode(Node node) {
-    node.visitChildren(this);
+    return node.visitChildren(this);
   }
 
   T visitNewExpression(NewExpression node) {
@@ -745,6 +745,7 @@
       if (Elements.isLocal(element)) {
         return locals.use(element);
       }
+      return null;
     }
   }
 
@@ -902,6 +903,7 @@
         visit(definition);
       }
     }
+    return null;
   }
 
   bool handleCondition(Node node, List<Send> tests) {
@@ -932,6 +934,7 @@
     visit(node.elsePart);
     saved.mergeDiamondFlow(thenLocals, locals);
     locals = saved;
+    return null;
   }
 
   void setupBreaksAndContinues(TargetElement element) {
@@ -980,6 +983,7 @@
         getBreaks(target), keepOwnLocals: keepOwnLocals);
     locals = saved;
     clearBreaksAndContinues(target);
+    return null;
   }
 
   T visitWhile(While node) {
@@ -1026,6 +1030,7 @@
       locals = saved;
     }
     visit(node.finallyBlock);
+    return null;
   }
 
   T visitThrow(Throw node) {
@@ -1048,6 +1053,7 @@
       locals.update(elements[trace], types.dynamicType, node);
     }
     visit(node.block);
+    return null;
   }
 
   T visitParenthesizedExpression(ParenthesizedExpression node) {
@@ -1061,6 +1067,7 @@
         if (locals.aborts) break;
       }
     }
+    return null;
   }
 
   T visitLabeledStatement(LabeledStatement node) {
@@ -1077,6 +1084,7 @@
       locals.mergeAfterBreaks(getBreaks(targetElement));
       clearBreaksAndContinues(targetElement);
     }
+    return null;
   }
 
   T visitBreakStatement(BreakStatement node) {
@@ -1085,6 +1093,7 @@
     // Do a deep-copy of the locals, because the code following the
     // break will change them.
     breaksFor[target].add(new LocalsHandler<T>.deepCopyOf(locals));
+    return null;
   }
 
   T visitContinueStatement(ContinueStatement node) {
@@ -1093,6 +1102,7 @@
     // Do a deep-copy of the locals, because the code following the
     // continue will change them.
     continuesFor[target].add(new LocalsHandler<T>.deepCopyOf(locals));
+    return null;
   }
 
   void internalError(String reason, {Node node}) {
@@ -1157,6 +1167,7 @@
       locals = saved;
     }
     clearBreaksAndContinues(elements[node]);
+    return null;
   }
 
   T visitCascadeReceiver(CascadeReceiver node) {
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 8137f75..181dd40 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
@@ -1224,6 +1224,7 @@
           : expression.accept(this));
     }
     locals.seenReturnOrThrow = true;
+    return null;
   }
 
   T visitForIn(ForIn node) {
diff --git a/sdk/lib/_internal/compiler/implementation/ir/ir_builder.dart b/sdk/lib/_internal/compiler/implementation/ir/ir_builder.dart
index 94b0810..ee33f7d 100644
--- a/sdk/lib/_internal/compiler/implementation/ir/ir_builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ir/ir_builder.dart
@@ -268,6 +268,7 @@
       n.accept(this);
       if (blockReturns) return null;
     }
+    return null;
   }
 
   IrNode visitReturn(Return node) {
@@ -282,6 +283,7 @@
     }
     builder.addStatement(new IrReturn(nodePosition(node), value));
     builder.block.hasReturn = true;
+    return null;
   }
 
   IrConstant visitLiteralBool(LiteralBool node) {
@@ -313,22 +315,27 @@
 
   IrNode visitAssert(Send node) {
     giveup();
+    return null;
   }
 
   IrNode visitClosureSend(Send node) {
     giveup();
+    return null;
   }
 
   IrNode visitDynamicSend(Send node) {
     giveup();
+    return null;
   }
 
   IrNode visitGetterSend(Send node) {
     giveup();
+    return null;
   }
 
   IrNode visitOperatorSend(Send node) {
     giveup();
+    return null;
   }
 
   IrNode visitStaticSend(Send node) {
@@ -365,10 +372,12 @@
 
   IrNode visitSuperSend(Send node) {
     giveup();
+    return null;
   }
 
   IrNode visitTypeReferenceSend(Send node) {
     giveup();
+    return null;
   }
 
   static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";
diff --git a/sdk/lib/_internal/compiler/implementation/ir/ir_unpickler.dart b/sdk/lib/_internal/compiler/implementation/ir/ir_unpickler.dart
index 04190e6..428785e 100644
--- a/sdk/lib/_internal/compiler/implementation/ir/ir_unpickler.dart
+++ b/sdk/lib/_internal/compiler/implementation/ir/ir_unpickler.dart
@@ -68,6 +68,7 @@
       return UTF8.decode(bytes);
     } else {
       compiler.internalError("Unexpected string tag: $tag");
+      return null;
     }
   }
 
@@ -110,6 +111,7 @@
       return readReturnNode();
     } else {
       compiler.internalError("Unexpected entry tag: $tag");
+      return null;
     }
   }
 
@@ -213,6 +215,7 @@
         return constantSystem.createNull();
       default:
         compiler.internalError("Unexpected constant tag: $tag");
+        return null;
     }
   }
 
@@ -229,6 +232,7 @@
             readDartString(readByte()), readDartString(readByte()));
       default:
         compiler.internalError("Unexpected dart string tag: $tag");
+        return null;
     }
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/js/builder.dart b/sdk/lib/_internal/compiler/implementation/js/builder.dart
index 8958b50..24b492a 100644
--- a/sdk/lib/_internal/compiler/implementation/js/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/js/builder.dart
@@ -489,6 +489,7 @@
       return expression;
     } else {
       error("Expected primary expression");
+      return null;
     }
   }
 
@@ -502,9 +503,10 @@
         expectCategory(RSQUARE);
         receiver = new PropertyAccess(receiver, inBraces);
       } else {
-        return receiver;
+        break;
       }
     }
+    return receiver;
   }
 
   Expression parseCall() {
@@ -534,9 +536,10 @@
       } else {
         // JS allows new without (), but we don't.
         if (constructor) error("Parentheses are required for new");
-        return receiver;
+        break;
       }
     }
+    return receiver;
   }
 
   Expression getDotRhs(Expression receiver) {
@@ -591,8 +594,7 @@
       if (lastCategory != SYMBOL ||
           !BINARY_PRECEDENCE.containsKey(symbol) ||
           BINARY_PRECEDENCE[symbol] > maxPrecedence) {
-        if (rhs == null) return lhs;
-        return new Binary(lastSymbol, lhs, rhs);
+        break;
       }
       expectCategory(SYMBOL);
       if (rhs == null || BINARY_PRECEDENCE[symbol] >= minPrecedence) {
@@ -605,6 +607,8 @@
         rhs = new Binary(symbol, rhs, higher);
       }
     }
+    if (rhs == null) return lhs;
+    return new Binary(lastSymbol, lhs, rhs);
   }
 
   Expression parseConditional() {
@@ -685,6 +689,7 @@
 
   Node visitNode(Node node) {
     error('Cannot handle $node');
+    return null;
   }
 
   Node copyPosition(Node oldNode, Node newNode) {
diff --git a/sdk/lib/_internal/compiler/implementation/js/nodes.dart b/sdk/lib/_internal/compiler/implementation/js/nodes.dart
index 5d18972..95191f0 100644
--- a/sdk/lib/_internal/compiler/implementation/js/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/js/nodes.dart
@@ -114,9 +114,9 @@
   T visitAssignment(Assignment node) => visitExpression(node);
   T visitVariableInitialization(VariableInitialization node) {
     if (node.value != null) {
-      visitAssignment(node);
+      return visitAssignment(node);
     } else {
-      visitExpression(node);
+      return visitExpression(node);
     }
   }
   T visitConditional(Conditional node) => visitExpression(node);
@@ -154,7 +154,7 @@
   T visitJSExpression(JSExpression node) => visitExpression(node);
 
   // Ignore comments by default.
-  T visitComment(Comment node) {}
+  T visitComment(Comment node) => null;
 }
 
 abstract class Node {
diff --git a/sdk/lib/_internal/compiler/implementation/js/printer.dart b/sdk/lib/_internal/compiler/implementation/js/printer.dart
index bc29bfe..ef27903 100644
--- a/sdk/lib/_internal/compiler/implementation/js/printer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js/printer.dart
@@ -974,6 +974,7 @@
 
   bool visitNode(Statement node) {
     compiler.internalError("Forgot node: $node");
+    return null;
   }
 
   bool visitBlock(Block node) => false;
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index 36ddfa5..444f6d0 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -637,8 +637,7 @@
     }
   }
 
-  Constant registerCompileTimeConstant(Constant constant,
-                                       TreeElements elements) {
+  void registerCompileTimeConstant(Constant constant, TreeElements elements) {
     registerCompileTimeConstantInternal(constant, elements);
     for (Constant dependency in constant.getDependencies()) {
       registerCompileTimeConstant(dependency, elements);
@@ -666,7 +665,9 @@
 
   void registerInstantiatedConstantType(DartType type, TreeElements elements) {
     Enqueuer enqueuer = compiler.enqueuer.codegen;
-    enqueuer.registerInstantiatedType(type, elements);
+    DartType instantiatedType =
+        type.kind == TypeKind.FUNCTION ? compiler.functionClass.rawType : type;
+    enqueuer.registerInstantiatedType(instantiatedType, elements);
     if (type is InterfaceType && !type.treatAsRaw &&
         classNeedsRti(type.element)) {
       enqueuer.registerStaticUse(getSetRuntimeTypeInfo());
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
index c436744..c8edc9b 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
@@ -181,6 +181,7 @@
   jsAst.Expression visitFunction(FunctionConstant constant) {
     compiler.internalError(
         "The function constant does not need specific JS code");
+    return null;
   }
 
   jsAst.Expression visitNull(NullConstant constant) {
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
index f3b4ff7..b42cc55 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
@@ -768,9 +768,11 @@
         compiler.internalError(
             'use instanceFieldPropertyName or instanceFieldAccessorName',
             node: element.parseNode(compiler));
+        return null;
       } else {
         compiler.internalError('getName for bad kind: ${element.kind}',
                                node: element.parseNode(compiler));
+        return null;
       }
     } else {
       // Use declaration element to ensure invariant on [globals].
@@ -807,6 +809,7 @@
       }
       compiler.internalError('getName for unknown kind: ${element.kind}',
                               node: element.parseNode(compiler));
+      return null;
     }
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
index c0d9c60..e09cc2f 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
@@ -603,6 +603,8 @@
          index++, variables = variables.tail) {
       if (variables.head.element == variable) return index;
     }
+    throw invariant(variable, false,
+                    message: "Couldn't find type-variable index");
   }
 
   /// Return all classes that are referenced in the type of the function, i.e.,
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 ed3e5ae..7e7fe90 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart
@@ -494,8 +494,7 @@
         String reflectionNameString = task.getReflectionName(member, name);
         reflectionName =
             new jsAst.LiteralString(
-                '"new ${Elements.reconstructConstructorName(member)}"'
-                ' /* $reflectionNameString */');
+                '"new ${Elements.reconstructConstructorName(member)}"');
       } else {
         reflectionName = js.string(member.name);
       }
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart
index 92b95c9..ee897b9 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart
@@ -12,6 +12,8 @@
 const OPTIONAL_PARAMETER_INDEX = 4;
 const DEFAULT_ARGUMENTS_INDEX = 5;
 
+const bool VALIDATE_DATA = false;
+
 // TODO(ahe): This code should be integrated in CodeEmitterTask.finishClasses.
 String getReflectionDataParser(String classesCollector,
                                JavaScriptBackend backend) {
@@ -336,6 +338,7 @@
 }
 
 String readChecked(String array, String index, String check, String type) {
+  if (!VALIDATE_DATA) return '$array[$index]';
   return '''
 (function() {
   var result = $array[$index];
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_instance_mirrors.dart b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_instance_mirrors.dart
index 40a5d3f..06197ee 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_instance_mirrors.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_instance_mirrors.dart
@@ -59,6 +59,7 @@
     return new Dart2JsConstructedConstantMirror(mirrorSystem, constant);

   }

   mirrorSystem.compiler.internalError("Unexpected constant $constant");

+  return null;

 }

 

 

@@ -280,6 +281,6 @@
       return new Dart2JsStringConstantMirror.fromString(mirrorSystem,

                                                         trimmedText);

     }

-    super.getField(fieldName);

+    return super.getField(fieldName);

   }

 }

diff --git a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirrors.dart b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirrors.dart
index a399a8c..549d4d1 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirrors.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirrors.dart
@@ -133,6 +133,7 @@
     }
     mirrorSystem.compiler.internalError(
         "Unexpected member type $element ${element.kind}");
+    return null;
   }
 
 }
@@ -348,6 +349,7 @@
       }
     }
     compiler.internalError("Unexpected type $type of kind ${type.kind}");
+    return null;
   }
 
   DeclarationMirror _getTypeDeclarationMirror(Element element) {
@@ -358,6 +360,8 @@
       return new Dart2JsTypedefDeclarationMirror(this,
           element.computeType(compiler));
     }
+    compiler.internalError("Unexpected element $element");
+    return null;
   }
 }
 
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_type_mirrors.dart b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_type_mirrors.dart
index 64c54c4..3f5bfdd 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_type_mirrors.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_type_mirrors.dart
@@ -54,6 +54,14 @@
 

   bool get isDynamic => false;

 

+  bool isSubtypeOf(TypeMirror other) {

+    return mirrorSystem.compiler.types.isSubtype(this._type, other._type);

+  }

+

+  bool isAssignableTo(TypeMirror other) {

+    return mirrorSystem.compiler.types.isAssignable(this._type, other._type);

+  }

+

   String toString() => _type.toString();

 }

 

@@ -226,6 +234,18 @@
                                 InterfaceType type)

       : super(system, type);

 

+  bool isSubclassOf(ClassMirror other) {

+    if (other is! ClassMirror) throw new ArgumentError(other);

+    ClassMirror otherDeclaration = other.originalDeclaration;

+    ClassMirror c = this;

+    while (c != null) {

+      c = c.originalDeclaration;

+      if (c == otherDeclaration) return true;

+      c = c.superclass;

+    }

+    return false;

+  }

+

   String toString() => 'Mirror on class ${_type.name}';

 }

 

diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 8f75bf1..caad757 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -27,9 +27,9 @@
   Selector getIteratorSelector(ForIn node);
   Selector getMoveNextSelector(ForIn node);
   Selector getCurrentSelector(ForIn node);
-  Selector setIteratorSelector(ForIn node, Selector selector);
-  Selector setMoveNextSelector(ForIn node, Selector selector);
-  Selector setCurrentSelector(ForIn node, Selector selector);
+  void setIteratorSelector(ForIn node, Selector selector);
+  void setMoveNextSelector(ForIn node, Selector selector);
+  void setCurrentSelector(ForIn node, Selector selector);
   void setConstant(Node node, Constant constant);
   Constant getConstant(Node node);
 
@@ -147,7 +147,7 @@
   // we're using three selectors, we need to use children of the node,
   // and we arbitrarily choose which ones.
 
-  Selector setIteratorSelector(ForIn node, Selector selector) {
+  void setIteratorSelector(ForIn node, Selector selector) {
     selectors[node] = selector;
   }
 
@@ -155,7 +155,7 @@
     return selectors[node];
   }
 
-  Selector setMoveNextSelector(ForIn node, Selector selector) {
+  void setMoveNextSelector(ForIn node, Selector selector) {
     selectors[node.forToken] = selector;
   }
 
@@ -163,7 +163,7 @@
     return selectors[node.forToken];
   }
 
-  Selector setCurrentSelector(ForIn node, Selector selector) {
+  void setCurrentSelector(ForIn node, Selector selector) {
     selectors[node.inToken] = selector;
   }
 
@@ -1531,6 +1531,7 @@
   R visitNode(Node node) {
     cancel(node,
            'internal error: Unhandled node: ${node.getObjectDescription()}');
+    return null;
   }
 
   R visitEmptyStatement(Node node) => null;
@@ -2238,7 +2239,7 @@
     visit(node.expression);
   }
 
-  Element visitClassNode(ClassNode node) {
+  visitClassNode(ClassNode node) {
     cancel(node, "shouldn't be called");
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/signatures.dart b/sdk/lib/_internal/compiler/implementation/resolution/signatures.dart
index 5e7c834..1978aa0 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/signatures.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/signatures.dart
@@ -113,6 +113,7 @@
       } else {
         cancel(node,
             'internal error: unimplemented receiver on parameter send');
+        return null;
       }
     }
   }
diff --git a/sdk/lib/_internal/compiler/implementation/resolved_visitor.dart b/sdk/lib/_internal/compiler/implementation/resolved_visitor.dart
index df68e6e..edf4c2c 100644
--- a/sdk/lib/_internal/compiler/implementation/resolved_visitor.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolved_visitor.dart
@@ -52,6 +52,7 @@
         return visitStaticSend(node);
       } else {
         internalError("Cannot generate code for send", node: node);
+        return null;
       }
     }
   }
@@ -69,5 +70,6 @@
 
   R visitNode(Node node) {
     internalError("Unhandled node", node: node);
+    return null;
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/listener.dart b/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
index 67fc779..6f7aa5c 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
@@ -2018,9 +2018,11 @@
   Token get endToken {
     Token token = beginToken;
     while (token.kind != EOF_TOKEN) {
-      if (identical(token.next, tokenAfterEndToken)) return token;
+      if (identical(token.next, tokenAfterEndToken)) break;
       token = token.next;
     }
+    assert(token != null);
+    return token;
   }
 
   Node parseNode(DiagnosticListener listener) {
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/parser.dart b/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
index 365a92b..8ce1bd4 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
@@ -131,10 +131,11 @@
         token = parseShow(token);
       } else {
         listener.endCombinators(count);
-        return token;
+        break;
       }
       count++;
     }
+    return token;
   }
 
   /// hide identifierList
@@ -1851,6 +1852,7 @@
       return token.next;
     } else {
       listener.unexpected(token);
+      return null;
     }
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/partial_parser.dart b/sdk/lib/_internal/compiler/implementation/scanner/partial_parser.dart
index 0181c88..63a0a5c 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/partial_parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/partial_parser.dart
@@ -32,8 +32,9 @@
       if ((identical(kind, EOF_TOKEN)) ||
           (identical(value, ';')) ||
           (identical(value, ',')) ||
-          (identical(value, ']')))
-        return token;
+          (identical(value, ']'))) {
+        break;
+      }
       if (identical(value, '=') ||
           identical(value, '?') ||
           identical(value, ':')) {
@@ -72,13 +73,16 @@
           continue;
         }
       }
-      if (!mayParseFunctionExpressions && identical(value, '{')) return token;
+      if (!mayParseFunctionExpressions && identical(value, '{')) {
+        break;
+      }
       if (token is BeginGroupToken) {
         BeginGroupToken begin = token;
         token = (begin.endGroup != null) ? begin.endGroup : token;
       }
       token = token.next;
     }
+    return token;
   }
 
   Token skipClassBody(Token token) {
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart b/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart
index c7e1ae7..8af864a 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart
@@ -605,6 +605,7 @@
         return next;
       }
     }
+    return null;
   }
 
   int tokenizeHexOrNumber(int next) {
@@ -633,6 +634,7 @@
         return next;
       }
     }
+    return null;
   }
 
   int tokenizeDotsOrNumber(int next) {
@@ -697,6 +699,7 @@
       }
       next = advance();
     }
+    return null;
   }
 
   int tokenizeSlashOrComment(int next) {
@@ -728,6 +731,7 @@
         return next;
       }
     }
+    return null;
   }
 
 
@@ -741,7 +745,7 @@
       if (identical($EOF, next)) {
         if (!asciiOnlyLines) handleUnicode(unicodeStart);
         appendStringToken(BAD_INPUT_INFO, "unterminated multi-line comment");
-        return next;
+        break;
       } else if (identical($STAR, next)) {
         next = advance();
         if (identical($SLASH, next)) {
@@ -750,7 +754,7 @@
             if (!asciiOnlyLines) handleUnicode(unicodeStart);
             next = advance();
             appendComment(start, asciiOnlyComment);
-            return next;
+            break;
           } else {
             next = advance();
           }
@@ -778,6 +782,7 @@
         next = advance();
       }
     }
+    return next;
   }
 
   int tokenizeRawStringKeywordOrIdentifier(int next) {
@@ -831,9 +836,10 @@
         } else {
           appendSubstringToken(IDENTIFIER_INFO, start, true);
         }
-        return next;
+        break;
       }
     }
+    return next;
   }
 
   int tokenizeAt(int next) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 0b58fde..5f49bd6 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -3938,6 +3938,7 @@
       // exception at runtime.
       compiler.cancel('Unimplemented unresolved type variable',
                       element: type.element);
+      return null;
     }
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
index 7b85b8c..0fe6c66 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
@@ -293,7 +293,7 @@
 
   String visitGreater(HGreater node) => handleInvokeBinary(node, '>');
   String visitGreaterEqual(HGreaterEqual node) {
-    handleInvokeBinary(node, '>=');
+    return handleInvokeBinary(node, '>=');
   }
   String visitIdentity(HIdentity node) => handleInvokeBinary(node, '===');
 
diff --git a/sdk/lib/_internal/compiler/implementation/tree/nodes.dart b/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
index 80f0b13..04b6000 100644
--- a/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
@@ -820,6 +820,7 @@
     if (identical(token.stringValue, 'true')) return true;
     if (identical(token.stringValue, 'false')) return false;
     (this.handler)(token, "not a bool ${token.value}");
+    throw false;
   }
 
   accept(Visitor visitor) => visitor.visitLiteralBool(this);
diff --git a/sdk/lib/_internal/compiler/implementation/typechecker.dart b/sdk/lib/_internal/compiler/implementation/typechecker.dart
index 533525b..53c5b75 100644
--- a/sdk/lib/_internal/compiler/implementation/typechecker.dart
+++ b/sdk/lib/_internal/compiler/implementation/typechecker.dart
@@ -930,6 +930,7 @@
     } else {
       compiler.internalErrorOnElement(
           element, 'unexpected element kind ${element.kind}');
+      return null;
     }
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
index 5d310ce..d9412e6 100644
--- a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
@@ -1335,8 +1335,7 @@
     TreeElements elements =
         compiler.enqueuer.resolution.resolvedElements[element.declaration];
     assert(elements != null);
-    ConcreteType specialResult = handleSpecialMethod(element, environment);
-    if (specialResult != null) return specialResult;
+    handleSpecialMethod(element, environment);
     FunctionExpression tree = element.parseNode(compiler);
     if (tree.hasBody()) {
       Visitor visitor =
@@ -1442,7 +1441,7 @@
    * Hook that performs side effects on some special method calls (like
    * [:List(length):]) and possibly returns a concrete type.
    */
-  ConcreteType handleSpecialMethod(FunctionElement element,
+  void handleSpecialMethod(FunctionElement element,
                                    ConcreteTypesEnvironment environment) {
     // When List([length]) is called with some length, we must augment
     // listElementType with {null}.
@@ -1689,14 +1688,17 @@
 
   ConcreteType visitCascade(Cascade node) {
     inferrer.fail(node, 'not yet implemented');
+    return null;
   }
 
   ConcreteType visitCascadeReceiver(CascadeReceiver node) {
     inferrer.fail(node, 'not yet implemented');
+    return null;
   }
 
   ConcreteType visitClassNode(ClassNode node) {
     inferrer.fail(node, 'not implemented');
+    return null;
   }
 
   ConcreteType visitDoWhile(DoWhile node) {
@@ -1798,6 +1800,7 @@
 
   ConcreteType visitLoop(Loop node) {
     inferrer.fail(node, 'not yet implemented');
+    return null;
   }
 
   ConcreteType analyzeSetElement(Selector selector,
@@ -1998,6 +2001,7 @@
 
   ConcreteType visitOperator(Operator node) {
     inferrer.fail(node, 'not yet implemented');
+    return null;
   }
 
   ConcreteType visitReturn(Return node) {
@@ -2014,10 +2018,12 @@
 
   ConcreteType visitTypeAnnotation(TypeAnnotation node) {
     inferrer.fail(node, 'not yet implemented');
+    return null;
   }
 
   ConcreteType visitTypeVariable(TypeVariable node) {
     inferrer.fail(node, 'not yet implemented');
+    return null;
   }
 
   ConcreteType visitVariableDefinitions(VariableDefinitions node) {
@@ -2053,6 +2059,7 @@
 
   ConcreteType visitModifiers(Modifiers node) {
     inferrer.fail(node, 'not yet implemented');
+    return null;
   }
 
   ConcreteType visitStringInterpolation(StringInterpolation node) {
@@ -2112,6 +2119,7 @@
 
   ConcreteType visitLabel(Label node) {
     inferrer.fail(node, 'not yet implemented');
+    return null;
   }
 
   ConcreteType visitLabeledStatement(LabeledStatement node) {
@@ -2131,34 +2139,42 @@
 
   ConcreteType visitNamedArgument(NamedArgument node) {
     inferrer.fail(node, 'not yet implemented');
+    return null;
   }
 
   ConcreteType visitSwitchStatement(SwitchStatement node) {
     inferrer.fail(node, 'not yet implemented');
+    return null;
   }
 
   ConcreteType visitSwitchCase(SwitchCase node) {
     inferrer.fail(node, 'not yet implemented');
+    return null;
   }
 
   ConcreteType visitCaseMatch(CaseMatch node) {
     inferrer.fail(node, 'not yet implemented');
+    return null;
   }
 
   ConcreteType visitTryStatement(TryStatement node) {
     inferrer.fail(node, 'not yet implemented');
+    return null;
   }
 
   ConcreteType visitCatchBlock(CatchBlock node) {
     inferrer.fail(node, 'not yet implemented');
+    return null;
   }
 
   ConcreteType visitTypedef(Typedef node) {
     inferrer.fail(node, 'not implemented');
+    return null;
   }
 
   ConcreteType visitSuperSend(Send node) {
     inferrer.fail(node, 'not implemented');
+    return null;
   }
 
   ConcreteType visitOperatorSend(Send node) {
diff --git a/sdk/lib/_internal/lib/constant_map.dart b/sdk/lib/_internal/lib/constant_map.dart
index 7dbedbc..f13f309 100644
--- a/sdk/lib/_internal/lib/constant_map.dart
+++ b/sdk/lib/_internal/lib/constant_map.dart
@@ -28,7 +28,7 @@
 
   // This constructor is not used.  The instantiation is shortcut by the
   // compiler. It is here to make the uninitialized final fields legal.
-  const ConstantStringMap._(this.length, this._jsObject, _keys) : super._();
+  const ConstantStringMap._(this.length, this._jsObject, this._keys) : super._();
 
   final int length;
   // A constant map is backed by a JavaScript object.
@@ -69,7 +69,7 @@
 class ConstantProtoMap<K, V> extends ConstantStringMap<K, V> {
   // This constructor is not used.  The instantiation is shortcut by the
   // compiler. It is here to make the uninitialized final fields legal.
-  ConstantProtoMap._(length, jsObject, keys) : super._(length, jsObject, keys);
+  ConstantProtoMap._(length, jsObject, keys, this._protoValue) : super._(length, jsObject, keys);
 
   final V _protoValue;
 
diff --git a/sdk/lib/_internal/lib/isolate_helper.dart b/sdk/lib/_internal/lib/isolate_helper.dart
index 0520864..cd3ee4a 100644
--- a/sdk/lib/_internal/lib/isolate_helper.dart
+++ b/sdk/lib/_internal/lib/isolate_helper.dart
@@ -22,8 +22,6 @@
                                    IsolateContext;
 import 'dart:_interceptors' show JSExtendableArray;
 
-ReceivePort controlPort;
-
 /**
  * Called by the compiler to support switching
  * between isolates when we get a callback from the DOM.
@@ -236,6 +234,39 @@
   // native object containing all globals of an isolate.
   final isolateStatics = JS_CREATE_ISOLATE();
 
+  final RawReceivePortImpl controlPort = new RawReceivePortImpl._controlPort();
+
+  final Capability pauseCapability = new Capability();
+
+  // TODO(lrn): Store these in single "pausestate" object, so they don't take
+  // up as much room when not pausing.
+  bool isPaused = false;
+  List<_IsolateEvent> delayedEvents = [];
+  Set<Capability> pauseTokens = new Set();
+
+  _IsolateContext() {
+    this.registerWeak(controlPort._id, controlPort);
+  }
+
+  void addPause(Capability authentification, Capability resume) {
+    if (pauseCapability != authentification) return;
+    if (pauseTokens.add(resume) && !isPaused) {
+      isPaused = true;
+    }
+  }
+
+  void removePause(Capability resume) {
+    if (!isPaused) return;
+    pauseTokens.remove(resume);
+    if (pauseTokens.isEmpty) {
+      while(delayedEvents.isNotEmpty) {
+        _IsolateEvent event = delayedEvents.removeLast();
+        _globalState.topEventLoop.prequeue(event);
+      }
+      isPaused = false;
+    }
+  }
+
   /**
    * Run [code] in the context of the isolate represented by [this].
    */
@@ -257,15 +288,32 @@
     JS_SET_CURRENT_ISOLATE(isolateStatics);
   }
 
+  void handleControlMessage(message) {
+    switch (message[0]) {
+      case "pause":
+        addPause(message[1], message[2]);
+        break;
+      case "resume":
+        removePause(message[1]);
+        break;
+      default:
+        print("UNKOWN MESSAGE: $message");
+    }
+  }
+
   /** Looks up a port registered for this isolate. */
   RawReceivePortImpl lookup(int portId) => ports[portId];
 
-  /** Registers a port on this isolate. */
-  void register(int portId, RawReceivePortImpl port)  {
+  void _addRegistration(int portId, RawReceivePortImpl port) {
     if (ports.containsKey(portId)) {
       throw new Exception("Registry: ports must be registered only once.");
     }
     ports[portId] = port;
+  }
+
+  /** Registers a port on this isolate. */
+  void register(int portId, RawReceivePortImpl port)  {
+    _addRegistration(portId, port);
     _updateGlobalState();
   }
 
@@ -276,8 +324,7 @@
    */
   void registerWeak(int portId, RawReceivePortImpl port)  {
     weakPorts.add(portId);
-    // 'register' updates the global state.
-    register(portId, port);
+    _addRegistration(portId, port);
   }
 
   _updateGlobalState() {
@@ -291,6 +338,7 @@
   /** Unregister a port on this isolate. */
   void unregister(int portId) {
     ports.remove(portId);
+    weakPorts.remove(portId);
     _updateGlobalState();
   }
 }
@@ -306,6 +354,10 @@
     events.addLast(new _IsolateEvent(isolate, fn, msg));
   }
 
+  void prequeue(_IsolateEvent event) {
+    events.addFirst(event);
+  }
+
   _IsolateEvent dequeue() {
     if (events.isEmpty) return null;
     return events.removeFirst();
@@ -383,6 +435,10 @@
   _IsolateEvent(this.isolate, this.fn, this.message);
 
   void process() {
+    if (isolate.isPaused) {
+      isolate.delayedEvents.add(this);
+      return;
+    }
     isolate.eval(fn);
   }
 }
@@ -582,7 +638,7 @@
     return JS("", "new #()", ctor);
   }
 
-  static Future<SendPort> spawnFunction(void topLevelFunction(message),
+  static Future<List> spawnFunction(void topLevelFunction(message),
                                         message) {
     final name = _getJSFunctionName(topLevelFunction);
     if (name == null) {
@@ -592,25 +648,25 @@
     return spawn(name, null, null, message, false, false);
   }
 
-  static Future<SendPort> spawnUri(Uri uri, List<String> args, message) {
+  static Future<List> spawnUri(Uri uri, List<String> args, message) {
     return spawn(null, uri.toString(), args, message, false, true);
   }
 
   // TODO(sigmund): clean up above, after we make the new API the default:
 
   /// If [uri] is `null` it is replaced with the current script.
-  static Future<SendPort> spawn(String functionName, String uri,
-                                List<String> args, message,
-                                bool isLight, bool isSpawnUri) {
+  static Future<List> spawn(String functionName, String uri,
+                            List<String> args, message,
+                            bool isLight, bool isSpawnUri) {
     // Assume that the compiled version of the Dart file lives just next to the
     // dart file.
     // TODO(floitsch): support precompiled version of dart2js output.
     if (uri != null && uri.endsWith(".dart")) uri += ".js";
 
     ReceivePort port = new ReceivePort();
-    Future<SendPort> result = port.first.then((msg) {
+    Future<List> result = port.first.then((msg) {
       assert(msg[0] == _SPAWNED_SIGNAL);
-      return msg[1];
+      return msg;
     });
 
     SendPort signalReply = port.sendPort;
@@ -666,8 +722,9 @@
     _IsolateContext context = JS_CURRENT_ISOLATE_CONTEXT();
     Primitives.initializeStatics(context.id);
     // The isolate's port does not keep the isolate open.
-    controlPort = new ReceivePortImpl.weak();
-    replyTo.send([_SPAWNED_SIGNAL, controlPort.sendPort]);
+    replyTo.send([_SPAWNED_SIGNAL,
+                  context.controlPort.sendPort,
+                  context.pauseCapability]);
     if (!isSpawnUri) {
       topLevel(message);
     } else if (topLevel is _MainFunctionArgsMessage) {
@@ -763,6 +820,10 @@
     if (shouldSerialize) {
       msg = _serializeMessage(msg);
     }
+    if (isolate.controlPort == _receivePort) {
+      isolate.handleControlMessage(msg);
+      return;
+    }
     _globalState.topEventLoop.enqueue(isolate, () {
       if (!_receivePort._isClosed) {
         if (shouldSerialize) {
@@ -823,18 +884,23 @@
 class RawReceivePortImpl implements RawReceivePort {
   static int _nextFreeId = 1;
 
-  final int _id = _nextFreeId++;
+  final int _id;
   Function _handler;
   bool _isClosed = false;
 
-  RawReceivePortImpl(this._handler) {
+  RawReceivePortImpl(this._handler) : _id = _nextFreeId++ {
     _globalState.currentContext.register(_id, this);
   }
 
-  RawReceivePortImpl.weak(this._handler) {
+  RawReceivePortImpl.weak(this._handler) : _id = _nextFreeId++ {
     _globalState.currentContext.registerWeak(_id, this);
   }
 
+  // Creates the control port of an isolate.
+  // This is created before the isolate context object itself,
+  // so it cannot access the static _nextFreeId field.
+  RawReceivePortImpl._controlPort() : _handler = null, _id = 0;
+
   void set handler(Function newHandler) {
     _handler = newHandler;
   }
diff --git a/sdk/lib/_internal/lib/isolate_patch.dart b/sdk/lib/_internal/lib/isolate_patch.dart
index 09b7955..9d931a9 100644
--- a/sdk/lib/_internal/lib/isolate_patch.dart
+++ b/sdk/lib/_internal/lib/isolate_patch.dart
@@ -15,7 +15,7 @@
   patch static Future<Isolate> spawn(void entryPoint(message), var message) {
     try {
       return IsolateNatives.spawnFunction(entryPoint, message)
-          .then((controlPort) => new Isolate._fromControlPort(controlPort));
+          .then((msg) => new Isolate._fromControlPort(msg[1], msg[2]));
     } catch (e, st) {
       return new Future<Isolate>.error(e, st);
     }
@@ -34,7 +34,7 @@
         throw new ArgumentError("Args must be a list of Strings $args");
       }
       return IsolateNatives.spawnUri(uri, args, message)
-          .then((controlPort) => new Isolate._fromControlPort(controlPort));
+          .then((msg) => new Isolate._fromControlPort(msg[1], msg[2]));
     } catch (e, st) {
       return new Future<Isolate>.error(e, st);
     }
diff --git a/sdk/lib/_internal/lib/js_mirrors.dart b/sdk/lib/_internal/lib/js_mirrors.dart
index 067b616..a5ee2bf 100644
--- a/sdk/lib/_internal/lib/js_mirrors.dart
+++ b/sdk/lib/_internal/lib/js_mirrors.dart
@@ -227,6 +227,9 @@
         owner, getMetadata(_typeVariable.bound));
   }
 
+  bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError();
+  bool isAssignableTo(TypeMirror other) => throw new UnimplementedError();
+
   _asRuntimeType() => _metadataIndex;
 }
 
@@ -255,6 +258,9 @@
   bool get isOriginalDeclaration => true;
   TypeMirror get originalDeclaration => this;
 
+  bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError();
+  bool isAssignableTo(TypeMirror other) => throw new UnimplementedError();
+
   _asRuntimeType() {
     if (this == JsMirrorSystem._dynamicType) return null;
     if (this == JsMirrorSystem._voidType) return null;
@@ -791,6 +797,10 @@
   Function operator [](Symbol name) => throw new UnimplementedError();
 
   bool get isAbstract => throw new UnimplementedError();
+
+  bool isSubclassOf(ClassMirror other) => throw new UnimplementedError();
+  bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError();
+  bool isAssignableTo(TypeMirror other) => throw new UnimplementedError();
 }
 
 abstract class JsObjectMirror implements ObjectMirror {
@@ -1364,6 +1374,8 @@
 
   bool get isAbstract => _class.isAbstract;
 
+  bool isSubclassOf(ClassMirror other) => _class.isSubclassOf(other);
+
   SourceLocation get location => _class.location;
 
   MirrorSystem get mirrors => _class.mirrors;
@@ -1381,6 +1393,9 @@
 
   // TODO(ahe): Implement this.
   Function operator [](Symbol name) => throw new UnimplementedError();
+
+  bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError();
+  bool isAssignableTo(TypeMirror other) => throw new UnimplementedError();
 }
 
 class JsSyntheticAccessor implements MethodMirror {
@@ -1887,6 +1902,8 @@
   Function operator [](Symbol name) => throw new UnimplementedError();
 
   bool get isAbstract => throw new UnimplementedError();
+
+  bool isSubclassOf(ClassMirror other) => throw new UnimplementedError();
 }
 
 class JsVariableMirror extends JsDeclarationMirror implements VariableMirror {
@@ -2332,6 +2349,9 @@
 
   // TODO(ahe): Implement this method.
   List<InstanceMirror> get metadata => throw new UnimplementedError();
+
+  bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError();
+  bool isAssignableTo(TypeMirror other) => throw new UnimplementedError();
 }
 
 // TODO(ahe): Remove this class when API is updated.
@@ -2473,6 +2493,10 @@
     return _cachedToString = "$s'";
   }
 
+  bool isSubclassOf(ClassMirror other) => throw new UnimplementedError();
+  bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError();
+  bool isAssignableTo(TypeMirror other) => throw new UnimplementedError();
+
   // TODO(ahe): Implement this method.
   MethodMirror get callMethod => throw new UnimplementedError();
 }
diff --git a/sdk/lib/_internal/pub/lib/src/barback/build_environment.dart b/sdk/lib/_internal/pub/lib/src/barback/build_environment.dart
index 9e1467b..af2eae8 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/build_environment.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/build_environment.dart
@@ -221,15 +221,18 @@
           var parts = path.split(event.path);
           if (parts.contains("packages") || parts.contains("assets")) return;
 
-          // Skip ".js" files that were (most likely) compiled from nearby
-          // ".dart" files. These are created by the Editor's "Run as
-          // JavaScript" command and are written directly into the package's
-          // directory. When pub's dart2js transformer then tries to create the
-          // same file name, we get a build error. To avoid that, just don't
-          // consider that file to be a source.
-          // TODO(rnystrom): Remove this when the Editor no longer generates
-          // .js files. See #15859.
+          // Skip files that were (most likely) compiled from nearby ".dart"
+          // files. These are created by the Editor's "Run as JavaScript"
+          // command and are written directly into the package's directory.
+          // When pub's dart2js transformer then tries to create the same file
+          // name, we get a build error. To avoid that, just don't consider
+          // that file to be a source.
+          // TODO(rnystrom): Remove these when the Editor no longer generates
+          // .js files and users have had enough time that they no longer have
+          // these files laying around. See #15859.
           if (event.path.endsWith(".dart.js")) return;
+          if (event.path.endsWith(".dart.js.map")) return;
+          if (event.path.endsWith(".dart.precompiled.js")) return;
 
           var id = new AssetId(package.name,
               path.relative(event.path, from: package.dir));
@@ -264,15 +267,18 @@
         // Skip directories.
         if (!fileExists(entry)) continue;
 
-        // Skip ".js" files that were (most likely) compiled from nearby ".dart"
-        // files. These are created by the Editor's "Run as JavaScript" command
-        // and are written directly into the package's directory. When pub's
-        // dart2js transformer then tries to create the same file name, we get
-        // a build error. To avoid that, just don't consider that file to be a
-        // source.
-        // TODO(rnystrom): Remove this when the Editor no longer generates .js
-        // files. See #15859.
+        // Skip files that were (most likely) compiled from nearby ".dart"
+        // files. These are created by the Editor's "Run as JavaScript"
+        // command and are written directly into the package's directory.
+        // When pub's dart2js transformer then tries to create the same file
+        // name, we get a build error. To avoid that, just don't consider
+        // that file to be a source.
+        // TODO(rnystrom): Remove these when the Editor no longer generates
+        // .js files and users have had enough time that they no longer have
+        // these files laying around. See #15859.
         if (entry.endsWith(".dart.js")) continue;
+        if (entry.endsWith(".dart.js.map")) continue;
+        if (entry.endsWith(".dart.precompiled.js")) continue;
 
         var id = new AssetId(package.name,
             path.relative(entry, from: package.dir));
diff --git a/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart b/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
index f6f64c5..84ca336 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
@@ -20,8 +20,6 @@
 import '../barback.dart';
 import '../dart.dart' as dart;
 import '../io.dart';
-import '../package.dart';
-import '../package_graph.dart';
 import '../utils.dart';
 import 'build_environment.dart';
 
@@ -33,7 +31,7 @@
 
 /// A [Transformer] that uses dart2js's library API to transform Dart
 /// entrypoints in "web" to JavaScript.
-class Dart2JSTransformer extends Transformer {
+class Dart2JSTransformer extends Transformer implements LazyTransformer {
   final BuildEnvironment _environment;
   final BarbackSettings _settings;
 
@@ -139,6 +137,14 @@
     });
   }
 
+  Future declareOutputs(DeclaringTransform transform) {
+    var primaryId = transform.primaryInput.id;
+    transform.declareOutput(primaryId.addExtension(".js"));
+    transform.declareOutput(primaryId.addExtension(".js.map"));
+    transform.declareOutput(primaryId.addExtension(".precompiled.js"));
+    return new Future.value();
+  }
+
   /// Parses and returns the "commandLineOptions" configuration option.
   List<String> get _configCommandLineOptions {
     if (!_settings.configuration.containsKey('commandLineOptions')) return null;
diff --git a/sdk/lib/_internal/pub/lib/src/barback/server.dart b/sdk/lib/_internal/pub/lib/src/barback/server.dart
index d285cfa..c783771 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/server.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/server.dart
@@ -9,6 +9,7 @@
 import 'dart:io';
 
 import 'package:barback/barback.dart';
+import 'package:mime/mime.dart';
 import 'package:path/path.dart' as path;
 import 'package:stack_trace/stack_trace.dart';
 
@@ -114,6 +115,10 @@
       return validateStream(asset.read()).then((stream) {
         _resultsController.add(
             new BarbackServerResult._success(request.uri, id));
+        var mimeType = lookupMimeType(id.path);
+        if (mimeType != null) {
+          request.response.headers.add('content-type', mimeType);
+        }
         // TODO(rnystrom): Set content-type based on asset type.
         return Chain.track(request.response.addStream(stream)).then((_) {
           // Log successful requests both so we can provide debugging
diff --git a/sdk/lib/_internal/pub/lib/src/command.dart b/sdk/lib/_internal/pub/lib/src/command.dart
index 3f6f35e..d5eb6ea 100644
--- a/sdk/lib/_internal/pub/lib/src/command.dart
+++ b/sdk/lib/_internal/pub/lib/src/command.dart
@@ -181,6 +181,8 @@
   }
 
   /// Displays usage information for this command.
+  ///
+  /// If [description] is omitted, defaults to the command's description.
   void printUsage([String description]) {
     if (description == null) description = this.description;
     log.message('$description\n\n${_getUsage()}');
diff --git a/sdk/lib/_internal/pub/lib/src/command/build.dart b/sdk/lib/_internal/pub/lib/src/command/build.dart
index 5131ea2..eba1a10 100644
--- a/sdk/lib/_internal/pub/lib/src/command/build.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/build.dart
@@ -177,14 +177,6 @@
       return new Future.value();
     }
 
-    // If the asset is from a package's "lib" directory, we make it available
-    // as an input for transformers, but don't want it in the final output.
-    // (Any Dart code in there should be imported and compiled to JS, anything
-    // else we want to omit.)
-    if (asset.id.path.startsWith("lib/")) {
-      return new Future.value();
-    }
-
     // Figure out the output directory for the asset, which is the same as the
     // path pub serve would use to serve it.
     var relativeUrl = barback.idtoUrlPath(entrypoint.root.name, asset.id,
@@ -193,9 +185,10 @@
     // Remove the leading "/".
     relativeUrl = relativeUrl.substring(1);
 
-    // If the asset is from the shared "assets" directory, copy it into all of
-    // the top-level build directories.
-    if (relativeUrl.startsWith("assets/")) {
+    // If the asset is from a public directory, copy it into all of the
+    // top-level build directories.
+    if (relativeUrl.startsWith("assets/") ||
+        relativeUrl.startsWith("packages/")) {
       builtFiles += buildDirectories.length;
       return Future.wait(buildDirectories.map(
           (buildDir) => _writeOutputFile(asset,
@@ -223,15 +216,19 @@
   /// Returns the number of files it copied.
   int _copyBrowserJsFiles(Iterable<AssetId> entrypoints) {
     // Must depend on the browser package.
-    if (!entrypoint.root.dependencies.any(
+    if (!entrypoint.root.immediateDependencies.any(
         (dep) => dep.name == 'browser' && dep.source == 'hosted')) {
       return 0;
     }
 
-    // Get all of the directories that contain Dart entrypoints.
+    // Get all of the subdirectories that contain Dart entrypoints.
     var entrypointDirs = entrypoints
-        .map((id) => path.url.split(id.path))
-        .map((relative) => path.dirname(path.joinAll(relative)))
+        // Convert the asset path to a native-separated one and get the
+        // directory containing the entrypoint.
+        .map((id) => path.dirname(path.joinAll(path.url.split(id.path))))
+        // Don't copy files to the top levels of the build directories since
+        // the normal lib asset copying will take care of that.
+        .where((dir) => dir.contains(path.separator))
         .toSet();
 
     for (var dir in entrypointDirs) {
diff --git a/sdk/lib/_internal/pub/lib/src/command/cache.dart b/sdk/lib/_internal/pub/lib/src/command/cache.dart
index dbef315..93897fa 100644
--- a/sdk/lib/_internal/pub/lib/src/command/cache.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/cache.dart
@@ -5,6 +5,7 @@
 library pub.command.cache;
 
 import '../command.dart';
+import 'cache_add.dart';
 import 'cache_list.dart';
 
 /// Handles the `cache` pub command.
@@ -13,6 +14,7 @@
   String get usage => "pub cache <subcommand>";
 
   final subcommands = {
+    "add": new CacheAddCommand(),
     "list": new CacheListCommand()
   };
 }
diff --git a/sdk/lib/_internal/pub/lib/src/command/cache_add.dart b/sdk/lib/_internal/pub/lib/src/command/cache_add.dart
new file mode 100644
index 0000000..7cf0be4
--- /dev/null
+++ b/sdk/lib/_internal/pub/lib/src/command/cache_add.dart
@@ -0,0 +1,98 @@
+// Copyright (c) 2014, 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 pub.command.cache_add;
+
+import 'dart:async';
+
+import '../command.dart';
+import '../exit_codes.dart' as exit_codes;
+import '../io.dart';
+import '../log.dart' as log;
+import '../package.dart';
+import '../utils.dart';
+import '../version.dart';
+
+/// Handles the `cache add` pub command.
+class CacheAddCommand extends PubCommand {
+  String get description => "Install a package.";
+  String get usage =>
+      "pub cache add <package> [--version <constraint>] [--all]";
+  bool get requiresEntrypoint => false;
+  bool get takesArguments => true;
+
+  CacheAddCommand() {
+    commandParser.addFlag("all",
+        help: "Install all matching versions.",
+        negatable: false);
+
+    commandParser.addOption("version", abbr: "v",
+        help: "Version constraint.");
+  }
+
+  Future onRun() {
+    // Make sure there is a package.
+    if (commandOptions.rest.isEmpty) {
+      usageError("No package to add given.");
+    }
+
+    // Don't allow extra arguments.
+    if (commandOptions.rest.length > 1) {
+      var unexpected = commandOptions.rest.skip(1).map((arg) => '"$arg"');
+      var arguments = pluralize("argument", unexpected.length);
+      usageError("Unexpected $arguments ${toSentence(unexpected)}.");
+    }
+
+    var package = commandOptions.rest.single;
+
+    // Parse the version constraint, if there is one.
+    var constraint = VersionConstraint.any;
+    if (commandOptions["version"] != null) {
+      try {
+        constraint = new VersionConstraint.parse(commandOptions["version"]);
+      } on FormatException catch (error) {
+        usageError(error.message);
+      }
+    }
+
+    // TODO(rnystrom): Support installing from git too.
+    var source = this.cache.sources["hosted"];
+
+    // TODO(rnystrom): Allow specifying the server.
+    return source.getVersions(package, package).then((versions) {
+      versions = versions.where(constraint.allows).toList();
+
+      if (versions.isEmpty) {
+        // TODO(rnystrom): Show most recent unmatching version?
+        throw new ApplicationException(
+            "Package $package has no versions that match $constraint.");
+      }
+
+      downloadVersion(Version version) {
+        var id = new PackageId(package, source.name, version, package);
+        return cache.contains(id).then((contained) {
+          if (contained) {
+            // TODO(rnystrom): Include source and description if not hosted.
+            // See solve_report.dart for code to harvest.
+            log.message("Already cached ${id.name} ${id.version}.");
+            return null;
+          }
+
+          // Download it.
+          return cache.download(id);
+        });
+      }
+
+      if (commandOptions["all"]) {
+        // Install them in ascending order.
+        versions.sort();
+        return Future.forEach(versions, downloadVersion);
+      } else {
+        // Pick the best matching version.
+        versions.sort(Version.prioritize);
+        return downloadVersion(versions.last);
+      }
+    });
+  }
+}
diff --git a/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart b/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart
index 60e71a6f..6ac4aad 100644
--- a/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart
+++ b/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart
@@ -181,17 +181,11 @@
     var source = _sources[package.source];
     return source.getVersions(package.name, package.description)
         .then((versions) {
-      // Sort by descending version so we try newer versions first.
-      versions.sort((a, b) {
-        // Sort all prerelease versions after all normal versions. This way
-        // the solver will prefer stable packages over unstable ones.
-        if (a.isPreRelease && !b.isPreRelease) return 1;
-        if (!a.isPreRelease && b.isPreRelease) return -1;
+      // Sort by priority so we try preferred versions first.
+      versions.sort(Version.prioritize);
 
-        return b.compareTo(a);
-      });
-
-      var ids = versions.map((version) => package.atVersion(version)).toList();
+      var ids = versions.reversed.map(
+          (version) => package.atVersion(version)).toList();
       _versions[package] = ids;
       return ids;
     });
diff --git a/sdk/lib/_internal/pub/lib/src/source.dart b/sdk/lib/_internal/pub/lib/src/source.dart
index 299f6cf..4e9fac6 100644
--- a/sdk/lib/_internal/pub/lib/src/source.dart
+++ b/sdk/lib/_internal/pub/lib/src/source.dart
@@ -144,10 +144,22 @@
         "be implemented for source $name.");
   }
 
-  /// Downloads the package identified by [id] to the system cache. This is only
-  /// called for sources with [shouldCache] set to true.
+  /// Determines if the package with [id] is already downloaded to the system
+  /// cache.
   ///
-  /// By default, this uses [systemCacheDirectory] and [get].
+  /// This should only be called for sources with [shouldCache] set to true.
+  /// Completes to true if the package is in the cache and appears to be
+  /// uncorrupted.
+  Future<bool> isInSystemCache(PackageId id) {
+    return systemCacheDirectory(id).then((packageDir) {
+      return dirExists(packageDir) && !_isCachedPackageCorrupted(packageDir);
+    });
+  }
+
+  /// Downloads the package identified by [id] to the system cache.
+  ///
+  /// This is only called for sources with [shouldCache] set to true. By
+  /// default, this uses [systemCacheDirectory] and [get].
   Future<Package> downloadToSystemCache(PackageId id) {
     var packageDir;
     return systemCacheDirectory(id).then((p) {
diff --git a/sdk/lib/_internal/pub/lib/src/system_cache.dart b/sdk/lib/_internal/pub/lib/src/system_cache.dart
index bfc6cea..4e011dd 100644
--- a/sdk/lib/_internal/pub/lib/src/system_cache.dart
+++ b/sdk/lib/_internal/pub/lib/src/system_cache.dart
@@ -66,6 +66,17 @@
     sources.register(source);
   }
 
+  /// Determines if the system cache contains the package identified by [id].
+  Future<bool> contains(PackageId id) {
+    var source = sources[id.source];
+
+    if (!source.shouldCache) {
+      throw new ArgumentError("Package $id is not cacheable.");
+    }
+
+    return source.isInSystemCache(id);
+  }
+
   /// Ensures that the package identified by [id] is downloaded to the cache,
   /// loads it, and returns it.
   ///
diff --git a/sdk/lib/_internal/pub/lib/src/version.dart b/sdk/lib/_internal/pub/lib/src/version.dart
index 8c34d57..1e92a3b 100644
--- a/sdk/lib/_internal/pub/lib/src/version.dart
+++ b/sdk/lib/_internal/pub/lib/src/version.dart
@@ -33,6 +33,27 @@
   /// No released version: i.e. "0.0.0".
   static Version get none => new Version(0, 0, 0);
 
+  /// Compares [a] and [b] to see which takes priority over the other.
+  ///
+  /// Returns `1` if [a] takes priority over [b] and `-1` if vice versa. If
+  /// [a] and [b] are equivalent, returns `0`.
+  ///
+  /// Unlike [compareTo], which *orders* versions, this determines which
+  /// version a user is likely to prefer. In particular, it prioritizes
+  /// pre-release versions lower than stable versions, regardless of their
+  /// version numbers.
+  ///
+  /// When used to sort a list, orders in ascending priority so that the
+  /// highest priority version is *last* in the result.
+  static int prioritize(Version a, Version b) {
+    // Sort all prerelease versions after all normal versions. This way
+    // the solver will prefer stable packages over unstable ones.
+    if (a.isPreRelease && !b.isPreRelease) return -1;
+    if (!a.isPreRelease && b.isPreRelease) return 1;
+
+    return a.compareTo(b);
+  }
+
   /// The major version number: "1" in "1.2.3".
   final int major;
 
diff --git a/sdk/lib/_internal/pub/pub.status b/sdk/lib/_internal/pub/pub.status
index 4e7d2c0..66c996f 100644
--- a/sdk/lib/_internal/pub/pub.status
+++ b/sdk/lib/_internal/pub/pub.status
@@ -2,13 +2,10 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
-test/hosted/version_negotiation_test: Pass, Timeout # Issue 14346
-
-test/upgrade/hosted/upgrade_removed_constraints_test: Pass, Fail # Issue 15349
+test/hosted/version_negotiation_test: Timeout # Issue 14346
 
 [ $runtime == vm && $system == windows ]
 test/serve/warns_on_assets_paths_test: Pass, Fail # Issue 15741
-test/serve/missing_file_test: Pass, Fail # Issue 16129
 
 # Pub only runs on the VM, so just rule out all compilers.
 [ $compiler == dart2js || $compiler == dart2dart ]
diff --git a/sdk/lib/_internal/pub/test/build/copies_browser_js_next_to_entrypoints_test.dart b/sdk/lib/_internal/pub/test/build/copies_browser_js_next_to_entrypoints_test.dart
index f8bf83d..e005f30 100644
--- a/sdk/lib/_internal/pub/test/build/copies_browser_js_next_to_entrypoints_test.dart
+++ b/sdk/lib/_internal/pub/test/build/copies_browser_js_next_to_entrypoints_test.dart
@@ -8,6 +8,7 @@
 
 import '../descriptor.dart' as d;
 import '../test_pub.dart';
+import 'utils.dart';
 
 main() {
   initConfig();
@@ -17,36 +18,7 @@
     // timeout to cope with that.
     currentSchedule.timeout *= 3;
 
-    serve([
-      d.dir('api', [
-        d.dir('packages', [
-          d.file('browser', JSON.encode({
-            'versions': [packageVersionApiMap(packageMap('browser', '1.0.0'))]
-          })),
-          d.dir('browser', [
-            d.dir('versions', [
-              d.file('1.0.0', JSON.encode(
-                  packageVersionApiMap(
-                      packageMap('browser', '1.0.0'),
-                      full: true)))
-            ])
-          ])
-        ])
-      ]),
-      d.dir('packages', [
-        d.dir('browser', [
-          d.dir('versions', [
-            d.tar('1.0.0.tar.gz', [
-              d.file('pubspec.yaml', yaml(packageMap("browser", "1.0.0"))),
-              d.dir('lib', [
-                d.file('dart.js', 'contents of dart.js'),
-                d.file('interop.js', 'contents of interop.js')
-              ])
-            ])
-          ])
-        ])
-      ])
-    ]);
+    serveBrowserPackage();
 
     d.dir(appPath, [
       d.appPubspec({"browser": "1.0.0"}),
diff --git a/sdk/lib/_internal/pub/test/build/copies_browser_js_with_dependency_override_test.dart b/sdk/lib/_internal/pub/test/build/copies_browser_js_with_dependency_override_test.dart
new file mode 100644
index 0000000..7d2bb90
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/build/copies_browser_js_with_dependency_override_test.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  // This is a regression test for http://dartbug.com/16617.
+
+  initConfig();
+
+  integration("compiles dart.js and interop.js next to entrypoints when "
+      "browser is a dependency_override", () {
+    // Dart2js can take a long time to compile dart code, so we increase the
+    // timeout to cope with that.
+    currentSchedule.timeout *= 3;
+
+    serveBrowserPackage();
+
+    d.dir(appPath, [
+      d.pubspec({
+        "name": "myapp",
+        "dependency_overrides": {
+          "browser": "any"
+        }
+      }),
+      d.dir('web', [
+        d.file('file.dart', 'void main() => print("hello");')
+      ])
+    ]).create();
+
+    pubGet();
+
+    schedulePub(args: ["build", "--all"],
+        output: new RegExp(r"Built 5 files!"));
+
+    d.dir(appPath, [
+      d.dir('build', [
+        d.dir('web', [
+          d.dir('packages', [d.dir('browser', [
+            d.file('dart.js', 'contents of dart.js'),
+            d.file('interop.js', 'contents of interop.js')
+          ])])
+        ])
+      ])
+    ]).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/build/copies_browser_js_with_dev_dependency_test.dart b/sdk/lib/_internal/pub/test/build/copies_browser_js_with_dev_dependency_test.dart
new file mode 100644
index 0000000..3849227
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/build/copies_browser_js_with_dev_dependency_test.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  // This is a regression test for http://dartbug.com/16617.
+
+  initConfig();
+
+  integration("compiles dart.js and interop.js next to entrypoints when "
+      "browser is a dev dependency", () {
+    // Dart2js can take a long time to compile dart code, so we increase the
+    // timeout to cope with that.
+    currentSchedule.timeout *= 3;
+
+    serveBrowserPackage();
+
+    d.dir(appPath, [
+      d.pubspec({
+        "name": "myapp",
+        "dev_dependencies": {
+          "browser": "any"
+        }
+      }),
+      d.dir('web', [
+        d.file('file.dart', 'void main() => print("hello");')
+      ])
+    ]).create();
+
+    pubGet();
+
+    schedulePub(args: ["build", "--all"],
+        output: new RegExp(r"Built 5 files!"));
+
+    d.dir(appPath, [
+      d.dir('build', [
+        d.dir('web', [
+          d.dir('packages', [d.dir('browser', [
+            d.file('dart.js', 'contents of dart.js'),
+            d.file('interop.js', 'contents of interop.js')
+          ])])
+        ])
+      ])
+    ]).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/build/ignores_existing_compiled_js_files_test.dart b/sdk/lib/_internal/pub/test/build/ignores_existing_compiled_js_files_test.dart
index 962e858..f9d16c6 100644
--- a/sdk/lib/_internal/pub/test/build/ignores_existing_compiled_js_files_test.dart
+++ b/sdk/lib/_internal/pub/test/build/ignores_existing_compiled_js_files_test.dart
@@ -20,9 +20,13 @@
       d.dir('web', [
         d.file('file.dart', 'void main() => print("hello");'),
         d.file('file.dart.js', 'some js code'),
+        d.file('file.dart.js.map', 'source map'),
+        d.file('file.dart.precompiled.js', 'some js code'),
         d.dir('subdir', [
           d.file('subfile.dart', 'void main() => print("ping");'),
-          d.file('subfile.dart.js', 'some js code')
+          d.file('subfile.dart.js', 'some js code'),
+          d.file('subfile.dart.js.map', 'source map'),
+          d.file('subfile.dart.precompiled.js', 'some js code')
         ])
       ])
     ]).create();
@@ -34,8 +38,14 @@
       d.dir('build', [
         d.dir('web', [
           d.matcherFile('file.dart.js', isNot(equals('some js code'))),
+          d.matcherFile('file.dart.js.map', isNot(equals('source map'))),
+          d.matcherFile('file.dart.precompiled.js',
+                        isNot(equals('some js code'))),
           d.dir('subdir', [
-            d.matcherFile('subfile.dart.js', isNot(equals('some js code')))
+            d.matcherFile('subfile.dart.js', isNot(equals('some js code'))),
+            d.matcherFile('subfile.dart.js.map', isNot(equals('source map'))),
+            d.matcherFile('subfile.dart.precompiled.js',
+                          isNot(equals('some js code')))
           ])
         ])
       ])
diff --git a/sdk/lib/_internal/pub/test/build/includes_assets_from_dependencies_in_lib_test.dart b/sdk/lib/_internal/pub/test/build/includes_assets_from_dependencies_in_lib_test.dart
new file mode 100644
index 0000000..6af3a81
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/build/includes_assets_from_dependencies_in_lib_test.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+main() {
+  initConfig();
+
+  integration("includes assets from the 'lib' directory of dependencies", () {
+    // Dart2js can take a long time to compile dart code, so we increase the
+    // timeout to cope with that.
+    currentSchedule.timeout *= 3;
+
+    d.dir("foo", [
+      d.libPubspec("foo", "0.0.1"),
+      d.dir("lib", [
+        d.file("foo.txt", "foo"),
+        d.dir("sub", [
+          d.file("bar.txt", "bar"),
+        ])
+      ])
+    ]).create();
+
+    d.dir(appPath, [
+      d.appPubspec({
+        "foo": {"path": "../foo"}
+      }),
+      d.dir("example", [
+        d.file("index.html", "html"),
+      ]),
+      d.dir("web", [
+        d.file("index.html", "html"),
+        d.dir("sub", [
+          d.file("index.html", "html")
+        ])
+      ])
+    ]).create();
+
+    schedulePub(args: ["build", "--all"],
+        output: new RegExp(r"Built 7 files!"));
+
+    d.dir(appPath, [
+      d.dir('build', [
+        d.dir('example', [
+          d.file("index.html", "html"),
+          d.dir('packages', [
+            d.dir('foo', [
+              d.file('foo.txt', 'foo'),
+              d.dir('sub', [
+                d.file('bar.txt', 'bar'),
+              ]),
+            ])
+          ])
+        ]),
+        d.dir('web', [
+          d.file("index.html", "html"),
+          d.dir('packages', [
+            d.dir('foo', [
+              d.file('foo.txt', 'foo'),
+              d.dir('sub', [
+                d.file('bar.txt', 'bar'),
+              ]),
+            ])
+          ]),
+          d.dir("sub", [
+            d.file("index.html", "html"),
+            // "packages" should *only* be created in the top-level directory.
+            d.nothing("packages")
+          ])
+        ])
+      ])
+    ]).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/build/includes_assets_from_dependencies_test.dart b/sdk/lib/_internal/pub/test/build/includes_assets_from_dependencies_test.dart
index a5098b6..35bda64 100644
--- a/sdk/lib/_internal/pub/test/build/includes_assets_from_dependencies_test.dart
+++ b/sdk/lib/_internal/pub/test/build/includes_assets_from_dependencies_test.dart
@@ -34,11 +34,14 @@
       ]),
       d.dir("web", [
         d.file("index.html", "html"),
+        d.dir("sub", [
+          d.file("index.html", "html")
+        ])
       ])
     ]).create();
 
     schedulePub(args: ["build", "--all"],
-        output: new RegExp(r"Built 6 files!"));
+        output: new RegExp(r"Built 7 files!"));
 
     d.dir(appPath, [
       d.dir('build', [
@@ -62,6 +65,11 @@
                 d.file('bar.txt', 'bar'),
               ]),
             ])
+          ]),
+          d.dir("sub", [
+            d.file("index.html", "html"),
+            // "assets" should *only* be created in the top-level directory.
+            d.nothing("assets")
           ])
         ])
       ])
diff --git a/sdk/lib/_internal/pub/test/build/includes_dart_files_from_dependencies_in_debug_test.dart b/sdk/lib/_internal/pub/test/build/includes_dart_files_from_dependencies_in_debug_test.dart
new file mode 100644
index 0000000..f8a719b
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/build/includes_dart_files_from_dependencies_in_debug_test.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+main() {
+  initConfig();
+
+  integration("includes .dart files from dependencies in debug mode", () {
+    // Dart2js can take a long time to compile dart code, so we increase the
+    // timeout to cope with that.
+    currentSchedule.timeout *= 3;
+
+    d.dir("foo", [
+      d.libPubspec("foo", "0.0.1"),
+      d.dir("lib", [
+        d.file('foo.dart', 'foo() => print("hello");'),
+        d.dir("sub", [
+          d.file('bar.dart', 'bar() => print("hello");'),
+        ])
+      ])
+    ]).create();
+
+    d.dir(appPath, [
+      d.appPubspec({
+        "foo": {"path": "../foo"}
+      }),
+      d.dir("example", [
+        d.file("main.dart", 'myapp() => print("not entrypoint");'),
+        d.dir("sub", [
+          d.file("main.dart", 'myapp() => print("not entrypoint");')
+        ])
+      ])
+    ]).create();
+
+    schedulePub(args: ["build", "--mode", "debug", "example"],
+        output: new RegExp(r"Built 4 files!"));
+
+    d.dir(appPath, [
+      d.dir('build', [
+        d.dir('example', [
+          d.file("main.dart", 'myapp() => print("not entrypoint");'),
+          d.dir('packages', [
+            d.dir('foo', [
+              d.file('foo.dart', 'foo() => print("hello");'),
+              d.dir("sub", [
+                d.file('bar.dart', 'bar() => print("hello");'),
+              ])
+            ])
+          ]),
+          d.dir("sub", [
+            d.file("main.dart", 'myapp() => print("not entrypoint");'),
+            // Does *not* copy packages into subdirectories.
+            d.nothing("packages")
+          ])
+        ])
+      ])
+    ]).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/build/utils.dart b/sdk/lib/_internal/pub/test/build/utils.dart
new file mode 100644
index 0000000..6f3df99
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/build/utils.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:convert';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+/// Runs the hosted test server and serves a valid "browser" package that
+/// contains the same files (but not their contents) as the real browser
+/// package.
+void serveBrowserPackage() {
+  serve([
+    d.dir('api', [
+      d.dir('packages', [
+        d.file('browser', JSON.encode({
+          'versions': [packageVersionApiMap(packageMap('browser', '1.0.0'))]
+        })),
+        d.dir('browser', [
+          d.dir('versions', [
+            d.file('1.0.0', JSON.encode(
+                packageVersionApiMap(
+                    packageMap('browser', '1.0.0'),
+                    full: true)))
+          ])
+        ])
+      ])
+    ]),
+    d.dir('packages', [
+      d.dir('browser', [
+        d.dir('versions', [
+          d.tar('1.0.0.tar.gz', [
+            d.file('pubspec.yaml', yaml(packageMap("browser", "1.0.0"))),
+            d.dir('lib', [
+              d.file('dart.js', 'contents of dart.js'),
+              d.file('interop.js', 'contents of interop.js')
+            ])
+          ])
+        ])
+      ])
+    ])
+  ]);
+}
diff --git a/sdk/lib/_internal/pub/test/cache/add/adds_latest_matching_version_test.dart b/sdk/lib/_internal/pub/test/cache/add/adds_latest_matching_version_test.dart
new file mode 100644
index 0000000..5d6701b
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/cache/add/adds_latest_matching_version_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2014, 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 pub_tests;
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+  integration('adds the latest version of the package matching the '
+              'version constraint', () {
+    servePackages([
+      packageMap("foo", "1.2.2"),
+      packageMap("foo", "1.2.3"),
+      packageMap("foo", "2.0.0-dev"),
+      packageMap("foo", "2.0.0")
+    ]);
+
+    schedulePub(args: ["cache", "add", "foo", "-v", ">=1.0.0 <2.0.0"],
+        output: 'Downloading foo 1.2.3...');
+
+    d.cacheDir({"foo": "1.2.3"}).validate();
+    d.hostedCache([
+      d.nothing("foo-1.2.2"),
+      d.nothing("foo-2.0.0-dev"),
+      d.nothing("foo-2.0.0")
+    ]).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/cache/add/adds_latest_version_test.dart b/sdk/lib/_internal/pub/test/cache/add/adds_latest_version_test.dart
new file mode 100644
index 0000000..5aae1dd
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/cache/add/adds_latest_version_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2014, 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 pub_tests;
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+  integration('adds the latest stable version of the package', () {
+    servePackages([
+      packageMap("foo", "1.2.2"),
+      packageMap("foo", "1.2.3"),
+      packageMap("foo", "1.2.4-dev")
+    ]);
+
+    schedulePub(args: ["cache", "add", "foo"],
+        output: 'Downloading foo 1.2.3...');
+
+    d.cacheDir({"foo": "1.2.3"}).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/cache/add/all_adds_all_matching_versions_test.dart b/sdk/lib/_internal/pub/test/cache/add/all_adds_all_matching_versions_test.dart
new file mode 100644
index 0000000..a63627b
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/cache/add/all_adds_all_matching_versions_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2014, 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 pub_tests;
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+  integration('"--all" adds all matching versions of the package', () {
+    servePackages([
+      packageMap("foo", "1.2.2"),
+      packageMap("foo", "1.2.3-dev"),
+      packageMap("foo", "1.2.3"),
+      packageMap("foo", "2.0.0-dev"),
+      packageMap("foo", "2.0.0")
+    ]);
+
+    schedulePub(args: ["cache", "add", "foo", "-v", ">=1.0.0 <2.0.0", "--all"],
+        output: '''
+          Downloading foo 1.2.2...
+          Downloading foo 1.2.3-dev...
+          Downloading foo 1.2.3...
+          Downloading foo 2.0.0-dev...''');
+
+    d.cacheDir({"foo": "1.2.2"}).validate();
+    d.cacheDir({"foo": "1.2.3-dev"}).validate();
+    d.cacheDir({"foo": "1.2.3"}).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/cache/add/all_with_some_versions_present_test.dart b/sdk/lib/_internal/pub/test/cache/add/all_with_some_versions_present_test.dart
new file mode 100644
index 0000000..3a90077
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/cache/add/all_with_some_versions_present_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2014, 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 pub_tests;
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+  integration('"--all" adds all non-installed versions of the package', () {
+    servePackages([
+      packageMap("foo", "1.2.1"),
+      packageMap("foo", "1.2.2"),
+      packageMap("foo", "1.2.3"),
+      packageMap("foo", "2.0.0")
+    ]);
+
+    // Install a couple of versions first.
+    schedulePub(args: ["cache", "add", "foo", "-v", "1.2.1"],
+        output: 'Downloading foo 1.2.1...');
+
+    schedulePub(args: ["cache", "add", "foo", "-v", "1.2.3"],
+        output: 'Downloading foo 1.2.3...');
+
+    // They should show up as already installed now.
+    schedulePub(args: ["cache", "add", "foo", "--all"],
+        output: '''
+          Already cached foo 1.2.1.
+          Downloading foo 1.2.2...
+          Already cached foo 1.2.3.
+          Downloading foo 2.0.0...''');
+
+    d.cacheDir({"foo": "1.2.1"}).validate();
+    d.cacheDir({"foo": "1.2.2"}).validate();
+    d.cacheDir({"foo": "1.2.3"}).validate();
+    d.cacheDir({"foo": "2.0.0"}).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/cache/add/already_cached_test.dart b/sdk/lib/_internal/pub/test/cache/add/already_cached_test.dart
new file mode 100644
index 0000000..ad68f6c
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/cache/add/already_cached_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2014, 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 pub_tests;
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+  integration('does nothing if the package is already cached', () {
+    servePackages([
+      packageMap("foo", "1.2.3")
+    ]);
+
+    // Run once to put it in the cache.
+    schedulePub(args: ["cache", "add", "foo"],
+        output: 'Downloading foo 1.2.3...');
+
+    // Should be in the cache now.
+    schedulePub(args: ["cache", "add", "foo"],
+        output: 'Already cached foo 1.2.3.');
+
+    d.cacheDir({"foo": "1.2.3"}).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/cache/add/bad_version_test.dart b/sdk/lib/_internal/pub/test/cache/add/bad_version_test.dart
new file mode 100644
index 0000000..b805992
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/cache/add/bad_version_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2014, 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 pub_tests;
+
+import '../../../lib/src/exit_codes.dart' as exit_codes;
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+  integration('fails if the version constraint cannot be parsed', () {
+    schedulePub(args: ["cache", "add", "foo", "-v", "1.0"],
+        error: """
+            Could not parse version "1.0". Unknown text at "1.0".
+            
+            Usage: pub cache add <package> [--version <constraint>] [--all]
+            -h, --help       Print usage information for this command.
+                --all        Install all matching versions.
+            -v, --version    Version constraint.
+            """,
+        exitCode: exit_codes.USAGE);
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/cache/add/missing_package_arg_test.dart b/sdk/lib/_internal/pub/test/cache/add/missing_package_arg_test.dart
new file mode 100644
index 0000000..e95ede7
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/cache/add/missing_package_arg_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2014, 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 pub_tests;
+
+import '../../../lib/src/exit_codes.dart' as exit_codes;
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+  integration('fails if no package was given', () {
+    schedulePub(args: ["cache", "add"],
+        error: """
+            No package to add given.
+            
+            Usage: pub cache add <package> [--version <constraint>] [--all]
+            -h, --help       Print usage information for this command.
+                --all        Install all matching versions.
+            -v, --version    Version constraint.
+            """,
+        exitCode: exit_codes.USAGE);
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/cache/add/no_matching_version_test.dart b/sdk/lib/_internal/pub/test/cache/add/no_matching_version_test.dart
new file mode 100644
index 0000000..2f8cc35
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/cache/add/no_matching_version_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2014, 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 pub_tests;
+
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+  integration('fails if no version matches the version constraint', () {
+    servePackages([
+      packageMap("foo", "1.2.2"),
+      packageMap("foo", "1.2.3")
+    ]);
+
+    schedulePub(args: ["cache", "add", "foo", "-v", ">2.0.0"],
+        error: 'Package foo has no versions that match >2.0.0.',
+        exitCode: 1);
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/cache/add/package_not_found_test.dart b/sdk/lib/_internal/pub/test/cache/add/package_not_found_test.dart
new file mode 100644
index 0000000..9e60b5f
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/cache/add/package_not_found_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2014, 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 pub_tests;
+
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+  integration('fails if the package cound not be found on the source', () {
+    servePackages([]);
+
+    schedulePub(args: ["cache", "add", "foo"],
+        error: new RegExp(r"Could not find package foo at http://.*"),
+        exitCode: 1);
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/cache/add/unexpected_arguments_test.dart b/sdk/lib/_internal/pub/test/cache/add/unexpected_arguments_test.dart
new file mode 100644
index 0000000..2ba1e67
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/cache/add/unexpected_arguments_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2014, 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 pub_tests;
+
+import '../../../lib/src/exit_codes.dart' as exit_codes;
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+  integration('fails if there are extra arguments', () {
+    schedulePub(args: ["cache", "add", "foo", "bar", "baz"],
+        error: """
+            Unexpected arguments "bar" and "baz".
+            
+            Usage: pub cache add <package> [--version <constraint>] [--all]
+            -h, --help       Print usage information for this command.
+                --all        Install all matching versions.
+            -v, --version    Version constraint.
+            """,
+        exitCode: exit_codes.USAGE);
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/pub_cache_test.dart b/sdk/lib/_internal/pub/test/cache/list_test.dart
similarity index 96%
rename from sdk/lib/_internal/pub/test/pub_cache_test.dart
rename to sdk/lib/_internal/pub/test/cache/list_test.dart
index 4483166..3a7bb8e 100644
--- a/sdk/lib/_internal/pub/test/pub_cache_test.dart
+++ b/sdk/lib/_internal/pub/test/cache/list_test.dart
@@ -6,8 +6,8 @@
 
 import 'package:path/path.dart' as path;
 
-import 'descriptor.dart' as d;
-import 'test_pub.dart';
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
 
 main() {
   initConfig();
diff --git a/sdk/lib/_internal/pub/test/descriptor.dart b/sdk/lib/_internal/pub/test/descriptor.dart
index d873997..25991ba 100644
--- a/sdk/lib/_internal/pub/test/descriptor.dart
+++ b/sdk/lib/_internal/pub/test/descriptor.dart
@@ -137,6 +137,12 @@
     }
   });
 
+  return hostedCache(contents);
+}
+
+/// Describes the main cache directory containing cached hosted packages
+/// downloaded from the mock package server.
+Descriptor hostedCache(Iterable<Descriptor> contents) {
   return dir(cachePath, [
     dir('hosted', [
       async(port.then((p) => dir('127.0.0.1%58$p', contents)))
diff --git a/sdk/lib/_internal/pub/test/pub_test.dart b/sdk/lib/_internal/pub/test/pub_test.dart
index 8c9e652..cc41e47 100644
--- a/sdk/lib/_internal/pub/test/pub_test.dart
+++ b/sdk/lib/_internal/pub/test/pub_test.dart
@@ -29,6 +29,7 @@
 
     Available commands:
       build      Apply transformers to build a package.
+      cache      Work with the system cache.
       get        Get the current package's dependencies.
       help       Display help information for Pub.
       publish    Publish the current package to pub.dartlang.org.
@@ -91,7 +92,7 @@
           -h, --help    Print usage information for this command.
           
           Available subcommands:
-            list   List packages in the system cache.
+            add   Install a package.
      ''');
   });
 
@@ -107,6 +108,7 @@
    
         Available commands:
           build      Apply transformers to build a package.
+          cache      Work with the system cache.
           get        Get the current package's dependencies.
           help       Display help information for Pub.
           publish    Publish the current package to pub.dartlang.org.
@@ -125,9 +127,9 @@
    
         Usage: pub cache <subcommand>
         -h, --help    Print usage information for this command.
-        
+
         Available subcommands:
-          list   List packages in the system cache.
+          add   Install a package.
         ''',
         exitCode: exit_codes.USAGE);
   });
@@ -172,7 +174,7 @@
         -h, --help    Print usage information for this command.
 
         Available subcommands:
-          list   List packages in the system cache.
+          add   Install a package.
         ''',
         exitCode: exit_codes.USAGE);
   });
@@ -221,9 +223,10 @@
       schedulePub(args: ['help', 'quylthulg'],
           error: '''
             Could not find a command named "quylthulg".
-       
+
             Available commands:
               build      Apply transformers to build a package.
+              cache      Work with the system cache.
               get        Get the current package's dependencies.
               help       Display help information for Pub.
               publish    Publish the current package to pub.dartlang.org.
@@ -239,12 +242,12 @@
       schedulePub(args: ['help', 'cache', 'quylthulg'],
           error: '''
             Could not find a subcommand named "quylthulg" for "pub cache".
-       
+
             Usage: pub cache <subcommand>
             -h, --help    Print usage information for this command.
-
+    
             Available subcommands:
-              list   List packages in the system cache.
+              add   Install a package.
             ''',
             exitCode: exit_codes.USAGE);
     });
@@ -253,7 +256,7 @@
       schedulePub(args: ['help', 'version', 'badsubcommand'],
           error: '''
             Command "pub version" does not expect a subcommand.
-            
+
             Usage: pub version
             -h, --help    Print usage information for this command.
             ''',
diff --git a/sdk/lib/_internal/pub/test/serve/does_not_watch_compiled_js_files_test.dart b/sdk/lib/_internal/pub/test/serve/does_not_watch_compiled_js_files_test.dart
index 7459869..4d620f6 100644
--- a/sdk/lib/_internal/pub/test/serve/does_not_watch_compiled_js_files_test.dart
+++ b/sdk/lib/_internal/pub/test/serve/does_not_watch_compiled_js_files_test.dart
@@ -26,12 +26,16 @@
       d.dir("web", [
         d.file('file.dart', 'void main() => print("hello");'),
         d.file("other.dart.js", "should be ignored"),
+        d.file("other.dart.js.map", "should be ignored"),
+        d.file("other.dart.precompiled.js", "should be ignored")
       ])
     ]).create();
 
     waitForBuildSuccess();
     requestShouldSucceed("file.dart", 'void main() => print("hello");');
     requestShould404("other.dart.js");
+    requestShould404("other.dart.js.map");
+    requestShould404("other.dart.precompiled.js");
     endPubServe();
   });
 }
diff --git a/sdk/lib/_internal/pub/test/serve/uses_appropriate_mime_types_test.dart b/sdk/lib/_internal/pub/test/serve/uses_appropriate_mime_types_test.dart
new file mode 100644
index 0000000..c5ebfdb
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/uses_appropriate_mime_types_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2014, 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 'package:scheduled_test/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("uses appropriate mime types", () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir("web", [
+        d.file("index.html", "<body>"),
+        d.file("file.dart", "main() => print('hello');"),
+        d.file("file.js", "console.log('hello');"),
+        d.file("file.css", "body {color: blue}")
+      ])
+    ]).create();
+
+    pubServe();
+    requestShouldSucceed("index.html", anything,
+        headers: containsPair('content-type', 'text/html'));
+    requestShouldSucceed("file.dart", anything,
+        headers: containsPair('content-type', 'application/dart'));
+    requestShouldSucceed("file.js", anything,
+        headers: containsPair('content-type', 'application/javascript'));
+    requestShouldSucceed("file.css", anything,
+        headers: containsPair('content-type', 'text/css'));
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/utils.dart b/sdk/lib/_internal/pub/test/serve/utils.dart
index 0394803..6ae1e1f 100644
--- a/sdk/lib/_internal/pub/test/serve/utils.dart
+++ b/sdk/lib/_internal/pub/test/serve/utils.dart
@@ -169,10 +169,12 @@
 /// verifies that it responds with a body that matches [expectation].
 ///
 /// [expectation] may either be a [Matcher] or a string to match an exact body.
-void requestShouldSucceed(String urlPath, expectation) {
+/// [headers] may be either a [Matcher] or a map to match an exact headers map.
+void requestShouldSucceed(String urlPath, expectation, {headers}) {
   schedule(() {
     return http.get("http://127.0.0.1:$_port/$urlPath").then((response) {
-      expect(response.body, expectation);
+      if (expectation != null) expect(response.body, expectation);
+      if (headers != null) expect(response.headers, headers);
     });
   }, "request $urlPath");
 }
diff --git a/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_compile_until_its_output_is_requested_test.dart b/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_compile_until_its_output_is_requested_test.dart
new file mode 100644
index 0000000..e71c925
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_compile_until_its_output_is_requested_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2014, 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 'package:scheduled_test/scheduled_test.dart';
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+import '../../serve/utils.dart';
+
+main() {
+  initConfig();
+  integration("does not compile until its output is requested", () {
+    d.dir(appPath, [
+      d.pubspec({
+        "name": "myapp",
+        "version": "0.0.1",
+      }),
+      d.dir("web", [
+        d.file("syntax-error.dart", "syntax error")
+      ])
+    ]).create();
+
+    createLockFile('myapp', pkg: ['barback']);
+
+    var server = pubServe();
+    expect(server.nextLine(),
+        completion(equals("Build completed successfully")));
+
+    // Once we request the output, it should start compiling and fail.
+    requestShould404("syntax-error.dart.js");
+    expect(server.nextLine(),
+        completion(equals("Build completed with 1 errors.")));
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_support_invalid_command_line_options_type_test.dart b/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_support_invalid_command_line_options_type_test.dart
index c13a5a2..66ee703 100644
--- a/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_support_invalid_command_line_options_type_test.dart
+++ b/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_support_invalid_command_line_options_type_test.dart
@@ -32,12 +32,13 @@
     createLockFile('myapp', pkg: ['barback']);
 
     var server = pubServe();
+    // Make a request first to trigger compilation.
+    requestShould404("main.dart.js");
     expect(server.nextErrLine(), completion(equals('Build error:')));
     expect(server.nextErrLine(), completion(equals(
         'Transform Dart2JS on myapp|web/main.dart threw error: '
             'FormatException: Invalid value for \$dart2js.commandLineOptions: '
             '"foo" (expected list of strings).')));
-    requestShould404("main.dart.js");
     endPubServe();
   });
 }
diff --git a/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_support_invalid_environment_type_test.dart b/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_support_invalid_environment_type_test.dart
index 4c882df..a9bb942 100644
--- a/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_support_invalid_environment_type_test.dart
+++ b/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_support_invalid_environment_type_test.dart
@@ -32,12 +32,13 @@
     createLockFile('myapp', pkg: ['barback']);
 
     var server = pubServe();
+    // Make a request first to trigger compilation.
+    requestShould404("main.dart.js");
     expect(server.nextErrLine(), completion(equals('Build error:')));
     expect(server.nextErrLine(), completion(equals(
         'Transform Dart2JS on myapp|web/main.dart threw error: '
             'FormatException: Invalid value for \$dart2js.environment: "foo" '
             '(expected map from strings to strings).')));
-    requestShould404("main.dart.js");
     endPubServe();
   });
 }
diff --git a/sdk/lib/collection/list.dart b/sdk/lib/collection/list.dart
index d4dac6a..7669a70a5 100644
--- a/sdk/lib/collection/list.dart
+++ b/sdk/lib/collection/list.dart
@@ -81,7 +81,7 @@
 
   bool contains(Object element) {
     int length = this.length;
-    for (int i = 0; i < length; i++) {
+    for (int i = 0; i < this.length; i++) {
       if (this[i] == element) return true;
       if (length != this.length) {
         throw new ConcurrentModificationError(this);
@@ -160,32 +160,9 @@
   }
 
   String join([String separator = ""]) {
-    int length = this.length;
-    if (!separator.isEmpty) {
-      if (length == 0) return "";
-      String first = "${this[0]}";
-      if (length != this.length) {
-        throw new ConcurrentModificationError(this);
-      }
-      StringBuffer buffer = new StringBuffer(first);
-      for (int i = 1; i < length; i++) {
-        buffer.write(separator);
-        buffer.write(this[i]);
-        if (length != this.length) {
-          throw new ConcurrentModificationError(this);
-        }
-      }
-      return buffer.toString();
-    } else {
-      StringBuffer buffer = new StringBuffer();
-      for (int i = 0; i < length; i++) {
-        buffer.write(this[i]);
-        if (length != this.length) {
-          throw new ConcurrentModificationError(this);
-        }
-      }
-      return buffer.toString();
-    }
+    if (length == 0) return "";
+    StringBuffer buffer = new StringBuffer()..writeAll(this, separator);
+    return buffer.toString();
   }
 
   Iterable<E> where(bool test(E element)) => new WhereIterable<E>(this, test);
diff --git a/sdk/lib/convert/json.dart b/sdk/lib/convert/json.dart
index 16001e6..aa06e6f 100644
--- a/sdk/lib/convert/json.dart
+++ b/sdk/lib/convert/json.dart
@@ -58,35 +58,64 @@
  */
 const JsonCodec JSON = const JsonCodec();
 
+typedef _Reviver(var key, var value);
+typedef _ToEncodable(var o);
+
+
 /**
  * A [JsonCodec] encodes JSON objects to strings and decodes strings to
  * JSON objects.
  */
 class JsonCodec extends Codec<Object, String> {
-  const JsonCodec();
+  final _Reviver _reviver;
+  final _ToEncodable _toEncodable;
+
+  /**
+   * Creates a `JsonCodec` with the given reviver and encoding function.
+   *
+   * The [reviver] function is called during decoding. It is invoked
+   * once for each object or list property that has been parsed.
+   * The `key` argument is either the
+   * integer list index for a list property, the string map key for object
+   * properties, or `null` for the final result.
+   *
+   * If [reviver] is omitted, it defaults to returning the value argument.
+   *
+   * The [toEncodable] function is used during encoding. It is invoked for
+   * values that are not directly encodable to a JSON
+   * string (a value that is not a number, boolean, string, null, list or a map
+   * with string keys). The function must return an object that is directly
+   * encodable.
+   *
+   * If [toEncodable] is omitted, it defaults to a function that returns the
+   * result of calling `.toJson()` on the unencodable object.
+   */
+  const JsonCodec({reviver(var key, var value), toEncodable(var object)})
+      : _reviver = reviver,
+        _toEncodable = toEncodable;
 
   /**
    * Creates a `JsonCodec` with the given reviver.
    *
    * The [reviver] function is called once for each object or list property
    * that has been parsed during decoding. The `key` argument is either the
-   * integer list index for a list property, the map string for object
+   * integer list index for a list property, the string map key for object
    * properties, or `null` for the final result.
    */
-  factory JsonCodec.withReviver(reviver(var key, var value)) =
-      _ReviverJsonCodec;
+  JsonCodec.withReviver(reviver(var key, var value)) : this(reviver: reviver);
 
   /**
    * Parses the string and returns the resulting Json object.
    *
    * The optional [reviver] function is called once for each object or list
    * property that has been parsed during decoding. The `key` argument is either
-   * the integer list index for a list property, the map string for object
+   * the integer list index for a list property, the string map key for object
    * properties, or `null` for the final result.
    *
    * The default [reviver] (when not provided) is the identity function.
    */
   dynamic decode(String source, {reviver(var key, var value)}) {
+    if (reviver == null) reviver = _reviver;
     if (reviver == null) return decoder.convert(source);
     return new JsonDecoder(reviver).convert(source);
   }
@@ -99,30 +128,24 @@
    * with string keys), the [toEncodable] function is used to convert it to an
    * object that must be directly encodable.
    *
-   * If [toEncodable] is omitted, it defaults to calling `.toJson()` on the
-   * unencodable object.
+   * If [toEncodable] is omitted, it defaults to a function that returns the
+   * result of calling `.toJson()` on the unencodable object.
    */
   String encode(Object value, {toEncodable(var object)}) {
+    if (toEncodable == null) toEncodable = _toEncodable;
     if (toEncodable == null) return encoder.convert(value);
     return new JsonEncoder(toEncodable).convert(value);
   }
 
-  JsonEncoder get encoder => const JsonEncoder();
-  JsonDecoder get decoder => const JsonDecoder(null);
-}
-
-typedef _Reviver(var key, var value);
-
-class _ReviverJsonCodec extends JsonCodec {
-  final _Reviver _reviver;
-  _ReviverJsonCodec(this._reviver);
-
-  dynamic decode(String source, {reviver(var key, var value)}) {
-    if (reviver == null) reviver = _reviver;
-    return new JsonDecoder(reviver).convert(source);
+  JsonEncoder get encoder {
+    if (_toEncodable == null) return const JsonEncoder();
+    return new JsonEncoder(_toEncodable);
   }
 
-  JsonDecoder get decoder => new JsonDecoder(_reviver);
+  JsonDecoder get decoder {
+    if (_reviver == null) return const JsonDecoder();
+    return new JsonDecoder(_reviver);
+  }
 }
 
 /**
@@ -239,7 +262,7 @@
    *
    * The [reviver] may be `null`.
    */
-  const JsonDecoder(reviver(var key, var value)) : this._reviver = reviver;
+  const JsonDecoder([reviver(var key, var value)]) : this._reviver = reviver;
 
   /**
    * Converts the given JSON-string [input] to its corresponding object.
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 43fc262..06fd6fb 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -153,6 +153,28 @@
 
 
 @DocsEditable()
+@DomName('AesCtrParams')
+@Experimental() // untriaged
+class AesCtrParams extends Algorithm native "AesCtrParams" {
+  // To suppress missing implicit constructor warnings.
+  factory AesCtrParams._() { throw new UnsupportedError("Not supported"); }
+
+  @DomName('AesCtrParams.counter')
+  @DocsEditable()
+  @Experimental() // untriaged
+  final Uint8List counter;
+
+  @DomName('AesCtrParams.length')
+  @DocsEditable()
+  @Experimental() // untriaged
+  final int length;
+}
+// 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('AesKeyGenParams')
 @Experimental() // untriaged
 class AesKeyGenParams extends Algorithm native "AesKeyGenParams" {
@@ -1422,7 +1444,7 @@
   @DocsEditable()
   @Creates('String|CanvasGradient|CanvasPattern')
   @Returns('String|CanvasGradient|CanvasPattern')
-  dynamic fillStyle;
+  Object fillStyle;
 
   @DomName('CanvasRenderingContext2D.font')
   @DocsEditable()
@@ -1487,7 +1509,7 @@
   @DocsEditable()
   @Creates('String|CanvasGradient|CanvasPattern')
   @Returns('String|CanvasGradient|CanvasPattern')
-  dynamic strokeStyle;
+  Object strokeStyle;
 
   @DomName('CanvasRenderingContext2D.textAlign')
   @DocsEditable()
@@ -2590,34 +2612,6 @@
 
 
 @DocsEditable()
-@DomName('CSSHostRule')
-@SupportedBrowser(SupportedBrowser.CHROME, '26')
-@Experimental()
-// https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#css-host-rule-interface
-class CssHostRule extends CssRule native "CSSHostRule" {
-  // To suppress missing implicit constructor warnings.
-  factory CssHostRule._() { throw new UnsupportedError("Not supported"); }
-
-  @DomName('CSSHostRule.cssRules')
-  @DocsEditable()
-  @Returns('_CssRuleList')
-  @Creates('_CssRuleList')
-  final List<CssRule> cssRules;
-
-  @DomName('CSSHostRule.deleteRule')
-  @DocsEditable()
-  void deleteRule(int index) native;
-
-  @DomName('CSSHostRule.insertRule')
-  @DocsEditable()
-  int insertRule(String rule, int index) 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('CSSImportRule')
 class CssImportRule extends CssRule native "CSSImportRule" {
   // To suppress missing implicit constructor warnings.
@@ -2790,12 +2784,6 @@
   @DocsEditable()
   static const int FONT_FACE_RULE = 5;
 
-  @DomName('CSSRule.HOST_RULE')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#api-css-rule-host-rule
-  @Experimental()
-  static const int HOST_RULE = 1001;
-
   @DomName('CSSRule.IMPORT_RULE')
   @DocsEditable()
   static const int IMPORT_RULE = 3;
@@ -7196,6 +7184,11 @@
   @DocsEditable()
   final HeadElement _head;
 
+  @DomName('Document.hidden')
+  @DocsEditable()
+  @Experimental() // untriaged
+  final bool hidden;
+
   @DomName('Document.implementation')
   @DocsEditable()
   final DomImplementation implementation;
@@ -7242,6 +7235,11 @@
   @DocsEditable()
   String _title;
 
+  @DomName('Document.visibilityState')
+  @DocsEditable()
+  @Experimental() // untriaged
+  final String visibilityState;
+
   @JSName('webkitFullscreenElement')
   @DomName('Document.webkitFullscreenElement')
   @DocsEditable()
@@ -7289,7 +7287,7 @@
 
   @DomName('Document.adoptNode')
   @DocsEditable()
-  Node adoptNode(Node source) native;
+  Node adoptNode(Node node) native;
 
   @JSName('caretRangeFromPoint')
   @DomName('Document.caretRangeFromPoint')
@@ -7316,12 +7314,6 @@
   @DocsEditable()
   Event _createEvent(String eventType) native;
 
-  @JSName('createNodeIterator')
-  @DomName('Document.createNodeIterator')
-  @DocsEditable()
-  @Unstable()
-  NodeIterator _createNodeIterator(Node root, [int whatToShow, NodeFilter filter, bool expandEntityReferences]) native;
-
   @DomName('Document.createRange')
   @DocsEditable()
   Range createRange() native;
@@ -7346,11 +7338,6 @@
   @Experimental()
   Touch _createTouch_1(Window window, target, identifier, pageX, pageY, screenX, screenY, webkitRadiusX, webkitRadiusY, webkitRotationAngle, webkitForce) native;
 
-  @JSName('createTreeWalker')
-  @DomName('Document.createTreeWalker')
-  @DocsEditable()
-  TreeWalker _createTreeWalker(Node root, [int whatToShow, NodeFilter filter, bool expandEntityReferences]) native;
-
   @JSName('elementFromPoint')
   @DomName('Document.elementFromPoint')
   @DocsEditable()
@@ -7375,7 +7362,7 @@
   @DocsEditable()
   @Returns('NodeList')
   @Creates('NodeList')
-  List<Node> getElementsByClassName(String tagname) native;
+  List<Node> getElementsByClassName(String classNames) native;
 
   @DomName('Document.getElementsByName')
   @DocsEditable()
@@ -7387,11 +7374,11 @@
   @DocsEditable()
   @Returns('NodeList')
   @Creates('NodeList')
-  List<Node> getElementsByTagName(String tagname) native;
+  List<Node> getElementsByTagName(String localName) native;
 
   @DomName('Document.importNode')
   @DocsEditable()
-  Node importNode(Node importedNode, [bool deep]) native;
+  Node importNode(Node node, [bool deep]) native;
 
   @DomName('Document.queryCommandEnabled')
   @DocsEditable()
@@ -7792,7 +7779,7 @@
     return new _FrozenElementList._wrap(_querySelectorAll(selectors));
   }
 
-  /** 
+  /**
    * Alias for [querySelector]. Note this function is deprecated because its
    * semantics will be changing in the future.
    */
@@ -7801,7 +7788,7 @@
   @DomName('Document.querySelector')
   Element query(String relativeSelectors) => querySelector(relativeSelectors);
 
-  /** 
+  /**
    * Alias for [querySelectorAll]. Note this function is deprecated because its
    * semantics will be changing in the future.
    */
@@ -7820,6 +7807,18 @@
   Element createElement(String tagName, [String typeExtension]) {
     return _createElement(tagName, typeExtension);
   }
+
+  @DomName('Document.createNodeIterator')
+  NodeIterator _createNodeIterator(Node root,
+      [int whatToShow, NodeFilter filter])
+      => JS('NodeIterator', '#.createNodeIterator(#, #, #, false)',
+          this, root, whatToShow, filter);
+
+  @DomName('Document.createTreeWalker')
+  TreeWalker _createTreeWalker(Node root,
+      [int whatToShow, NodeFilter filter])
+      => JS('TreeWalker', '#.createTreeWalker(#, #, #, false)',
+          this, root, whatToShow, filter);
 }
 // 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
@@ -8221,11 +8220,11 @@
   // To suppress missing implicit constructor warnings.
   factory DomStringMap._() { throw new UnsupportedError("Not supported"); }
 
-  bool __delete__(String name);
+  bool __delete__(index_OR_name);
 
-  String __getter__(String name);
+  String __getter__(index_OR_name);
 
-  void __setter__(String name, String value);
+  void __setter__(index_OR_name, String value);
 }
 // 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
@@ -11112,6 +11111,11 @@
   // http://dev.w3.org/csswg/css-regions/#dom-region-regionoverset
   final String regionOverset;
 
+  @DomName('Element.animate')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void animate(List<Map> keyframes, [num duration]) native;
+
   @DomName('Element.blur')
   @DocsEditable()
   void blur() native;
@@ -11198,7 +11202,7 @@
   @DocsEditable()
   @Returns('NodeList')
   @Creates('NodeList')
-  List<Node> getElementsByClassName(String name) native;
+  List<Node> getElementsByClassName(String classNames) native;
 
   @JSName('getElementsByTagName')
   @DomName('Element.getElementsByTagName')
@@ -12533,6 +12537,11 @@
   // To suppress missing implicit constructor warnings.
   factory File._() { throw new UnsupportedError("Not supported"); }
 
+  @DomName('File.lastModified')
+  @DocsEditable()
+  @Experimental() // untriaged
+  final int lastModified;
+
   @DomName('File.lastModifiedDate')
   @DocsEditable()
   DateTime get lastModifiedDate => convertNativeToDart_DateTime(this._get_lastModifiedDate);
@@ -13178,6 +13187,11 @@
   @DocsEditable()
   @Experimental() // untriaged
   String weight;
+
+  @DomName('FontFace.load')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void load() 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
@@ -13904,6 +13918,11 @@
    * This can only be called by subclasses from their created constructor.
    */
   HRElement.created() : super.created();
+
+  @DomName('HTMLHRElement.color')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String color;
 }
 // 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
@@ -14593,6 +14612,17 @@
    *
    * This is similar to [request] but specialized for HTTP GET requests which
    * return text content.
+   * 
+   * To add query parameters, append them to the [url] following a `?`,
+   * joining each key to its value with `=` and separating key-value pairs with
+   * `&`.
+   * 
+   *     var name = Uri.encodeQueryComponent('John');
+   *     var id = Uri.encodeQueryComponent('42');
+   *     HttpRequest.getString('users.json?name=$name&id=$id')
+   *       .then((HttpRequest resp) {
+   *         // Do something with the response.
+   *     });
    *
    * See also:
    *
@@ -14611,6 +14641,20 @@
    * to sending a FormData object with broader browser support but limited to
    * String values.
    *
+   * If [data] is supplied, the key/value pairs are URI encoded with
+   * [Uri.encodeQueryComponent] and converted into an HTTP query string.
+   * 
+   * Unless otherwise specified, this method appends the following header:
+   *
+   *     Content-Type: application/x-www-form-urlencoded; charset=UTF-8
+   * 
+   * Here's an example of using this method:
+   * 
+   *     var data = { 'firstName' : 'John', 'lastName' : 'Doe' };
+   *     HttpRequest.postFormData('/send', data).then((HttpRequest resp) {
+   *       // Do something with the response.
+   *     });
+   *
    * See also:
    *
    * * [request]
@@ -14662,6 +14706,25 @@
    * * The `Access-Control-Allow-Credentials` header of `url` must be set to true.
    * * If `Access-Control-Expose-Headers` has not been set to true, only a subset of all the response headers will be returned when calling [getAllRequestHeaders].
    *
+   * 
+   * The following is equivalent to the [getString] sample above:
+   *
+   *     var name = Uri.encodeQueryComponent('John');
+   *     var id = Uri.encodeQueryComponent('42');
+   *     HttpRequest.request('users.json?name=$name&id=$id')
+   *       .then((HttpRequest resp) {
+   *         // Do something with the response.
+   *     });
+   *
+   * Here's an example of submitting an entire form with [FormData].
+   *
+   *     var myForm = querySelector('form#myForm');
+   *     var data = new FormData(myForm);
+   *     HttpRequest.request('/submit', method: 'POST', sendData: data)
+   *       .then((HttpRequest resp) {
+   *         // Do something with the response.
+   *     });
+   *
    * Note that requests for file:// URIs are only supported by Chrome extensions
    * with appropriate permissions in their manifest. Requests to file:// URIs
    * will also never fail- the Future will always complete successfully, even
@@ -16413,6 +16476,16 @@
   @DocsEditable()
   final Composition composition;
 
+  @DomName('InputMethodContext.compositionEndOffset')
+  @DocsEditable()
+  @Experimental() // untriaged
+  final int compositionEndOffset;
+
+  @DomName('InputMethodContext.compositionStartOffset')
+  @DocsEditable()
+  @Experimental() // untriaged
+  final int compositionStartOffset;
+
   @DomName('InputMethodContext.locale')
   @DocsEditable()
   final String locale;
@@ -16425,10 +16498,6 @@
   @DomName('InputMethodContext.confirmComposition')
   @DocsEditable()
   void confirmComposition() native;
-
-  @DomName('InputMethodContext.setCaretRectangle')
-  @DocsEditable()
-  void setCaretRectangle(Node anchor, int x, int y, int w, int h) 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
@@ -17353,6 +17422,11 @@
   @DocsEditable()
   bool controls;
 
+  @DomName('HTMLMediaElement.crossOrigin')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String crossOrigin;
+
   @DomName('HTMLMediaElement.currentSrc')
   @DocsEditable()
   final String currentSrc;
@@ -17979,28 +18053,6 @@
   @DomName('MediaQueryList.media')
   @DocsEditable()
   final String media;
-
-  @DomName('MediaQueryList.addListener')
-  @DocsEditable()
-  void addListener(MediaQueryListListener listener) native;
-
-  @DomName('MediaQueryList.removeListener')
-  @DocsEditable()
-  void removeListener(MediaQueryListListener listener) 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('MediaQueryListListener')
-@Unstable()
-abstract class MediaQueryListListener extends Interceptor {
-  // To suppress missing implicit constructor warnings.
-  factory MediaQueryListListener._() { throw new UnsupportedError("Not supported"); }
-
-  void queryChanged(MediaQueryList list);
 }
 // 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
@@ -20336,7 +20388,7 @@
 @Unstable()
 class NodeIterator extends Interceptor native "NodeIterator" {
   factory NodeIterator(Node root, int whatToShow) {
-    return document._createNodeIterator(root, whatToShow, null, false);
+    return document._createNodeIterator(root, whatToShow, null);
   }
   // To suppress missing implicit constructor warnings.
   factory NodeIterator._() { throw new UnsupportedError("Not supported"); }
@@ -20480,17 +20532,6 @@
   static const EventStreamProvider<Event> closeEvent = const EventStreamProvider<Event>('close');
 
   /**
-   * Static factory designed to expose `display` events to event
-   * handlers that are not necessarily instances of [Notification].
-   *
-   * See [EventStreamProvider] for usage information.
-   */
-  @DomName('Notification.displayEvent')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  static const EventStreamProvider<Event> displayEvent = const EventStreamProvider<Event>('display');
-
-  /**
    * Static factory designed to expose `error` events to event
    * handlers that are not necessarily instances of [Notification].
    *
@@ -20521,29 +20562,39 @@
   static Notification _create_1(title, options) => JS('Notification', 'new Notification(#,#)', title, options);
   static Notification _create_2(title) => JS('Notification', 'new Notification(#)', title);
 
+  @DomName('Notification.body')
+  @DocsEditable()
+  @Experimental() // untriaged
+  final String body;
+
   @DomName('Notification.dir')
   @DocsEditable()
   @Experimental() // nonstandard
-  String dir;
+  final String dir;
+
+  @DomName('Notification.icon')
+  @DocsEditable()
+  @Experimental() // untriaged
+  final String icon;
+
+  @DomName('Notification.lang')
+  @DocsEditable()
+  @Experimental() // untriaged
+  final String lang;
 
   @DomName('Notification.permission')
   @DocsEditable()
   final String permission;
 
-  @DomName('Notification.replaceId')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  String replaceId;
-
   @DomName('Notification.tag')
   @DocsEditable()
   @Experimental() // nonstandard
-  String tag;
+  final String tag;
 
-  @DomName('Notification.cancel')
+  @DomName('Notification.title')
   @DocsEditable()
-  @Experimental() // nonstandard
-  void cancel() native;
+  @Experimental() // untriaged
+  final String title;
 
   @DomName('Notification.close')
   @DocsEditable()
@@ -20564,11 +20615,6 @@
     return completer.future;
   }
 
-  @DomName('Notification.show')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  void show() native;
-
   /// Stream of `click` events handled by this [Notification].
   @DomName('Notification.onclick')
   @DocsEditable()
@@ -20579,12 +20625,6 @@
   @DocsEditable()
   Stream<Event> get onClose => closeEvent.forTarget(this);
 
-  /// Stream of `display` events handled by this [Notification].
-  @DomName('Notification.ondisplay')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  Stream<Event> get onDisplay => displayEvent.forTarget(this);
-
   /// Stream of `error` events handled by this [Notification].
   @DomName('Notification.onerror')
   @DocsEditable()
@@ -23366,6 +23406,18 @@
 
 
 @DocsEditable()
+@DomName('ServiceWorkerGlobalScope')
+@Experimental() // untriaged
+class ServiceWorkerGlobalScope extends WorkerGlobalScope native "ServiceWorkerGlobalScope" {
+  // To suppress missing implicit constructor warnings.
+  factory ServiceWorkerGlobalScope._() { 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()
@@ -25512,6 +25564,11 @@
   @DocsEditable()
   final TextTrackCueList cues;
 
+  @DomName('TextTrack.id')
+  @DocsEditable()
+  @Experimental() // untriaged
+  final String id;
+
   @DomName('TextTrack.kind')
   @DocsEditable()
   final String kind;
@@ -25589,18 +25646,6 @@
   @DocsEditable()
   static const EventStreamProvider<Event> exitEvent = const EventStreamProvider<Event>('exit');
 
-  @DomName('TextTrackCue.TextTrackCue')
-  @DocsEditable()
-  factory TextTrackCue(num startTime, num endTime, String text) {
-    return TextTrackCue._create_1(startTime, endTime, text);
-  }
-  static TextTrackCue _create_1(startTime, endTime, text) => JS('TextTrackCue', 'new TextTrackCue(#,#,#)', startTime, endTime, text);
-
-  @DomName('TextTrackCue.align')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  String align;
-
   @DomName('TextTrackCue.endTime')
   @DocsEditable()
   num endTime;
@@ -25609,59 +25654,18 @@
   @DocsEditable()
   String id;
 
-  @DomName('TextTrackCue.line')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  int line;
-
   @DomName('TextTrackCue.pauseOnExit')
   @DocsEditable()
   bool pauseOnExit;
 
-  @DomName('TextTrackCue.position')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  int position;
-
-  @DomName('TextTrackCue.regionId')
-  @DocsEditable()
-  @Experimental() // untriaged
-  String regionId;
-
-  @DomName('TextTrackCue.size')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  int size;
-
-  @DomName('TextTrackCue.snapToLines')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  bool snapToLines;
-
   @DomName('TextTrackCue.startTime')
   @DocsEditable()
   num startTime;
 
-  @DomName('TextTrackCue.text')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  String text;
-
   @DomName('TextTrackCue.track')
   @DocsEditable()
   final TextTrack track;
 
-  @DomName('TextTrackCue.vertical')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  String vertical;
-
-  @JSName('getCueAsHTML')
-  @DomName('TextTrackCue.getCueAsHTML')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  DocumentFragment getCueAsHtml() native;
-
   /// Stream of `enter` events handled by this [TextTrackCue].
   @DomName('TextTrackCue.onenter')
   @DocsEditable()
@@ -25764,6 +25768,11 @@
   @DocsEditable()
   static const EventStreamProvider<TrackEvent> addTrackEvent = const EventStreamProvider<TrackEvent>('addtrack');
 
+  @DomName('TextTrackList.changeEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const EventStreamProvider<Event> changeEvent = const EventStreamProvider<Event>('change');
+
   @DomName('TextTrackList.length')
   @DocsEditable()
   int get length => JS("int", "#.length", this);
@@ -25812,6 +25821,11 @@
   TextTrack elementAt(int index) => this[index];
   // -- end List<TextTrack> mixins.
 
+  @DomName('TextTrackList.getTrackById')
+  @DocsEditable()
+  @Experimental() // untriaged
+  TextTrack getTrackById(String id) native;
+
   @DomName('TextTrackList.item')
   @DocsEditable()
   TextTrack item(int index) native;
@@ -25820,6 +25834,11 @@
   @DomName('TextTrackList.onaddtrack')
   @DocsEditable()
   Stream<TrackEvent> get onAddTrack => addTrackEvent.forTarget(this);
+
+  @DomName('TextTrackList.onchange')
+  @DocsEditable()
+  @Experimental() // untriaged
+  Stream<Event> get onChange => changeEvent.forTarget(this);
 }
 // 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
@@ -26244,7 +26263,7 @@
 @Unstable()
 class TreeWalker extends Interceptor native "TreeWalker" {
   factory TreeWalker(Node root, int whatToShow) {
-    return document._createTreeWalker(root, whatToShow, null, false);
+    return document._createTreeWalker(root, whatToShow, null);
   }
   // To suppress missing implicit constructor warnings.
   factory TreeWalker._() { throw new UnsupportedError("Not supported"); }
@@ -26770,6 +26789,71 @@
 
 
 @DocsEditable()
+@DomName('VTTCue')
+@Experimental() // untriaged
+class VttCue extends TextTrackCue native "VTTCue" {
+  // To suppress missing implicit constructor warnings.
+  factory VttCue._() { throw new UnsupportedError("Not supported"); }
+
+  @DomName('VTTCue.VTTCue')
+  @DocsEditable()
+  factory VttCue(num startTime, num endTime, String text) {
+    return VttCue._create_1(startTime, endTime, text);
+  }
+  static VttCue _create_1(startTime, endTime, text) => JS('VttCue', 'new VTTCue(#,#,#)', startTime, endTime, text);
+
+  @DomName('VTTCue.align')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String align;
+
+  @DomName('VTTCue.line')
+  @DocsEditable()
+  @Experimental() // untriaged
+  int line;
+
+  @DomName('VTTCue.position')
+  @DocsEditable()
+  @Experimental() // untriaged
+  int position;
+
+  @DomName('VTTCue.regionId')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String regionId;
+
+  @DomName('VTTCue.size')
+  @DocsEditable()
+  @Experimental() // untriaged
+  int size;
+
+  @DomName('VTTCue.snapToLines')
+  @DocsEditable()
+  @Experimental() // untriaged
+  bool snapToLines;
+
+  @DomName('VTTCue.text')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String text;
+
+  @DomName('VTTCue.vertical')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String vertical;
+
+  @JSName('getCueAsHTML')
+  @DomName('VTTCue.getCueAsHTML')
+  @DocsEditable()
+  @Experimental() // untriaged
+  DocumentFragment getCueAsHtml() 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('VTTRegion')
 @Experimental() // untriaged
 class VttRegion extends Interceptor native "VTTRegion" {
@@ -30501,25 +30585,6 @@
 
 
 @DocsEditable()
-@DomName('HTMLBaseFontElement')
-// http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#basefont
-@deprecated // deprecated
-abstract class _HTMLBaseFontElement extends HtmlElement native "HTMLBaseFontElement" {
-  // To suppress missing implicit constructor warnings.
-  factory _HTMLBaseFontElement._() { throw new UnsupportedError("Not supported"); }
-  /**
-   * Constructor instantiated by the DOM when a custom element has been created.
-   *
-   * This can only be called by subclasses from their created constructor.
-   */
-  _HTMLBaseFontElement.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.
-
-
-@DocsEditable()
 @DomName('HTMLDirectoryElement')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dir
 @deprecated // deprecated
@@ -31130,6 +31195,18 @@
 
 
 @DocsEditable()
+@DomName('WebKitNotification')
+@Experimental() // untriaged
+abstract class _WebKitNotification extends EventTarget native "WebKitNotification" {
+  // To suppress missing implicit constructor warnings.
+  factory _WebKitNotification._() { 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('WebKitSourceBuffer')
 @Experimental() // untriaged
 abstract class _WebKitSourceBuffer extends Interceptor native "WebKitSourceBuffer" {
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 52544f0..7a17fb6 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -148,6 +148,31 @@
 
 
 @DocsEditable()
+@DomName('AesCtrParams')
+@Experimental() // untriaged
+class AesCtrParams extends Algorithm {
+  // To suppress missing implicit constructor warnings.
+  factory AesCtrParams._() { throw new UnsupportedError("Not supported"); }
+
+  @DomName('AesCtrParams.counter')
+  @DocsEditable()
+  @Experimental() // untriaged
+  Uint8List get counter native "AesCtrParams_counter_Getter";
+
+  @DomName('AesCtrParams.length')
+  @DocsEditable()
+  @Experimental() // untriaged
+  int get length native "AesCtrParams_length_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.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable()
 @DomName('AesKeyGenParams')
 @Experimental() // untriaged
 class AesKeyGenParams extends Algorithm {
@@ -1670,11 +1695,11 @@
 
   @DomName('CanvasRenderingContext2D.fillStyle')
   @DocsEditable()
-  dynamic get fillStyle native "CanvasRenderingContext2D_fillStyle_Getter";
+  Object get fillStyle native "CanvasRenderingContext2D_fillStyle_Getter";
 
   @DomName('CanvasRenderingContext2D.fillStyle')
   @DocsEditable()
-  void set fillStyle(dynamic value) native "CanvasRenderingContext2D_fillStyle_Setter";
+  void set fillStyle(Object value) native "CanvasRenderingContext2D_fillStyle_Setter";
 
   @DomName('CanvasRenderingContext2D.font')
   @DocsEditable()
@@ -1804,11 +1829,11 @@
 
   @DomName('CanvasRenderingContext2D.strokeStyle')
   @DocsEditable()
-  dynamic get strokeStyle native "CanvasRenderingContext2D_strokeStyle_Getter";
+  Object get strokeStyle native "CanvasRenderingContext2D_strokeStyle_Getter";
 
   @DomName('CanvasRenderingContext2D.strokeStyle')
   @DocsEditable()
-  void set strokeStyle(dynamic value) native "CanvasRenderingContext2D_strokeStyle_Setter";
+  void set strokeStyle(Object value) native "CanvasRenderingContext2D_strokeStyle_Setter";
 
   @DomName('CanvasRenderingContext2D.textAlign')
   @DocsEditable()
@@ -3013,35 +3038,6 @@
 
 
 @DocsEditable()
-@DomName('CSSHostRule')
-@SupportedBrowser(SupportedBrowser.CHROME, '26')
-@Experimental()
-// https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#css-host-rule-interface
-class CssHostRule extends CssRule {
-  // To suppress missing implicit constructor warnings.
-  factory CssHostRule._() { throw new UnsupportedError("Not supported"); }
-
-  @DomName('CSSHostRule.cssRules')
-  @DocsEditable()
-  List<CssRule> get cssRules native "CSSHostRule_cssRules_Getter";
-
-  @DomName('CSSHostRule.deleteRule')
-  @DocsEditable()
-  void deleteRule(int index) native "CSSHostRule_deleteRule_Callback";
-
-  @DomName('CSSHostRule.insertRule')
-  @DocsEditable()
-  int insertRule(String rule, int index) native "CSSHostRule_insertRule_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('CSSImportRule')
 class CssImportRule extends CssRule {
   // To suppress missing implicit constructor warnings.
@@ -3239,12 +3235,6 @@
   @DocsEditable()
   static const int FONT_FACE_RULE = 5;
 
-  @DomName('CSSRule.HOST_RULE')
-  @DocsEditable()
-  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#api-css-rule-host-rule
-  @Experimental()
-  static const int HOST_RULE = 1001;
-
   @DomName('CSSRule.IMPORT_RULE')
   @DocsEditable()
   static const int IMPORT_RULE = 3;
@@ -7647,6 +7637,11 @@
   @DocsEditable()
   HeadElement get _head native "Document_head_Getter";
 
+  @DomName('Document.hidden')
+  @DocsEditable()
+  @Experimental() // untriaged
+  bool get hidden native "Document_hidden_Getter";
+
   @DomName('Document.implementation')
   @DocsEditable()
   DomImplementation get implementation native "Document_implementation_Getter";
@@ -7693,6 +7688,11 @@
   @DocsEditable()
   void set _title(String value) native "Document_title_Setter";
 
+  @DomName('Document.visibilityState')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String get visibilityState native "Document_visibilityState_Getter";
+
   @DomName('Document.webkitFullscreenElement')
   @DocsEditable()
   @SupportedBrowser(SupportedBrowser.CHROME)
@@ -7735,7 +7735,7 @@
 
   @DomName('Document.adoptNode')
   @DocsEditable()
-  Node adoptNode(Node source) native "Document_adoptNode_Callback";
+  Node adoptNode(Node node) native "Document_adoptNode_Callback";
 
   @DomName('Document.caretRangeFromPoint')
   @DocsEditable()
@@ -7759,26 +7759,21 @@
   @DocsEditable()
   Event _createEvent(String eventType) native "Document_createEvent_Callback";
 
-  NodeIterator _createNodeIterator(Node root, [int whatToShow, NodeFilter filter, bool expandEntityReferences]) {
-    if (expandEntityReferences != null) {
-      return _createNodeIterator_1(root, whatToShow, filter, expandEntityReferences);
-    }
+  NodeIterator _createNodeIterator(Node root, [int whatToShow, NodeFilter filter]) {
     if (filter != null) {
-      return _createNodeIterator_2(root, whatToShow, filter);
+      return _createNodeIterator_1(root, whatToShow, filter);
     }
     if (whatToShow != null) {
-      return _createNodeIterator_3(root, whatToShow);
+      return _createNodeIterator_2(root, whatToShow);
     }
-    return _createNodeIterator_4(root);
+    return _createNodeIterator_3(root);
   }
 
-  NodeIterator _createNodeIterator_1(root, whatToShow, filter, expandEntityReferences) native "Document__createNodeIterator_1_Callback";
+  NodeIterator _createNodeIterator_1(root, whatToShow, filter) native "Document__createNodeIterator_1_Callback";
 
-  NodeIterator _createNodeIterator_2(root, whatToShow, filter) native "Document__createNodeIterator_2_Callback";
+  NodeIterator _createNodeIterator_2(root, whatToShow) native "Document__createNodeIterator_2_Callback";
 
-  NodeIterator _createNodeIterator_3(root, whatToShow) native "Document__createNodeIterator_3_Callback";
-
-  NodeIterator _createNodeIterator_4(root) native "Document__createNodeIterator_4_Callback";
+  NodeIterator _createNodeIterator_3(root) native "Document__createNodeIterator_3_Callback";
 
   @DomName('Document.createRange')
   @DocsEditable()
@@ -7794,26 +7789,21 @@
   @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";
 
-  TreeWalker _createTreeWalker(Node root, [int whatToShow, NodeFilter filter, bool expandEntityReferences]) {
-    if (expandEntityReferences != null) {
-      return _createTreeWalker_1(root, whatToShow, filter, expandEntityReferences);
-    }
+  TreeWalker _createTreeWalker(Node root, [int whatToShow, NodeFilter filter]) {
     if (filter != null) {
-      return _createTreeWalker_2(root, whatToShow, filter);
+      return _createTreeWalker_1(root, whatToShow, filter);
     }
     if (whatToShow != null) {
-      return _createTreeWalker_3(root, whatToShow);
+      return _createTreeWalker_2(root, whatToShow);
     }
-    return _createTreeWalker_4(root);
+    return _createTreeWalker_3(root);
   }
 
-  TreeWalker _createTreeWalker_1(root, whatToShow, filter, expandEntityReferences) native "Document__createTreeWalker_1_Callback";
+  TreeWalker _createTreeWalker_1(root, whatToShow, filter) native "Document__createTreeWalker_1_Callback";
 
-  TreeWalker _createTreeWalker_2(root, whatToShow, filter) native "Document__createTreeWalker_2_Callback";
+  TreeWalker _createTreeWalker_2(root, whatToShow) native "Document__createTreeWalker_2_Callback";
 
-  TreeWalker _createTreeWalker_3(root, whatToShow) native "Document__createTreeWalker_3_Callback";
-
-  TreeWalker _createTreeWalker_4(root) native "Document__createTreeWalker_4_Callback";
+  TreeWalker _createTreeWalker_3(root) native "Document__createTreeWalker_3_Callback";
 
   @DomName('Document.elementFromPoint')
   @DocsEditable()
@@ -7835,7 +7825,7 @@
 
   @DomName('Document.getElementsByClassName')
   @DocsEditable()
-  List<Node> getElementsByClassName(String tagname) native "Document_getElementsByClassName_Callback";
+  List<Node> getElementsByClassName(String classNames) native "Document_getElementsByClassName_Callback";
 
   @DomName('Document.getElementsByName')
   @DocsEditable()
@@ -7843,18 +7833,18 @@
 
   @DomName('Document.getElementsByTagName')
   @DocsEditable()
-  List<Node> getElementsByTagName(String tagname) native "Document_getElementsByTagName_Callback";
+  List<Node> getElementsByTagName(String localName) native "Document_getElementsByTagName_Callback";
 
-  Node importNode(Node importedNode, [bool deep]) {
+  Node importNode(Node node, [bool deep]) {
     if (deep != null) {
-      return _importNode_1(importedNode, deep);
+      return _importNode_1(node, deep);
     }
-    return _importNode_2(importedNode);
+    return _importNode_2(node);
   }
 
-  Node _importNode_1(importedNode, deep) native "Document__importNode_1_Callback";
+  Node _importNode_1(node, deep) native "Document__importNode_1_Callback";
 
-  Node _importNode_2(importedNode) native "Document__importNode_2_Callback";
+  Node _importNode_2(node) native "Document__importNode_2_Callback";
 
   @DomName('Document.queryCommandEnabled')
   @DocsEditable()
@@ -8243,7 +8233,7 @@
     return new _FrozenElementList._wrap(_querySelectorAll(selectors));
   }
 
-  /** 
+  /**
    * Alias for [querySelector]. Note this function is deprecated because its
    * semantics will be changing in the future.
    */
@@ -8252,7 +8242,7 @@
   @DomName('Document.querySelector')
   Element query(String relativeSelectors) => querySelector(relativeSelectors);
 
-  /** 
+  /**
    * Alias for [querySelectorAll]. Note this function is deprecated because its
    * semantics will be changing in the future.
    */
@@ -8276,6 +8266,7 @@
       return _Utils.createElement(this, tagName);
     }
   }
+
 }
 // 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
@@ -8683,17 +8674,49 @@
   // To suppress missing implicit constructor warnings.
   factory DomStringMap._() { throw new UnsupportedError("Not supported"); }
 
-  @DomName('DOMStringMap.__delete__')
-  @DocsEditable()
-  bool __delete__(String name) native "DOMStringMap___delete___Callback";
+  bool __delete__(index_OR_name) {
+    if ((index_OR_name is int || index_OR_name == null)) {
+      return ___delete___1(index_OR_name);
+    }
+    if ((index_OR_name is String || index_OR_name == null)) {
+      return ___delete___2(index_OR_name);
+    }
+    throw new ArgumentError("Incorrect number or type of arguments");
+  }
 
-  @DomName('DOMStringMap.__getter__')
-  @DocsEditable()
-  String __getter__(String name) native "DOMStringMap___getter___Callback";
+  bool ___delete___1(index_OR_name) native "DOMStringMap____delete___1_Callback";
 
-  @DomName('DOMStringMap.__setter__')
-  @DocsEditable()
-  void __setter__(String name, String value) native "DOMStringMap___setter___Callback";
+  bool ___delete___2(index_OR_name) native "DOMStringMap____delete___2_Callback";
+
+  String __getter__(index_OR_name) {
+    if ((index_OR_name is int || index_OR_name == null)) {
+      return ___getter___1(index_OR_name);
+    }
+    if ((index_OR_name is String || index_OR_name == null)) {
+      return ___getter___2(index_OR_name);
+    }
+    throw new ArgumentError("Incorrect number or type of arguments");
+  }
+
+  String ___getter___1(index_OR_name) native "DOMStringMap____getter___1_Callback";
+
+  String ___getter___2(index_OR_name) native "DOMStringMap____getter___2_Callback";
+
+  void __setter__(index_OR_name, String value) {
+    if ((value is String || value == null) && (index_OR_name is int || index_OR_name == null)) {
+      ___setter___1(index_OR_name, value);
+      return;
+    }
+    if ((value is String || value == null) && (index_OR_name is String || index_OR_name == null)) {
+      ___setter___2(index_OR_name, value);
+      return;
+    }
+    throw new ArgumentError("Incorrect number or type of arguments");
+  }
+
+  void ___setter___1(index_OR_name, value) native "DOMStringMap____setter___1_Callback";
+
+  void ___setter___2(index_OR_name, value) native "DOMStringMap____setter___2_Callback";
 
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -11183,8 +11206,6 @@
 
   Element insertAdjacentElement(String where, Element element);
 
-  void insertAdjacentHtml(String where, String html);
-
   void insertAdjacentText(String where, String text);
 
   @DomName('Element.attributes')
@@ -11363,6 +11384,19 @@
   // http://dev.w3.org/csswg/css-regions/#dom-region-regionoverset
   String get regionOverset native "Element_webkitRegionOverset_Getter";
 
+  void animate(List<Map> keyframes, [num duration]) {
+    if (duration != null) {
+      _animate_1(keyframes, duration);
+      return;
+    }
+    _animate_2(keyframes);
+    return;
+  }
+
+  void _animate_1(keyframes, duration) native "Element__animate_1_Callback";
+
+  void _animate_2(keyframes) native "Element__animate_2_Callback";
+
   @DomName('Element.blur')
   @DocsEditable()
   void blur() native "Element_blur_Callback";
@@ -11450,7 +11484,7 @@
    */
   @DomName('Element.getElementsByClassName')
   @DocsEditable()
-  List<Node> getElementsByClassName(String name) native "Element_getElementsByClassName_Callback";
+  List<Node> getElementsByClassName(String classNames) native "Element_getElementsByClassName_Callback";
 
   @DomName('Element.getElementsByTagName')
   @DocsEditable()
@@ -11464,6 +11498,11 @@
   @DocsEditable()
   bool _hasAttributeNS(String namespaceURI, String localName) native "Element_hasAttributeNS_Callback";
 
+  @DomName('Element.insertAdjacentHTML')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void insertAdjacentHtml(String where, String html) native "Element_insertAdjacentHTML_Callback";
+
   /**
    * Finds the first descendant element of this element that matches the
    * specified group of selectors.
@@ -12806,6 +12845,11 @@
   // To suppress missing implicit constructor warnings.
   factory File._() { throw new UnsupportedError("Not supported"); }
 
+  @DomName('File.lastModified')
+  @DocsEditable()
+  @Experimental() // untriaged
+  int get lastModified native "File_lastModified_Getter";
+
   @DomName('File.lastModifiedDate')
   @DocsEditable()
   DateTime get lastModifiedDate native "File_lastModifiedDate_Getter";
@@ -13531,6 +13575,11 @@
   @Experimental() // untriaged
   void set weight(String value) native "FontFace_weight_Setter";
 
+  @DomName('FontFace.load')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void load() native "FontFace_load_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
@@ -14302,6 +14351,16 @@
    */
   HRElement.created() : super.created();
 
+  @DomName('HTMLHRElement.color')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String get color native "HTMLHRElement_color_Getter";
+
+  @DomName('HTMLHRElement.color')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void set color(String value) native "HTMLHRElement_color_Setter";
+
 }
 // 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
@@ -15263,10 +15322,6 @@
   @Experimental() // non-standard
   Element insertAdjacentElement(String where, Element element) native "HTMLElement_insertAdjacentElement_Callback";
 
-  @DomName('HTMLElement.insertAdjacentHTML')
-  @DocsEditable()
-  void insertAdjacentHtml(String where, String html) native "HTMLElement_insertAdjacentHTML_Callback";
-
   @DomName('HTMLElement.insertAdjacentText')
   @DocsEditable()
   @Experimental() // non-standard
@@ -17757,6 +17812,16 @@
   @DocsEditable()
   Composition get composition native "InputMethodContext_composition_Getter";
 
+  @DomName('InputMethodContext.compositionEndOffset')
+  @DocsEditable()
+  @Experimental() // untriaged
+  int get compositionEndOffset native "InputMethodContext_compositionEndOffset_Getter";
+
+  @DomName('InputMethodContext.compositionStartOffset')
+  @DocsEditable()
+  @Experimental() // untriaged
+  int get compositionStartOffset native "InputMethodContext_compositionStartOffset_Getter";
+
   @DomName('InputMethodContext.locale')
   @DocsEditable()
   String get locale native "InputMethodContext_locale_Getter";
@@ -17770,10 +17835,6 @@
   @DocsEditable()
   void confirmComposition() native "InputMethodContext_confirmComposition_Callback";
 
-  @DomName('InputMethodContext.setCaretRectangle')
-  @DocsEditable()
-  void setCaretRectangle(Node anchor, int x, int y, int w, int h) native "InputMethodContext_setCaretRectangle_Callback";
-
   @DomName('InputMethodContext.addEventListener')
   @DocsEditable()
   @Experimental() // untriaged
@@ -18832,6 +18893,16 @@
   @DocsEditable()
   void set controls(bool value) native "HTMLMediaElement_controls_Setter";
 
+  @DomName('HTMLMediaElement.crossOrigin')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String get crossOrigin native "HTMLMediaElement_crossOrigin_Getter";
+
+  @DomName('HTMLMediaElement.crossOrigin')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void set crossOrigin(String value) native "HTMLMediaElement_crossOrigin_Setter";
+
   @DomName('HTMLMediaElement.currentSrc')
   @DocsEditable()
   String get currentSrc native "HTMLMediaElement_currentSrc_Getter";
@@ -19563,33 +19634,6 @@
   @DocsEditable()
   String get media native "MediaQueryList_media_Getter";
 
-  @DomName('MediaQueryList.addListener')
-  @DocsEditable()
-  void addListener(MediaQueryListListener listener) native "MediaQueryList_addListener_Callback";
-
-  @DomName('MediaQueryList.removeListener')
-  @DocsEditable()
-  void removeListener(MediaQueryListListener listener) native "MediaQueryList_removeListener_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('MediaQueryListListener')
-@Unstable()
-abstract class MediaQueryListListener extends NativeFieldWrapperClass2 {
-  // To suppress missing implicit constructor warnings.
-  factory MediaQueryListListener._() { throw new UnsupportedError("Not supported"); }
-
-  @DomName('MediaQueryListListener.queryChanged')
-  @DocsEditable()
-  void queryChanged(MediaQueryList list) native "MediaQueryListListener_queryChanged_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
@@ -22088,7 +22132,7 @@
 @Unstable()
 class NodeIterator extends NativeFieldWrapperClass2 {
   factory NodeIterator(Node root, int whatToShow) {
-    return document._createNodeIterator(root, whatToShow, null, false);
+    return document._createNodeIterator(root, whatToShow, null);
   }
   // To suppress missing implicit constructor warnings.
   factory NodeIterator._() { throw new UnsupportedError("Not supported"); }
@@ -22235,17 +22279,6 @@
   static const EventStreamProvider<Event> closeEvent = const EventStreamProvider<Event>('close');
 
   /**
-   * Static factory designed to expose `display` events to event
-   * handlers that are not necessarily instances of [Notification].
-   *
-   * See [EventStreamProvider] for usage information.
-   */
-  @DomName('Notification.displayEvent')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  static const EventStreamProvider<Event> displayEvent = const EventStreamProvider<Event>('display');
-
-  /**
    * Static factory designed to expose `error` events to event
    * handlers that are not necessarily instances of [Notification].
    *
@@ -22274,44 +22307,39 @@
   @DocsEditable()
   static Notification _create_1(title, options) native "Notification__create_1constructorCallback";
 
+  @DomName('Notification.body')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String get body native "Notification_body_Getter";
+
   @DomName('Notification.dir')
   @DocsEditable()
   @Experimental() // nonstandard
   String get dir native "Notification_dir_Getter";
 
-  @DomName('Notification.dir')
+  @DomName('Notification.icon')
   @DocsEditable()
-  @Experimental() // nonstandard
-  void set dir(String value) native "Notification_dir_Setter";
+  @Experimental() // untriaged
+  String get icon native "Notification_icon_Getter";
+
+  @DomName('Notification.lang')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String get lang native "Notification_lang_Getter";
 
   @DomName('Notification.permission')
   @DocsEditable()
   String get permission native "Notification_permission_Getter";
 
-  @DomName('Notification.replaceId')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  String get replaceId native "Notification_replaceId_Getter";
-
-  @DomName('Notification.replaceId')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  void set replaceId(String value) native "Notification_replaceId_Setter";
-
   @DomName('Notification.tag')
   @DocsEditable()
   @Experimental() // nonstandard
   String get tag native "Notification_tag_Getter";
 
-  @DomName('Notification.tag')
+  @DomName('Notification.title')
   @DocsEditable()
-  @Experimental() // nonstandard
-  void set tag(String value) native "Notification_tag_Setter";
-
-  @DomName('Notification.cancel')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  void cancel() native "Notification_cancel_Callback";
+  @Experimental() // untriaged
+  String get title native "Notification_title_Getter";
 
   @DomName('Notification.close')
   @DocsEditable()
@@ -22328,11 +22356,6 @@
     return completer.future;
   }
 
-  @DomName('Notification.show')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  void show() native "Notification_show_Callback";
-
   @DomName('Notification.addEventListener')
   @DocsEditable()
   void addEventListener(String type, EventListener listener, [bool useCapture]) native "Notification_addEventListener_Callback";
@@ -22355,12 +22378,6 @@
   @DocsEditable()
   Stream<Event> get onClose => closeEvent.forTarget(this);
 
-  /// Stream of `display` events handled by this [Notification].
-  @DomName('Notification.ondisplay')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  Stream<Event> get onDisplay => displayEvent.forTarget(this);
-
   /// Stream of `error` events handled by this [Notification].
   @DomName('Notification.onerror')
   @DocsEditable()
@@ -25396,6 +25413,21 @@
 
 
 @DocsEditable()
+@DomName('ServiceWorkerGlobalScope')
+@Experimental() // untriaged
+class ServiceWorkerGlobalScope extends WorkerGlobalScope {
+  // To suppress missing implicit constructor warnings.
+  factory ServiceWorkerGlobalScope._() { 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()
@@ -27898,6 +27930,11 @@
   @DocsEditable()
   TextTrackCueList get cues native "TextTrack_cues_Getter";
 
+  @DomName('TextTrack.id')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String get id native "TextTrack_id_Getter";
+
   @DomName('TextTrack.kind')
   @DocsEditable()
   String get kind native "TextTrack_kind_Getter";
@@ -27994,25 +28031,6 @@
   @DocsEditable()
   static const EventStreamProvider<Event> exitEvent = const EventStreamProvider<Event>('exit');
 
-  @DomName('TextTrackCue.TextTrackCue')
-  @DocsEditable()
-  factory TextTrackCue(num startTime, num endTime, String text) {
-    return TextTrackCue._create_1(startTime, endTime, text);
-  }
-
-  @DocsEditable()
-  static TextTrackCue _create_1(startTime, endTime, text) native "TextTrackCue__create_1constructorCallback";
-
-  @DomName('TextTrackCue.align')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  String get align native "TextTrackCue_align_Getter";
-
-  @DomName('TextTrackCue.align')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  void set align(String value) native "TextTrackCue_align_Setter";
-
   @DomName('TextTrackCue.endTime')
   @DocsEditable()
   num get endTime native "TextTrackCue_endTime_Getter";
@@ -28029,16 +28047,6 @@
   @DocsEditable()
   void set id(String value) native "TextTrackCue_id_Setter";
 
-  @DomName('TextTrackCue.line')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  int get line native "TextTrackCue_line_Getter";
-
-  @DomName('TextTrackCue.line')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  void set line(int value) native "TextTrackCue_line_Setter";
-
   @DomName('TextTrackCue.pauseOnExit')
   @DocsEditable()
   bool get pauseOnExit native "TextTrackCue_pauseOnExit_Getter";
@@ -28047,46 +28055,6 @@
   @DocsEditable()
   void set pauseOnExit(bool value) native "TextTrackCue_pauseOnExit_Setter";
 
-  @DomName('TextTrackCue.position')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  int get position native "TextTrackCue_position_Getter";
-
-  @DomName('TextTrackCue.position')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  void set position(int value) native "TextTrackCue_position_Setter";
-
-  @DomName('TextTrackCue.regionId')
-  @DocsEditable()
-  @Experimental() // untriaged
-  String get regionId native "TextTrackCue_regionId_Getter";
-
-  @DomName('TextTrackCue.regionId')
-  @DocsEditable()
-  @Experimental() // untriaged
-  void set regionId(String value) native "TextTrackCue_regionId_Setter";
-
-  @DomName('TextTrackCue.size')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  int get size native "TextTrackCue_size_Getter";
-
-  @DomName('TextTrackCue.size')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  void set size(int value) native "TextTrackCue_size_Setter";
-
-  @DomName('TextTrackCue.snapToLines')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  bool get snapToLines native "TextTrackCue_snapToLines_Getter";
-
-  @DomName('TextTrackCue.snapToLines')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  void set snapToLines(bool value) native "TextTrackCue_snapToLines_Setter";
-
   @DomName('TextTrackCue.startTime')
   @DocsEditable()
   num get startTime native "TextTrackCue_startTime_Getter";
@@ -28095,35 +28063,10 @@
   @DocsEditable()
   void set startTime(num value) native "TextTrackCue_startTime_Setter";
 
-  @DomName('TextTrackCue.text')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  String get text native "TextTrackCue_text_Getter";
-
-  @DomName('TextTrackCue.text')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  void set text(String value) native "TextTrackCue_text_Setter";
-
   @DomName('TextTrackCue.track')
   @DocsEditable()
   TextTrack get track native "TextTrackCue_track_Getter";
 
-  @DomName('TextTrackCue.vertical')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  String get vertical native "TextTrackCue_vertical_Getter";
-
-  @DomName('TextTrackCue.vertical')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  void set vertical(String value) native "TextTrackCue_vertical_Setter";
-
-  @DomName('TextTrackCue.getCueAsHTML')
-  @DocsEditable()
-  @Experimental() // nonstandard
-  DocumentFragment getCueAsHtml() native "TextTrackCue_getCueAsHTML_Callback";
-
   @DomName('TextTrackCue.addEventListener')
   @DocsEditable()
   void addEventListener(String type, EventListener listener, [bool useCapture]) native "TextTrackCue_addEventListener_Callback";
@@ -28245,6 +28188,11 @@
   @DocsEditable()
   static const EventStreamProvider<TrackEvent> addTrackEvent = const EventStreamProvider<TrackEvent>('addtrack');
 
+  @DomName('TextTrackList.changeEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const EventStreamProvider<Event> changeEvent = const EventStreamProvider<Event>('change');
+
   @DomName('TextTrackList.length')
   @DocsEditable()
   int get length native "TextTrackList_length_Getter";
@@ -28294,6 +28242,11 @@
   TextTrack elementAt(int index) => this[index];
   // -- end List<TextTrack> mixins.
 
+  @DomName('TextTrackList.getTrackById')
+  @DocsEditable()
+  @Experimental() // untriaged
+  TextTrack getTrackById(String id) native "TextTrackList_getTrackById_Callback";
+
   @DomName('TextTrackList.item')
   @DocsEditable()
   TextTrack item(int index) native "TextTrackList_item_Callback";
@@ -28315,6 +28268,11 @@
   @DocsEditable()
   Stream<TrackEvent> get onAddTrack => addTrackEvent.forTarget(this);
 
+  @DomName('TextTrackList.onchange')
+  @DocsEditable()
+  @Experimental() // untriaged
+  Stream<Event> get onChange => changeEvent.forTarget(this);
+
 }
 // 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
@@ -28756,7 +28714,7 @@
 @Unstable()
 class TreeWalker extends NativeFieldWrapperClass2 {
   factory TreeWalker(Node root, int whatToShow) {
-    return document._createTreeWalker(root, whatToShow, null, false);
+    return document._createTreeWalker(root, whatToShow, null);
   }
   // To suppress missing implicit constructor warnings.
   factory TreeWalker._() { throw new UnsupportedError("Not supported"); }
@@ -28964,13 +28922,13 @@
     if ((blob_OR_source_OR_stream is Blob || blob_OR_source_OR_stream == null)) {
       return _createObjectURL_1(blob_OR_source_OR_stream);
     }
-    if ((blob_OR_source_OR_stream is MediaSource || blob_OR_source_OR_stream == null)) {
+    if ((blob_OR_source_OR_stream is MediaStream || blob_OR_source_OR_stream == null)) {
       return _createObjectURL_2(blob_OR_source_OR_stream);
     }
-    if ((blob_OR_source_OR_stream is _WebKitMediaSource || blob_OR_source_OR_stream == null)) {
+    if ((blob_OR_source_OR_stream is MediaSource || blob_OR_source_OR_stream == null)) {
       return _createObjectURL_3(blob_OR_source_OR_stream);
     }
-    if ((blob_OR_source_OR_stream is MediaStream || blob_OR_source_OR_stream == null)) {
+    if ((blob_OR_source_OR_stream is _WebKitMediaSource || blob_OR_source_OR_stream == null)) {
       return _createObjectURL_4(blob_OR_source_OR_stream);
     }
     throw new ArgumentError("Incorrect number or type of arguments");
@@ -29492,6 +29450,115 @@
 
 
 @DocsEditable()
+@DomName('VTTCue')
+@Experimental() // untriaged
+class VttCue extends TextTrackCue {
+  // To suppress missing implicit constructor warnings.
+  factory VttCue._() { throw new UnsupportedError("Not supported"); }
+
+  @DomName('VTTCue.VTTCue')
+  @DocsEditable()
+  factory VttCue(num startTime, num endTime, String text) {
+    return VttCue._create_1(startTime, endTime, text);
+  }
+
+  @DocsEditable()
+  static VttCue _create_1(startTime, endTime, text) native "VTTCue__create_1constructorCallback";
+
+  @DomName('VTTCue.align')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String get align native "VTTCue_align_Getter";
+
+  @DomName('VTTCue.align')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void set align(String value) native "VTTCue_align_Setter";
+
+  @DomName('VTTCue.line')
+  @DocsEditable()
+  @Experimental() // untriaged
+  int get line native "VTTCue_line_Getter";
+
+  @DomName('VTTCue.line')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void set line(int value) native "VTTCue_line_Setter";
+
+  @DomName('VTTCue.position')
+  @DocsEditable()
+  @Experimental() // untriaged
+  int get position native "VTTCue_position_Getter";
+
+  @DomName('VTTCue.position')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void set position(int value) native "VTTCue_position_Setter";
+
+  @DomName('VTTCue.regionId')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String get regionId native "VTTCue_regionId_Getter";
+
+  @DomName('VTTCue.regionId')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void set regionId(String value) native "VTTCue_regionId_Setter";
+
+  @DomName('VTTCue.size')
+  @DocsEditable()
+  @Experimental() // untriaged
+  int get size native "VTTCue_size_Getter";
+
+  @DomName('VTTCue.size')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void set size(int value) native "VTTCue_size_Setter";
+
+  @DomName('VTTCue.snapToLines')
+  @DocsEditable()
+  @Experimental() // untriaged
+  bool get snapToLines native "VTTCue_snapToLines_Getter";
+
+  @DomName('VTTCue.snapToLines')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void set snapToLines(bool value) native "VTTCue_snapToLines_Setter";
+
+  @DomName('VTTCue.text')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String get text native "VTTCue_text_Getter";
+
+  @DomName('VTTCue.text')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void set text(String value) native "VTTCue_text_Setter";
+
+  @DomName('VTTCue.vertical')
+  @DocsEditable()
+  @Experimental() // untriaged
+  String get vertical native "VTTCue_vertical_Getter";
+
+  @DomName('VTTCue.vertical')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void set vertical(String value) native "VTTCue_vertical_Setter";
+
+  @DomName('VTTCue.getCueAsHTML')
+  @DocsEditable()
+  @Experimental() // untriaged
+  DocumentFragment getCueAsHtml() native "VTTCue_getCueAsHTML_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('VTTRegion')
 @Experimental() // untriaged
 class VttRegion extends NativeFieldWrapperClass2 {
@@ -33042,28 +33109,6 @@
 
 
 @DocsEditable()
-@DomName('HTMLBaseFontElement')
-// http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#basefont
-@deprecated // deprecated
-abstract class _HTMLBaseFontElement extends HtmlElement {
-  // To suppress missing implicit constructor warnings.
-  factory _HTMLBaseFontElement._() { throw new UnsupportedError("Not supported"); }
-  /**
-   * Constructor instantiated by the DOM when a custom element has been created.
-   *
-   * This can only be called by subclasses from their created constructor.
-   */
-  _HTMLBaseFontElement.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('HTMLDirectoryElement')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dir
 @deprecated // deprecated
@@ -33741,6 +33786,21 @@
 
 
 @DocsEditable()
+@DomName('WebKitNotification')
+@Experimental() // untriaged
+abstract class _WebKitNotification extends EventTarget {
+  // To suppress missing implicit constructor warnings.
+  factory _WebKitNotification._() { 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('WebKitSourceBuffer')
 @Experimental() // untriaged
 abstract class _WebKitSourceBuffer extends NativeFieldWrapperClass2 {
diff --git a/sdk/lib/html/html_common/conversions.dart b/sdk/lib/html/html_common/conversions.dart
index c65c3ab..255b3e5 100644
--- a/sdk/lib/html/html_common/conversions.dart
+++ b/sdk/lib/html/html_common/conversions.dart
@@ -304,9 +304,11 @@
   bool premultipliedAlpha;
   bool preserveDrawingBuffer;
   bool stencil;
+  bool failIfMajorPerformanceCaveat;
 
   _TypedContextAttributes(this.alpha, this.antialias, this.depth,
-      this.premultipliedAlpha, this.preserveDrawingBuffer, this.stencil);
+      this.failIfMajorPerformanceCaveat, this.premultipliedAlpha,
+      this.preserveDrawingBuffer, this.stencil);
 }
 
 gl.ContextAttributes convertNativeToDart_ContextAttributes(
@@ -322,6 +324,7 @@
       JS('var', '#.alpha', nativeContextAttributes),
       JS('var', '#.antialias', nativeContextAttributes),
       JS('var', '#.depth', nativeContextAttributes),
+      JS('var', '#.failIfMajorPerformanceCaveat', nativeContextAttributes),
       JS('var', '#.premultipliedAlpha', nativeContextAttributes),
       JS('var', '#.preserveDrawingBuffer', nativeContextAttributes),
       JS('var', '#.stencil', nativeContextAttributes));
diff --git a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index 5ce201b..b344977 100644
--- a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -264,12 +264,17 @@
   @DocsEditable()
   @Creates('Null')
   @Returns('ObjectStore|Index|Null')
-  final dynamic source;
+  final Object source;
 
   @DomName('IDBCursor.advance')
   @DocsEditable()
   void advance(int count) native;
 
+  @DomName('IDBCursor.continuePrimaryKey')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void continuePrimaryKey(Object key, Object primaryKey) native;
+
   @JSName('delete')
   @DomName('IDBCursor.delete')
   @DocsEditable()
@@ -442,7 +447,7 @@
   @DocsEditable()
   @Creates('int|String|Null')
   @Returns('int|String|Null')
-  final dynamic version;
+  final Object version;
 
   @DomName('IDBDatabase.close')
   @DocsEditable()
@@ -731,7 +736,7 @@
   @DomName('IDBIndex.keyPath')
   @DocsEditable()
   @annotation_Creates_SerializedScriptValue
-  final dynamic keyPath;
+  final Object keyPath;
 
   @DomName('IDBIndex.multiEntry')
   @DocsEditable()
@@ -1007,7 +1012,7 @@
   @DomName('IDBObjectStore.keyPath')
   @DocsEditable()
   @annotation_Creates_SerializedScriptValue
-  final dynamic keyPath;
+  final Object keyPath;
 
   @DomName('IDBObjectStore.name')
   @DocsEditable()
@@ -1279,7 +1284,7 @@
   @DomName('IDBRequest.source')
   @DocsEditable()
   @Creates('Null')
-  final dynamic source;
+  final Object source;
 
   @DomName('IDBRequest.transaction')
   @DocsEditable()
@@ -1427,23 +1432,11 @@
   @DocsEditable()
   @Creates('int|String|Null')
   @Returns('int|String|Null')
-  final dynamic newVersion;
+  final Object newVersion;
 
   @DomName('IDBVersionChangeEvent.oldVersion')
   @DocsEditable()
   @Creates('int|String|Null')
   @Returns('int|String|Null')
-  final dynamic oldVersion;
-}
-// 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('IDBAny')
-@deprecated // nonstandard
-abstract class _IDBAny extends Interceptor native "IDBAny" {
-  // To suppress missing implicit constructor warnings.
-  factory _IDBAny._() { throw new UnsupportedError("Not supported"); }
+  final Object oldVersion;
 }
diff --git a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
index b2dbd4c..541826e 100644
--- a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
+++ b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
@@ -76,12 +76,17 @@
 
   @DomName('IDBCursor.source')
   @DocsEditable()
-  dynamic get source native "IDBCursor_source_Getter";
+  Object get source native "IDBCursor_source_Getter";
 
   @DomName('IDBCursor.advance')
   @DocsEditable()
   void advance(int count) native "IDBCursor_advance_Callback";
 
+  @DomName('IDBCursor.continuePrimaryKey')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void continuePrimaryKey(Object key, Object primaryKey) native "IDBCursor_continuePrimaryKey_Callback";
+
   @DomName('IDBCursor.delete')
   @DocsEditable()
   Request _delete() native "IDBCursor_delete_Callback";
@@ -203,7 +208,7 @@
 
   @DomName('IDBDatabase.version')
   @DocsEditable()
-  dynamic get version native "IDBDatabase_version_Getter";
+  Object get version native "IDBDatabase_version_Getter";
 
   @DomName('IDBDatabase.close')
   @DocsEditable()
@@ -514,7 +519,7 @@
 
   @DomName('IDBIndex.keyPath')
   @DocsEditable()
-  dynamic get keyPath native "IDBIndex_keyPath_Getter";
+  Object get keyPath native "IDBIndex_keyPath_Getter";
 
   @DomName('IDBIndex.multiEntry')
   @DocsEditable()
@@ -767,7 +772,7 @@
 
   @DomName('IDBObjectStore.keyPath')
   @DocsEditable()
-  dynamic get keyPath native "IDBObjectStore_keyPath_Getter";
+  Object get keyPath native "IDBObjectStore_keyPath_Getter";
 
   @DomName('IDBObjectStore.name')
   @DocsEditable()
@@ -949,11 +954,11 @@
 
   @DomName('IDBRequest.result')
   @DocsEditable()
-  dynamic get result native "IDBRequest_result_Getter";
+  Object get result native "IDBRequest_result_Getter";
 
   @DomName('IDBRequest.source')
   @DocsEditable()
-  dynamic get source native "IDBRequest_source_Getter";
+  Object get source native "IDBRequest_source_Getter";
 
   @DomName('IDBRequest.transaction')
   @DocsEditable()
@@ -1126,25 +1131,10 @@
 
   @DomName('IDBVersionChangeEvent.newVersion')
   @DocsEditable()
-  dynamic get newVersion native "IDBVersionChangeEvent_newVersion_Getter";
+  Object get newVersion native "IDBVersionChangeEvent_newVersion_Getter";
 
   @DomName('IDBVersionChangeEvent.oldVersion')
   @DocsEditable()
-  dynamic get oldVersion native "IDBVersionChangeEvent_oldVersion_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.
-
-// WARNING: Do not edit - generated code.
-
-
-@DocsEditable()
-@DomName('IDBAny')
-@deprecated // nonstandard
-abstract class _IDBAny extends NativeFieldWrapperClass2 {
-  // To suppress missing implicit constructor warnings.
-  factory _IDBAny._() { throw new UnsupportedError("Not supported"); }
+  Object get oldVersion native "IDBVersionChangeEvent_oldVersion_Getter";
 
 }
diff --git a/sdk/lib/io/directory.dart b/sdk/lib/io/directory.dart
index e1fb143..c23307f 100644
--- a/sdk/lib/io/directory.dart
+++ b/sdk/lib/io/directory.dart
@@ -7,7 +7,7 @@
 /**
  * A reference to a directory (or _folder_) on the file system.
  */
-abstract class Directory implements FileSystemEntity {
+abstract class Directory extends FileSystemEntity {
   /**
    * Gets the path of this directory.
    */
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index 9bba4be..9bf6632 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -45,7 +45,7 @@
  *    this.[openWrite]().
  *  * Open the file for random access operations using [open].
  */
-abstract class File implements FileSystemEntity {
+abstract class File extends FileSystemEntity {
   /**
    * Create a File object.
    */
diff --git a/sdk/lib/io/link.dart b/sdk/lib/io/link.dart
index 3fc8376..5833ac3 100644
--- a/sdk/lib/io/link.dart
+++ b/sdk/lib/io/link.dart
@@ -8,7 +8,7 @@
  * [Link] objects are references to filesystem links.
  *
  */
-abstract class Link implements FileSystemEntity {
+abstract class Link extends FileSystemEntity {
   /**
    * Creates a Link object.
    */
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index 8590284..b3c7063 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.dart
@@ -263,10 +263,11 @@
    * connection is prepared for TLS handshake.
    *
    * If the [socket] already has a subscription, pass the existing
-   * subscription in the [subscription] parameter. The secure socket
-   * will take over the subscription and process any subsequent
-   * events. In most cases calling `pause` on this subscription before
-   * starting TLS handshake is the right thing to do.
+   * subscription in the [subscription] parameter. The [secure]
+   * operation will take over the subscription by replacing the
+   * handlers with it own secure processing. The caller must not touch
+   * this subscription anymore. Passing a paused subscription is an
+   * error.
    *
    * If the [host] argument is passed it will be used as the host name
    * for the TLS handshake. If [host] is not passed the host name from
@@ -310,9 +311,11 @@
    * connection is going to start the TLS handshake.
    *
    * If the [socket] already has a subscription, pass the existing
-   * subscription in the [subscription] parameter. The secure socket
-   * will take over the subscription and process any subsequent
-   * events.
+   * subscription in the [subscription] parameter. The [secureServer]
+   * operation will take over the subscription by replacing the
+   * handlers with it own secure processing. The caller must not touch
+   * this subscription anymore. Passing a paused subscription is an
+   * error.
    *
    * If some of the data of the TLS handshake has already been read
    * from the socket this data can be passed in the [bufferedData]
@@ -535,6 +538,9 @@
                                              onError: _reportError,
                                              onDone: _doneHandler);
       } else {
+        if (_socketSubscription.isPaused) {
+          throw new StateError("Subscription passed to TLS upgrade is paused");
+        }
         _socketSubscription
             ..onData(_eventDispatcher)
             ..onError(_reportError)
diff --git a/sdk/lib/mirrors/mirrors.dart b/sdk/lib/mirrors/mirrors.dart
index 1c4c799..31e4cd3 100644
--- a/sdk/lib/mirrors/mirrors.dart
+++ b/sdk/lib/mirrors/mirrors.dart
@@ -674,6 +674,20 @@
    * variables.
    */
   TypeMirror get originalDeclaration;
+
+
+  /**
+   * Checks the subtype relationship, denoted by [:<::] in the language
+   * specification. This is the type relationship used in [:is:] test checks.
+   */
+  bool isSubtypeOf(TypeMirror other);
+
+  /**
+   * Checks the assignability relationship, denoted by [:<=>:] in the language
+   * specification. This is the type relationship tested on assignment in
+   * checked mode.
+   */
+  bool isAssignableTo(TypeMirror other);
 }
 
 /**
@@ -829,6 +843,14 @@
    * [ArgumentError] is thrown.
    */
   Function operator [](Symbol name);
+
+  /**
+   * Returns whether the class denoted by the receiver is a subclass of the
+   * class denoted by the argument.
+   *
+   * Note that the subclass relationship is reflexive.
+   */
+  bool isSubclassOf(ClassMirror other);
 }
 
 /**
diff --git a/sdk/lib/svg/dart2js/svg_dart2js.dart b/sdk/lib/svg/dart2js/svg_dart2js.dart
index 1fc55d8..83888f4 100644
--- a/sdk/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk/lib/svg/dart2js/svg_dart2js.dart
@@ -582,7 +582,7 @@
 @DocsEditable()
 @DomName('SVGCircleElement')
 @Unstable()
-class CircleElement extends GraphicsElement implements ExternalResourcesRequired native "SVGCircleElement" {
+class CircleElement extends GeometryElement implements ExternalResourcesRequired native "SVGCircleElement" {
   // To suppress missing implicit constructor warnings.
   factory CircleElement._() { throw new UnsupportedError("Not supported"); }
 
@@ -1388,7 +1388,7 @@
 @DocsEditable()
 @DomName('SVGEllipseElement')
 @Unstable()
-class EllipseElement extends GraphicsElement implements ExternalResourcesRequired native "SVGEllipseElement" {
+class EllipseElement extends GeometryElement implements ExternalResourcesRequired native "SVGEllipseElement" {
   // To suppress missing implicit constructor warnings.
   factory EllipseElement._() { throw new UnsupportedError("Not supported"); }
 
@@ -3122,6 +3122,34 @@
 
 
 @DocsEditable()
+@DomName('SVGGeometryElement')
+@Experimental() // untriaged
+class GeometryElement extends GraphicsElement native "SVGGeometryElement" {
+  // To suppress missing implicit constructor warnings.
+  factory GeometryElement._() { throw new UnsupportedError("Not supported"); }
+  /**
+   * Constructor instantiated by the DOM when a custom element has been created.
+   *
+   * This can only be called by subclasses from their created constructor.
+   */
+  GeometryElement.created() : super.created();
+
+  @DomName('SVGGeometryElement.isPointInFill')
+  @DocsEditable()
+  @Experimental() // untriaged
+  bool isPointInFill(Point point) native;
+
+  @DomName('SVGGeometryElement.isPointInStroke')
+  @DocsEditable()
+  @Experimental() // untriaged
+  bool isPointInStroke(Point point) 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('SVGGraphicsElement')
 @Experimental() // untriaged
 class GraphicsElement extends SvgElement implements Tests native "SVGGraphicsElement" {
@@ -3430,7 +3458,7 @@
 @DocsEditable()
 @DomName('SVGLineElement')
 @Unstable()
-class LineElement extends GraphicsElement implements ExternalResourcesRequired native "SVGLineElement" {
+class LineElement extends GeometryElement implements ExternalResourcesRequired native "SVGLineElement" {
   // To suppress missing implicit constructor warnings.
   factory LineElement._() { throw new UnsupportedError("Not supported"); }
 
@@ -3884,7 +3912,7 @@
 @DocsEditable()
 @DomName('SVGPathElement')
 @Unstable()
-class PathElement extends GraphicsElement implements ExternalResourcesRequired native "SVGPathElement" {
+class PathElement extends GeometryElement implements ExternalResourcesRequired native "SVGPathElement" {
   // To suppress missing implicit constructor warnings.
   factory PathElement._() { throw new UnsupportedError("Not supported"); }
 
@@ -4847,7 +4875,7 @@
 @DocsEditable()
 @DomName('SVGPolygonElement')
 @Unstable()
-class PolygonElement extends GraphicsElement implements ExternalResourcesRequired native "SVGPolygonElement" {
+class PolygonElement extends GeometryElement implements ExternalResourcesRequired native "SVGPolygonElement" {
   // To suppress missing implicit constructor warnings.
   factory PolygonElement._() { throw new UnsupportedError("Not supported"); }
 
@@ -4883,7 +4911,7 @@
 @DocsEditable()
 @DomName('SVGPolylineElement')
 @Unstable()
-class PolylineElement extends GraphicsElement implements ExternalResourcesRequired native "SVGPolylineElement" {
+class PolylineElement extends GeometryElement implements ExternalResourcesRequired native "SVGPolylineElement" {
   // To suppress missing implicit constructor warnings.
   factory PolylineElement._() { throw new UnsupportedError("Not supported"); }
 
@@ -5069,7 +5097,7 @@
 @DocsEditable()
 @DomName('SVGRectElement')
 @Unstable()
-class RectElement extends GraphicsElement implements ExternalResourcesRequired native "SVGRectElement" {
+class RectElement extends GeometryElement implements ExternalResourcesRequired native "SVGRectElement" {
   // To suppress missing implicit constructor warnings.
   factory RectElement._() { throw new UnsupportedError("Not supported"); }
 
diff --git a/sdk/lib/svg/dartium/svg_dartium.dart b/sdk/lib/svg/dartium/svg_dartium.dart
index e257800..4994919 100644
--- a/sdk/lib/svg/dartium/svg_dartium.dart
+++ b/sdk/lib/svg/dartium/svg_dartium.dart
@@ -660,7 +660,7 @@
 @DocsEditable()
 @DomName('SVGCircleElement')
 @Unstable()
-class CircleElement extends GraphicsElement implements ExternalResourcesRequired {
+class CircleElement extends GeometryElement implements ExternalResourcesRequired {
   // To suppress missing implicit constructor warnings.
   factory CircleElement._() { throw new UnsupportedError("Not supported"); }
 
@@ -1488,7 +1488,7 @@
 @DocsEditable()
 @DomName('SVGEllipseElement')
 @Unstable()
-class EllipseElement extends GraphicsElement implements ExternalResourcesRequired {
+class EllipseElement extends GeometryElement implements ExternalResourcesRequired {
   // To suppress missing implicit constructor warnings.
   factory EllipseElement._() { throw new UnsupportedError("Not supported"); }
 
@@ -3285,6 +3285,37 @@
 
 
 @DocsEditable()
+@DomName('SVGGeometryElement')
+@Experimental() // untriaged
+class GeometryElement extends GraphicsElement {
+  // To suppress missing implicit constructor warnings.
+  factory GeometryElement._() { throw new UnsupportedError("Not supported"); }
+  /**
+   * Constructor instantiated by the DOM when a custom element has been created.
+   *
+   * This can only be called by subclasses from their created constructor.
+   */
+  GeometryElement.created() : super.created();
+
+  @DomName('SVGGeometryElement.isPointInFill')
+  @DocsEditable()
+  @Experimental() // untriaged
+  bool isPointInFill(Point point) native "SVGGeometryElement_isPointInFill_Callback";
+
+  @DomName('SVGGeometryElement.isPointInStroke')
+  @DocsEditable()
+  @Experimental() // untriaged
+  bool isPointInStroke(Point point) native "SVGGeometryElement_isPointInStroke_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('SVGGraphicsElement')
 @Experimental() // untriaged
 class GraphicsElement extends SvgElement implements Tests {
@@ -3609,7 +3640,7 @@
 @DocsEditable()
 @DomName('SVGLineElement')
 @Unstable()
-class LineElement extends GraphicsElement implements ExternalResourcesRequired {
+class LineElement extends GeometryElement implements ExternalResourcesRequired {
   // To suppress missing implicit constructor warnings.
   factory LineElement._() { throw new UnsupportedError("Not supported"); }
 
@@ -4105,7 +4136,7 @@
 @DocsEditable()
 @DomName('SVGPathElement')
 @Unstable()
-class PathElement extends GraphicsElement implements ExternalResourcesRequired {
+class PathElement extends GeometryElement implements ExternalResourcesRequired {
   // To suppress missing implicit constructor warnings.
   factory PathElement._() { throw new UnsupportedError("Not supported"); }
 
@@ -5354,7 +5385,7 @@
 @DocsEditable()
 @DomName('SVGPolygonElement')
 @Unstable()
-class PolygonElement extends GraphicsElement implements ExternalResourcesRequired {
+class PolygonElement extends GeometryElement implements ExternalResourcesRequired {
   // To suppress missing implicit constructor warnings.
   factory PolygonElement._() { throw new UnsupportedError("Not supported"); }
 
@@ -5391,7 +5422,7 @@
 @DocsEditable()
 @DomName('SVGPolylineElement')
 @Unstable()
-class PolylineElement extends GraphicsElement implements ExternalResourcesRequired {
+class PolylineElement extends GeometryElement implements ExternalResourcesRequired {
   // To suppress missing implicit constructor warnings.
   factory PolylineElement._() { throw new UnsupportedError("Not supported"); }
 
@@ -5611,7 +5642,7 @@
 @DocsEditable()
 @DomName('SVGRectElement')
 @Unstable()
-class RectElement extends GraphicsElement implements ExternalResourcesRequired {
+class RectElement extends GeometryElement implements ExternalResourcesRequired {
   // To suppress missing implicit constructor warnings.
   factory RectElement._() { throw new UnsupportedError("Not supported"); }
 
diff --git a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
index 561e1f0..f9ff6005 100644
--- a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
+++ b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
@@ -521,6 +521,11 @@
   @DocsEditable()
   bool depth;
 
+  @DomName('WebGLContextAttributes.failIfMajorPerformanceCaveat')
+  @DocsEditable()
+  @Experimental() // untriaged
+  bool failIfMajorPerformanceCaveat;
+
   @DomName('WebGLContextAttributes.premultipliedAlpha')
   @DocsEditable()
   bool premultipliedAlpha;
diff --git a/sdk/lib/web_gl/dartium/web_gl_dartium.dart b/sdk/lib/web_gl/dartium/web_gl_dartium.dart
index 867aa67..dc75871 100644
--- a/sdk/lib/web_gl/dartium/web_gl_dartium.dart
+++ b/sdk/lib/web_gl/dartium/web_gl_dartium.dart
@@ -544,6 +544,16 @@
   @DocsEditable()
   void set depth(bool value) native "WebGLContextAttributes_depth_Setter";
 
+  @DomName('WebGLContextAttributes.failIfMajorPerformanceCaveat')
+  @DocsEditable()
+  @Experimental() // untriaged
+  bool get failIfMajorPerformanceCaveat native "WebGLContextAttributes_failIfMajorPerformanceCaveat_Getter";
+
+  @DomName('WebGLContextAttributes.failIfMajorPerformanceCaveat')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void set failIfMajorPerformanceCaveat(bool value) native "WebGLContextAttributes_failIfMajorPerformanceCaveat_Setter";
+
   @DomName('WebGLContextAttributes.premultipliedAlpha')
   @DocsEditable()
   bool get premultipliedAlpha native "WebGLContextAttributes_premultipliedAlpha_Getter";
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index 0378dd2..ee5f5bb 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -53,11 +53,6 @@
 [ $runtime == dartium || $compiler == dart2js ]
 LibTest/async/Future/Future.delayed_A01_t02: Pass, Fail # Issue 15524
 
-[ $runtime == vm || $compiler == dart2js ]
-LibTest/math/exp_A01_t01: PASS, FAIL, OK # co19 issue 44
-LibTest/math/sin_A01_t01: PASS, FAIL, OK # co19 issue 44
-
-
 [ $runtime == vm || $compiler == none || $compiler == dart2js ]
 LibTest/isolate/IsolateStream/any_A01_t01: Fail # Co19 issue 639 (Fixed in r674)
 LibTest/isolate/IsolateStream/asBroadcastStream_A01_t01: Fail # Co19 issue 639
@@ -82,7 +77,6 @@
 LibTest/isolate/SendPort/call_A01_t01: Fail # Co19 issue 639
 LibTest/isolate/SendPort/hashCode_A01_t01: Fail # Co19 issue 639
 LibTest/isolate/SendPort/operator_equality_A01_t01: Fail # Co19 issue 639
-LibTest/isolate/SendPort/send_A01_t01: Pass
 LibTest/isolate/SendPort/send_A02_t01: Fail # Co19 issue 639
 LibTest/isolate/SendPort/send_A02_t04: Fail # Co19 issue 639
 LibTest/isolate/SendPort/send_A02_t05: Fail # Co19 issue 639
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index fbdee70..c699f76 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -12,7 +12,6 @@
 
 Language/13_Statements/04_Local_Function_Declaration_A04_t01: Fail, MissingCompileTimeError # co19-roll r607: Please triage this failure
 
-LibTest/async/Stream/Stream.periodic_A01_t01: Pass, Fail # Issue 12562.
 LibTest/core/Symbol/Symbol_A01_t02: CompileTimeError # co19-roll r607: Please triage this failure
 
 Language/12_Expressions/12_Instance_Creation/1_New_A04_t02: RuntimeError # co19-roll r607: Please triage this failure
@@ -59,8 +58,6 @@
 LibTest/core/int/toRadixString_A01_t01: Fail # inherited from VM
 LibTest/isolate/ReceivePort/receive_A01_t02: Fail, OK # co19 issue 276
 LibTest/isolate/SendPort/send_A02_t01: CompileTimeError # Issue 13683
-LibTest/math/exp_A01_t01: Fail # Issue co19 - 44
-LibTest/math/sin_A01_t01: Fail # Inherited from VM.
 LibTest/math/tan_A01_t01: Fail # Issue co19 - 44
 LibTest/typed_data/Float32x4/equal_A01_t01: Skip # co19 issue 656
 LibTest/typed_data/Float32x4/notEqual_A01_t01: Skip # co19 issue 656
@@ -123,7 +120,6 @@
 Language/14_Libraries_and_Scripts/1_Imports_A03_t28: fail # co19-roll r546: Please triage this failure
 Language/14_Libraries_and_Scripts/1_Imports_A03_t29: fail # co19-roll r546: Please triage this failure
 Language/14_Libraries_and_Scripts/1_Imports_A03_t30: fail # co19-roll r546: Please triage this failure
-Language/14_Libraries_and_Scripts/1_Imports_A03_t65: pass, fail, ok # co19 issue 560
 Language/14_Libraries_and_Scripts/4_Scripts_A03_t01: fail # co19-roll r546: Please triage this failure
 Language/14_Libraries_and_Scripts/4_Scripts_A03_t03: fail # co19-roll r546: Please triage this failure
 Language/14_Libraries_and_Scripts/5_URIs_A01_t01: fail # co19-roll r546: Please triage this failure
@@ -134,11 +130,8 @@
 Language/15_Types/5_Function_Types_A06_t01: fail # co19-roll r546: Please triage this failure
 Language/16_Reference/1_Lexical_Rules/1_Reserved_Words_A40_t04: fail # co19-roll r546: Please triage this failure
 Language/16_Reference/1_Lexical_Rules_A02_t06: fail # co19-roll r546: Please triage this failure
-LibTest/async/Stream/Stream.periodic_A03_t01: fail, pass # co19-roll r546: Please triage this failure
-LibTest/async/Timer/Timer.periodic_A02_t01: fail, pass # co19-roll r546: Please triage this failure
 LibTest/core/DateTime/parse_A03_t01: fail # co19-roll r546: Please triage this failure
 LibTest/isolate/IsolateStream/any_A02_t01: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/SendPort/send_A01_t01: fail # co19-roll r546: Please triage this failure
 LibTest/isolate/SendPort/send_A02_t02: timeout # co19-roll r546: Please triage this failure
 LibTest/isolate/SendPort/send_A02_t03: timeout # co19-roll r546: Please triage this failure
 Language/12_Expressions/15_Method_Invocation/3_Static_Invocation_A04_t09: RuntimeError # co19-roll r623: Please triage this failure
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index beab79d..c476a70 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -162,7 +162,6 @@
 # can understand so he can file a bug later.
 #
 [ $compiler == dart2js ]
-Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t02: fail # co19 issue 648
 Language/03_Overview/2_Privacy_A01_t09: RuntimeError, OK # co19 issue 198
 Language/03_Overview/2_Privacy_A01_t11: Pass, OK # co19 issue 316
 Language/06_Functions/4_External_Functions_A01_t01: CompileTimeError, OK # http://dartbug.com/5021
@@ -483,7 +482,6 @@
 LibTest/core/RegExp/allMatches_A01_t01: fail # co19-roll r559: Please triage this failure
 LibTest/isolate/IsolateStream/any_A02_t01: fail # co19-roll r546: Please triage this failure
 LibTest/isolate/IsolateStream/contains_A02_t01: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/SendPort/send_A01_t01: fail # co19-roll r546: Please triage this failure
 LibTest/typed_data/Float32List/Float32List.view_A05_t01: RuntimeError # co19-roll r559: Please triage this failure
 LibTest/typed_data/Float32List/Float32List.view_A05_t02: RuntimeError # co19-roll r559: Please triage this failure
 LibTest/typed_data/Float32List/Float32List.view_A05_t03: RuntimeError # co19-roll r559: Please triage this failure
@@ -549,7 +547,7 @@
 LibTest/typed_data/Int32List/hashCode_A01_t01: fail # co19-roll r559: Please triage this failure
 LibTest/typed_data/Int32List/Int32List.view_A06_t01: fail # co19-roll r587: Please triage this failure
 LibTest/typed_data/Int32List/toList_A01_t01: fail # co19-roll r559: Please triage this failure
-LibTest/typed_data/Int32List/toList_A01_t01: pass, timeout # co19-roll r559: Please triage this failure
+LibTest/typed_data/Int32List/toList_A01_t01: timeout # co19-roll r559: Please triage this failure
 LibTest/typed_data/Int8List/hashCode_A01_t01: fail # co19-roll r559: Please triage this failure
 LibTest/typed_data/Int8List/toList_A01_t01: fail, timeout # co19-roll r559: Please triage this failure
 LibTest/typed_data/Uint16List/hashCode_A01_t01: fail # co19-roll r559: Please triage this failure
@@ -557,7 +555,7 @@
 LibTest/typed_data/Uint16List/toList_A01_t01: timeout # co19-roll r559: Please triage this failure
 LibTest/typed_data/Uint16List/Uint16List.view_A06_t01: fail # co19-roll r587: Please triage this failure
 LibTest/typed_data/Uint32List/hashCode_A01_t01: fail # co19-roll r559: Please triage this failure
-LibTest/typed_data/Uint32List/toList_A01_t01: fail, timeout # co19-roll r559: Please triage this failure
+LibTest/typed_data/Uint32List/toList_A01_t01: timeout # co19-roll r559: Please triage this failure
 LibTest/typed_data/Uint32List/Uint32List.view_A06_t01: fail # co19-roll r587: Please triage this failure
 LibTest/typed_data/Uint8ClampedList/hashCode_A01_t01: fail # co19-roll r559: Please triage this failure
 LibTest/typed_data/Uint8ClampedList/toList_A01_t01: fail, timeout # co19-roll r559: Please triage this failure
@@ -654,7 +652,6 @@
 [ $compiler == dart2js ]
 LibTest/core/List/List_class_A01_t01: RuntimeError # co19-roll r623: Please triage this failure
 Language/03_Overview/2_Privacy_A01_t02: RuntimeError # co19-roll r667: Please triage this failure
-Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t02: Pass # co19-roll r667: Please triage this failure
 Language/12_Expressions/20_Logical_Boolean_Expressions_A06_t16: RuntimeError # co19-roll r667: Please triage this failure
 Language/12_Expressions/20_Logical_Boolean_Expressions_A06_t17: RuntimeError # co19-roll r667: Please triage this failure
 LibTest/convert/JsonDecoder/fuse_A01_t01: RuntimeError # co19-roll r667: Please triage this failure
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 4fd2150..b91152b 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -70,8 +70,5 @@
 LibTest/collection/ListMixin/ListMixin_class_A01_t01: Skip # Timeouts
 LibTest/collection/ListBase/ListBase_class_A01_t01: Skip # Timeouts
 
-[ $compiler == none && $runtime == vm && $arch == simarm ]
-LibTest/typed_data/Float32x4/sqrt_A01_t01: Pass, Fail # co19 issue 666.
-
 [ $runtime == vm ]
 LibTest/isolate/Isolate/spawn_A02_t01: Skip # co19 issue 667
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index 90ce342..3bfe7a8 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -3,19 +3,20 @@
 # BSD-style license that can be found in the LICENSE file.
 
 identity_test: Fail # Issue 6638
-constant_folding_string_test: Fail
 boolified_operator_test: Fail # Issue 8001
 
 # simple_function_subtype_test is temporarily(?) disabled due to new method for
 # building function type tests.
 simple_function_subtype_test: Fail
 
-mirror_final_field_inferrer2_test: Crash, Pass # dartbug.com/15581
-
 simple_inferrer_const_closure_test: Fail # Issue 16507
 simple_inferrer_const_closure2_test: Fail # Issue 16507
 simple_inferrer_global_field_closure_test: Fail # Issue 16507
 
+mirrors/relation_subtype_test: Fail # Issue 16736
+mirrors/relation_assignable_test: Fail # Issue 16736
+mirrors/relation_subclass_test: Fail # Issue 16737
+
 [ $mode == debug ]
 mirror_final_field_inferrer2_test: Crash, Pass, Slow # dartbug.com/15581
 
diff --git a/tests/compiler/dart2js/mirrors/relation_assignable_test.dart b/tests/compiler/dart2js/mirrors/relation_assignable_test.dart
new file mode 100644
index 0000000..3f57a14
--- /dev/null
+++ b/tests/compiler/dart2js/mirrors/relation_assignable_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.

+

+import "dart:mirrors";

+

+import "package:async_helper/async_helper.dart";

+

+import "mirrors_test_helper.dart";

+import "../../../lib/mirrors/relation_assignable_test.dart";

+

+main() {

+  asyncTest(() => analyze("relation_assignable_test.dart").

+      then((MirrorSystem mirrors) {

+    test(mirrors);

+  }));

+}

diff --git a/tests/compiler/dart2js/mirrors/relation_subclass_test.dart b/tests/compiler/dart2js/mirrors/relation_subclass_test.dart
new file mode 100644
index 0000000..eaab608
--- /dev/null
+++ b/tests/compiler/dart2js/mirrors/relation_subclass_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.

+

+import "dart:mirrors";

+

+import "package:async_helper/async_helper.dart";

+

+import "mirrors_test_helper.dart";

+import "../../../lib/mirrors/relation_subclass_test.dart";

+

+main() {

+  asyncTest(() => analyze("relation_subclass_test.dart").

+      then((MirrorSystem mirrors) {

+    test(mirrors);

+  }));

+}

diff --git a/tests/compiler/dart2js/mirrors/relation_subtype_test.dart b/tests/compiler/dart2js/mirrors/relation_subtype_test.dart
new file mode 100644
index 0000000..036af05
--- /dev/null
+++ b/tests/compiler/dart2js/mirrors/relation_subtype_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.

+

+import "dart:mirrors";

+

+import "package:async_helper/async_helper.dart";

+

+import "mirrors_test_helper.dart";

+import "../../../lib/mirrors/relation_subtype_test.dart";

+

+main() {

+  asyncTest(() => analyze("relation_subtype_test.dart").

+      then((MirrorSystem mirrors) {

+    test(mirrors);

+  }));

+}

diff --git a/tests/compiler/dart2js_native/internal_library_test.dart b/tests/compiler/dart2js_native/internal_library_test.dart
index 9645f55..0bf6c4f 100644
--- a/tests/compiler/dart2js_native/internal_library_test.dart
+++ b/tests/compiler/dart2js_native/internal_library_test.dart
@@ -8,5 +8,5 @@
 import 'dart:_isolate_helper';
 
 void main() {
-  print(controlPort);
-}
\ No newline at end of file
+  print(startRootIsolate);
+}
diff --git a/tests/html/custom/attribute_changed_callback_test.dart b/tests/html/custom/attribute_changed_callback_test.dart
index 69d9357..14b8614 100644
--- a/tests/html/custom/attribute_changed_callback_test.dart
+++ b/tests/html/custom/attribute_changed_callback_test.dart
@@ -49,15 +49,13 @@
   // Adapted from Blink's fast/dom/custom/attribute-changed-callback test.
 
   var registered = false;
-  setUp(() {
-    return loadPolyfills().then((_) {
-      if (!registered) {
-        registered = true;
-        document.register(A.tag, A);
-        document.register(B.tag, B);
-      }
-    });
-  });
+  setUp(() => customElementsReady.then((_) {
+    if (!registered) {
+      registered = true;
+      document.register(A.tag, A);
+      document.register(B.tag, B);
+    }
+  }));
 
   group('fully_supported', () {
     test('transfer attribute changed callback', () {
diff --git a/tests/html/custom/attribute_changed_callback_test.html b/tests/html/custom/attribute_changed_callback_test.html
new file mode 100644
index 0000000..83697ec
--- /dev/null
+++ b/tests/html/custom/attribute_changed_callback_test.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> attribute_changed_callback_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/platform.concat.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running attribute_changed_callback_test </h1>
+  <script type="text/javascript"
+      src="/packages/unittest/test_controller.js"></script>
+  <script type="text/javascript"
+      src="/packages/browser/interop.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/html/custom/constructor_calls_created_synchronously_test.dart b/tests/html/custom/constructor_calls_created_synchronously_test.dart
index d2bc3af..0eb1f5c 100644
--- a/tests/html/custom/constructor_calls_created_synchronously_test.dart
+++ b/tests/html/custom/constructor_calls_created_synchronously_test.dart
@@ -27,7 +27,7 @@
 
   var registered = false;
   setUp(() {
-    return loadPolyfills().then((_) {
+    return customElementsReady.then((_) {
       if (!registered) {
         registered = true;
         document.register(A.tag, A);
diff --git a/tests/html/custom/constructor_calls_created_synchronously_test.html b/tests/html/custom/constructor_calls_created_synchronously_test.html
new file mode 100644
index 0000000..6bea50e
--- /dev/null
+++ b/tests/html/custom/constructor_calls_created_synchronously_test.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> entered_left_view_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/platform.concat.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running entered_left_view_test </h1>
+  <script type="text/javascript"
+      src="/packages/unittest/test_controller.js"></script>
+  <script type="text/javascript"
+      src="/packages/browser/interop.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/html/custom/created_callback_test.dart b/tests/html/custom/created_callback_test.dart
index 49845c1..8652520 100644
--- a/tests/html/custom/created_callback_test.dart
+++ b/tests/html/custom/created_callback_test.dart
@@ -62,7 +62,7 @@
 
   var registered = false;
   setUp(() {
-    return loadPolyfills().then((_) {
+    return customElementsReady.then((_) {
       if (!registered) {
         registered = true;
         document.register(B.tag, B);
diff --git a/tests/html/custom/created_callback_test.html b/tests/html/custom/created_callback_test.html
new file mode 100644
index 0000000..da08386
--- /dev/null
+++ b/tests/html/custom/created_callback_test.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> created_callback_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/platform.concat.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running created_callback_test </h1>
+  <script type="text/javascript"
+      src="/packages/unittest/test_controller.js"></script>
+  <script type="text/javascript"
+      src="/packages/browser/interop.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/html/custom/document_register_basic_test.dart b/tests/html/custom/document_register_basic_test.dart
index 22b45b2..c5a0d6e 100644
--- a/tests/html/custom/document_register_basic_test.dart
+++ b/tests/html/custom/document_register_basic_test.dart
@@ -45,7 +45,7 @@
 
   // Adapted from Blink's fast/dom/custom/document-register-basic test.
 
-  setUp(loadPolyfills);
+  setUp(() => customElementsReady);
 
   test('Testing document.register() basic behaviors', () {
     document.register(Foo.tag, Foo);
diff --git a/tests/html/custom/document_register_basic_test.html b/tests/html/custom/document_register_basic_test.html
new file mode 100644
index 0000000..f956be3
--- /dev/null
+++ b/tests/html/custom/document_register_basic_test.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> document_register_basic_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/platform.concat.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running document_register_basic_test </h1>
+  <script type="text/javascript"
+      src="/packages/unittest/test_controller.js"></script>
+  <script type="text/javascript"
+      src="/packages/browser/interop.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/html/custom/document_register_type_extensions_test.dart b/tests/html/custom/document_register_type_extensions_test.dart
index 9ce14e6..80f703f 100644
--- a/tests/html/custom/document_register_type_extensions_test.dart
+++ b/tests/html/custom/document_register_type_extensions_test.dart
@@ -101,7 +101,7 @@
     document.register(CustomCustomDiv.tag, CustomCustomDiv, extendsTag: 'div');
   }
 
-  setUp(loadPolyfills);
+  setUp(() => customElementsReady);
 
   group('registration', () {
     setUp(registerTypes);
diff --git a/tests/html/custom/document_register_type_extensions_test.html b/tests/html/custom/document_register_type_extensions_test.html
new file mode 100644
index 0000000..d0a0fbc
--- /dev/null
+++ b/tests/html/custom/document_register_type_extensions_test.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> document_register_type_extensions_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/platform.concat.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running document_register_type_extensions_test </h1>
+  <script type="text/javascript"
+      src="/packages/unittest/test_controller.js"></script>
+  <script type="text/javascript"
+      src="/packages/browser/interop.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/html/custom/entered_left_view_test.dart b/tests/html/custom/entered_left_view_test.dart
index 06795cf..4822d0e 100644
--- a/tests/html/custom/entered_left_view_test.dart
+++ b/tests/html/custom/entered_left_view_test.dart
@@ -31,13 +31,6 @@
   }
 }
 
-// Pump custom events polyfill events.
-void customElementsTakeRecords() {
-  if (js.context.hasProperty('CustomElements')) {
-    js.context['CustomElements'].callMethod('takeRecords');
-  }
-}
-
 main() {
   useHtmlIndividualConfiguration();
 
@@ -50,15 +43,11 @@
   var nullSanitizer = new NullTreeSanitizer();
 
   var registeredTypes = false;
-  setUp(() {
-    return loadPolyfills().then((_) {
-      if (registeredTypes) {
-        return;
-      }
-      registeredTypes = true;
-      document.register('x-a', Foo);
-    });
-  });
+  setUp(() => customElementsReady.then((_) {
+    if (registeredTypes) return;
+    registeredTypes = true;
+    document.register('x-a', Foo);
+  }));
 
   group('standard_events', () {
     var a;
diff --git a/tests/html/custom/entered_left_view_test.html b/tests/html/custom/entered_left_view_test.html
index 7c1059c..6bea50e 100644
--- a/tests/html/custom/entered_left_view_test.html
+++ b/tests/html/custom/entered_left_view_test.html
@@ -10,7 +10,8 @@
      .unittest-fail { background: #d55;}
      .unittest-error { background: #a11;}
   </style>
-  <script src="/packages/shadow_dom/shadow_dom.debug.js"></script>
+  <script src="/packages/web_components/platform.concat.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
 </head>
 <body>
   <h1> Running entered_left_view_test </h1>
diff --git a/tests/html/custom/js_custom_test.dart b/tests/html/custom/js_custom_test.dart
index 412cb2e..1abf32f 100644
--- a/tests/html/custom/js_custom_test.dart
+++ b/tests/html/custom/js_custom_test.dart
@@ -28,7 +28,7 @@
 
   var registered = false;
   setUp(() {
-    return loadPolyfills().then((_) {
+    return customElementsReady.then((_) {
       if (!registered) {
         registered = true;
         document.register(A.tag, A);
diff --git a/tests/html/custom/js_custom_test.html b/tests/html/custom/js_custom_test.html
new file mode 100644
index 0000000..43c3ffe
--- /dev/null
+++ b/tests/html/custom/js_custom_test.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> js_custom_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/platform.concat.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running js_custom_test </h1>
+  <script type="text/javascript"
+      src="/packages/unittest/test_controller.js"></script>
+  <script type="text/javascript"
+      src="/packages/browser/interop.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/html/custom/mirrors_test.dart b/tests/html/custom/mirrors_test.dart
index 9cf892b..e8778d1 100644
--- a/tests/html/custom/mirrors_test.dart
+++ b/tests/html/custom/mirrors_test.dart
@@ -19,7 +19,7 @@
   useHtmlConfiguration();
 
   var registered = false;
-  setUp(() => loadPolyfills().then((_) {
+  setUp(() => customElementsReady.then((_) {
     if (!registered) {
       registered = true;
       document.register(A.tag, A);
diff --git a/tests/html/custom/mirrors_test.html b/tests/html/custom/mirrors_test.html
new file mode 100644
index 0000000..550e43c
--- /dev/null
+++ b/tests/html/custom/mirrors_test.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> mirrors_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/platform.concat.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running mirrors_test </h1>
+  <script type="text/javascript"
+      src="/packages/unittest/test_controller.js"></script>
+  <script type="text/javascript"
+      src="/packages/browser/interop.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/html/custom/template_wrappers_test.dart b/tests/html/custom/template_wrappers_test.dart
index c52ad7b..4953d33 100644
--- a/tests/html/custom/template_wrappers_test.dart
+++ b/tests/html/custom/template_wrappers_test.dart
@@ -22,17 +22,10 @@
   }
 }
 
-// Pump custom events polyfill events.
-void customElementsTakeRecords() {
-  if (js.context != null && js.context.hasProperty('CustomElements')) {
-    js.context['CustomElements'].callMethod('takeRecords');
-  }
-}
-
 main() {
   useHtmlConfiguration();
 
-  setUp(loadPolyfills);
+  setUp(customElementsReady);
 
   test('element is upgraded once', () {
 
diff --git a/tests/html/custom/template_wrappers_test.html b/tests/html/custom/template_wrappers_test.html
index 2613bdc..c0844b6 100644
--- a/tests/html/custom/template_wrappers_test.html
+++ b/tests/html/custom/template_wrappers_test.html
@@ -10,6 +10,8 @@
      .unittest-fail { background: #d55;}
      .unittest-error { background: #a11;}
   </style>
+  <script src="/packages/web_components/platform.concat.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
 </head>
 <body>
   <h1> Running template_wrappers_test </h1>
diff --git a/tests/html/custom_elements_test.dart b/tests/html/custom_elements_test.dart
index bbd3ce7..f31f84a 100644
--- a/tests/html/custom_elements_test.dart
+++ b/tests/html/custom_elements_test.dart
@@ -41,7 +41,7 @@
 main() {
   useHtmlIndividualConfiguration();
 
-  setUp(loadPolyfills);
+  setUp(() => customElementsReady);
 
   group('register', () {
     test('register', () {
diff --git a/tests/html/custom_elements_test.html b/tests/html/custom_elements_test.html
new file mode 100644
index 0000000..6812767
--- /dev/null
+++ b/tests/html/custom_elements_test.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> custom_elements_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/platform.concat.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running custom_elements_test </h1>
+  <script type="text/javascript"
+      src="/packages/unittest/test_controller.js"></script>
+  <script type="text/javascript" src="/packages/browser/interop.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/html/html.status b/tests/html/html.status
index 26672d0..cd3b67d 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -5,13 +5,13 @@
 event_test: Skip  # Issue 1996
 interactive_test: Skip # Must be run manually.
 dromaeo_smoke_test: Skip # Issue 14521, 8257
+custom/template_wrappers_test: Pass, Fail # Issue 16656 (Chrome 33 regression)
 
 [ $compiler == dart2js && $csp ]
 custom/js_custom_test: Fail # Issue 14643
 
 [ $compiler == dart2js && $browser ]
-element_offset_test/offset: Pass, Fail # Issue 13296
-custom/template_wrappers_test: Pass, Fail # Test is for Dartium GC issues
+custom/template_wrappers_test: RuntimeError # Test is for Dartium GC issues
 
 [ $compiler == dart2js && $browser ]
 custom/created_callback_test: Fail # Support for created constructor.
@@ -35,6 +35,9 @@
 async_test: Fail # Background timers not implemented.
 keyboard_event_test: Fail # Issue 13902
 isolates_test: Fail # Issue 13921
+indexeddb_5_test: RuntimeError # Issue 16657 Chrome 33 regression)
+fileapi_test/fileEntry: RuntimeError # Issue 16657 (Chrome 33 regression)
+audiocontext_test/functional: RuntimeError # Issue 16657 (Chrome 33 regression)
 
 [ $compiler == none && $runtime == drt && $system == windows ]
 worker_test/functional: Pass, Crash # Issue 9929.
@@ -64,7 +67,6 @@
 
 
 [ $compiler == dart2js && $runtime == ie10 ]
-async_test: Pass, Fail # timers test fails on ie10.
 indexeddb_5_test: Fail # Issue 12893
 js_test: Fail # Issue 14246
 
@@ -72,9 +74,6 @@
 worker_api_test: Fail # IE does not support URL.createObjectURL in web workers.
 
 [ $runtime == chrome ]
-canvasrenderingcontext2d_test/drawImage_video_element: Pass,Fail # Issue 11836
-canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Pass,Fail # Issue 11836
-
 xhr_test: Pass, Fail # Issue 11884
 xhr_cross_origin_test: Pass, Fail # Issue 11884
 
@@ -97,10 +96,7 @@
 
 [$runtime == ie10 ]
 element_test/click: Fail                # IE does not support firing this event.
-history_test/history: Pass, Fail # issue 8183
-native_gc_test: Fail, Pass # BUG(7774): Untriaged.
 serialized_script_value_test: Fail
-storage_test: Fail, Pass
 transferables_test: Fail # Issue 9846
 websocket_test/websocket: Fail # TODO(efortuna): Issue 7875.
 canvasrenderingcontext2d_test/drawImage_video_element: Fail # IE does not support drawImage w/ video element
@@ -173,6 +169,8 @@
 xhr_cross_origin_test: Skip # Issue 12920
 xhr_test/json: Fail # IE9 returns null because of unsupported type
 js_test: RuntimeError # Issue 14645
+custom: Pass, Fail, Timeout # Issue 16717
+custom_elements_test: Pass, Fail, Timeout # Issue 16717
 
 # IE9 Feature support statuses-
 # All changes should be accompanied by platform support annotation changes.
@@ -259,7 +257,6 @@
 [ $runtime == safari ]
 worker_test: Skip # Issue 13221
 worker_api_test: Skip # Issue 13221
-element_types_test/supported_track: Pass, Fail
 input_element_test/supported_month: RuntimeError
 input_element_test/supported_time: RuntimeError
 input_element_test/supported_week: RuntimeError
@@ -268,7 +265,6 @@
 canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Fail # Safari does not support drawImage w/ video element
 audiocontext_test/functional: Fail # Issue 14354
 websql_test/functional: RuntimeError # Issue 14523
-custom/mirrors_test: Fail # Issue 15737
 
 # Safari Feature support statuses-
 # All changes should be accompanied by platform support annotation changes.
@@ -358,7 +354,6 @@
 input_element_test/supported_datetime-local: Fail
 input_element_test/supported_month: Fail
 input_element_test/supported_number: Fail
-input_element_test/supported_range: Fail, Pass # FF 23 is introducing support.
 input_element_test/supported_time: Fail
 input_element_test/supported_week: Fail
 media_stream_test/supported_MediaStreamEvent: Fail
diff --git a/tests/html/utils.dart b/tests/html/utils.dart
index 9b469b1..f8d2e6d 100644
--- a/tests/html/utils.dart
+++ b/tests/html/utils.dart
@@ -5,6 +5,7 @@
 import 'dart:js' as js;
 import 'dart:typed_data';
 import 'package:unittest/unittest.dart';
+export 'package:web_components/polyfill.dart';
 
 /**
  * Verifies that [actual] has the same graph structure as [expected].
@@ -161,20 +162,6 @@
   }
 }
 
-Future loadCustomElementPolyfill() {
-  if (!document.supportsRegister) {
-    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();
-}
-
-Future loadPolyfills() {
-  return loadCustomElementPolyfill();
-}
-
 /**
  * Upgrade all custom elements in the subtree which have not been upgraded.
  *
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index a753ec2..b2d32ba 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -11,17 +11,14 @@
 isolate_throws_test/01: Skip # Issue 12587
 compile_time_error_test/01: Skip # Issue 12587
 capability_test: Fail  # Not implemented yet
-pause_test: Fail
+pause_test: Fail       # Not implemented yet
 
 [ $compiler == dart2js && $jscl ]
 browser/*: SkipByDesign  # Browser specific tests
-
-[ $compiler == dart2js && $runtime == drt ]
-isolate_stress_test: Pass, Crash # Issue 14438
+pause_test: Fail  # non-zero timer not supported.
 
 [ $compiler == dart2js ]
 serialization_test: RuntimeError # Issue 1882, tries to access class TestingOnly declared in isolate_patch.dart
-pause_test: Fail
 
 [ $compiler == dart2js && $runtime == ie9 ]
 browser/typed_data_message_test: Fail # Issue 12624
diff --git a/tests/isolate/pause_test.dart b/tests/isolate/pause_test.dart
index 71691ad..22a4fce 100644
--- a/tests/isolate/pause_test.dart
+++ b/tests/isolate/pause_test.dart
@@ -24,10 +24,10 @@
   reply.handler = completer.complete;
   Isolate.spawn(isomain1, reply.sendPort).then((Isolate iso) {
     isolate = iso;
-    resume = isolate.pause();
     return completer.future;
   }).then((echoPort) {
     // Isolate has been created, and first response has been returned.
+    resume = isolate.pause();
     echoPort.send(24);
     reply.handler = (v) {
       throw "RESPONSE WHILE PAUSED?!?";
diff --git a/tests/language/language.status b/tests/language/language.status
index 8980845..70b57c5 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -46,6 +46,7 @@
 compile_time_constant_checked3_test/04: Fail, OK
 compile_time_constant_checked3_test/05: Fail, OK
 compile_time_constant_checked3_test/06: Fail, OK
+type_check_const_function_typedef2_test/00: Fail, OK
 malformed2_test/01: Fail, OK
 
 [ $runtime == vm || (($runtime == drt || $runtime == dartium) && $compiler == none) ]
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index 026333e..b28f529 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -18,14 +18,10 @@
 override_field_test/03: fail
 method_override7_test/03: Fail # Issue 11496
 
-assignable_expression_test/02: Fail # Issue 15471
-assignable_expression_test/12: Fail # Issue 15471
-assignable_expression_test/22: Fail # Issue 15471
-assignable_expression_test/32: Fail # Issue 15471
-assignable_expression_test/42: Fail # Issue 15471
-
 unicode_bom_test: Fail # Issue 16314
 
+type_check_const_function_typedef2_test/00: MissingCompileTimeError, Ok # Compile-time error in checked mode, because of constants.
+
 # Please add new failing tests before this line.
 # Section below is for invalid tests.
 #
diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status
index c48c244..3f0c39d 100644
--- a/tests/language/language_analyzer2.status
+++ b/tests/language/language_analyzer2.status
@@ -26,6 +26,8 @@
 
 unicode_bom_test: Fail # Issue 16314
 
+type_check_const_function_typedef2_test/00: MissingCompileTimeError, Ok # Compile-time error in checked mode, because of constants.
+
 # Please add new failing tests before this line.
 # Section below is for invalid tests.
 #
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 8f9111d..662d9a9 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -75,6 +75,7 @@
 compile_time_constant_checked3_test/04: MissingCompileTimeError, OK
 compile_time_constant_checked3_test/05: MissingCompileTimeError, OK
 compile_time_constant_checked3_test/06: MissingCompileTimeError, OK
+type_check_const_function_typedef2_test/00: MissingCompileTimeError, OK
 malformed2_test/01: MissingCompileTimeError, OK
 generic_test: RuntimeError, OK
 named_parameters_type_test/01: MissingRuntimeError, OK
@@ -150,6 +151,9 @@
 [ ($compiler == dart2js || $compiler == dart2dart) && $checked ]
 cyclic_typedef_test/07: Crash # Issue 15237
 
+[ ($compiler == dart2js || $compiler == dart2dart) && $unchecked ]
+type_check_const_function_typedef2_test/00: MissingCompileTimeError, OK
+
 [ $compiler == dart2js && $runtime == none ]
 *: Fail, Pass # TODO(ahe): Triage these tests.
 
@@ -275,9 +279,6 @@
 super_getter_setter_test: Fail # Issue 11065.
 f_bounded_quantification4_test: Fail # Issue 12605.
 f_bounded_quantification5_test: Fail # Issue 12605.
-many_overridden_no_such_method_test: Pass, Fail # Issue 13078
-overridden_no_such_method_test: Pass, Fail # Issue 13078
-no_such_method_test: Pass, Fail # Issue 13078
 type_variable_typedef_test: Fail # Issue 11467
 type_variable_conflict2_test/01: RuntimeError # Issue 16180
 
diff --git a/tests/language/type_check_const_function_typedef2_test.dart b/tests/language/type_check_const_function_typedef2_test.dart
new file mode 100644
index 0000000..fa9609b
--- /dev/null
+++ b/tests/language/type_check_const_function_typedef2_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2014, 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 that typechecks on const objects with typedefs work.
+
+import "package:expect/expect.dart";
+
+typedef String Int2String(int x);
+
+class A {
+  final Int2String f;
+  const A(this.f);
+}
+
+int  /// 00: compile-time error
+foo(
+String  /// 00: continued
+x) => 499;
+
+const a = const A(foo);
+
+main() {
+  Expect.equals(499, a.f(499));
+}
diff --git a/tests/language/type_check_const_function_typedef_test.dart b/tests/language/type_check_const_function_typedef_test.dart
new file mode 100644
index 0000000..484c61a
--- /dev/null
+++ b/tests/language/type_check_const_function_typedef_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2014, 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 that typechecks on const objects with typedefs work.
+
+import "package:expect/expect.dart";
+
+typedef String Int2String(int x);
+
+class A {
+  final Int2String f;
+  const A(this.f);
+}
+
+String foo(int x) => "str";
+
+const a = const A(foo);
+
+main() {
+  Expect.equals("str", a.f(499));
+}
diff --git a/tests/language/vm/reusable_boxes_test.dart b/tests/language/vm/reusable_boxes_test.dart
new file mode 100644
index 0000000..a70cade
--- /dev/null
+++ b/tests/language/vm/reusable_boxes_test.dart
@@ -0,0 +1,92 @@
+// 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 correct handling reusable boxes.
+// VMOptions=--optimization_counter_threshold=100
+
+library reusable_boxes_test;
+
+import 'dart:typed_data';
+import 'package:expect/expect.dart';
+
+class D {
+  var a = 0.0;
+  var b = 1.0;
+  var c = 2.0;
+  test() {
+    a = 0.0;
+    b = 1.0;
+    c = a + b;
+    return c;
+  }
+
+  testParam(x, y) {
+    x = x * x;
+    y = y * y;
+    c = x + y;
+  }
+}
+
+testD() {
+  var f = new D();
+  var r = 0.0;
+  for (var i = 0; i < 20; i++) {
+    r += f.test();
+  }
+  Expect.equals(20.0, r);
+  // Trigger a deopt of test.
+  f.testParam(new Float32x4(1.0, 2.0, 3.0, 4.0), new Float32x4.zero());
+  r = 0.0;
+  for (var i = 0; i < 20; i++) {
+    r += f.test();
+  }
+  Expect.equals(20.0, r);
+}
+
+
+class F {
+  var a = new Float32x4.zero();
+  var b = new Float32x4(1.0, 2.0, 3.0, 4.0);
+  var c = new Float32x4.zero();
+  test() {
+    a = new Float32x4.zero();
+    b = new Float32x4(1.0, 2.0, 3.0, 4.0);
+    c = a + b;
+    return c;
+  }
+
+  testParam(x, y) {
+    x = x * x;
+    y = y * y;
+    c = x + y;
+  }
+
+}
+
+testF() {
+  var f = new F();
+  var r = new Float32x4.zero();
+  for (var i = 0; i < 20; i++) {
+    r += f.test();
+  }
+  Expect.equals(20.0, r.x);
+  Expect.equals(40.0, r.y);
+  Expect.equals(60.0, r.z);
+  Expect.equals(80.0, r.w);
+  // Trigger a deopt of test.
+  f.testParam(1.0, 2.0);
+  r = new Float32x4.zero();
+  for (var i = 0; i < 20; i++) {
+    r += f.test();
+  }
+  Expect.equals(20.0, r.x);
+  Expect.equals(40.0, r.y);
+  Expect.equals(60.0, r.z);
+  Expect.equals(80.0, r.w);
+}
+
+
+main() {
+  testD();
+  testF();
+}
diff --git a/tests/lib/analyzer/analyze_library.status b/tests/lib/analyzer/analyze_library.status
index e2ec9f3..3490ff7 100644
--- a/tests/lib/analyzer/analyze_library.status
+++ b/tests/lib/analyzer/analyze_library.status
@@ -30,7 +30,3 @@
 lib/_internal/compiler/samples/jsonify/jsonify: CompileTimeError # issue 16466
 lib/_internal/compiler/implementation/mirrors/analyze: CompileTimeError # issue 16466
 lib/_internal/compiler/implementation/mirrors/dart2js_mirrors: CompileTimeError # issue 16466
-
-# Pass necessary, since CompileTimeError is valid for everything in that
-# directory (not only for src/command.dart)
-lib/_internal/pub/lib/src/command: Pass, CompileTimeError
diff --git a/tests/lib/convert/json_toEncodable_reviver_test.dart b/tests/lib/convert/json_toEncodable_reviver_test.dart
new file mode 100644
index 0000000..5843887
--- /dev/null
+++ b/tests/lib/convert/json_toEncodable_reviver_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2014, 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 json_tests;
+import 'package:expect/expect.dart';
+import 'dart:convert';
+
+class A {
+  final x;
+  A(this.x);
+}
+
+toEncodable(A a) => { "A": a.x };
+reviver(key, value) {
+  if (value is Map && value.length == 1 && value["A"] != null) {
+    return new A(value["A"]);
+  }
+  return value;
+}
+
+const extendedJson =
+    const JsonCodec(toEncodable: toEncodable, reviver: reviver);
+
+main() {
+  var encoded = extendedJson.encode([new A(0), { "2": new A(1) }]);
+  Expect.equals('[{"A":0},{"2":{"A":1}}]', encoded);
+  var decoded = extendedJson.decode(encoded);
+  Expect.isTrue(decoded is List);
+  Expect.equals(2, decoded.length);
+  Expect.isTrue(decoded[0] is A);
+  Expect.equals(0, decoded[0].x);
+  Expect.isTrue(decoded[1] is Map);
+  Expect.isNotNull(decoded[1]["2"]);
+  Expect.isTrue(decoded[1]["2"] is A);
+  Expect.equals(1, decoded[1]["2"].x);
+
+  var a = extendedJson.decode(extendedJson.encode(new A(499)));
+  Expect.isTrue(a is A);
+  Expect.equals(499, a.x);
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 986be7e..a4feb07 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -13,9 +13,14 @@
 convert/streamed_conversion_json_utf8_encode_test: Skip # http://dartbug.com/15498
 convert/streamed_conversion_utf8_encode_test: Skip # http://dartbug.com/15498
 
+mirrors/mirrors_reader_test: Timeout, Slow, RuntimeError # Issue 16589
+
 [ $csp ]
 mirrors/delegate_test: RuntimeError # Issue 13864
 
+[ $compiler == dart2js && $checked && $runtime == drt && $nocsp ]
+async/stream_transform_test: RuntimeError # Issue 16719
+
 [ $compiler == dart2js ]
 async/schedule_microtask6_test: RuntimeError # global error handling is not supported. http://dartbug.com/5958
 
@@ -26,7 +31,6 @@
 mirrors/abstract_class_test: RuntimeError # Issue 12826
 mirrors/basic_types_in_dart_core_test: RuntimeError # Issue 14025
 mirrors/class_declarations_test/none: RuntimeError # Issue 13440
-mirrors/closures_test/none: RuntimeError # Issue 6490
 mirrors/constructor_kinds_test: RuntimeError # Issue 13799
 mirrors/constructor_private_name_test: CompileTimeError # Issue 13597
 mirrors/delegate_call_through_getter_test: RuntimeError # Issue 15138
@@ -79,6 +83,9 @@
 mirrors/proxy_type_test: RuntimeError # Issue 13842
 mirrors/redirecting_factory_test/none: RuntimeError # Issue 6490
 mirrors/redirecting_factory_test/02: RuntimeError # Issue 6490
+mirrors/relation_assignable_test: RuntimeError # Issue 6490
+mirrors/relation_subtype_test: RuntimeError # Issue 6490
+mirrors/relation_subclass_test: RuntimeError # Issue 6490
 mirrors/repeated_private_anon_mixin_app_test: RuntimeError # Issue 14670
 mirrors/symbol_validation_test: RuntimeError # Issue 13597
 mirrors/static_members_test: RuntimeError # Issue 14633, Issue 12164
@@ -183,11 +190,8 @@
 
 [ $runtime == ff ]
 # FF setTimeout can fire early: https://bugzilla.mozilla.org/show_bug.cgi?id=291386
-async/multiple_timer_test: Pass, Fail # Issue 14734
-async/timer_isolate_test: Pass, Fail # Issue 14734
-async/timer_test: Pass, Fail # Issue 14734
-convert/streamed_conversion_utf8_encode_test: Pass, Timeout  # Issue 12029
 convert/streamed_conversion_utf8_decode_test: Pass, Slow  # Issue 12029
+mirrors/mirrors_reader_test: Timeout, Slow, RuntimeError # Issue 16589
 
 [ $runtime == ie9 ]
 # IE9 doesn't support typed arrays.
@@ -197,7 +201,6 @@
 async/deferred/deferred_api_test: Pass, Timeout # http://dartbug.com/12635
 convert/streamed_conversion_utf8_decode_test: Pass, Timeout # http://dartbug.com/12768
 convert/utf85_test: Skip # Issue 12029.
-async/timer_isolate_test: Pass, Fail # Issue 14734
 convert/json_util_test: Fail # Issue 16109
 mirrors/mirrors_reader_test: Slow, RuntimeError # Issue 16589
 
@@ -229,18 +232,10 @@
 
 async/timer_not_available_test: SkipByDesign # only meant to test when there is no way to implement timer (currently only in d8)
 
-[ $compiler == none ]
-mirrors/mirrors_reader_test: Slow, Pass
-
-[ $compiler == none && $checked ]
-mirrors/mirrors_reader_test: Slow, RuntimeError # Issue 16588
-
-[ $compiler == none && $runtime == dartium ]
-mirrors/mirrors_reader_test: Slow, RuntimeError # Issue 16626
-
 [ $compiler == none && ( $runtime == drt || $runtime == dartium ) ]
 async/schedule_microtask6_test: Fail # Issue 10910
 mirrors/immutable_collections_test: Pass, Slow # Dartium debug uses -O0
+mirrors/mirrors_reader_test: Pass, Slow # Dartium debug uses -O0
 mirrors/library_uri_io_test: Skip # Not intended for drt as it uses dart:io.
 mirrors/local_isolate_test: Skip # http://dartbug.com/12188
 
diff --git a/tests/lib/mirrors/relation_assignable_test.dart b/tests/lib/mirrors/relation_assignable_test.dart
new file mode 100644
index 0000000..970aedf
--- /dev/null
+++ b/tests/lib/mirrors/relation_assignable_test.dart
@@ -0,0 +1,319 @@
+// Copyright (c) 2014, 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 test.relation_assignable;
+
+import "dart:mirrors";
+
+import "package:expect/expect.dart";
+
+class Superclass {}
+class Subclass1 extends Superclass {}
+class Subclass2 extends Superclass {}
+
+typedef bool NumberPredicate(num x);
+typedef bool IntegerPredicate(int x);
+typedef bool DoublePredicate(double x);
+
+typedef num NumberGenerator();
+typedef int IntegerGenerator();
+typedef double DoubleGenerator();
+
+class A<T> {}
+class B<T> extends A<T> {}
+class C<T extends num> {}
+
+test(MirrorSystem mirrors) {
+  LibraryMirror coreLibrary = mirrors.findLibrary(#dart.core);
+  LibraryMirror thisLibrary = mirrors.findLibrary(#test.relation_assignable);
+
+  // Classes.
+  TypeMirror Super = thisLibrary.declarations[#Superclass];
+  TypeMirror Sub1 = thisLibrary.declarations[#Subclass1];
+  TypeMirror Sub2 = thisLibrary.declarations[#Subclass2];
+  TypeMirror Obj = coreLibrary.declarations[#Object];
+
+  Expect.isTrue(Obj.isAssignableTo(Obj));
+  Expect.isTrue(Super.isAssignableTo(Super));
+  Expect.isTrue(Sub1.isAssignableTo(Sub1));
+  Expect.isTrue(Sub2.isAssignableTo(Sub2));
+
+  Expect.isTrue(Sub1.isAssignableTo(Super));
+  Expect.isTrue(Super.isAssignableTo(Sub1));
+
+  Expect.isTrue(Sub2.isAssignableTo(Super));
+  Expect.isTrue(Super.isAssignableTo(Sub2));
+
+  Expect.isFalse(Sub2.isAssignableTo(Sub1));
+  Expect.isFalse(Sub1.isAssignableTo(Sub2));
+
+  Expect.isTrue(Sub1.isAssignableTo(Obj));
+  Expect.isTrue(Obj.isAssignableTo(Sub1));
+
+  Expect.isTrue(Sub2.isAssignableTo(Obj));
+  Expect.isTrue(Obj.isAssignableTo(Sub2));
+
+  Expect.isTrue(Super.isAssignableTo(Obj));
+  Expect.isTrue(Obj.isAssignableTo(Super));
+
+
+  // Function typedef - argument type.
+  TypeMirror Func = coreLibrary.declarations[#Function];
+  TypedefMirror NumPred = thisLibrary.declarations[#NumberPredicate];
+  TypedefMirror IntPred = thisLibrary.declarations[#IntegerPredicate];
+  TypedefMirror DubPred = thisLibrary.declarations[#DoublePredicate];
+
+  Expect.isTrue(Func.isAssignableTo(Func));
+  Expect.isTrue(NumPred.isAssignableTo(NumPred));
+  Expect.isTrue(IntPred.isAssignableTo(IntPred));
+  Expect.isTrue(DubPred.isAssignableTo(DubPred));
+
+  Expect.isTrue(NumPred.isAssignableTo(Func));
+  Expect.isTrue(NumPred.isAssignableTo(IntPred));
+  Expect.isTrue(NumPred.isAssignableTo(DubPred));
+
+  Expect.isTrue(IntPred.isAssignableTo(Func));
+  Expect.isTrue(IntPred.isAssignableTo(NumPred));
+  Expect.isFalse(IntPred.isAssignableTo(DubPred));
+
+  Expect.isTrue(DubPred.isAssignableTo(Func));
+  Expect.isTrue(DubPred.isAssignableTo(NumPred));
+  Expect.isFalse(DubPred.isAssignableTo(IntPred));
+
+  Expect.isTrue(Func.isAssignableTo(Obj));
+  Expect.isTrue(NumPred.isAssignableTo(Obj));
+  Expect.isTrue(IntPred.isAssignableTo(Obj));
+  Expect.isTrue(DubPred.isAssignableTo(Obj));
+  Expect.isTrue(Obj.isAssignableTo(Func));
+  Expect.isTrue(Obj.isAssignableTo(NumPred));
+  Expect.isTrue(Obj.isAssignableTo(IntPred));
+  Expect.isTrue(Obj.isAssignableTo(DubPred));
+
+
+  // Function typedef - return type.
+  TypedefMirror NumGen = thisLibrary.declarations[#NumberGenerator];
+  TypedefMirror IntGen = thisLibrary.declarations[#IntegerGenerator];
+  TypedefMirror DubGen = thisLibrary.declarations[#DoubleGenerator];
+
+  Expect.isTrue(NumGen.isAssignableTo(NumGen));
+  Expect.isTrue(IntGen.isAssignableTo(IntGen));
+  Expect.isTrue(DubGen.isAssignableTo(DubGen));
+
+  Expect.isTrue(NumGen.isAssignableTo(Func));
+  Expect.isTrue(NumGen.isAssignableTo(IntGen));
+  Expect.isTrue(NumGen.isAssignableTo(DubGen));
+
+  Expect.isTrue(IntGen.isAssignableTo(Func));
+  Expect.isTrue(IntGen.isAssignableTo(NumGen));
+  Expect.isFalse(IntGen.isAssignableTo(DubGen));
+
+  Expect.isTrue(DubGen.isAssignableTo(Func));
+  Expect.isTrue(DubGen.isAssignableTo(NumGen));
+  Expect.isFalse(DubGen.isAssignableTo(IntGen));
+
+  Expect.isTrue(Func.isAssignableTo(Obj));
+  Expect.isTrue(NumGen.isAssignableTo(Obj));
+  Expect.isTrue(IntGen.isAssignableTo(Obj));
+  Expect.isTrue(DubGen.isAssignableTo(Obj));
+  Expect.isTrue(Obj.isAssignableTo(Func));
+  Expect.isTrue(Obj.isAssignableTo(NumGen));
+  Expect.isTrue(Obj.isAssignableTo(IntGen));
+  Expect.isTrue(Obj.isAssignableTo(DubGen));
+
+  
+  // Function - argument type.
+  TypeMirror NumPredRef = NumPred.referent;
+  TypeMirror IntPredRef = IntPred.referent;
+  TypeMirror DubPredRef = DubPred.referent;
+
+  Expect.isTrue(Func.isAssignableTo(Func));
+  Expect.isTrue(NumPredRef.isAssignableTo(NumPredRef));
+  Expect.isTrue(IntPredRef.isAssignableTo(IntPredRef));
+  Expect.isTrue(DubPredRef.isAssignableTo(DubPredRef));
+
+  Expect.isTrue(NumPredRef.isAssignableTo(Func));
+  Expect.isTrue(NumPredRef.isAssignableTo(IntPredRef));
+  Expect.isTrue(NumPredRef.isAssignableTo(DubPredRef));
+
+  Expect.isTrue(IntPredRef.isAssignableTo(Func));
+  Expect.isTrue(IntPredRef.isAssignableTo(NumPredRef));
+  Expect.isFalse(IntPredRef.isAssignableTo(DubPredRef));
+
+  Expect.isTrue(DubPredRef.isAssignableTo(Func));
+  Expect.isTrue(DubPredRef.isAssignableTo(NumPredRef));
+  Expect.isFalse(DubPredRef.isAssignableTo(IntPredRef));
+
+  Expect.isTrue(Func.isAssignableTo(Obj));
+  Expect.isTrue(NumPredRef.isAssignableTo(Obj));
+  Expect.isTrue(IntPredRef.isAssignableTo(Obj));
+  Expect.isTrue(DubPredRef.isAssignableTo(Obj));
+  Expect.isTrue(Obj.isAssignableTo(Func));
+  Expect.isTrue(Obj.isAssignableTo(NumPredRef));
+  Expect.isTrue(Obj.isAssignableTo(IntPredRef));
+  Expect.isTrue(Obj.isAssignableTo(DubPredRef));
+
+
+  // Function - return type.
+  TypeMirror NumGenRef = NumGen.referent;
+  TypeMirror IntGenRef = IntGen.referent;
+  TypeMirror DubGenRef = DubGen.referent;
+
+  Expect.isTrue(NumGenRef.isAssignableTo(NumGenRef));
+  Expect.isTrue(IntGenRef.isAssignableTo(IntGenRef));
+  Expect.isTrue(DubGenRef.isAssignableTo(DubGenRef));
+
+  Expect.isTrue(NumGenRef.isAssignableTo(Func));
+  Expect.isTrue(NumGenRef.isAssignableTo(IntGenRef));
+  Expect.isTrue(NumGenRef.isAssignableTo(DubGenRef));
+
+  Expect.isTrue(IntGenRef.isAssignableTo(Func));
+  Expect.isTrue(IntGenRef.isAssignableTo(NumGenRef));
+  Expect.isFalse(IntGenRef.isAssignableTo(DubGenRef));
+
+  Expect.isTrue(DubGenRef.isAssignableTo(Func));
+  Expect.isTrue(DubGenRef.isAssignableTo(NumGenRef));
+  Expect.isFalse(DubGenRef.isAssignableTo(IntGenRef));
+
+  Expect.isTrue(Func.isAssignableTo(Obj));
+  Expect.isTrue(NumGenRef.isAssignableTo(Obj));
+  Expect.isTrue(IntGenRef.isAssignableTo(Obj));
+  Expect.isTrue(DubGenRef.isAssignableTo(Obj));
+  Expect.isTrue(Obj.isAssignableTo(Func));
+  Expect.isTrue(Obj.isAssignableTo(NumGenRef));
+  Expect.isTrue(Obj.isAssignableTo(IntGenRef));
+  Expect.isTrue(Obj.isAssignableTo(DubGenRef));
+
+
+  // Function typedef / function.
+  Expect.isTrue(NumPred.isAssignableTo(NumPredRef));
+  Expect.isTrue(IntPred.isAssignableTo(IntPredRef));
+  Expect.isTrue(DubPred.isAssignableTo(DubPredRef));
+  Expect.isTrue(NumPredRef.isAssignableTo(NumPred));
+  Expect.isTrue(IntPredRef.isAssignableTo(IntPred));
+  Expect.isTrue(DubPredRef.isAssignableTo(DubPred));
+
+
+  // Function typedef / function.
+  Expect.isTrue(NumGen.isAssignableTo(NumGenRef));
+  Expect.isTrue(IntGen.isAssignableTo(IntGenRef));
+  Expect.isTrue(DubGen.isAssignableTo(DubGenRef));
+  Expect.isTrue(NumGenRef.isAssignableTo(NumGen));
+  Expect.isTrue(IntGenRef.isAssignableTo(IntGen));
+  Expect.isTrue(DubGenRef.isAssignableTo(DubGen));
+
+
+  // Type variable.
+  TypeMirror TFromA =
+      (thisLibrary.declarations[#A] as ClassMirror).typeVariables.single;
+  TypeMirror TFromB =
+      (thisLibrary.declarations[#B] as ClassMirror).typeVariables.single;
+  TypeMirror TFromC =
+      (thisLibrary.declarations[#C] as ClassMirror).typeVariables.single;
+
+  Expect.isTrue(TFromA.isAssignableTo(TFromA));
+  Expect.isTrue(TFromB.isAssignableTo(TFromB));
+  Expect.isTrue(TFromC.isAssignableTo(TFromC));
+
+  Expect.isFalse(TFromA.isAssignableTo(TFromB));
+  Expect.isFalse(TFromA.isAssignableTo(TFromC));
+  Expect.isFalse(TFromB.isAssignableTo(TFromA));
+  Expect.isFalse(TFromB.isAssignableTo(TFromC));
+  Expect.isFalse(TFromC.isAssignableTo(TFromA));
+  Expect.isFalse(TFromC.isAssignableTo(TFromB));
+  
+  TypeMirror Num = coreLibrary.declarations[#num];
+  Expect.isTrue(TFromC.isAssignableTo(Num));
+  Expect.isTrue(Num.isAssignableTo(TFromC));
+
+
+  // dynamic & void.
+  TypeMirror Dynamic = mirrors.dynamicType;
+  Expect.isTrue(Dynamic.isAssignableTo(Dynamic));
+  Expect.isTrue(Obj.isAssignableTo(Dynamic));
+  Expect.isTrue(Super.isAssignableTo(Dynamic));
+  Expect.isTrue(Sub1.isAssignableTo(Dynamic));
+  Expect.isTrue(Sub2.isAssignableTo(Dynamic));
+  Expect.isTrue(NumPred.isAssignableTo(Dynamic));
+  Expect.isTrue(IntPred.isAssignableTo(Dynamic));
+  Expect.isTrue(DubPred.isAssignableTo(Dynamic));
+  Expect.isTrue(NumPredRef.isAssignableTo(Dynamic));
+  Expect.isTrue(IntPredRef.isAssignableTo(Dynamic));
+  Expect.isTrue(DubPredRef.isAssignableTo(Dynamic));
+  Expect.isTrue(NumGen.isAssignableTo(Dynamic));
+  Expect.isTrue(IntGen.isAssignableTo(Dynamic));
+  Expect.isTrue(DubGen.isAssignableTo(Dynamic));
+  Expect.isTrue(NumGenRef.isAssignableTo(Dynamic));
+  Expect.isTrue(IntGenRef.isAssignableTo(Dynamic));
+  Expect.isTrue(DubGenRef.isAssignableTo(Dynamic));
+  Expect.isTrue(TFromA.isAssignableTo(Dynamic));
+  Expect.isTrue(TFromB.isAssignableTo(Dynamic));
+  Expect.isTrue(TFromC.isAssignableTo(Dynamic));
+  Expect.isTrue(Dynamic.isAssignableTo(Obj));
+  Expect.isTrue(Dynamic.isAssignableTo(Super));
+  Expect.isTrue(Dynamic.isAssignableTo(Sub1));
+  Expect.isTrue(Dynamic.isAssignableTo(Sub2));
+  Expect.isTrue(Dynamic.isAssignableTo(NumPred));
+  Expect.isTrue(Dynamic.isAssignableTo(IntPred));
+  Expect.isTrue(Dynamic.isAssignableTo(DubPred));
+  Expect.isTrue(Dynamic.isAssignableTo(NumPredRef));
+  Expect.isTrue(Dynamic.isAssignableTo(IntPredRef));
+  Expect.isTrue(Dynamic.isAssignableTo(DubPredRef));
+  Expect.isTrue(Dynamic.isAssignableTo(NumGen));
+  Expect.isTrue(Dynamic.isAssignableTo(IntGen));
+  Expect.isTrue(Dynamic.isAssignableTo(DubGen));
+  Expect.isTrue(Dynamic.isAssignableTo(NumGenRef));
+  Expect.isTrue(Dynamic.isAssignableTo(IntGenRef));
+  Expect.isTrue(Dynamic.isAssignableTo(DubGenRef));
+  Expect.isTrue(Dynamic.isAssignableTo(TFromA));
+  Expect.isTrue(Dynamic.isAssignableTo(TFromB));
+  Expect.isTrue(Dynamic.isAssignableTo(TFromC));
+
+  TypeMirror Void = mirrors.voidType;
+  Expect.isTrue(Void.isAssignableTo(Void));
+  Expect.isFalse(Obj.isAssignableTo(Void));
+  Expect.isFalse(Super.isAssignableTo(Void));
+  Expect.isFalse(Sub1.isAssignableTo(Void));
+  Expect.isFalse(Sub2.isAssignableTo(Void));
+  Expect.isFalse(NumPred.isAssignableTo(Void));
+  Expect.isFalse(IntPred.isAssignableTo(Void));
+  Expect.isFalse(DubPred.isAssignableTo(Void));
+  Expect.isFalse(NumPredRef.isAssignableTo(Void));
+  Expect.isFalse(IntPredRef.isAssignableTo(Void));
+  Expect.isFalse(DubPredRef.isAssignableTo(Void));
+  Expect.isFalse(NumGen.isAssignableTo(Void));
+  Expect.isFalse(IntGen.isAssignableTo(Void));
+  Expect.isFalse(DubGen.isAssignableTo(Void));
+  Expect.isFalse(NumGenRef.isAssignableTo(Void));
+  Expect.isFalse(IntGenRef.isAssignableTo(Void));
+  Expect.isFalse(DubGenRef.isAssignableTo(Void));
+  Expect.isFalse(TFromA.isAssignableTo(Void));
+  Expect.isFalse(TFromB.isAssignableTo(Void));
+  Expect.isFalse(TFromC.isAssignableTo(Void));
+  Expect.isFalse(Void.isAssignableTo(Obj));
+  Expect.isFalse(Void.isAssignableTo(Super));
+  Expect.isFalse(Void.isAssignableTo(Sub1));
+  Expect.isFalse(Void.isAssignableTo(Sub2));
+  Expect.isFalse(Void.isAssignableTo(NumPred));
+  Expect.isFalse(Void.isAssignableTo(IntPred));
+  Expect.isFalse(Void.isAssignableTo(DubPred));
+  Expect.isFalse(Void.isAssignableTo(NumPredRef));
+  Expect.isFalse(Void.isAssignableTo(IntPredRef));
+  Expect.isFalse(Void.isAssignableTo(DubPredRef));
+  Expect.isFalse(Void.isAssignableTo(NumGen));
+  Expect.isFalse(Void.isAssignableTo(IntGen));
+  Expect.isFalse(Void.isAssignableTo(DubGen));
+  Expect.isFalse(Void.isAssignableTo(NumGenRef));
+  Expect.isFalse(Void.isAssignableTo(IntGenRef));
+  Expect.isFalse(Void.isAssignableTo(DubGenRef));
+  Expect.isFalse(Void.isAssignableTo(TFromA));
+  Expect.isFalse(Void.isAssignableTo(TFromB));
+  Expect.isFalse(Void.isAssignableTo(TFromC));
+
+  Expect.isTrue(Dynamic.isAssignableTo(Void));
+  Expect.isTrue(Void.isAssignableTo(Dynamic));
+}
+
+main() {
+  test(currentMirrorSystem());
+}
diff --git a/tests/lib/mirrors/relation_subclass_test.dart b/tests/lib/mirrors/relation_subclass_test.dart
new file mode 100644
index 0000000..2e8bbc2
--- /dev/null
+++ b/tests/lib/mirrors/relation_subclass_test.dart
@@ -0,0 +1,110 @@
+// Copyright (c) 2014, 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 test.relation_subclass;
+
+import "dart:mirrors";
+
+import "package:expect/expect.dart";
+
+class Superclass {}
+class Subclass1 extends Superclass {}
+class Subclass2 extends Superclass {}
+
+typedef bool NumberPredicate(num x);
+typedef bool IntegerPredicate(int x);
+typedef bool DoublePredicate(double x);
+
+typedef num NumberGenerator();
+typedef int IntegerGenerator();
+typedef double DoubleGenerator();
+
+test(MirrorSystem mirrors) {
+  LibraryMirror coreLibrary = mirrors.findLibrary(#dart.core);
+  LibraryMirror thisLibrary = mirrors.findLibrary(#test.relation_subclass);
+
+  ClassMirror Super = thisLibrary.declarations[#Superclass];
+  ClassMirror Sub1 = thisLibrary.declarations[#Subclass1];
+  ClassMirror Sub2 = thisLibrary.declarations[#Subclass2];
+  ClassMirror Obj = coreLibrary.declarations[#Object];
+
+  Expect.isTrue(Obj.isSubclassOf(Obj));
+  Expect.isTrue(Super.isSubclassOf(Super));
+  Expect.isTrue(Sub1.isSubclassOf(Sub1));
+  Expect.isTrue(Sub2.isSubclassOf(Sub2));
+
+  Expect.isTrue(Sub1.isSubclassOf(Super));
+  Expect.isFalse(Super.isSubclassOf(Sub1));
+
+  Expect.isTrue(Sub2.isSubclassOf(Super));
+  Expect.isFalse(Super.isSubclassOf(Sub2));
+
+  Expect.isFalse(Sub2.isSubclassOf(Sub1));
+  Expect.isFalse(Sub1.isSubclassOf(Sub2));
+
+  Expect.isTrue(Sub1.isSubclassOf(Obj));
+  Expect.isFalse(Obj.isSubclassOf(Sub1));
+
+  Expect.isTrue(Sub2.isSubclassOf(Obj));
+  Expect.isFalse(Obj.isSubclassOf(Sub2));
+
+  Expect.isTrue(Super.isSubclassOf(Obj));
+  Expect.isFalse(Obj.isSubclassOf(Super));
+
+  var Func = coreLibrary.declarations[#Function];
+  Expect.isTrue(Func.isSubclassOf(Obj));
+  Expect.isFalse(Obj.isSubclassOf(Func));
+
+  // Function typedef.
+  var NumPred = thisLibrary.declarations[#NumberPredicate];
+  var IntPred = thisLibrary.declarations[#IntegerPredicate];
+  var DubPred = thisLibrary.declarations[#DoublePredicate];
+  var NumGen = thisLibrary.declarations[#NumberGenerator];
+  var IntGen = thisLibrary.declarations[#IntegerGenerator];
+  var DubGen = thisLibrary.declarations[#DoubleGenerator];
+
+  isArgumentOrTypeError(e) => e is ArgumentError || e is TypeError;
+  Expect.throws(() => Func.isSubclassOf(NumPred), isArgumentOrTypeError);
+  Expect.throws(() => Func.isSubclassOf(IntPred), isArgumentOrTypeError);
+  Expect.throws(() => Func.isSubclassOf(DubPred), isArgumentOrTypeError);
+  Expect.throws(() => Func.isSubclassOf(NumGen), isArgumentOrTypeError);
+  Expect.throws(() => Func.isSubclassOf(IntGen), isArgumentOrTypeError);
+  Expect.throws(() => Func.isSubclassOf(DubGen), isArgumentOrTypeError);
+
+  isNoSuchMethodError(e) => e is NoSuchMethodError;
+  Expect.throws(() => NumPred.isSubclassOf(Func), isNoSuchMethodError);
+  Expect.throws(() => IntPred.isSubclassOf(Func), isNoSuchMethodError);
+  Expect.throws(() => DubPred.isSubclassOf(Func), isNoSuchMethodError);
+  Expect.throws(() => NumGen.isSubclassOf(Func), isNoSuchMethodError);
+  Expect.throws(() => IntGen.isSubclassOf(Func), isNoSuchMethodError);
+  Expect.throws(() => DubGen.isSubclassOf(Func), isNoSuchMethodError);
+
+  // Function type.
+  TypeMirror NumPredRef = (NumPred as TypedefMirror).referent;
+  TypeMirror IntPredRef = (IntPred as TypedefMirror).referent;
+  TypeMirror DubPredRef = (DubPred as TypedefMirror).referent;
+  TypeMirror NumGenRef = (NumGen as TypedefMirror).referent;
+  TypeMirror IntGenRef = (IntGen as TypedefMirror).referent;
+  TypeMirror DubGenRef = (DubGen as TypedefMirror).referent;
+
+  Expect.isFalse(Func.isSubclassOf(NumPredRef));
+  Expect.isFalse(Func.isSubclassOf(IntPredRef));
+  Expect.isFalse(Func.isSubclassOf(DubPredRef));
+  Expect.isFalse(Func.isSubclassOf(NumGenRef));
+  Expect.isFalse(Func.isSubclassOf(IntGenRef));
+  Expect.isFalse(Func.isSubclassOf(DubGenRef));
+
+  // The spec doesn't require these to be either value, only that they implement
+  // Function.
+  // NumPredRef.isSubclassOf(Func);
+  // IntPredRef.isSubclassOf(Func);
+  // DubPredRef.isSubclassOf(Func);
+  // NumGenRef.isSubclassOf(Func);
+  // IntGenRef.isSubclassOf(Func);
+  // DubGenRef.isSubclassOf(Func);
+}
+
+main() {
+  test(currentMirrorSystem());
+}
diff --git a/tests/lib/mirrors/relation_subtype_test.dart b/tests/lib/mirrors/relation_subtype_test.dart
new file mode 100644
index 0000000..9504c8c
--- /dev/null
+++ b/tests/lib/mirrors/relation_subtype_test.dart
@@ -0,0 +1,303 @@
+// Copyright (c) 2014, 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 test.relation_subtype;
+
+import "dart:mirrors";
+
+import "package:expect/expect.dart";
+
+class Superclass {}
+class Subclass1 extends Superclass {}
+class Subclass2 extends Superclass {}
+
+typedef bool NumberPredicate(num x);
+typedef bool IntegerPredicate(int x);
+typedef bool DoublePredicate(double x);
+
+typedef num NumberGenerator();
+typedef int IntegerGenerator();
+typedef double DoubleGenerator();
+
+class A<T> {}
+class B<T> extends A<T> {}
+class C<T extends num> {}
+
+test(MirrorSystem mirrors) {
+  LibraryMirror coreLibrary = mirrors.findLibrary(#dart.core);
+  LibraryMirror thisLibrary = mirrors.findLibrary(#test.relation_subtype);
+
+  // Classes.
+  TypeMirror Super = thisLibrary.declarations[#Superclass];
+  TypeMirror Sub1 = thisLibrary.declarations[#Subclass1];
+  TypeMirror Sub2 = thisLibrary.declarations[#Subclass2];
+  TypeMirror Obj = coreLibrary.declarations[#Object];
+
+  Expect.isTrue(Obj.isSubtypeOf(Obj));
+  Expect.isTrue(Super.isSubtypeOf(Super));
+  Expect.isTrue(Sub1.isSubtypeOf(Sub1));
+  Expect.isTrue(Sub2.isSubtypeOf(Sub2));
+
+  Expect.isTrue(Sub1.isSubtypeOf(Super));
+  Expect.isFalse(Super.isSubtypeOf(Sub1));
+
+  Expect.isTrue(Sub2.isSubtypeOf(Super));
+  Expect.isFalse(Super.isSubtypeOf(Sub2));
+
+  Expect.isFalse(Sub2.isSubtypeOf(Sub1));
+  Expect.isFalse(Sub1.isSubtypeOf(Sub2));
+
+  Expect.isTrue(Sub1.isSubtypeOf(Obj));
+  Expect.isFalse(Obj.isSubtypeOf(Sub1));
+
+  Expect.isTrue(Sub2.isSubtypeOf(Obj));
+  Expect.isFalse(Obj.isSubtypeOf(Sub2));
+
+  Expect.isTrue(Super.isSubtypeOf(Obj));
+  Expect.isFalse(Obj.isSubtypeOf(Super));
+
+
+  // Function typedef - argument type.
+  TypeMirror Func = coreLibrary.declarations[#Function];
+  TypedefMirror NumPred = thisLibrary.declarations[#NumberPredicate];
+  TypedefMirror IntPred = thisLibrary.declarations[#IntegerPredicate];
+  TypedefMirror DubPred = thisLibrary.declarations[#DoublePredicate];
+
+  Expect.isTrue(Func.isSubtypeOf(Func));
+  Expect.isTrue(NumPred.isSubtypeOf(NumPred));
+  Expect.isTrue(IntPred.isSubtypeOf(IntPred));
+  Expect.isTrue(DubPred.isSubtypeOf(DubPred));
+
+  Expect.isTrue(NumPred.isSubtypeOf(Func));
+  Expect.isTrue(NumPred.isSubtypeOf(IntPred));
+  Expect.isTrue(NumPred.isSubtypeOf(DubPred));
+
+  Expect.isTrue(IntPred.isSubtypeOf(Func));
+  Expect.isTrue(IntPred.isSubtypeOf(NumPred));
+  Expect.isFalse(IntPred.isSubtypeOf(DubPred));
+
+  Expect.isTrue(DubPred.isSubtypeOf(Func));
+  Expect.isTrue(DubPred.isSubtypeOf(NumPred));
+  Expect.isFalse(DubPred.isSubtypeOf(IntPred));
+
+  Expect.isTrue(Func.isSubtypeOf(Obj));
+  Expect.isTrue(NumPred.isSubtypeOf(Obj));
+  Expect.isTrue(IntPred.isSubtypeOf(Obj));
+  Expect.isTrue(DubPred.isSubtypeOf(Obj));
+
+
+  // Function typedef - return type.
+  TypedefMirror NumGen = thisLibrary.declarations[#NumberGenerator];
+  TypedefMirror IntGen = thisLibrary.declarations[#IntegerGenerator];
+  TypedefMirror DubGen = thisLibrary.declarations[#DoubleGenerator];
+
+  Expect.isTrue(NumGen.isSubtypeOf(NumGen));
+  Expect.isTrue(IntGen.isSubtypeOf(IntGen));
+  Expect.isTrue(DubGen.isSubtypeOf(DubGen));
+
+  Expect.isTrue(NumGen.isSubtypeOf(Func));
+  Expect.isTrue(NumGen.isSubtypeOf(IntGen));
+  Expect.isTrue(NumGen.isSubtypeOf(DubGen));
+
+  Expect.isTrue(IntGen.isSubtypeOf(Func));
+  Expect.isTrue(IntGen.isSubtypeOf(NumGen));
+  Expect.isFalse(IntGen.isSubtypeOf(DubGen));
+
+  Expect.isTrue(DubGen.isSubtypeOf(Func));
+  Expect.isTrue(DubGen.isSubtypeOf(NumGen));
+  Expect.isFalse(DubGen.isSubtypeOf(IntGen));
+
+  Expect.isTrue(Func.isSubtypeOf(Obj));
+  Expect.isTrue(NumGen.isSubtypeOf(Obj));
+  Expect.isTrue(IntGen.isSubtypeOf(Obj));
+  Expect.isTrue(DubGen.isSubtypeOf(Obj));
+
+  
+  // Function - argument type.
+  TypeMirror NumPredRef = NumPred.referent;
+  TypeMirror IntPredRef = IntPred.referent;
+  TypeMirror DubPredRef = DubPred.referent;
+
+  Expect.isTrue(Func.isSubtypeOf(Func));
+  Expect.isTrue(NumPredRef.isSubtypeOf(NumPredRef));
+  Expect.isTrue(IntPredRef.isSubtypeOf(IntPredRef));
+  Expect.isTrue(DubPredRef.isSubtypeOf(DubPredRef));
+
+  Expect.isTrue(NumPredRef.isSubtypeOf(Func));
+  Expect.isTrue(NumPredRef.isSubtypeOf(IntPredRef));
+  Expect.isTrue(NumPredRef.isSubtypeOf(DubPredRef));
+
+  Expect.isTrue(IntPredRef.isSubtypeOf(Func));
+  Expect.isTrue(IntPredRef.isSubtypeOf(NumPredRef));
+  Expect.isFalse(IntPredRef.isSubtypeOf(DubPredRef));
+
+  Expect.isTrue(DubPredRef.isSubtypeOf(Func));
+  Expect.isTrue(DubPredRef.isSubtypeOf(NumPredRef));
+  Expect.isFalse(DubPredRef.isSubtypeOf(IntPredRef));
+
+  Expect.isTrue(Func.isSubtypeOf(Obj));
+  Expect.isTrue(NumPredRef.isSubtypeOf(Obj));
+  Expect.isTrue(IntPredRef.isSubtypeOf(Obj));
+  Expect.isTrue(DubPredRef.isSubtypeOf(Obj));
+
+
+  // Function - return type.
+  TypeMirror NumGenRef = NumGen.referent;
+  TypeMirror IntGenRef = IntGen.referent;
+  TypeMirror DubGenRef = DubGen.referent;
+
+  Expect.isTrue(NumGenRef.isSubtypeOf(NumGenRef));
+  Expect.isTrue(IntGenRef.isSubtypeOf(IntGenRef));
+  Expect.isTrue(DubGenRef.isSubtypeOf(DubGenRef));
+
+  Expect.isTrue(NumGenRef.isSubtypeOf(Func));
+  Expect.isTrue(NumGenRef.isSubtypeOf(IntGenRef));
+  Expect.isTrue(NumGenRef.isSubtypeOf(DubGenRef));
+
+  Expect.isTrue(IntGenRef.isSubtypeOf(Func));
+  Expect.isTrue(IntGenRef.isSubtypeOf(NumGenRef));
+  Expect.isFalse(IntGenRef.isSubtypeOf(DubGenRef));
+
+  Expect.isTrue(DubGenRef.isSubtypeOf(Func));
+  Expect.isTrue(DubGenRef.isSubtypeOf(NumGenRef));
+  Expect.isFalse(DubGenRef.isSubtypeOf(IntGenRef));
+
+  Expect.isTrue(Func.isSubtypeOf(Obj));
+  Expect.isTrue(NumGenRef.isSubtypeOf(Obj));
+  Expect.isTrue(IntGenRef.isSubtypeOf(Obj));
+  Expect.isTrue(DubGenRef.isSubtypeOf(Obj));
+
+
+  // Function typedef / function.
+  Expect.isTrue(NumPred.isSubtypeOf(NumPredRef));
+  Expect.isTrue(IntPred.isSubtypeOf(IntPredRef));
+  Expect.isTrue(DubPred.isSubtypeOf(DubPredRef));
+  Expect.isTrue(NumPredRef.isSubtypeOf(NumPred));
+  Expect.isTrue(IntPredRef.isSubtypeOf(IntPred));
+  Expect.isTrue(DubPredRef.isSubtypeOf(DubPred));
+
+
+  // Function typedef / function.
+  Expect.isTrue(NumGen.isSubtypeOf(NumGenRef));
+  Expect.isTrue(IntGen.isSubtypeOf(IntGenRef));
+  Expect.isTrue(DubGen.isSubtypeOf(DubGenRef));
+  Expect.isTrue(NumGenRef.isSubtypeOf(NumGen));
+  Expect.isTrue(IntGenRef.isSubtypeOf(IntGen));
+  Expect.isTrue(DubGenRef.isSubtypeOf(DubGen));
+
+
+  // Type variable.
+  TypeMirror TFromA =
+      (thisLibrary.declarations[#A] as ClassMirror).typeVariables.single;
+  TypeMirror TFromB =
+      (thisLibrary.declarations[#B] as ClassMirror).typeVariables.single;
+  TypeMirror TFromC =
+      (thisLibrary.declarations[#C] as ClassMirror).typeVariables.single;
+
+  Expect.isTrue(TFromA.isSubtypeOf(TFromA));
+  Expect.isTrue(TFromB.isSubtypeOf(TFromB));
+  Expect.isTrue(TFromC.isSubtypeOf(TFromC));
+
+  Expect.isFalse(TFromA.isSubtypeOf(TFromB));
+  Expect.isFalse(TFromA.isSubtypeOf(TFromC));
+  Expect.isFalse(TFromB.isSubtypeOf(TFromA));
+  Expect.isFalse(TFromB.isSubtypeOf(TFromC));
+  Expect.isFalse(TFromC.isSubtypeOf(TFromA));
+  Expect.isFalse(TFromC.isSubtypeOf(TFromB));
+  
+  TypeMirror Num = coreLibrary.declarations[#num];
+  Expect.isTrue(TFromC.isSubtypeOf(Num));
+  Expect.isFalse(Num.isSubtypeOf(TFromC));
+
+
+  // dynamic & void.
+  TypeMirror Dynamic = mirrors.dynamicType;
+  Expect.isTrue(Dynamic.isSubtypeOf(Dynamic));
+  Expect.isTrue(Obj.isSubtypeOf(Dynamic));
+  Expect.isTrue(Super.isSubtypeOf(Dynamic));
+  Expect.isTrue(Sub1.isSubtypeOf(Dynamic));
+  Expect.isTrue(Sub2.isSubtypeOf(Dynamic));
+  Expect.isTrue(NumPred.isSubtypeOf(Dynamic));
+  Expect.isTrue(IntPred.isSubtypeOf(Dynamic));
+  Expect.isTrue(DubPred.isSubtypeOf(Dynamic));
+  Expect.isTrue(NumPredRef.isSubtypeOf(Dynamic));
+  Expect.isTrue(IntPredRef.isSubtypeOf(Dynamic));
+  Expect.isTrue(DubPredRef.isSubtypeOf(Dynamic));
+  Expect.isTrue(NumGen.isSubtypeOf(Dynamic));
+  Expect.isTrue(IntGen.isSubtypeOf(Dynamic));
+  Expect.isTrue(DubGen.isSubtypeOf(Dynamic));
+  Expect.isTrue(NumGenRef.isSubtypeOf(Dynamic));
+  Expect.isTrue(IntGenRef.isSubtypeOf(Dynamic));
+  Expect.isTrue(DubGenRef.isSubtypeOf(Dynamic));
+  Expect.isTrue(TFromA.isSubtypeOf(Dynamic));
+  Expect.isTrue(TFromB.isSubtypeOf(Dynamic));
+  Expect.isTrue(TFromC.isSubtypeOf(Dynamic));
+  Expect.isTrue(Dynamic.isSubtypeOf(Obj));
+  Expect.isTrue(Dynamic.isSubtypeOf(Super));
+  Expect.isTrue(Dynamic.isSubtypeOf(Sub1));
+  Expect.isTrue(Dynamic.isSubtypeOf(Sub2));
+  Expect.isTrue(Dynamic.isSubtypeOf(NumPred));
+  Expect.isTrue(Dynamic.isSubtypeOf(IntPred));
+  Expect.isTrue(Dynamic.isSubtypeOf(DubPred));
+  Expect.isTrue(Dynamic.isSubtypeOf(NumPredRef));
+  Expect.isTrue(Dynamic.isSubtypeOf(IntPredRef));
+  Expect.isTrue(Dynamic.isSubtypeOf(DubPredRef));
+  Expect.isTrue(Dynamic.isSubtypeOf(NumGen));
+  Expect.isTrue(Dynamic.isSubtypeOf(IntGen));
+  Expect.isTrue(Dynamic.isSubtypeOf(DubGen));
+  Expect.isTrue(Dynamic.isSubtypeOf(NumGenRef));
+  Expect.isTrue(Dynamic.isSubtypeOf(IntGenRef));
+  Expect.isTrue(Dynamic.isSubtypeOf(DubGenRef));
+  Expect.isTrue(Dynamic.isSubtypeOf(TFromA));
+  Expect.isTrue(Dynamic.isSubtypeOf(TFromB));
+  Expect.isTrue(Dynamic.isSubtypeOf(TFromC));
+
+  TypeMirror Void = mirrors.voidType;
+  Expect.isTrue(Void.isSubtypeOf(Void));
+  Expect.isFalse(Obj.isSubtypeOf(Void));
+  Expect.isFalse(Super.isSubtypeOf(Void));
+  Expect.isFalse(Sub1.isSubtypeOf(Void));
+  Expect.isFalse(Sub2.isSubtypeOf(Void));
+  Expect.isFalse(NumPred.isSubtypeOf(Void));
+  Expect.isFalse(IntPred.isSubtypeOf(Void));
+  Expect.isFalse(DubPred.isSubtypeOf(Void));
+  Expect.isFalse(NumPredRef.isSubtypeOf(Void));
+  Expect.isFalse(IntPredRef.isSubtypeOf(Void));
+  Expect.isFalse(DubPredRef.isSubtypeOf(Void));
+  Expect.isFalse(NumGen.isSubtypeOf(Void));
+  Expect.isFalse(IntGen.isSubtypeOf(Void));
+  Expect.isFalse(DubGen.isSubtypeOf(Void));
+  Expect.isFalse(NumGenRef.isSubtypeOf(Void));
+  Expect.isFalse(IntGenRef.isSubtypeOf(Void));
+  Expect.isFalse(DubGenRef.isSubtypeOf(Void));
+  Expect.isFalse(TFromA.isSubtypeOf(Void));
+  Expect.isFalse(TFromB.isSubtypeOf(Void));
+  Expect.isFalse(TFromC.isSubtypeOf(Void));
+  Expect.isFalse(Void.isSubtypeOf(Obj));
+  Expect.isFalse(Void.isSubtypeOf(Super));
+  Expect.isFalse(Void.isSubtypeOf(Sub1));
+  Expect.isFalse(Void.isSubtypeOf(Sub2));
+  Expect.isFalse(Void.isSubtypeOf(NumPred));
+  Expect.isFalse(Void.isSubtypeOf(IntPred));
+  Expect.isFalse(Void.isSubtypeOf(DubPred));
+  Expect.isFalse(Void.isSubtypeOf(NumPredRef));
+  Expect.isFalse(Void.isSubtypeOf(IntPredRef));
+  Expect.isFalse(Void.isSubtypeOf(DubPredRef));
+  Expect.isFalse(Void.isSubtypeOf(NumGen));
+  Expect.isFalse(Void.isSubtypeOf(IntGen));
+  Expect.isFalse(Void.isSubtypeOf(DubGen));
+  Expect.isFalse(Void.isSubtypeOf(NumGenRef));
+  Expect.isFalse(Void.isSubtypeOf(IntGenRef));
+  Expect.isFalse(Void.isSubtypeOf(DubGenRef));
+  Expect.isFalse(Void.isSubtypeOf(TFromA));
+  Expect.isFalse(Void.isSubtypeOf(TFromB));
+  Expect.isFalse(Void.isSubtypeOf(TFromC));
+
+  Expect.isTrue(Dynamic.isSubtypeOf(Void));
+  Expect.isTrue(Void.isSubtypeOf(Dynamic));
+}
+
+main() {
+  test(currentMirrorSystem());
+}
diff --git a/tests/standalone/io/raw_secure_server_socket_test.dart b/tests/standalone/io/raw_secure_server_socket_test.dart
index 44cb7fc..49c04fb 100644
--- a/tests/standalone/io/raw_secure_server_socket_test.dart
+++ b/tests/standalone/io/raw_secure_server_socket_test.dart
@@ -472,6 +472,67 @@
   }
 }
 
+testPausedSecuringSubscription(bool pausedServer, bool pausedClient) {
+  bool expectFail = pausedServer || pausedClient;
+
+  asyncStart();
+  var clientComplete = new Completer();
+  RawServerSocket.bind(HOST_NAME, 0).then((server) {
+    server.listen((client) {
+      var subscription;
+      subscription = client.listen((_) {
+        if (pausedServer) {
+          subscription.pause();
+        }
+        RawSecureSocket.secureServer(
+            client, CERTIFICATE, subscription: subscription).then((client) {
+          if (expectFail) {
+            Expect.fail("secureServer succeeded with paused subscription");
+          }
+        }).catchError((e) {
+          if (!expectFail) {
+            Expect.fail("secureServer failed with non-paused subscriptions");
+          }
+          if (pausedServer) {
+            Expect.isTrue(e is StateError);
+          }
+        }).whenComplete(() {
+          server.close();
+          clientComplete.future.then((_) {
+            client.close();
+            asyncEnd();
+          });
+        });
+      });
+    });
+
+    RawSocket.connect(HOST_NAME, server.port).then((socket) {
+      var subscription;
+      subscription = socket.listen((_) {
+        if (pausedClient) {
+          subscription.pause();
+        }
+        RawSecureSocket.secure(
+            socket, subscription: subscription).then((socket) {
+          if (expectFail) {
+            Expect.fail("secure succeeded with paused subscription");
+          }
+          socket.close();
+        }).catchError((e) {
+          if (!expectFail) {
+            Expect.fail("secure failed with non-paused subscriptions ($e)");
+          }
+          if (pausedClient) {
+            Expect.isTrue(e is StateError);
+          }
+        }).whenComplete(() {
+          clientComplete.complete(null);
+        });
+      });
+    });
+  });
+}
+
 main() {
   var certificateDatabase = Platform.script.resolve('pkcert').toFilePath();
   SecureSocket.initialize(database: certificateDatabase,
@@ -526,4 +587,8 @@
                       handshakeBeforeSecure: true,
                       postponeSecure: true,
                       dropReads: true);
+  testPausedSecuringSubscription(false, false);
+  testPausedSecuringSubscription(true, false);
+  testPausedSecuringSubscription(false, true);
+  testPausedSecuringSubscription(true, true);
 }
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index fc3c77b..97c3f5e 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -9,7 +9,7 @@
 
 package/invalid_uri_test: Fail, OK # CompileTimeErrors intentionally
 
-issue14236_test: Crash, RuntimeError # Issue 14516.
+issue14236_test: Crash # Issue 14516.
 
 [ $runtime == vm ]
 package/package_isolate_test: Fail # Issue 12474
@@ -81,7 +81,6 @@
 oom_error_stacktrace_test: RuntimeError, OK # (OOM on JS may produce a stacktrace).
 vmservice/*: Skip # Do not run standalone vm service tests with dart2js.
 issue14236_test: Skip # dart2js does not deal with Script snapshots.
-io/platform_test: Pass, CompileTimeError # Issue 14603
 
 [ $compiler == dart2js && $jscl ]
 assert_test: RuntimeError, OK # Assumes unspecified fields on the AssertionError.
diff --git a/tools/VERSION b/tools/VERSION
index 624a175..c1f1325 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 2
 PATCH 0
-PRERELEASE 4
+PRERELEASE 5
 PRERELEASE_PATCH 0
diff --git a/tools/bots/src-tarball.py b/tools/bots/src-tarball.py
index 3441e93..1c32034 100644
--- a/tools/bots/src-tarball.py
+++ b/tools/bots/src-tarball.py
@@ -36,6 +36,9 @@
     args = [sys.executable, './tools/create_tarball.py']
     print 'Building src tarball'
     bot.RunProcess(args)
+    print 'Building Debian packages'
+    args = [sys.executable, './tools/create_debian_packages.py']
+    bot.RunProcess(args)
 
 if __name__ == '__main__':
   # We pass in None for build_step to avoid building the sdk.
diff --git a/tools/create_debian_packages.py b/tools/create_debian_packages.py
new file mode 100755
index 0000000..b76c2e3
--- /dev/null
+++ b/tools/create_debian_packages.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2014, 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 to build a Debian packages from a Dart tarball. The script
+# will build a source package and a 32-bit (i386) and 64-bit (amd64)
+# binary packages.
+
+import sys
+import tarfile
+import subprocess
+import utils
+
+from os.path import join, exists, abspath
+from shutil import copyfile
+
+HOST_OS = utils.GuessOS()
+HOST_CPUS = utils.GuessCpus()
+DART_DIR = abspath(join(__file__, '..', '..'))
+
+def RunBuildPackage(opt, cwd):
+  cmd = ['dpkg-buildpackage', '-j%d' % HOST_CPUS]
+  cmd.extend(opt)
+  process = subprocess.Popen(cmd,
+                             stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+                             cwd=cwd)
+  (stdout, stderr) = process.communicate()
+  if process.returncode != 0:
+    raise Exception('Command \'%s\' failed: %s\nSTDOUT: %s' %
+                    (' '.join(cmd), stderr, stdout))
+
+def BuildDebianPackage():
+  version = utils.GetVersion()
+  builddir = join(DART_DIR, utils.GetBuildDir(HOST_OS, HOST_OS))
+  tarroot = 'dart-%s' % version
+  tarname = 'dart-%s.tar.gz' % version
+  origtarname = 'dart_%s.orig.tar.gz' % version
+  tarball = join(builddir, tarname)
+  if not exists(join(builddir, tarball)):
+    print 'Source tarball not found'
+    return -1
+
+  with utils.TempDir() as temp_dir:
+    origtarball = join(temp_dir, origtarname)
+    copyfile(tarball, origtarball)
+
+    with tarfile.open(origtarball) as tar:
+      tar.extractall(path=temp_dir)
+
+    # Build source package.
+    print "Building source package"
+    RunBuildPackage(['-S', '-us', '-uc'], join(temp_dir, tarroot));
+
+    # Build 32-bit binary package.
+    print "Building i386 package"
+    RunBuildPackage(['-B', '-ai386', '-us', '-uc'], join(temp_dir, tarroot));
+
+    # Build 64-bit binary package.
+    print "Building amd64 package"
+    RunBuildPackage(['-B', '-aamd64', '-us', '-uc'], join(temp_dir, tarroot));
+
+    # Copy the Debian package files to the build directory.
+    debbase = 'dart_%s' % version
+    source_package = [
+      '%s-1.dsc' % debbase,
+      '%s.orig.tar.gz' % debbase,
+      '%s-1.debian.tar.gz' % debbase
+    ]
+    i386_package = [
+      '%s-1_i386.deb' % debbase
+    ]
+    amd64_package = [
+      '%s-1_amd64.deb' % debbase
+    ]
+    for name in source_package:
+      copyfile(join(temp_dir, name), join(builddir, name))
+    for name in i386_package:
+      copyfile(join(temp_dir, name), join(builddir, name))
+    for name in amd64_package:
+      copyfile(join(temp_dir, name), join(builddir, name))
+
+def Main():
+  if HOST_OS != 'linux':
+    print 'Debian build only supported on linux'
+    return -1
+
+  BuildDebianPackage()
+
+if __name__ == '__main__':
+  sys.exit(Main())
diff --git a/tools/create_sdk.py b/tools/create_sdk.py
index 4d12ae8..015d0dd 100755
--- a/tools/create_sdk.py
+++ b/tools/create_sdk.py
@@ -15,12 +15,15 @@
 # ....bin/
 # ......dart or dart.exe (executable)
 # ......dart.lib (import library for VM native extensions on Windows)
+# ......dartfmt
 # ......dart2js
 # ......dartanalyzer
 # ......pub
 # ......snapshots/
-# ........utils_wrapper.dart.snapshot
+# ........dart2js.dart.snapshot
+# ........dartfmt.dart.snapshot
 # ........pub.dart.snapshot
+# ........utils_wrapper.dart.snapshot
 # ....include/
 # ......dart_api.h
 # ......dart_debugger_api.h
@@ -105,13 +108,13 @@
 
 
 def CopyDartScripts(home, sdk_root):
-  for executable in ['dart2js', 'dartanalyzer', 'docgen', 'pub']:
+  for executable in ['dart2js', 'dartanalyzer', 'dartfmt', 'docgen', 'pub']:
     CopyShellScript(os.path.join(home, 'sdk', 'bin', executable),
                     os.path.join(sdk_root, 'bin'))
 
 
 def CopySnapshots(snapshots, sdk_root):
-  for snapshot in ['dart2js', 'utils_wrapper', 'pub']:
+  for snapshot in ['dart2js', 'dartfmt', 'utils_wrapper', 'pub']:
     snapshot += '.dart.snapshot'
     copyfile(join(snapshots, snapshot),
              join(sdk_root, 'bin', 'snapshots', snapshot))
diff --git a/tools/create_tarball.py b/tools/create_tarball.py
index 71ed4a8..caaa81c 100755
--- a/tools/create_tarball.py
+++ b/tools/create_tarball.py
@@ -33,62 +33,6 @@
 HOST_OS = utils.GuessOS()
 DART_DIR = abspath(join(__file__, '..', '..'))
 
-# TODO (16582): Remove this when the LICENSE file becomes part of
-# all checkouts.
-license = [
-  'This license applies to all parts of Dart that are not externally',
-  'maintained libraries. The external maintained libraries used by',
-  'Dart are:',
-  '',
-  '7-Zip - in third_party/7zip',
-  'JSCRE - in runtime/third_party/jscre',
-  'Ant - in third_party/apache_ant',
-  'args4j - in third_party/args4j',
-  'bzip2 - in third_party/bzip2',
-  'Commons IO - in third_party/commons-io',
-  'Commons Lang in third_party/commons-lang',
-  'dromaeo - in samples/third_party/dromaeo',
-  'Eclipse - in third_party/eclipse',
-  'gsutil - in third_party/gsutil',
-  'Guava - in third_party/guava',
-  'hamcrest - in third_party/hamcrest',
-  'Httplib2 - in samples/third_party/httplib2',
-  'JSON - in third_party/json',
-  'JUnit - in third_party/junit',
-  'Oauth - in samples/third_party/oauth2client',
-  'weberknecht - in third_party/weberknecht',
-  'fest - in third_party/fest',
-  'mockito - in third_party/mockito',
-  '',
-  'The libraries may have their own licenses; we recommend you read them,',
-  'as their terms may differ from the terms below.',
-  '',
-  'Copyright 2012, the Dart project authors. All rights reserved.',
-  'Redistribution and use in source and binary forms, with or without',
-  'modification, are permitted provided that the following conditions are',
-  'met:',
-  '    * Redistributions of source code must retain the above copyright',
-  '      notice, this list of conditions and the following disclaimer.',
-  '    * Redistributions in binary form must reproduce the above',
-  '      copyright notice, this list of conditions and the following',
-  '      disclaimer in the documentation and/or other materials provided',
-  '      with the distribution.',
-  '    * Neither the name of Google Inc. nor the names of its',
-  '      contributors may be used to endorse or promote products derived',
-  '      from this software without specific prior written permission.',
-  'THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS',
-  '"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT',
-  'LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR',
-  'A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT',
-  'OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,',
-  'SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT',
-  'LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,',
-  'DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY',
-  '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.'
-]
-
 # Flags.
 verbose = False
 
@@ -134,14 +78,8 @@
   return tar_info
 
 def GenerateCopyright(filename):
-  license_lines = license
-  try:
-    # TODO (16582): The LICENSE file is currently not in a normal the
-    # dart checkout.
-    with open(join(DART_DIR, 'LICENSE')) as lf:
-      license_lines = lf.read().splitlines()
-  except:
-    pass
+  with open(join(DART_DIR, 'LICENSE')) as lf:
+    license_lines = lf.readlines()
 
   with open(filename, 'w') as f:
     f.write('Name: dart\n')
@@ -149,7 +87,7 @@
     f.write('Source: https://code.google.com/p/dart/\n')
     f.write('License:\n')
     for line in license_lines:
-      f.write(' %s\n' % line)
+      f.write(' %s' % line)  # Line already contains trailing \n.
 
 def GenerateChangeLog(filename, version):
   with open(filename, 'w') as f:
@@ -174,9 +112,11 @@
   tarname = '%s.tar.gz' % versiondir
   debian_dir = 'tools/linux_dist_support/debian'
   # Create the tar file in the build directory.
-  tardir = join(DART_DIR, utils.GetBuildDir(HOST_OS, HOST_OS))
-  # Don't include the build directory in the tarball.
-  ignoredPaths.append(tardir)
+  builddir = utils.GetBuildDir(HOST_OS, HOST_OS)
+  tardir = join(DART_DIR, builddir)
+  # Don't include the build directory in the tarball (ignored paths
+  # are relative to DART_DIR).
+  ignoredPaths.append(builddir)
   if not exists(tardir):
     makedirs(tardir)
   tarfilename = join(tardir, tarname)
diff --git a/tools/dom/dom.json b/tools/dom/dom.json
index 20aff36..e9576fa 100644
--- a/tools/dom/dom.json
+++ b/tools/dom/dom.json
@@ -34,6 +34,17 @@
     },
     "support_level": "untriaged"
   },
+  "AesCtrParams": {
+    "members": {
+      "counter": {
+        "support_level": "untriaged"
+      },
+      "length": {
+        "support_level": "untriaged"
+      }
+    },
+    "support_level": "untriaged"
+  },
   "AesKeyGenParams": {
     "members": {
       "length": {
@@ -1771,6 +1782,9 @@
         "dart_action": "unstable"
       },
       "head": {},
+      "hidden": {
+        "support_level": "untriaged"
+      },
       "images": {
         "dart_action": "suppress"
       },
@@ -1972,6 +1986,9 @@
       },
       "styleSheets": {},
       "title": {},
+      "visibilityState": {
+        "support_level": "untriaged"
+      },
       "webkitCancelFullScreen": {
         "comment": "https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html",
         "dart_action": "suppress",
@@ -2127,6 +2144,9 @@
         "dart_action": "suppress",
         "support_level": "deprecated"
       },
+      "animate": {
+        "support_level": "untriaged"
+      },
       "attributes": {},
       "blur": {},
       "childElementCount": {},
@@ -2826,6 +2846,9 @@
   "File": {
     "comment": "http://www.w3.org/TR/FileAPI/#dfn-file",
     "members": {
+      "lastModified": {
+        "support_level": "untriaged"
+      },
       "lastModifiedDate": {},
       "name": {},
       "webkitRelativePath": {
@@ -3035,6 +3058,9 @@
       "featureSettings": {
         "support_level": "untriaged"
       },
+      "load": {
+        "support_level": "untriaged"
+      },
       "status": {
         "support_level": "untriaged"
       },
@@ -4103,6 +4129,9 @@
         "dart_action": "suppress",
         "support_level": "deprecated"
       },
+      "color": {
+        "support_level": "untriaged"
+      },
       "noShade": {
         "comment": "http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#HTMLHRElement-partial",
         "dart_action": "suppress",
@@ -4522,6 +4551,9 @@
       },
       "controller": {},
       "controls": {},
+      "crossOrigin": {
+        "support_level": "untriaged"
+      },
       "currentSrc": {},
       "currentTime": {},
       "defaultMuted": {},
@@ -5501,6 +5533,9 @@
     "members": {
       "advance": {},
       "continue": {},
+      "continuePrimaryKey": {
+        "support_level": "untriaged"
+      },
       "delete": {},
       "direction": {},
       "key": {},
@@ -5726,6 +5761,12 @@
         "support_level": "untriaged"
       },
       "composition": {},
+      "compositionEndOffset": {
+        "support_level": "untriaged"
+      },
+      "compositionStartOffset": {
+        "support_level": "untriaged"
+      },
       "confirmComposition": {},
       "dispatchEvent": {
         "support_level": "untriaged"
@@ -6758,6 +6799,9 @@
     "members": {
       "Notification": {},
       "addEventListener": {},
+      "body": {
+        "support_level": "untriaged"
+      },
       "cancel": {
         "dart_action": "experimental",
         "support_level": "nonstandard"
@@ -6768,6 +6812,12 @@
         "support_level": "nonstandard"
       },
       "dispatchEvent": {},
+      "icon": {
+        "support_level": "untriaged"
+      },
+      "lang": {
+        "support_level": "untriaged"
+      },
       "onclick": {},
       "onclose": {},
       "ondisplay": {
@@ -6790,6 +6840,9 @@
       "tag": {
         "dart_action": "experimental",
         "support_level": "nonstandard"
+      },
+      "title": {
+        "support_level": "untriaged"
       }
     },
     "support_level": "experimental"
@@ -9368,6 +9421,17 @@
     },
     "support_level": "stable"
   },
+  "SVGGeometryElement": {
+    "members": {
+      "isPointInFill": {
+        "support_level": "untriaged"
+      },
+      "isPointInStroke": {
+        "support_level": "untriaged"
+      }
+    },
+    "support_level": "untriaged"
+  },
   "SVGGlyphElement": {
     "comment": "http://www.w3.org/TR/SVG/fonts.html#InterfaceSVGGlyphElement",
     "dart_action": "unstable",
@@ -11140,6 +11204,10 @@
     "members": {},
     "support_level": "untriaged"
   },
+  "ServiceWorkerGlobalScope": {
+    "members": {},
+    "support_level": "untriaged"
+  },
   "ShadowRoot": {
     "comment": "https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#api-shadow-root",
     "members": {
@@ -11648,6 +11716,9 @@
       },
       "cues": {},
       "dispatchEvent": {},
+      "id": {
+        "support_level": "untriaged"
+      },
       "kind": {},
       "label": {},
       "language": {},
@@ -11730,9 +11801,15 @@
     "members": {
       "addEventListener": {},
       "dispatchEvent": {},
+      "getTrackById": {
+        "support_level": "untriaged"
+      },
       "item": {},
       "length": {},
       "onaddtrack": {},
+      "onchange": {
+        "support_level": "untriaged"
+      },
       "removeEventListener": {}
     },
     "support_level": "experimental"
@@ -12051,6 +12128,39 @@
     },
     "support_level": "stable"
   },
+  "VTTCue": {
+    "members": {
+      "VTTCue": {},
+      "align": {
+        "support_level": "untriaged"
+      },
+      "getCueAsHTML": {
+        "support_level": "untriaged"
+      },
+      "line": {
+        "support_level": "untriaged"
+      },
+      "position": {
+        "support_level": "untriaged"
+      },
+      "regionId": {
+        "support_level": "untriaged"
+      },
+      "size": {
+        "support_level": "untriaged"
+      },
+      "snapToLines": {
+        "support_level": "untriaged"
+      },
+      "text": {
+        "support_level": "untriaged"
+      },
+      "vertical": {
+        "support_level": "untriaged"
+      }
+    },
+    "support_level": "untriaged"
+  },
   "VTTRegion": {
     "members": {
       "VTTRegion": {},
@@ -12205,6 +12315,9 @@
       "alpha": {},
       "antialias": {},
       "depth": {},
+      "failIfMajorPerformanceCaveat": {
+        "support_level": "untriaged"
+      },
       "premultipliedAlpha": {},
       "preserveDrawingBuffer": {},
       "stencil": {}
@@ -12977,6 +13090,10 @@
     },
     "support_level": "experimental"
   },
+  "WebKitNotification": {
+    "members": {},
+    "support_level": "untriaged"
+  },
   "WebKitPoint": {
     "comment": "http://developer.apple.com/library/safari/#documentation/DataManagement/Reference/DOMWindowAdditionsReference/DOMWindowAdditions/DOMWindowAdditions.html",
     "members": {
diff --git a/tools/dom/idl/dart/dart.idl b/tools/dom/idl/dart/dart.idl
index 415b914..b33973a 100644
--- a/tools/dom/idl/dart/dart.idl
+++ b/tools/dom/idl/dart/dart.idl
@@ -299,7 +299,7 @@
   [Custom] void send(ArrayBufferView data);
 };
 
-[Supplemental]
+[Supplemental, Constructor]
 interface XMLHttpRequest {
    [Custom] void send();
    [Custom] void send(ArrayBuffer data); // FIXME: this should be eventually deprecated.
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py
index 570255b..58d77b4 100644
--- a/tools/dom/scripts/generator.py
+++ b/tools/dom/scripts/generator.py
@@ -595,15 +595,15 @@
     # all requests.  Read requests like IDBDataStore.getObject need
     # conversion, but other requests like opening a database return
     # something that does not need conversion.
-    'IDBAny get IDBRequest.result':
+    '* get IDBRequest.result':
       Conversion('_convertNativeToDart_IDBAny', 'dynamic', 'dynamic'),
 
     # "source: On getting, returns the IDBObjectStore or IDBIndex that the
     # cursor is iterating. ...".  So we should not try to convert it.
-    'IDBAny get IDBCursor.source': None,
+    '* get IDBCursor.source': None,
 
     # Should be either a DOMString, an Array of DOMStrings or null.
-    'IDBAny get IDBObjectStore.keyPath': None,
+    '* get IDBObjectStore.keyPath': None,
 
     '* get XMLHttpRequest.response':
       Conversion('_convertNativeToDart_XHR_Response',
@@ -666,7 +666,7 @@
     cls = self.bindings_class()
 
     if 'Callback' in idl_node.ext_attrs:
-      return '%s', 'RefPtr<%s>' % self.native_type(), cls, 'create'
+      return '%s.release()', 'OwnPtr<%s>' % self.native_type(), cls, 'create'
 
     if self.custom_to_native():
       type = 'RefPtr<%s>' % self.native_type()
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index 077a3a1..be8372a 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -128,6 +128,7 @@
   'WebKitCSSMixFunctionValue',
   'WebKitCSSTransformValue',
   'WebKitMediaSource',
+  'WebKitNotification',
   'WebKitSourceBuffer',
   'WebKitSourceBufferList',
   'WorkerLocation', # Workers
@@ -603,6 +604,7 @@
     '=Event.returnValue', # Only suppress on Event, allow for BeforeUnloadEvnt.
     'Event.srcElement',
     'EventSource.URL',
+    'FontFace.ready',
     'FontFaceSet.load',
     'FontFaceSet.ready',
     'HTMLAnchorElement.charset',
@@ -813,7 +815,7 @@
     if self.ShouldSuppressMember(interface, member, member_prefix):
       return None
 
-    if 'CheckSecurityForNode' in member_node.ext_attrs:
+    if 'CheckSecurity' in member_node.ext_attrs:
       return None
 
     name = self._FindMatch(interface, member, member_prefix,
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py
index a8cc579..c5c0434 100644
--- a/tools/dom/scripts/systemhtml.py
+++ b/tools/dom/scripts/systemhtml.py
@@ -61,6 +61,8 @@
     'Element.webkitMatchesSelector',
     'ElementEvents.mouseWheel',
     'ElementEvents.transitionEnd',
+    'Document.createNodeIterator',
+    'Document.createTreeWalker',
     'DOMException.name',
     'HTMLTableElement.createTBody',
     'IDBCursor.next',
diff --git a/tools/dom/scripts/systemnative.py b/tools/dom/scripts/systemnative.py
index d1c9c3f..36f73cc 100644
--- a/tools/dom/scripts/systemnative.py
+++ b/tools/dom/scripts/systemnative.py
@@ -39,6 +39,7 @@
   ('DOMWindow', 'clearTimeout'): 'DOMWindowTimers',
   ('DOMWindow', 'clearInterval'): 'DOMWindowTimers',
   ('DOMWindow', 'createImageBitmap'): 'ImageBitmapFactories',
+  ('Element', 'animate'): 'ElementAnimation',
   ('HTMLInputElement', 'webkitEntries'): 'HTMLInputElementFileSystem',
   ('HTMLVideoElement', 'getVideoPlaybackQuality'): 'HTMLVideoElementMediaSource',
   ('Navigator', 'doNotTrack'): 'NavigatorDoNotTrack',
@@ -199,6 +200,7 @@
     class_name = 'Dart%s' % self._interface.id
     for operation in self._interface.operations:
       function_name = operation.id
+      return_type = self.SecureOutputType(operation.type.id)
       parameters = []
       arguments = []
       if operation.ext_attrs.get('CallWith') == 'ThisValue':
@@ -212,20 +214,28 @@
         conversion_includes.extend(argument_type_info.conversion_includes())
 
       # FIXME(vsm): Handle ThisValue attribute.
+      if (return_type == 'void'):
+        ret = ''
+      else:
+        ret = '        return 0;\n'
+
       if operation.ext_attrs.get('CallWith') == 'ThisValue':
         cpp_header_handlers_emitter.Emit(
             '\n'
-            '    virtual bool $FUNCTION($PARAMETERS) {\n'
+            '    virtual $RETURN_TYPE $FUNCTION($PARAMETERS) {\n'
             '        DART_UNIMPLEMENTED();\n'
-            '        return false;\n'
+            '$RET'
             '    }\n',
+            RETURN_TYPE=return_type,
+            RET=ret,
             FUNCTION=function_name,
             PARAMETERS=', '.join(parameters))
         continue
 
       cpp_header_handlers_emitter.Emit(
           '\n'
-          '    virtual bool $FUNCTION($PARAMETERS);\n',
+          '    virtual $RETURN_TYPE $FUNCTION($PARAMETERS);\n',
+          RETURN_TYPE=return_type,
           FUNCTION=function_name,
           PARAMETERS=', '.join(parameters))
 
@@ -236,17 +246,26 @@
       arguments_declaration = 'Dart_Handle arguments[] = { %s }' % ', '.join(arguments)
       if not len(arguments):
         arguments_declaration = 'Dart_Handle* arguments = 0'
+      if (return_type == 'void'):
+        ret1 = 'return'
+        ret2 = ''
+      else:
+        ret1 = 'return 0'
+        ret2 = ' return'
       cpp_impl_handlers_emitter.Emit(
           '\n'
-          'bool $CLASS_NAME::$FUNCTION($PARAMETERS)\n'
+          '$RETURN_TYPE $CLASS_NAME::$FUNCTION($PARAMETERS)\n'
           '{\n'
           '    if (!m_callback.isIsolateAlive())\n'
-          '        return false;\n'
+          '        $RET1;\n'
           '    DartIsolateScope scope(m_callback.isolate());\n'
           '    DartApiScope apiScope;\n'
           '    $ARGUMENTS_DECLARATION;\n'
-          '    return m_callback.handleEvent($ARGUMENT_COUNT, arguments);\n'
+          '   $RET2 m_callback.handleEvent($ARGUMENT_COUNT, arguments);\n'
           '}\n',
+          RETURN_TYPE=return_type,
+          RET1=ret1,
+          RET2=ret2,
           CLASS_NAME=class_name,
           FUNCTION=function_name,
           PARAMETERS=', '.join(parameters),
@@ -508,6 +527,8 @@
         'PureInterface' in ext_attrs or
         'CPPPureInterface' in ext_attrs or
         'SpecialWrapFor' in ext_attrs or
+        ('Custom' in ext_attrs and ext_attrs['Custom'] == 'Wrap') or
+        ('Custom' in ext_attrs and ext_attrs['Custom'] == 'ToV8') or
         self._interface_type_info.custom_to_dart()):
       to_dart_emitter.Emit(
           '    static Dart_Handle createWrapper(DartDOMData* domData, NativeType* value);\n')
@@ -586,6 +607,8 @@
         webcore_function_name = self._ToWebKitName(attr.id)
 
     function_expression = self._GenerateWebCoreFunctionExpression(webcore_function_name, attr)
+    raises = ('RaisesException' in attr.ext_attrs and
+              attr.ext_attrs['RaisesException'] != 'Setter')
     self._GenerateNativeCallback(
         cpp_callback_name,
         True,
@@ -594,7 +617,7 @@
         [],
         attr.type.id,
         attr.type.nullable,
-        'GetterRaisesException' in attr.ext_attrs or 'RaisesException' in attr.ext_attrs,
+        raises,
         auto_scope_setup)
 
   def _AddSetter(self, attr, html_name):
@@ -611,12 +634,18 @@
     if 'Reflect' in attr.ext_attrs:
       webcore_function_name = self._TypeInfo(attr.type.id).webcore_setter_name()
     else:
+      if 'ImplementedAs' in attr.ext_attrs:
+        attr_name = attr.ext_attrs['ImplementedAs']
+      else:
+        attr_name = attr.id
       webcore_function_name = re.sub(r'^(xml|css|(?=[A-Z])|\w)',
                                      lambda s: s.group(1).upper(),
-                                     attr.id)
+                                     attr_name)
       webcore_function_name = 'set%s' % webcore_function_name
 
     function_expression = self._GenerateWebCoreFunctionExpression(webcore_function_name, attr)
+    raises = ('RaisesException' in attr.ext_attrs and
+              attr.ext_attrs['RaisesException'] != 'Getter')
     self._GenerateNativeCallback(
         cpp_callback_name,
         True,
@@ -625,7 +654,7 @@
         [attr],
         'void',
         False,
-        'SetterRaisesException' in attr.ext_attrs,
+        raises,
         auto_scope_setup,
         generate_custom_element_scope_if_needed=True)
 
@@ -1082,7 +1111,7 @@
       # In this case, the getter is mapped to a static method.
       if (not function_expression.startswith('receiver->') and
           not function_expression.startswith(interface_name + '::')):
-        if interface_name == 'DOMWindow' or interface_name == 'Navigator' or interface_name == 'WorkerGlobalScope':
+        if interface_name in ['DOMWindow', 'Element', 'Navigator', 'WorkerGlobalScope']:
           cpp_arguments.insert(0, 'receiver')
         else:
           cpp_arguments.append('receiver')
@@ -1104,7 +1133,7 @@
           '        $NATIVE_TYPE result = $FUNCTION_CALL;\n'
           '        if (isNull)\n'
           '            return;\n',
-          NATIVE_TYPE=return_type_info.native_type(),
+          NATIVE_TYPE=return_type_info.parameter_type(),
           FUNCTION_CALL=function_call)
         value_expression = 'result'
       else:
diff --git a/tools/dom/templates/html/dartium/cpp_callback_header.template b/tools/dom/templates/html/dartium/cpp_callback_header.template
index 001207f..2a245c4 100644
--- a/tools/dom/templates/html/dartium/cpp_callback_header.template
+++ b/tools/dom/templates/html/dartium/cpp_callback_header.template
@@ -16,31 +16,31 @@
 
 class Dart$(INTERFACE) : public $(INTERFACE), public ActiveDOMCallback {
 public:
-    typedef $(INTERFACE) NativeType;
+    typedef Dart$(INTERFACE) NativeType;
 
-    static PassRefPtr<NativeType> create(Dart_Handle object, Dart_Handle& exception)
+    static PassOwnPtr<NativeType> create(Dart_Handle object, Dart_Handle& exception)
     {
-        return adoptRef(new Dart$(INTERFACE)(object, exception, DartUtilities::scriptExecutionContext()));
+        return adoptPtr(new Dart$(INTERFACE)(object, exception, DartUtilities::scriptExecutionContext()));
     }
 
-    static PassRefPtr<NativeType> createWithNullCheck(Dart_Handle object, Dart_Handle& exception)
+    static PassOwnPtr<NativeType> createWithNullCheck(Dart_Handle object, Dart_Handle& exception)
     {
         if (Dart_IsNull(object))
-            return 0;
+            return PassOwnPtr<NativeType>();
         return create(object, exception);
     }
 
-    static PassRefPtr<NativeType> create(Dart_NativeArguments args, int idx, Dart_Handle& exception)
+    static PassOwnPtr<NativeType> create(Dart_NativeArguments args, int idx, Dart_Handle& exception)
     {
         Dart_Handle object = Dart_GetNativeArgument(args, idx);
         return create(object, exception);
     }
 
-    static PassRefPtr<NativeType> createWithNullCheck(Dart_NativeArguments args, int idx, Dart_Handle& exception)
+    static PassOwnPtr<NativeType> createWithNullCheck(Dart_NativeArguments args, int idx, Dart_Handle& exception)
     {
         Dart_Handle object = Dart_GetNativeArgument(args, idx);
         if (Dart_IsNull(object))
-            return 0;
+            return PassOwnPtr<NativeType>();
         return create(object, exception);
     }
 
diff --git a/tools/dom/templates/html/impl/impl_Document.darttemplate b/tools/dom/templates/html/impl/impl_Document.darttemplate
index b39ee90..98df72e 100644
--- a/tools/dom/templates/html/impl/impl_Document.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Document.darttemplate
@@ -29,7 +29,7 @@
     return new _FrozenElementList._wrap(_querySelectorAll(selectors));
   }
 
-  /** 
+  /**
    * Alias for [querySelector]. Note this function is deprecated because its
    * semantics will be changing in the future.
    */
@@ -38,7 +38,7 @@
   @DomName('Document.querySelector')
   Element query(String relativeSelectors) => querySelector(relativeSelectors);
 
-  /** 
+  /**
    * Alias for [querySelectorAll]. Note this function is deprecated because its
    * semantics will be changing in the future.
    */
@@ -70,4 +70,18 @@
     }
 $endif
   }
+
+$if DART2JS
+  @DomName('Document.createNodeIterator')
+  NodeIterator _createNodeIterator(Node root,
+      [int whatToShow, NodeFilter filter])
+      => JS('NodeIterator', '#.createNodeIterator(#, #, #, false)',
+          this, root, whatToShow, filter);
+
+  @DomName('Document.createTreeWalker')
+  TreeWalker _createTreeWalker(Node root,
+      [int whatToShow, NodeFilter filter])
+      => JS('TreeWalker', '#.createTreeWalker(#, #, #, false)',
+          this, root, whatToShow, filter);
+$endif
 }
diff --git a/tools/dom/templates/html/impl/impl_NodeIterator.darttemplate b/tools/dom/templates/html/impl/impl_NodeIterator.darttemplate
index 4322a1b..c850360 100644
--- a/tools/dom/templates/html/impl/impl_NodeIterator.darttemplate
+++ b/tools/dom/templates/html/impl/impl_NodeIterator.darttemplate
@@ -6,7 +6,7 @@
 
 $(ANNOTATIONS)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
   factory NodeIterator(Node root, int whatToShow) {
-    return document._createNodeIterator(root, whatToShow, null, false);
+    return document._createNodeIterator(root, whatToShow, null);
   }
 $!MEMBERS
 }
diff --git a/tools/dom/templates/html/impl/impl_TreeWalker.darttemplate b/tools/dom/templates/html/impl/impl_TreeWalker.darttemplate
index 6861cd1..60733cc 100644
--- a/tools/dom/templates/html/impl/impl_TreeWalker.darttemplate
+++ b/tools/dom/templates/html/impl/impl_TreeWalker.darttemplate
@@ -6,7 +6,7 @@
 
 $(ANNOTATIONS)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
   factory TreeWalker(Node root, int whatToShow) {
-    return document._createTreeWalker(root, whatToShow, null, false);
+    return document._createTreeWalker(root, whatToShow, null);
   }
 $!MEMBERS
 }
diff --git a/tools/linux_dist_support/debian/control b/tools/linux_dist_support/debian/control
index bc8c570..2e8ce4d 100644
--- a/tools/linux_dist_support/debian/control
+++ b/tools/linux_dist_support/debian/control
@@ -4,9 +4,7 @@
 Priority: optional
 Standards-Version: 3.9.2
 Build-Depends: debhelper (>= 9),
-	subversion,
 	python,
-	g++-4.6,
 	openjdk-6-jdk
 
 Package: dart
diff --git a/tools/linux_dist_support/debian/rules b/tools/linux_dist_support/debian/rules
index e733811..e2ebca3 100755
--- a/tools/linux_dist_support/debian/rules
+++ b/tools/linux_dist_support/debian/rules
@@ -43,6 +43,9 @@
 	make -C dart -j$(PARALLEL_JOBS) \
 		BUILDTYPE=$(BUILD_TYPE) $(BUILD_ARGS) create_sdk
 
+# Building the Dart SDK will already strip all binaries.
+override_dh_strip:
+
 override_dh_auto_install:
 	mkdir -p debian/tmp/out
 	cp -R dart/out/$(BUILD_TYPE)/dart-sdk debian/tmp/out
diff --git a/tools/test.dart b/tools/test.dart
index a0f5525..b4f7b63 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -49,6 +49,7 @@
     new Path('pkg'),
     new Path('runtime/tests/vm'),
     new Path('samples'),
+    new Path('samples-dev'),
     new Path('tests/benchmark_smoke'),
     new Path('tests/chrome'),
     new Path('tests/compiler/dart2js'),
diff --git a/utils/dartfmt/dartfmt.gyp b/utils/dartfmt/dartfmt.gyp
new file mode 100644
index 0000000..a5e6c25
--- /dev/null
+++ b/utils/dartfmt/dartfmt.gyp
@@ -0,0 +1,36 @@
+# Copyright (c) 2014, 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.
+
+{
+  'targets': [
+    {
+      'target_name': 'dartfmt',
+      'type': 'none',
+      'dependencies': [
+        '../../runtime/dart-runtime.gyp:dart',
+        '../../pkg/pkg.gyp:pkg_packages',
+      ],
+      'actions': [
+        {
+          'action_name': 'generate_dartfmt_snapshot',
+          'inputs': [
+            '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart<(EXECUTABLE_SUFFIX)',
+            '../../sdk/lib/_internal/libraries.dart',
+            '<(SHARED_INTERMEDIATE_DIR)/packages.stamp',
+            '<!@(["python", "../../tools/list_files.py", "\\.dart$", "../../pkg/analyzer"])',
+          ],
+          'outputs': [
+            '<(SHARED_INTERMEDIATE_DIR)/dartfmt.dart.snapshot',
+          ],
+          'action': [
+            '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart<(EXECUTABLE_SUFFIX)',
+            '--snapshot=<(SHARED_INTERMEDIATE_DIR)/dartfmt.dart.snapshot',
+            '--package-root=<(PRODUCT_DIR)/packages/',
+            '../../pkg/analyzer/bin/formatter.dart',
+          ],
+        },
+      ],
+    },
+  ],
+}