Version 1.5.0-dev.4.0

svn merge -r 36817:36978 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@36979 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/analysis_server/lib/src/analysis_manager.dart b/pkg/analysis_server/lib/src/analysis_manager.dart
index 59677e2..2c4ad01 100644
--- a/pkg/analysis_server/lib/src/analysis_manager.dart
+++ b/pkg/analysis_server/lib/src/analysis_manager.dart
@@ -7,7 +7,7 @@
 import 'dart:io';
 
 import 'package:analysis_server/src/channel.dart';
-import 'package:analysis_server/src/domain_server.dart';
+import 'package:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/protocol.dart';
 
 /**
@@ -121,7 +121,7 @@
       return channel.close().then((_) => false);
     }
     return channel
-        .sendRequest(new Request('0', ServerDomainHandler.SHUTDOWN_METHOD))
+        .sendRequest(new Request('0', METHOD_SHUTDOWN))
         .timeout(new Duration(seconds: 2), onTimeout: () {
           print('Expected shutdown response');
         })
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index d4bcb3d..db5be05 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -8,18 +8,22 @@
 
 import 'package:analysis_server/src/analysis_logger.dart';
 import 'package:analysis_server/src/channel.dart';
+import 'package:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/context_directory_manager.dart';
 import 'package:analysis_server/src/domain_analysis.dart';
+import 'package:analysis_server/src/operation/operation_analysis.dart';
+import 'package:analysis_server/src/operation/operation.dart';
+import 'package:analysis_server/src/operation/operation_queue.dart';
 import 'package:analysis_server/src/protocol.dart';
 import 'package:analysis_server/src/resource.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/sdk_io.dart';
 import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
 
 
 /**
@@ -38,7 +42,7 @@
     ContextDirectory contextDirectory = new ContextDirectory(
         analysisServer.defaultSdk, folder, pubspecFile);
     analysisServer.folderMap[folder] = contextDirectory;
-    analysisServer.addContextToWorkQueue(contextDirectory.context);
+    analysisServer.schedulePerformAnalysisOperation(contextDirectory.context);
   }
 
   void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) {
@@ -52,26 +56,6 @@
  */
 class AnalysisServer {
   /**
-   * The name of the parameter whose value is a list of errors.
-   */
-  static const String ERRORS_PARAM = 'errors';
-
-  /**
-   * The name of the parameter whose value is a file path.
-   */
-  static const String FILE_PARAM = 'file';
-
-  /**
-   * The event name of the connected notification.
-   */
-  static const String CONNECTED_NOTIFICATION = 'server.connected';
-
-  /**
-   * The event name of the status notification.
-   */
-  static const String STATUS_NOTIFICATION = 'server.status';
-
-  /**
    * The channel from which requests are received and to which responses should
    * be sent.
    */
@@ -85,7 +69,7 @@
 
   /**
    * A flag indicating whether the server is running.  When false, contexts
-   * will no longer be added to [contextWorkQueue], and [performTask] will
+   * will no longer be added to [contextWorkQueue], and [performOperation] will
    * discard any tasks it finds on [contextWorkQueue].
    */
   bool running;
@@ -96,17 +80,6 @@
    */
   List<RequestHandler> handlers;
 
-  // TODO(scheglov) remove once setAnalysisRoots() is completely implemented
-//  /**
-//   * A table mapping context id's to the analysis contexts associated with them.
-//   */
-//  final Map<String, AnalysisContext> contextMap = new Map<String, AnalysisContext>();
-//
-//  /**
-//   * A table mapping analysis contexts to the context id's associated with them.
-//   */
-//  final Map<AnalysisContext, String> contextIdMap = new Map<AnalysisContext, String>();
-
   /**
    * The current default [DartSdk].
    */
@@ -118,19 +91,13 @@
   final Map<Folder, ContextDirectory> folderMap = <Folder, ContextDirectory>{};
 
   /**
-   * The context identifier used in the last status notification.
-   */
-  String lastStatusNotificationContextId = null;
-
-  /**
-   * A list of the analysis contexts for which analysis work needs to be
-   * performed.
+   * A queue of the operations to perform in this server.
    *
-   * Invariant: when this list is non-empty, there is exactly one pending call
-   * to [performTask] on the event queue.  When this list is empty, there are
-   * no calls to [performTask] on the event queue.
+   * Invariant: when this queue is non-empty, there is exactly one pending call
+   * to [performOperation] on the event queue.  When this list is empty, there are
+   * no calls to [performOperation] on the event queue.
    */
-  final List<AnalysisContext> contextWorkQueue = new List<AnalysisContext>();
+  ServerOperationQueue operationQueue;
 
   /**
    * A set of the [ServerService]s to send notifications for.
@@ -138,34 +105,61 @@
   Set<ServerService> serverServices = new Set<ServerService>();
 
   /**
+   * A table mapping [AnalysisService]s to the file paths for which these
+   * notifications should be sent.
+   */
+  Map<AnalysisService, Set<String>> analysisServices = <AnalysisService, Set<String>>{};
+
+  /**
+   * True if any exceptions thrown by analysis should be propagated up the call
+   * stack.
+   */
+  bool rethrowExceptions;
+
+  /**
    * Initialize a newly created server to receive requests from and send
    * responses to the given [channel].
+   *
+   * If [rethrowExceptions] is true, then any exceptions thrown by analysis are
+   * propagated up the call stack.  The default is true to allow analysis
+   * exceptions to show up in unit tests, but it should be set to false when
+   * running a full analysis server.
    */
-  AnalysisServer(this.channel, ResourceProvider resourceProvider) {
+  AnalysisServer(this.channel, ResourceProvider resourceProvider,
+      {this.rethrowExceptions: true}) {
+    operationQueue = new ServerOperationQueue(this);
     contextDirectoryManager = new AnalysisServerContextDirectoryManager(this, resourceProvider);
     AnalysisEngine.instance.logger = new AnalysisLogger();
     running = true;
-    Notification notification = new Notification(CONNECTED_NOTIFICATION);
+    Notification notification = new Notification(NOTIFICATION_CONNECTED);
     channel.sendNotification(notification);
     channel.listen(handleRequest, onDone: done, onError: error);
   }
 
   /**
-   * If [running] is true, add the given [context] to the list of analysis
-   * contexts for which analysis work needs to be performed, and ensure that
-   * the work will be performed.
+   * Schedules analysis of the given context.
    */
-  void addContextToWorkQueue(AnalysisContext context) {
-    if (!running) {
-      return;
+  void schedulePerformAnalysisOperation(AnalysisContext context) {
+    scheduleOperation(new PerformAnalysisOperation(context, false));
+  }
+
+  /**
+   * Schedules execution of the given [ServerOperation].
+   */
+  void scheduleOperation(ServerOperation operation) {
+    bool wasEmpty = operationQueue.isEmpty;
+    addOperation(operation);
+    if (wasEmpty) {
+      _schedulePerformOperation();
     }
-    if (!contextWorkQueue.contains(context)) {
-      contextWorkQueue.add(context);
-      if (contextWorkQueue.length == 1) {
-        // Work queue was previously empty, so schedule analysis.
-        _scheduleTask();
-      }
-    }
+  }
+
+  /**
+   * Adds the given [ServerOperation] to the queue, but does not schedule
+   * operations execution.
+   */
+  void addOperation(ServerOperation operation) {
+    operationQueue.add(operation);
   }
 
   /**
@@ -204,70 +198,49 @@
   }
 
   /**
-   * Perform the next available task. If a request was received that has not yet
-   * been performed, perform it next. Otherwise, look for some analysis that
-   * needs to be done and do that. Otherwise, do nothing.
+   * Returns `true` if there is a subscription for the given [server] and [file].
    */
-  void performTask() {
-    if (!running) {
-      // An error has occurred, or the connection to the client has been
-      // closed, since performTask() was scheduled on the event queue.  So
-      // don't do any analysis.  Instead clear the work queue.
-      contextWorkQueue.clear();
-    }
-    if (contextWorkQueue.isEmpty) {
-      // Nothing to do.
-      return;
-    }
-    //
-    // Look for a context that has work to be done and then perform one task.
-    //
-    List<ChangeNotice> notices = null;
-//    String contextId;
-    try {
-      AnalysisContext context = contextWorkQueue[0];
-//      contextId = contextIdMap[context];
-      // TODO(danrubel): Replace with context identifier or similar
-      sendStatusNotification(context.toString());
-      AnalysisResult result = context.performAnalysisTask();
-      notices = result.changeNotices;
-    } finally {
-      if (notices == null) {
-        // Either we have no more work to do for this context, or there was an
-        // unhandled exception trying to perform the analysis.  In either case,
-        // remove the context form the work queue so we won't try to do more
-        // analysis on it.
-        contextWorkQueue.removeAt(0);
-      }
-      //
-      // Schedule this method to be run again if there is any more work to be
-      // done.
-      //
-      if (!contextWorkQueue.isEmpty) {
-        _scheduleTask();
-      }
-    }
-    if (notices != null) {
-      sendNotices(notices);
-    } else {
-      sendStatusNotification(null);
-    }
+  bool hasAnalysisSubscription(AnalysisService service, String file) {
+    Set<String> files = analysisServices[service];
+    return files != null && files.contains(file);
   }
 
   /**
-   * Send the information in the given list of notices back to the client.
+   * Returns `true` if the given [AnalysisContext] is a priority one.
    */
-  void sendNotices(List<ChangeNotice> notices) {
-    for (int i = 0; i < notices.length; i++) {
-      ChangeNotice notice = notices[i];
-      Source source = notice.source;
-      // send "analysis.errors" notification
-      // TODO(scheglov) use subscriptions to determine if we should do this
-      if (!source.isInSystemLibrary) {
-        Notification notification = new Notification(AnalysisDomainHandler.ERRORS_NOTIFICATION);
-        notification.setParameter(FILE_PARAM, source.fullName);
-        notification.setParameter(ERRORS_PARAM, notice.errors.map(errorToJson).toList());
-        sendNotification(notification);
+  bool isPriorityContext(AnalysisContext context) {
+    // TODO(scheglov) implement support for priority sources/contexts
+    return false;
+  }
+
+  /**
+   * Perform the next available [ServerOperation].
+   */
+  void performOperation() {
+    if (!running) {
+      // An error has occurred, or the connection to the client has been
+      // closed, since this method was scheduled on the event queue.  So
+      // don't do anything.  Instead clear the operation queue.
+      operationQueue.clear();
+      return;
+    }
+    // prepare next operation
+    ServerOperation operation = operationQueue.take();
+    // perform the operation
+    try {
+      operation.perform(this);
+    } catch (exception, stackTrace) {
+      AnalysisEngine.instance.logger.logError("${exception}\n${stackTrace}");
+      if (rethrowExceptions) {
+        throw new AnalysisException(
+            'Unexpected exception during analysis',
+            new CaughtException(exception, stackTrace));
+      }
+    } finally {
+      if (!operationQueue.isEmpty) {
+        _schedulePerformOperation();
+      } else {
+        sendStatusNotification(null);
       }
     }
   }
@@ -277,11 +250,11 @@
    * the current context being analyzed or `null` if analysis is complete.
    */
   void sendStatusNotification(String contextId) {
-    if (contextId == lastStatusNotificationContextId) {
-      return;
-    }
-    lastStatusNotificationContextId = contextId;
-    Notification notification = new Notification(STATUS_NOTIFICATION);
+//    if (contextId == lastStatusNotificationContextId) {
+//      return;
+//    }
+//    lastStatusNotificationContextId = contextId;
+    Notification notification = new Notification(NOTIFICATION_STATUS);
     Map<String, Object> analysis = new Map();
     if (contextId != null) {
       analysis['analyzing'] = true;
@@ -332,12 +305,39 @@
           analysisContext.setChangedContents(source, change.content,
               change.offset, change.oldLength, change.newLength);
         }
-        addContextToWorkQueue(analysisContext);
+        schedulePerformAnalysisOperation(analysisContext);
       }
     });
   }
 
   /**
+   * Implementation for `analysis.setSubscriptions`.
+   */
+  void setAnalysisSubscriptions(Map<AnalysisService, Set<String>> subscriptions) {
+    // send notifications for already analyzed sources
+    subscriptions.forEach((service, Set<String> newFiles) {
+      Set<String> oldFiles = analysisServices[service];
+      Set<String> todoFiles = oldFiles != null ? newFiles.difference(oldFiles) : newFiles;
+      for (String file in todoFiles) {
+        if (service == AnalysisService.ERRORS) {
+          Source source = _getSource(file);
+          AnalysisContext analysisContext = _getAnalysisContext(file);
+          List<AnalysisError> errors = analysisContext.getErrors(source).errors;
+          sendAnalysisNotificationErrors(this, file, errors);
+        }
+        if (service == AnalysisService.HIGHLIGHTS) {
+          CompilationUnit dartUnit = test_getResolvedCompilationUnit(file);
+          if (dartUnit != null) {
+            sendAnalysisNotificationHighlights(this, file, dartUnit);
+          }
+        }
+      }
+    });
+    // remember new subscriptions
+    this.analysisServices = subscriptions;
+  }
+
+  /**
    * Return the [AnalysisContext] that is used to analyze the given [path].
    * Return `null` if there is no such context.
    */
@@ -379,27 +379,10 @@
   }
 
   /**
-   * Return `true` if all tasks are finished in this [AnalysisServer].
+   * Return `true` if all operations have been performed in this [AnalysisServer].
    */
-  bool test_areTasksFinished() {
-    return contextWorkQueue.isEmpty;
-  }
-
-  static Map<String, Object> errorToJson(AnalysisError analysisError) {
-    // TODO(paulberry): move this function into the AnalysisError class.
-    ErrorCode errorCode = analysisError.errorCode;
-    Map<String, Object> result = {
-      'file': analysisError.source.fullName,
-      // TODO(scheglov) add Enum.fullName ?
-      'errorCode': '${errorCode.runtimeType}.${(errorCode as Enum).name}',
-      'offset': analysisError.offset,
-      'length': analysisError.length,
-      'message': analysisError.message
-    };
-    if (analysisError.correction != null) {
-      result['correction'] = analysisError.correction;
-    }
-    return result;
+  bool test_areOperationsFinished() {
+    return operationQueue.isEmpty;
   }
 
   /**
@@ -409,10 +392,11 @@
     channel.sendNotification(notification);
   }
 
-  void _scheduleTask() {
-    new Future(performTask).catchError((ex, st) {
-      AnalysisEngine.instance.logger.logError("${ex}\n${st}");
-    });
+  /**
+   * Schedules [performOperation] exection.
+   */
+  void _schedulePerformOperation() {
+    new Future(performOperation);
   }
 }
 
diff --git a/pkg/analysis_server/lib/src/computers.dart b/pkg/analysis_server/lib/src/computers.dart
new file mode 100644
index 0000000..6b954dc
--- /dev/null
+++ b/pkg/analysis_server/lib/src/computers.dart
@@ -0,0 +1,712 @@
+// 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 computers;
+
+import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/element.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/source.dart';
+
+
+/**
+ * A computer for [HighlightRegion]s in a Dart [CompilationUnit].
+ */
+class DartUnitHighlightsComputer {
+  final CompilationUnit _unit;
+
+  final List<Map<String, Object>> _regions = <Map<String, Object>>[];
+
+  DartUnitHighlightsComputer(this._unit);
+
+  /**
+   * Returns the computed highlight regions, not `null`.
+   */
+  List<Map<String, Object>> compute() {
+    _unit.accept(new _DartUnitHighlightsComputerVisitor(this));
+    return _regions;
+  }
+
+  void _addIdentifierRegion(SimpleIdentifier node) {
+    if (_addIdentifierRegion_keyword(node)) {
+      return;
+    }
+    if (_addIdentifierRegion_class(node)) {
+      return;
+    }
+    if (_addIdentifierRegion_constructor(node)) {
+      return;
+    }
+    if (_addIdentifierRegion_dynamicType(node)) {
+      return;
+    }
+    if (_addIdentifierRegion_getterSetterDeclaration(node)) {
+      return;
+    }
+    if (_addIdentifierRegion_field(node)) {
+      return;
+    }
+    if (_addIdentifierRegion_function(node)) {
+      return;
+    }
+    if (_addIdentifierRegion_functionTypeAlias(node)) {
+      return;
+    }
+    if (_addIdentifierRegion_importPrefix(node)) {
+      return;
+    }
+    if (_addIdentifierRegion_localVariable(node)) {
+      return;
+    }
+    if (_addIdentifierRegion_method(node)) {
+      return;
+    }
+    if (_addIdentifierRegion_parameter(node)) {
+      return;
+    }
+    if (_addIdentifierRegion_topLevelVariable(node)) {
+      return;
+    }
+    if (_addIdentifierRegion_typeParameter(node)) {
+      return;
+    }
+    _addRegion_node(node, HighlightType.IDENTIFIER_DEFAULT);
+  }
+
+  void _addIdentifierRegion_annotation(Annotation node) {
+    ArgumentList arguments = node.arguments;
+    if (arguments == null) {
+      _addRegion_node(node, HighlightType.ANNOTATION);
+    } else {
+      _addRegion_nodeStart_tokenEnd(node, arguments.beginToken, HighlightType.ANNOTATION);
+      _addRegion_token(arguments.endToken, HighlightType.ANNOTATION);
+    }
+  }
+
+  bool _addIdentifierRegion_class(SimpleIdentifier node) {
+    Element element = node.staticElement;
+    if (element is! ClassElement) {
+      return false;
+    }
+    return _addRegion_node(node, HighlightType.CLASS);
+  }
+
+  bool _addIdentifierRegion_constructor(SimpleIdentifier node) {
+    Element element = node.staticElement;
+    if (element is! ConstructorElement) {
+      return false;
+    }
+    return _addRegion_node(node, HighlightType.CONSTRUCTOR);
+  }
+
+  bool _addIdentifierRegion_dynamicType(SimpleIdentifier node) {
+    // should be variable
+    Element element = node.staticElement;
+    if (element is! VariableElement) {
+      return false;
+    }
+    // has propagated type
+    if (node.propagatedType != null) {
+      return false;
+    }
+    // has dynamic static type
+    DartType staticType = node.staticType;
+    if (staticType == null || !staticType.isDynamic) {
+      return false;
+    }
+    // OK
+    return _addRegion_node(node, HighlightType.DYNAMIC_TYPE);
+  }
+
+  bool _addIdentifierRegion_field(SimpleIdentifier node) {
+    Element element = node.bestElement;
+    if (element is FieldFormalParameterElement) {
+      element = (element as FieldFormalParameterElement).field;
+    }
+    if (element is FieldElement) {
+      if ((element as FieldElement).isStatic) {
+        return _addRegion_node(node, HighlightType.FIELD_STATIC);
+      } else {
+        return _addRegion_node(node, HighlightType.FIELD);
+      }
+    }
+    if (element is PropertyAccessorElement) {
+      if ((element as PropertyAccessorElement).isStatic) {
+        return _addRegion_node(node, HighlightType.FIELD_STATIC);
+      } else {
+        return _addRegion_node(node, HighlightType.FIELD);
+      }
+    }
+    return false;
+  }
+
+  bool _addIdentifierRegion_function(SimpleIdentifier node) {
+    Element element = node.staticElement;
+    if (element is! FunctionElement) {
+      return false;
+    }
+    HighlightType type;
+    if (node.inDeclarationContext()) {
+      type = HighlightType.FUNCTION_DECLARATION;
+    } else {
+      type = HighlightType.FUNCTION;
+    }
+    return _addRegion_node(node, type);
+  }
+
+  bool _addIdentifierRegion_functionTypeAlias(SimpleIdentifier node) {
+    Element element = node.staticElement;
+    if (element is! FunctionTypeAliasElement) {
+      return false;
+    }
+    return _addRegion_node(node, HighlightType.FUNCTION_TYPE_ALIAS);
+  }
+
+  bool _addIdentifierRegion_getterSetterDeclaration(SimpleIdentifier node) {
+    // should be declaration
+    AstNode parent = node.parent;
+    if (!(parent is MethodDeclaration || parent is FunctionDeclaration)) {
+      return false;
+    }
+    // should be property accessor
+    Element element = node.staticElement;
+    if (element is! PropertyAccessorElement) {
+      return false;
+    }
+    // getter or setter
+    PropertyAccessorElement propertyAccessorElement = element as PropertyAccessorElement;
+    if (propertyAccessorElement.isGetter) {
+      return _addRegion_node(node, HighlightType.GETTER_DECLARATION);
+    } else {
+      return _addRegion_node(node, HighlightType.SETTER_DECLARATION);
+    }
+  }
+
+  bool _addIdentifierRegion_importPrefix(SimpleIdentifier node) {
+    Element element = node.staticElement;
+    if (element is! PrefixElement) {
+      return false;
+    }
+    return _addRegion_node(node, HighlightType.IMPORT_PREFIX);
+  }
+
+  bool _addIdentifierRegion_keyword(SimpleIdentifier node) {
+    String name = node.name;
+    if (name == "void") {
+      return _addRegion_node(node, HighlightType.KEYWORD);
+    }
+    return false;
+  }
+
+  bool _addIdentifierRegion_localVariable(SimpleIdentifier node) {
+    Element element = node.staticElement;
+    if (element is! LocalVariableElement) {
+      return false;
+    }
+    // OK
+    HighlightType type;
+    if (node.inDeclarationContext()) {
+      type = HighlightType.LOCAL_VARIABLE_DECLARATION;
+    } else {
+      type = HighlightType.LOCAL_VARIABLE;
+    }
+    return _addRegion_node(node, type);
+  }
+
+  bool _addIdentifierRegion_method(SimpleIdentifier node) {
+    Element element = node.bestElement;
+    if (element is! MethodElement) {
+      return false;
+    }
+    MethodElement methodElement = element as MethodElement;
+    bool isStatic = methodElement.isStatic;
+    // OK
+    HighlightType type;
+    if (node.inDeclarationContext()) {
+      if (isStatic) {
+        type = HighlightType.METHOD_DECLARATION_STATIC;
+      } else {
+        type = HighlightType.METHOD_DECLARATION;
+      }
+    } else {
+      if (isStatic) {
+        type = HighlightType.METHOD_STATIC;
+      } else {
+        type = HighlightType.METHOD;
+      }
+    }
+    return _addRegion_node(node, type);
+  }
+
+  bool _addIdentifierRegion_parameter(SimpleIdentifier node) {
+    Element element = node.staticElement;
+    if (element is! ParameterElement) {
+      return false;
+    }
+    return _addRegion_node(node, HighlightType.PARAMETER);
+  }
+
+  bool _addIdentifierRegion_topLevelVariable(SimpleIdentifier node) {
+    Element element = node.staticElement;
+    if (element is! TopLevelVariableElement) {
+      return false;
+    }
+    return _addRegion_node(node, HighlightType.TOP_LEVEL_VARIABLE);
+  }
+
+  bool _addIdentifierRegion_typeParameter(SimpleIdentifier node) {
+    Element element = node.staticElement;
+    if (element is! TypeParameterElement) {
+      return false;
+    }
+    return _addRegion_node(node, HighlightType.TYPE_PARAMETER);
+  }
+
+  void _addRegion(int offset, int length, HighlightType type) {
+    _regions.add({'offset': offset, 'length': length, 'type': type.name});
+  }
+
+  bool _addRegion_node(AstNode node, HighlightType type) {
+    int offset = node.offset;
+    int length = node.length;
+    _addRegion(offset, length, type);
+    return true;
+  }
+
+  void _addRegion_nodeStart_tokenEnd(AstNode a, Token b, HighlightType type) {
+    int offset = a.offset;
+    int end = b.end;
+    _addRegion(offset, end - offset, type);
+  }
+
+  void _addRegion_token(Token token, HighlightType type) {
+    if (token != null) {
+      int offset = token.offset;
+      int length = token.length;
+      _addRegion(offset, length, type);
+    }
+  }
+
+  void _addRegion_tokenStart_tokenEnd(Token a, Token b, HighlightType type) {
+    int offset = a.offset;
+    int end = b.end;
+    _addRegion(offset, end - offset, type);
+  }
+}
+
+
+/**
+ * An AST visitor for [DartUnitHighlightsComputer].
+ */
+class _DartUnitHighlightsComputerVisitor extends RecursiveAstVisitor<Object> {
+  final DartUnitHighlightsComputer computer;
+
+  _DartUnitHighlightsComputerVisitor(this.computer);
+
+  @override
+  Object visitAnnotation(Annotation node) {
+    computer._addIdentifierRegion_annotation(node);
+    return super.visitAnnotation(node);
+  }
+
+  @override
+  Object visitAsExpression(AsExpression node) {
+    computer._addRegion_token(node.asOperator, HighlightType.BUILT_IN);
+    return super.visitAsExpression(node);
+  }
+
+  @override
+  Object visitBooleanLiteral(BooleanLiteral node) {
+    computer._addRegion_node(node, HighlightType.LITERAL_BOOLEAN);
+    return super.visitBooleanLiteral(node);
+  }
+
+  @override
+  Object visitCatchClause(CatchClause node) {
+    computer._addRegion_token(node.onKeyword, HighlightType.BUILT_IN);
+    return super.visitCatchClause(node);
+  }
+
+  @override
+  Object visitClassDeclaration(ClassDeclaration node) {
+    computer._addRegion_token(node.abstractKeyword, HighlightType.BUILT_IN);
+    return super.visitClassDeclaration(node);
+  }
+
+  @override
+  Object visitConstructorDeclaration(ConstructorDeclaration node) {
+    computer._addRegion_token(node.externalKeyword, HighlightType.BUILT_IN);
+    computer._addRegion_token(node.factoryKeyword, HighlightType.BUILT_IN);
+    return super.visitConstructorDeclaration(node);
+  }
+
+  @override
+  Object visitDoubleLiteral(DoubleLiteral node) {
+    computer._addRegion_node(node, HighlightType.LITERAL_DOUBLE);
+    return super.visitDoubleLiteral(node);
+  }
+
+  @override
+  Object visitExportDirective(ExportDirective node) {
+    computer._addRegion_token(node.keyword, HighlightType.BUILT_IN);
+    return super.visitExportDirective(node);
+  }
+
+  @override
+  Object visitFieldDeclaration(FieldDeclaration node) {
+    computer._addRegion_token(node.staticKeyword, HighlightType.BUILT_IN);
+    return super.visitFieldDeclaration(node);
+  }
+
+  @override
+  Object visitFunctionDeclaration(FunctionDeclaration node) {
+    computer._addRegion_token(node.externalKeyword, HighlightType.BUILT_IN);
+    computer._addRegion_token(node.propertyKeyword, HighlightType.BUILT_IN);
+    return super.visitFunctionDeclaration(node);
+  }
+
+  @override
+  Object visitFunctionTypeAlias(FunctionTypeAlias node) {
+    computer._addRegion_token(node.keyword, HighlightType.BUILT_IN);
+    return super.visitFunctionTypeAlias(node);
+  }
+
+  @override
+  Object visitHideCombinator(HideCombinator node) {
+    computer._addRegion_token(node.keyword, HighlightType.BUILT_IN);
+    return super.visitHideCombinator(node);
+  }
+
+  @override
+  Object visitImplementsClause(ImplementsClause node) {
+    computer._addRegion_token(node.keyword, HighlightType.BUILT_IN);
+    return super.visitImplementsClause(node);
+  }
+
+  @override
+  Object visitImportDirective(ImportDirective node) {
+    computer._addRegion_token(node.keyword, HighlightType.BUILT_IN);
+    computer._addRegion_token(node.deferredToken, HighlightType.BUILT_IN);
+    computer._addRegion_token(node.asToken, HighlightType.BUILT_IN);
+    return super.visitImportDirective(node);
+  }
+
+  @override
+  Object visitIntegerLiteral(IntegerLiteral node) {
+    computer._addRegion_node(node, HighlightType.LITERAL_INTEGER);
+    return super.visitIntegerLiteral(node);
+  }
+
+  @override
+  Object visitLibraryDirective(LibraryDirective node) {
+    computer._addRegion_token(node.keyword, HighlightType.BUILT_IN);
+    return super.visitLibraryDirective(node);
+  }
+
+  @override
+  Object visitMethodDeclaration(MethodDeclaration node) {
+    computer._addRegion_token(node.externalKeyword, HighlightType.BUILT_IN);
+    computer._addRegion_token(node.modifierKeyword, HighlightType.BUILT_IN);
+    computer._addRegion_token(node.operatorKeyword, HighlightType.BUILT_IN);
+    computer._addRegion_token(node.propertyKeyword, HighlightType.BUILT_IN);
+    return super.visitMethodDeclaration(node);
+  }
+
+  @override
+  Object visitNativeClause(NativeClause node) {
+    computer._addRegion_token(node.keyword, HighlightType.BUILT_IN);
+    return super.visitNativeClause(node);
+  }
+
+  @override
+  Object visitNativeFunctionBody(NativeFunctionBody node) {
+    computer._addRegion_token(node.nativeToken, HighlightType.BUILT_IN);
+    return super.visitNativeFunctionBody(node);
+  }
+
+  @override
+  Object visitPartDirective(PartDirective node) {
+    computer._addRegion_token(node.keyword, HighlightType.BUILT_IN);
+    return super.visitPartDirective(node);
+  }
+
+  @override
+  Object visitPartOfDirective(PartOfDirective node) {
+    computer._addRegion_tokenStart_tokenEnd(node.partToken, node.ofToken, HighlightType.BUILT_IN);
+    return super.visitPartOfDirective(node);
+  }
+
+  @override
+  Object visitShowCombinator(ShowCombinator node) {
+    computer._addRegion_token(node.keyword, HighlightType.BUILT_IN);
+    return super.visitShowCombinator(node);
+  }
+
+  @override
+  Object visitSimpleIdentifier(SimpleIdentifier node) {
+    computer._addIdentifierRegion(node);
+    return super.visitSimpleIdentifier(node);
+  }
+
+  @override
+  Object visitSimpleStringLiteral(SimpleStringLiteral node) {
+    computer._addRegion_node(node, HighlightType.LITERAL_STRING);
+    return super.visitSimpleStringLiteral(node);
+  }
+
+  @override
+  Object visitTypeName(TypeName node) {
+    DartType type = node.type;
+    if (type != null) {
+      if (type.isDynamic && node.name.name == "dynamic") {
+        computer._addRegion_node(node, HighlightType.TYPE_NAME_DYNAMIC);
+        return null;
+      }
+    }
+    return super.visitTypeName(node);
+  }
+}
+
+
+/**
+ * Highlighting kinds constants.
+ */
+class HighlightType {
+  static const HighlightType ANNOTATION = const HighlightType('ANNOTATION');
+  static const HighlightType BUILT_IN = const HighlightType('BUILT_IN');
+  static const HighlightType CLASS = const HighlightType('CLASS');
+  static const HighlightType COMMENT_BLOCK = const HighlightType('COMMENT_BLOCK');
+  static const HighlightType COMMENT_DOCUMENTATION = const HighlightType('COMMENT_DOCUMENTATION');
+  static const HighlightType COMMENT_END_OF_LINE = const HighlightType('COMMENT_END_OF_LINE');
+  static const HighlightType CONSTRUCTOR = const HighlightType('CONSTRUCTOR');
+  static const HighlightType DIRECTIVE = const HighlightType('DIRECTIVE');
+  static const HighlightType DYNAMIC_TYPE = const HighlightType('DYNAMIC_TYPE');
+  static const HighlightType FIELD = const HighlightType('FIELD');
+  static const HighlightType FIELD_STATIC = const HighlightType('FIELD_STATIC');
+  static const HighlightType FUNCTION_DECLARATION = const HighlightType('FUNCTION_DECLARATION');
+  static const HighlightType FUNCTION = const HighlightType('FUNCTION');
+  static const HighlightType FUNCTION_TYPE_ALIAS = const HighlightType('FUNCTION_TYPE_ALIAS');
+  static const HighlightType GETTER_DECLARATION = const HighlightType('GETTER_DECLARATION');
+  static const HighlightType KEYWORD = const HighlightType('KEYWORD');
+  static const HighlightType IDENTIFIER_DEFAULT = const HighlightType('IDENTIFIER_DEFAULT');
+  static const HighlightType IMPORT_PREFIX = const HighlightType('IMPORT_PREFIX');
+  static const HighlightType LITERAL_BOOLEAN = const HighlightType('LITERAL_BOOLEAN');
+  static const HighlightType LITERAL_DOUBLE = const HighlightType('LITERAL_DOUBLE');
+  static const HighlightType LITERAL_INTEGER = const HighlightType('LITERAL_INTEGER');
+  static const HighlightType LITERAL_LIST = const HighlightType('LITERAL_LIST');
+  static const HighlightType LITERAL_MAP = const HighlightType('LITERAL_MAP');
+  static const HighlightType LITERAL_STRING = const HighlightType('LITERAL_STRING');
+  static const HighlightType LOCAL_VARIABLE_DECLARATION = const HighlightType('LOCAL_VARIABLE_DECLARATION');
+  static const HighlightType LOCAL_VARIABLE = const HighlightType('LOCAL_VARIABLE');
+  static const HighlightType METHOD_DECLARATION = const HighlightType('METHOD_DECLARATION');
+  static const HighlightType METHOD_DECLARATION_STATIC = const HighlightType('METHOD_DECLARATION_STATIC');
+  static const HighlightType METHOD = const HighlightType('METHOD');
+  static const HighlightType METHOD_STATIC = const HighlightType('METHOD_STATIC');
+  static const HighlightType PARAMETER = const HighlightType('PARAMETER');
+  static const HighlightType SETTER_DECLARATION = const HighlightType('SETTER_DECLARATION');
+  static const HighlightType TOP_LEVEL_VARIABLE = const HighlightType('TOP_LEVEL_VARIABLE');
+  static const HighlightType TYPE_NAME_DYNAMIC = const HighlightType('TYPE_NAME_DYNAMIC');
+  static const HighlightType TYPE_PARAMETER = const HighlightType('TYPE_PARAMETER');
+
+  final String name;
+
+  @override
+  String toString() => name;
+
+  const HighlightType(this.name);
+}
+
+
+/**
+ * A computer for navigation regions in a Dart [CompilationUnit].
+ */
+class DartUnitNavigationComputer {
+  final CompilationUnit _unit;
+
+  List<Map<String, Object>> _regions = [];
+
+  DartUnitNavigationComputer(this._unit);
+
+  /**
+   * Returns the computed navigation regions, not `null`.
+   */
+  List<Map<String, Object>> compute() {
+    _unit.accept(new _DartUnitNavigationComputerVisitor(this));
+    return new List.from(_regions);
+  }
+
+  void _addRegion(int offset, int length, Element element) {
+    Map<String, Object> target = _createTarget(element);
+    if (target == null) {
+      return;
+    }
+    _regions.add({
+      'offset': offset,
+      'length': length,
+      'targets': [target]
+    });
+  }
+
+  void _addRegion_nodeStart_nodeEnd(AstNode a, AstNode b, Element element) {
+    int offset = a.offset;
+    int length = b.end - offset;
+    _addRegion(offset, length, element);
+  }
+
+  void _addRegion_nodeStart_nodeStart(AstNode a, AstNode b, Element element) {
+    int offset = a.offset;
+    int length = b.offset - offset;
+    _addRegion(offset, length, element);
+  }
+
+  void _addRegion_tokenStart_nodeEnd(Token a, AstNode b, Element element) {
+    int offset = a.offset;
+    int length = b.end - offset;
+    _addRegion(offset, length, element);
+  }
+
+  void _addRegionForNode(AstNode node, Element element) {
+    int offset = node.offset;
+    int length = node.length;
+    _addRegion(offset, length, element);
+  }
+
+  void _addRegionForToken(Token token, Element element) {
+    int offset = token.offset;
+    int length = token.length;
+    _addRegion(offset, length, element);
+  }
+
+  /**
+   * Returns the JSON for the given [Element], maybe `null` if `null` was given.
+   */
+  Map<String, Object> _createTarget(Element element) {
+    if (element == null) {
+      return null;
+    }
+    if (element is FieldFormalParameterElement) {
+      element = (element as FieldFormalParameterElement).field;
+    }
+    // prepare Source
+    Source source = element.source;
+    if (source == null) {
+      return null;
+    }
+    // prepare location
+    int offset = element.nameOffset;
+    int length = element.displayName.length;
+    if (element is CompilationUnitElement) {
+      offset = 0;
+      length = 0;
+    }
+    // return as JSON
+    return {
+      'file': source.fullName,
+      'offset': offset,
+      'length': length,
+      'elementId': element.location.encoding
+    };
+  }
+}
+
+
+
+class _DartUnitNavigationComputerVisitor extends RecursiveAstVisitor {
+  final DartUnitNavigationComputer computer;
+
+  _DartUnitNavigationComputerVisitor(this.computer);
+
+  @override
+  visitAssignmentExpression(AssignmentExpression node) {
+    computer._addRegionForToken(node.operator, node.bestElement);
+    return super.visitAssignmentExpression(node);
+  }
+
+  @override
+  visitBinaryExpression(BinaryExpression node) {
+    computer._addRegionForToken(node.operator, node.bestElement);
+    return super.visitBinaryExpression(node);
+  }
+
+  @override
+  visitConstructorDeclaration(ConstructorDeclaration node) {
+    // associate constructor with "T" or "T.name"
+    {
+      AstNode firstNode = node.returnType;
+      AstNode lastNode = node.name;
+      if (lastNode == null) {
+        lastNode = firstNode;
+      }
+      if (firstNode != null && lastNode != null) {
+        computer._addRegion_nodeStart_nodeEnd(firstNode, lastNode, node.element);
+      }
+    }
+    return super.visitConstructorDeclaration(node);
+  }
+
+  @override
+  visitExportDirective(ExportDirective node) {
+    ExportElement exportElement = node.element;
+    if (exportElement != null) {
+      Element element = exportElement.exportedLibrary;
+      computer._addRegion_tokenStart_nodeEnd(node.keyword, node.uri, element);
+    }
+    return super.visitExportDirective(node);
+  }
+
+  @override
+  visitImportDirective(ImportDirective node) {
+    ImportElement importElement = node.element;
+    if (importElement != null) {
+      Element element = importElement.importedLibrary;
+      computer._addRegion_tokenStart_nodeEnd(node.keyword, node.uri, element);
+    }
+    return super.visitImportDirective(node);
+  }
+
+  @override
+  visitIndexExpression(IndexExpression node) {
+    computer._addRegionForToken(node.rightBracket, node.bestElement);
+    return super.visitIndexExpression(node);
+  }
+
+  @override
+  visitInstanceCreationExpression(InstanceCreationExpression node) {
+    computer._addRegion_nodeStart_nodeStart(node, node.argumentList, node.staticElement);
+    return super.visitInstanceCreationExpression(node);
+  }
+
+  @override
+  visitPartDirective(PartDirective node) {
+    computer._addRegion_tokenStart_nodeEnd(node.keyword, node.uri, node.element);
+    return super.visitPartDirective(node);
+  }
+
+  @override
+  visitPartOfDirective(PartOfDirective node) {
+    computer._addRegion_tokenStart_nodeEnd(node.keyword, node.libraryName, node.element);
+    return super.visitPartOfDirective(node);
+  }
+
+  @override
+  visitPostfixExpression(PostfixExpression node) {
+    computer._addRegionForToken(node.operator, node.bestElement);
+    return super.visitPostfixExpression(node);
+  }
+
+  @override
+  visitPrefixExpression(PrefixExpression node) {
+    computer._addRegionForToken(node.operator, node.bestElement);
+    return super.visitPrefixExpression(node);
+  }
+
+  @override
+  visitSimpleIdentifier(SimpleIdentifier node) {
+    if (node.parent is ConstructorDeclaration) {
+    } else {
+      computer._addRegionForNode(node, node.bestElement);
+    }
+    return super.visitSimpleIdentifier(node);
+  }
+}
diff --git a/pkg/analysis_server/lib/src/constants.dart b/pkg/analysis_server/lib/src/constants.dart
new file mode 100644
index 0000000..32f5d8a
--- /dev/null
+++ b/pkg/analysis_server/lib/src/constants.dart
@@ -0,0 +1,78 @@
+// 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 constants;
+
+
+//
+// Server methods
+//
+const String METHOD_GET_VERSION =              'server.getVersion';
+const String METHOD_SHUTDOWN =                 'server.shutdown';
+const String METHOD_SET_SERVER_SUBSCRIPTIONS = 'server.setSubscriptions';
+
+//
+// Analysis methods
+//
+const String METHOD_GET_FIXES =                  'analysis.getFixes';
+const String METHOD_GET_MINOR_REFACTORINGS =     'analysis.getMinorRefactorings';
+const String METHOD_SET_ANALYSIS_ROOTS =         'analysis.setAnalysisRoots';
+const String METHOD_SET_PRIORITY_FILES =         'analysis.setPriorityFiles';
+const String METHOD_SET_ANALYSIS_SUBSCRIPTIONS = 'analysis.setSubscriptions';
+const String METHOD_UPDATE_CONTENT =             'analysis.updateContent';
+const String METHOD_UPDATE_OPTIONS =             'analysis.updateOptions';
+const String METHOD_UPDATE_SDKS =                'analysis.updateSdks';
+
+//
+// Server notifications
+//
+const String NOTIFICATION_CONNECTED  = 'server.connected';
+const String NOTIFICATION_STATUS =     'server.status';
+
+//
+// Analysis notifications
+//
+const String NOTIFICATION_ERRORS =     'analysis.errors';
+const String NOTIFICATION_HIGHLIGHTS = 'analysis.highlights';
+const String NOTIFICATION_NAVIGATION = 'analysis.navigation';
+const String NOTIFICATION_OUTLINE =    'analysis.outline';
+
+
+const String ADDED = 'added';
+const String CONTENT = 'content';
+const String DEFAULT = 'default';
+const String EXCLUDED = 'excluded';
+const String ERRORS = 'errors';
+const String FILE = 'file';
+const String FILES = 'files';
+const String FIXES = 'fixes';
+const String INCLUDED = 'included';
+const String LENGTH = 'length';
+const String NEW_LENGTH = 'newLength';
+const String OFFSET = 'offset';
+const String OLD_LENGTH = 'oldLength';
+const String OPTIONS = 'options';
+const String OUTLINE = 'outline';
+const String REFACTORINGS = 'refactorings';
+const String REGIONS = 'regions';
+const String REMOVED = 'removed';
+const String SUBSCRIPTIONS = 'subscriptions';
+const String VERSION = 'version';
+
+
+// TODO(scheglov) remove it with ContextDomain
+const String APPLY_CHANGES_NAME = 'context.applyChanges';
+const String GET_FIXES_NAME = 'context.getFixes';
+const String SET_OPTIONS_NAME = 'context.setOptions';
+const String SET_PRIORITY_SOURCES_NAME = 'context.setPrioritySources';
+const String CHANGES_PARAM = 'changes';
+const String CONTEXT_ID_PARAM = 'contextId';
+const String MODIFIED_PARAM = "modified";
+const String SOURCES_PARAM = 'sources';
+const String CACHE_SIZE_OPTION = 'cacheSize';
+const String GENERATE_HINTS_OPTION = 'generateHints';
+const String GENERATE_DART2JS_OPTION = 'generateDart2jsHints';
+const String PROVIDE_ERRORS_OPTION = 'provideErrors';
+const String PROVIDE_NAVIGATION_OPTION = 'provideNavigation';
+const String PROVIDE_OUTLINE_OPTION = 'provideOutline';
diff --git a/pkg/analysis_server/lib/src/context_directory_manager.dart b/pkg/analysis_server/lib/src/context_directory_manager.dart
index c171798..cadbb0f 100644
--- a/pkg/analysis_server/lib/src/context_directory_manager.dart
+++ b/pkg/analysis_server/lib/src/context_directory_manager.dart
@@ -100,6 +100,11 @@
   void _handleWatchEvent(Folder folder, _ContextDirectoryInfo info, WatchEvent event) {
     switch (event.type) {
       case ChangeType.ADD:
+        if (_isInPackagesDir(event.path, folder)) {
+          // TODO(paulberry): perhaps we should only skip packages dirs if
+          // there is a pubspec.yaml?
+          break;
+        }
         // TODO(paulberry): handle adding pubspec.yaml
         if (_shouldFileBeAnalyzed(event.path)) {
           ChangeSet changeSet = new ChangeSet();
@@ -133,6 +138,21 @@
   }
 
   /**
+   * Determine if the path from [folder] to [path] contains a 'packages'
+   * directory.
+   */
+  bool _isInPackagesDir(String path, Folder folder) {
+    String relativePath = resourceProvider.pathContext.relative(path, from: folder.path);
+    List<String> pathParts = resourceProvider.pathContext.split(relativePath);
+    for (int i = 0; i < pathParts.length - 1; i++) {
+      if (pathParts[i] == 'packages') {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
    * Resursively adds all Dart and HTML files to the [changeSet].
    */
   static void _addSourceFiles(ChangeSet changeSet, Folder folder, _ContextDirectoryInfo info) {
@@ -145,6 +165,11 @@
           info.sources[child.path] = source;
         }
       } else if (child is Folder) {
+        if (child.shortName == 'packages') {
+          // TODO(paulberry): perhaps we should only skip packages dirs if
+          // there is a pubspec.yaml?
+          continue;
+        }
         _addSourceFiles(changeSet, child, info);
       }
     }
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index c0d2983..129ac81 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -5,6 +5,7 @@
 library domain.analysis;
 
 import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/protocol.dart';
 
 /**
@@ -13,161 +14,6 @@
  */
 class AnalysisDomainHandler implements RequestHandler {
   /**
-   * The name of the `analysis.getFixes` request.
-   */
-  static const String GET_FIXES_METHOD = 'analysis.getFixes';
-
-  /**
-   * The name of the `analysis.getMinorRefactorings` request.
-   */
-  static const String GET_MINOR_REFACTORINGS_METHOD = 'analysis.getMinorRefactorings';
-
-  /**
-   * The name of the `analysis.setAnalysisRoots` request.
-   */
-  static const String SET_ANALYSIS_ROOTS_METHOD = 'analysis.setAnalysisRoots';
-
-  /**
-   * The name of the `analysis.setPriorityFiles` request.
-   */
-  static const String SET_PRIORITY_FILES_METHOD = 'analysis.setPriorityFiles';
-
-  /**
-   * The name of the `analysis.setSubscriptions` request.
-   */
-  static const String SET_SUBSCRIPTIONS_METHOD = 'analysis.setSubscriptions';
-
-  /**
-   * The name of the `analysis.updateContent` request.
-   */
-  static const String UPDATE_CONTENT_METHOD = 'analysis.updateContent';
-
-  /**
-   * The name of the `analysis.updateOptions` request.
-   */
-  static const String UPDATE_OPTIONS_METHOD = 'analysis.updateOptions';
-
-  /**
-   * The name of the `analysis.updateSdks` request.
-   */
-  static const String UPDATE_SDKS_METHOD = 'analysis.updateSdks';
-
-  /**
-   * The name of the `analysis.errors` notification.
-   */
-  static const String ERRORS_NOTIFICATION = 'analysis.errors';
-
-  /**
-   * The name of the `analysis.highlights` notification.
-   */
-  static const String HIGHLIGHTS_NOTIFICATION = 'analysis.highlights';
-
-  /**
-   * The name of the `analysis.navigation` notification.
-   */
-  static const String NAVIGATION_NOTIFICATION = 'analysis.navigation';
-
-  /**
-   * The name of the `analysis.outline` notification.
-   */
-  static const String OUTLINE_NOTIFICATION = 'analysis.outline';
-
-  /**
-   * The name of the `aadded` parameter.
-   */
-  static const String ADDED_PARAM = 'added';
-
-  /**
-   * The name of the `content` parameter.
-   */
-  static const String CONTENT_PARAM = 'content';
-
-  /**
-   * The name of the `default` parameter.
-   */
-  static const String DEFAULT_PARAM = 'default';
-
-  /**
-   * The name of the `errors` parameter.
-   */
-  static const String ERRORS_PARAM = 'errors';
-
-  /**
-   * The name of the `excluded` parameter.
-   */
-  static const String EXCLUDED_PARAM = 'excluded';
-
-  /**
-   * The name of the `file` parameter.
-   */
-  static const String FILE_PARAM = 'file';
-
-  /**
-   * The name of the `files` parameter.
-   */
-  static const String FILES_PARAM = 'files';
-
-  /**
-   * The name of the `fixes` parameter.
-   */
-  static const String FIXES_PARAM = 'fixes';
-
-  /**
-   * The name of the `included` parameter.
-   */
-  static const String INCLUDED_PARAM = 'included';
-
-  /**
-   * The name of the `length` parameter.
-   */
-  static const String LENGTH_PARAM = 'length';
-
-  /**
-   * The name of the `newLength` parameter.
-   */
-  static const String NEW_LENGTH_PARAM = 'newLength';
-
-  /**
-   * The name of the `offset` parameter.
-   */
-  static const String OFFSET_PARAM = 'offset';
-
-  /**
-   * The name of the `oldLength` parameter.
-   */
-  static const String OLD_LENGTH_PARAM = 'oldLength';
-
-  /**
-   * The name of the `options` parameter.
-   */
-  static const String OPTIONS_PARAM = 'options';
-
-  /**
-   * The name of the `outline` parameter.
-   */
-  static const String OUTLINE_PARAM = 'outline';
-
-  /**
-   * The name of the `refactorings` parameter.
-   */
-  static const String REFACTORINGS_PARAM = 'refactorings';
-
-  /**
-   * The name of the `regions` parameter.
-   */
-  static const String REGIONS_PARAM = 'regions';
-
-  /**
-   * The name of the `removed` parameter.
-   */
-  static const String REMOVED_PARAM = 'removed';
-
-  /**
-   * The name of the `subscriptions` parameter.
-   */
-  static const String SUBSCRIPTIONS_PARAM = 'subscriptions';
-
-  /**
    * The analysis server that is using this handler to process requests.
    */
   final AnalysisServer server;
@@ -181,21 +27,21 @@
   Response handleRequest(Request request) {
     try {
       String requestName = request.method;
-      if (requestName == GET_FIXES_METHOD) {
+      if (requestName == METHOD_GET_FIXES) {
         return getFixes(request);
-      } else if (requestName == GET_MINOR_REFACTORINGS_METHOD) {
+      } else if (requestName == METHOD_GET_MINOR_REFACTORINGS) {
           return getMinorRefactorings(request);
-      } else if (requestName == SET_ANALYSIS_ROOTS_METHOD) {
+      } else if (requestName == METHOD_SET_ANALYSIS_ROOTS) {
         return setAnalysisRoots(request);
-      } else if (requestName == SET_PRIORITY_FILES_METHOD) {
+      } else if (requestName == METHOD_SET_PRIORITY_FILES) {
         return setPriorityFiles(request);
-      } else if (requestName == SET_SUBSCRIPTIONS_METHOD) {
+      } else if (requestName == METHOD_SET_ANALYSIS_SUBSCRIPTIONS) {
         return setSubscriptions(request);
-      } else if (requestName == UPDATE_CONTENT_METHOD) {
+      } else if (requestName == METHOD_UPDATE_CONTENT) {
         return updateContent(request);
-      } else if (requestName == UPDATE_OPTIONS_METHOD) {
+      } else if (requestName == METHOD_UPDATE_OPTIONS) {
         return updateOptions(request);
-      } else if (requestName == UPDATE_SDKS_METHOD) {
+      } else if (requestName == METHOD_UPDATE_SDKS) {
         return updateSdks(request);
       }
     } on RequestFailure catch (exception) {
@@ -216,10 +62,10 @@
 
   Response setAnalysisRoots(Request request) {
     // included
-    RequestDatum includedDatum = request.getRequiredParameter(INCLUDED_PARAM);
+    RequestDatum includedDatum = request.getRequiredParameter(INCLUDED);
     List<String> includedPaths = includedDatum.asStringList();
     // excluded
-    RequestDatum excludedDatum = request.getRequiredParameter(EXCLUDED_PARAM);
+    RequestDatum excludedDatum = request.getRequiredParameter(EXCLUDED);
     List<String> excludedPaths = excludedDatum.asStringList();
     // continue in server
     server.setAnalysisRoots(request.id, includedPaths, excludedPaths);
@@ -232,20 +78,35 @@
   }
 
   Response setSubscriptions(Request request) {
-    // TODO(scheglov) implement
-    return null;
+    // parse subscriptions
+    Map<AnalysisService, Set<String>> subMap;
+    {
+      RequestDatum subDatum = request.getRequiredParameter(SUBSCRIPTIONS);
+      Map<String, List<String>> subStringMap = subDatum.asStringListMap();
+      subMap = new Map<AnalysisService, Set<String>>();
+      subStringMap.forEach((String serviceName, List<String> paths) {
+        AnalysisService service = Enum2.valueOf(AnalysisService.VALUES, serviceName);
+        if (service == null) {
+          throw new RequestFailure(
+              new Response.unknownAnalysisService(request, serviceName));
+        }
+        subMap[service] = new Set.from(paths);
+      });
+    }
+    server.setAnalysisSubscriptions(subMap);
+    return new Response(request.id);
   }
 
   Response updateContent(Request request) {
     var changes = new Map<String, ContentChange>();
-    RequestDatum filesDatum = request.getRequiredParameter(FILES_PARAM);
+    RequestDatum filesDatum = request.getRequiredParameter(FILES);
     filesDatum.forEachMap((file, changeDatum) {
       var change = new ContentChange();
-      change.content = changeDatum[CONTENT_PARAM].asString();
-      if (changeDatum.hasKey(OFFSET_PARAM)) {
-        change.offset = changeDatum[OFFSET_PARAM].asInt();
-        change.oldLength = changeDatum[OLD_LENGTH_PARAM].asInt();
-        change.newLength = changeDatum[NEW_LENGTH_PARAM].asInt();
+      change.content = changeDatum[CONTENT].asString();
+      if (changeDatum.hasKey(OFFSET)) {
+        change.offset = changeDatum[OFFSET].asInt();
+        change.oldLength = changeDatum[OLD_LENGTH].asInt();
+        change.newLength = changeDatum[NEW_LENGTH].asInt();
       }
       changes[file] = change;
     });
diff --git a/pkg/analysis_server/lib/src/domain_context.dart b/pkg/analysis_server/lib/src/domain_context.dart
deleted file mode 100644
index d7ff3ff..0000000
--- a/pkg/analysis_server/lib/src/domain_context.dart
+++ /dev/null
@@ -1,277 +0,0 @@
-// 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 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';
-
-/**
- * Instances of the class [ContextDomainHandler] implement a [RequestHandler]
- * that handles requests in the context domain.
- *
- * TODO(scheglov) this class is replaces with [AnalysisDomainHandler].
- */
-class ContextDomainHandler implements RequestHandler {
-  /**
-   * The name of the context.applyChanges request.
-   */
-  static const String APPLY_CHANGES_NAME = 'context.applyChanges';
-
-  /**
-   * The name of the context.getFixes request.
-   */
-  static const String GET_FIXES_NAME = 'context.getFixes';
-
-  /**
-   * The name of the context.setOptions request.
-   */
-  static const String SET_OPTIONS_NAME = 'context.setOptions';
-
-  /**
-   * The name of the context.setPrioritySources request.
-   */
-  static const String SET_PRIORITY_SOURCES_NAME = 'context.setPrioritySources';
-
-  /**
-   * The name of the added parameter.
-   */
-  static const String ADDED_PARAM = "added";
-
-  /**
-   * The name of the changes parameter.
-   */
-  static const String CHANGES_PARAM = 'changes';
-
-  /**
-   * The name of the contextId parameter.
-   */
-  static const String CONTEXT_ID_PARAM = 'contextId';
-
-  /**
-   * The name of the modified parameter.
-   */
-  static const String MODIFIED_PARAM = "modified";
-
-  /**
-   * The name of the options parameter.
-   */
-  static const String OPTIONS_PARAM = 'options';
-
-  /**
-   * The name of the removed parameter.
-   */
-  static const String REMOVED_PARAM = "removed";
-
-  /**
-   * The name of the sources parameter.
-   */
-  static const String SOURCES_PARAM = 'sources';
-
-  /**
-   * The name of the cacheSize option.
-   */
-  static const String CACHE_SIZE_OPTION = 'cacheSize';
-
-  /**
-   * The name of the generateHints option.
-   */
-  static const String GENERATE_HINTS_OPTION = 'generateHints';
-
-  /**
-   * The name of the generateDart2jsHints option.
-   */
-  static const String GENERATE_DART2JS_OPTION = 'generateDart2jsHints';
-
-  /**
-   * The name of the provideErrors option.
-   */
-  static const String PROVIDE_ERRORS_OPTION = 'provideErrors';
-
-  /**
-   * The name of the provideNavigation option.
-   */
-  static const String PROVIDE_NAVIGATION_OPTION = 'provideNavigation';
-
-  /**
-   * The name of the provideOutline option.
-   */
-  static const String PROVIDE_OUTLINE_OPTION = 'provideOutline';
-
-  /**
-   * The analysis server that is using this handler to process requests.
-   */
-  final AnalysisServer server;
-
-  /**
-   * Initialize a newly created handler to handle requests for the given [server].
-   */
-  ContextDomainHandler(this.server);
-
-  @override
-  Response handleRequest(Request request) {
-    try {
-      String requestName = request.method;
-      if (requestName == APPLY_CHANGES_NAME) {
-        return applyChanges(request);
-      } else if (requestName == GET_FIXES_NAME) {
-        return getFixes(request);
-      } else if (requestName == SET_OPTIONS_NAME) {
-        return setOptions(request);
-      } else if (requestName == SET_PRIORITY_SOURCES_NAME) {
-        return setPrioritySources(request);
-      }
-    } on RequestFailure catch (exception) {
-      return exception.response;
-    }
-    return null;
-  }
-
-  /**
-   * Inform the specified context that the changes encoded in the change set
-   * have been made. Any invalidated analysis results will be flushed from the
-   * context.
-   */
-  Response applyChanges(Request request) {
-    AnalysisContext context = getAnalysisContext(request);
-    RequestDatum changesData = request.getRequiredParameter(CHANGES_PARAM);
-    ChangeSet changeSet = createChangeSet(
-        request,
-        context.sourceFactory,
-        changesData);
-
-    context.applyChanges(changeSet);
-    server.addContextToWorkQueue(context);
-    Response response = new Response(request.id);
-    return response;
-  }
-
-  /**
-   * Convert the given JSON object into a [ChangeSet], using the given
-   * [sourceFactory] to convert the embedded strings into sources.
-   */
-  ChangeSet createChangeSet(Request request, SourceFactory sourceFactory,
-                            RequestDatum jsonData) {
-    ChangeSet changeSet = new ChangeSet();
-    if (jsonData.hasKey(ADDED_PARAM)) {
-      convertSources(request, sourceFactory, jsonData[ADDED_PARAM], (Source source) {
-        changeSet.addedSource(source);
-      });
-    }
-    if (jsonData.hasKey(MODIFIED_PARAM)) {
-      convertSources(request, sourceFactory, jsonData[MODIFIED_PARAM], (Source source) {
-        changeSet.changedSource(source);
-      });
-    }
-    if (jsonData.hasKey(REMOVED_PARAM)) {
-      convertSources(request, sourceFactory, jsonData[REMOVED_PARAM], (Source source) {
-        changeSet.removedSource(source);
-      });
-    }
-    return changeSet;
-  }
-
-  /**
-   * If the given [sources] is a list of strings, use the given [sourceFactory]
-   * to convert each string into a source and pass the source to the given
-   * [handler]. Otherwise, throw an exception indicating that the data in the
-   * request was not valid.
-   */
-  void convertSources(Request request, SourceFactory sourceFactory, RequestDatum sources, void handler(Source source)) {
-    convertToSources(sourceFactory, sources.asStringList()).forEach(handler);
-  }
-
-  /**
-   * Return the list of fixes that are available for problems related to the
-   * given error in the specified context.
-   */
-  Response getFixes(Request request) {
-    // TODO(brianwilkerson) Implement this.
-    Response response = new Response(request.id);
-    return response;
-  }
-
-  /**
-   * Set the options controlling analysis within a context to the given set of
-   * options.
-   */
-  Response setOptions(Request request) {
-    AnalysisContext context = getAnalysisContext(request);
-
-    context.analysisOptions = createAnalysisOptions(request);
-    Response response = new Response(request.id);
-    return response;
-  }
-
-  /**
-   * Return the set of analysis options associated with the given [request], or
-   * throw a [RequestFailure] exception if the analysis options are not valid.
-   */
-  AnalysisOptions createAnalysisOptions(Request request) {
-    RequestDatum optionsData = request.getRequiredParameter(OPTIONS_PARAM);
-    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
-    optionsData.forEachMap((String key, RequestDatum value) {
-      if (key == CACHE_SIZE_OPTION) {
-        options.cacheSize = value.asInt();
-      } else if (key == GENERATE_HINTS_OPTION) {
-        options.hint = value.asBool();
-      } else if (key == GENERATE_DART2JS_OPTION) {
-        options.dart2jsHint = value.asBool();
-      } else if (key == PROVIDE_ERRORS_OPTION) {
-//        options.provideErrors = value.asBool();
-      } else if (key == PROVIDE_NAVIGATION_OPTION) {
-//        options.provideNavigation = value.asBool();
-      } else if (key == PROVIDE_OUTLINE_OPTION) {
-//        options.provideOutline = value.asBool();
-      } else {
-        throw new RequestFailure(new Response.unknownAnalysisOption(request, key));
-      }
-    });
-    return options;
-  }
-
-  /**
-   * Set the priority sources in the specified context to the sources in the
-   * given array.
-   */
-  Response setPrioritySources(Request request) {
-    AnalysisContext context = getAnalysisContext(request);
-    List<String> sourcesData = request.getRequiredParameter(SOURCES_PARAM).asStringList();
-    List<Source> sources = convertToSources(context.sourceFactory, sourcesData);
-
-    context.analysisPriorityOrder = sources;
-    Response response = new Response(request.id);
-    return response;
-  }
-
-  /**
-   * Convert the given list of strings into a list of sources owned by the given
-   * [sourceFactory].
-   */
-  List<Source> convertToSources(SourceFactory sourceFactory, List<String> sourcesData) {
-    List<Source> sources = new List<Source>();
-    sourcesData.forEach((String string) {
-      sources.add(sourceFactory.fromEncoding(string));
-    });
-    return sources;
-  }
-
-  /**
-   * Return the analysis context specified by the given request, or throw a
-   * [RequestFailure] exception if either there is no specified context or if
-   * the specified context does not exist.
-   */
-  AnalysisContext getAnalysisContext(Request request) {
-    // TODO(scheglov) remove it after migrating to the new API
-    return null;
-//    String contextId = request.getRequiredParameter(CONTEXT_ID_PARAM).asString();
-//    AnalysisContext context = server.contextMap[contextId];
-//    if (context == null) {
-//      throw new RequestFailure(new Response.contextDoesNotExist(request));
-//    }
-//    return context;
-  }
-}
diff --git a/pkg/analysis_server/lib/src/domain_server.dart b/pkg/analysis_server/lib/src/domain_server.dart
index 89e101d..9f9867b 100644
--- a/pkg/analysis_server/lib/src/domain_server.dart
+++ b/pkg/analysis_server/lib/src/domain_server.dart
@@ -5,6 +5,7 @@
 library domain.server;
 
 import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/protocol.dart';
 
 /**
@@ -13,31 +14,6 @@
  */
 class ServerDomainHandler implements RequestHandler {
   /**
-   * The name of the `server.getVersion` request.
-   */
-  static const String GET_VERSION_METHOD = 'server.getVersion';
-
-  /**
-   * The name of the `server.setSubscriptions` request.
-   */
-  static const String SET_SUBSCRIPTIONS_METHOD = 'server.setSubscriptions';
-
-  /**
-   * The name of the `server.shutdown` request.
-   */
-  static const String SHUTDOWN_METHOD = 'server.shutdown';
-
-  /**
-   * The name of the `subscriptions` parameter.
-   */
-  static const String SUBSCRIPTIONS_PARAMETER = 'subscriptions';
-
-  /**
-   * The name of the version result value.
-   */
-  static const String VERSION_RESULT = 'version';
-
-  /**
    * The analysis server that is using this handler to process requests.
    */
   final AnalysisServer server;
@@ -51,11 +27,11 @@
   Response handleRequest(Request request) {
     try {
       String requestName = request.method;
-      if (requestName == GET_VERSION_METHOD) {
+      if (requestName == METHOD_GET_VERSION) {
         return getVersion(request);
-      } else if (requestName == SET_SUBSCRIPTIONS_METHOD) {
+      } else if (requestName == METHOD_SET_SERVER_SUBSCRIPTIONS) {
           return setSubscriptions(request);
-      } else if (requestName == SHUTDOWN_METHOD) {
+      } else if (requestName == METHOD_SHUTDOWN) {
         return shutdown(request);
       }
     } on RequestFailure catch (exception) {
@@ -70,7 +46,7 @@
    * All previous subscriptions are replaced by the given set of subscriptions.
    */
   Response setSubscriptions(Request request) {
-    RequestDatum subDatum = request.getRequiredParameter(SUBSCRIPTIONS_PARAMETER);
+    RequestDatum subDatum = request.getRequiredParameter(SUBSCRIPTIONS);
     server.serverServices = subDatum.asEnumSet(ServerService.VALUES);
     return new Response(request.id);
   }
@@ -142,7 +118,7 @@
    */
   Response getVersion(Request request) {
     Response response = new Response(request.id);
-    response.setResult(VERSION_RESULT, '0.0.1');
+    response.setResult(VERSION, '0.0.1');
     return response;
   }
 }
diff --git a/pkg/analysis_server/lib/src/operation/operation.dart b/pkg/analysis_server/lib/src/operation/operation.dart
new file mode 100644
index 0000000..e7ce47a
--- /dev/null
+++ b/pkg/analysis_server/lib/src/operation/operation.dart
@@ -0,0 +1,47 @@
+// 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 operation;
+
+import 'package:analysis_server/src/analysis_server.dart';
+
+
+/**
+ * The enumeration [ServerOperationPriority] defines the priority levels used
+ * to organize [ServerOperation]s in an optimal order. A smaller ordinal value
+ * equates to a higher priority.
+ */
+class ServerOperationPriority {
+  final int ordinal;
+  final String name;
+
+  static const int COUNT = 4;
+
+  static const ServerOperationPriority ANALYSIS_CONTINUE = const ServerOperationPriority._(0, "ANALYSIS_CONTINUE");
+  static const ServerOperationPriority ANALYSIS = const ServerOperationPriority._(1, "ANALYSIS");
+  static const ServerOperationPriority SEARCH = const ServerOperationPriority._(2, "SEARCH");
+  static const ServerOperationPriority REFACTORING = const ServerOperationPriority._(3, "REFACTORING");
+
+  @override
+  String toString() => name;
+
+  const ServerOperationPriority._(this.ordinal, this.name);
+}
+
+
+/**
+ * The class [ServerOperation] defines the behavior of objects used to perform
+ * operations on a [AnalysisServer].
+ */
+abstract class ServerOperation {
+  /**
+   * Returns the priority of this operation.
+   */
+  ServerOperationPriority get priority;
+
+  /**
+   * Performs the operation implemented by this operation.
+   */
+  void perform(AnalysisServer server);
+}
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
new file mode 100644
index 0000000..ed8cfd8
--- /dev/null
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -0,0 +1,129 @@
+// 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 operation.analysis;
+
+import 'package:analysis_server/src/operation/operation.dart';
+import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/computers.dart';
+import 'package:analysis_server/src/constants.dart';
+import 'package:analysis_server/src/protocol.dart';
+import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/java_core.dart';
+import 'package:analyzer/src/generated/source.dart';
+
+
+/**
+ * Instances of [PerformAnalysisOperation] perform a single analysis task.
+ */
+class PerformAnalysisOperation extends ServerOperation {
+  final AnalysisContext context;
+  final bool isContinue;
+
+  PerformAnalysisOperation(this.context, this.isContinue);
+
+  @override
+  ServerOperationPriority get priority {
+    if (isContinue) {
+      return ServerOperationPriority.ANALYSIS_CONTINUE;
+    } else {
+      return ServerOperationPriority.ANALYSIS;
+    }
+  }
+
+  @override
+  void perform(AnalysisServer server) {
+    //
+    // TODO(brianwilkerson) Add an optional function-valued parameter to
+    // performAnalysisTask that will be called when the task has been computed
+    // but before it is performed and send notification in the function:
+    //
+    // AnalysisResult result = context.performAnalysisTask((taskDescription) {
+    //   sendStatusNotification(context.toString(), taskDescription);
+    // });
+    // prepare results
+    AnalysisResult result = context.performAnalysisTask();
+    List<ChangeNotice> notices = result.changeNotices;
+    if (notices == null) {
+      return;
+    }
+    // TODO(scheglov) remember known sources
+    // TODO(scheglov) index units
+    // TODO(scheglov) schedule notifications
+    sendNotices(server, notices);
+    // continue analysis
+    server.addOperation(new PerformAnalysisOperation(context, true));
+  }
+
+  /**
+   * Send the information in the given list of notices back to the client.
+   */
+  void sendNotices(AnalysisServer server, List<ChangeNotice> notices) {
+    for (int i = 0; i < notices.length; i++) {
+      ChangeNotice notice = notices[i];
+      Source source = notice.source;
+      CompilationUnit dartUnit = notice.compilationUnit;
+      // TODO(scheglov) use default subscriptions
+      String file = source.fullName;
+      if (dartUnit != null) {
+        if (server.hasAnalysisSubscription(AnalysisService.HIGHLIGHTS, file)) {
+          sendAnalysisNotificationHighlights(server, file, dartUnit);
+        }
+        if (server.hasAnalysisSubscription(AnalysisService.NAVIGATION, file)) {
+          sendAnalysisNotificationNavigation(server, file, dartUnit);
+        }
+      }
+      if (!source.isInSystemLibrary) {
+        sendAnalysisNotificationErrors(server, file, notice.errors);
+      }
+    }
+  }
+}
+
+void sendAnalysisNotificationErrors(AnalysisServer server,
+                                    String file, List<AnalysisError> errors) {
+  Notification notification = new Notification(NOTIFICATION_ERRORS);
+  notification.setParameter(FILE, file);
+  notification.setParameter(ERRORS, errors.map(errorToJson).toList());
+  server.sendNotification(notification);
+}
+
+void sendAnalysisNotificationHighlights(AnalysisServer server,
+                                        String file, CompilationUnit dartUnit) {
+  Notification notification = new Notification(NOTIFICATION_HIGHLIGHTS);
+  notification.setParameter(FILE, file);
+  notification.setParameter(
+      REGIONS,
+      new DartUnitHighlightsComputer(dartUnit).compute());
+  server.sendNotification(notification);
+}
+
+void sendAnalysisNotificationNavigation(AnalysisServer server,
+                                        String file, CompilationUnit dartUnit) {
+  Notification notification = new Notification(NOTIFICATION_NAVIGATION);
+  notification.setParameter(FILE, file);
+  notification.setParameter(
+      REGIONS,
+      new DartUnitNavigationComputer(dartUnit).compute());
+  server.sendNotification(notification);
+}
+
+Map<String, Object> errorToJson(AnalysisError analysisError) {
+  // TODO(paulberry): move this function into the AnalysisError class.
+  ErrorCode errorCode = analysisError.errorCode;
+  Map<String, Object> result = {
+    'file': analysisError.source.fullName,
+    // TODO(scheglov) add Enum.fullName ?
+    'errorCode': '${errorCode.runtimeType}.${(errorCode as Enum).name}',
+    'offset': analysisError.offset,
+    'length': analysisError.length,
+    'message': analysisError.message
+  };
+  if (analysisError.correction != null) {
+    result['correction'] = analysisError.correction;
+  }
+  return result;
+}
diff --git a/pkg/analysis_server/lib/src/operation/operation_queue.dart b/pkg/analysis_server/lib/src/operation/operation_queue.dart
new file mode 100644
index 0000000..c033185
--- /dev/null
+++ b/pkg/analysis_server/lib/src/operation/operation_queue.dart
@@ -0,0 +1,83 @@
+// 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 operation.queue;
+
+import 'dart:collection';
+
+import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/operation/operation_analysis.dart';
+import 'package:analysis_server/src/operation/operation.dart';
+
+
+/**
+ * A queue of operations in an [AnalysisServer].
+ */
+class ServerOperationQueue {
+  final List<ServerOperationPriority> _analysisPriorities = [
+      ServerOperationPriority.ANALYSIS_CONTINUE,
+      ServerOperationPriority.ANALYSIS];
+
+  final AnalysisServer _server;
+  final List<Queue<ServerOperation>> _queues = <Queue<ServerOperation>>[];
+
+  ServerOperationQueue(this._server) {
+    for (int i = 0; i < ServerOperationPriority.COUNT; i++) {
+      var queue = new DoubleLinkedQueue<ServerOperation>();
+      _queues.add(queue);
+    }
+  }
+
+  /**
+   * Adds the given operation to this queue. The exact position in the queue
+   * depends on the priority of the given operation relative to the priorities
+   * of the other operations in the queue.
+   */
+   void add(ServerOperation operation) {
+    int queueIndex = operation.priority.ordinal;
+    Queue<ServerOperation> queue = _queues[queueIndex];
+    queue.addLast(operation);
+  }
+
+  /**
+   * Removes all elements in the queue.
+   */
+  void clear() {
+    for (Queue<ServerOperation> queue in _queues) {
+      queue.clear();
+    }
+  }
+
+  /**
+   * Returns `true` if there are no queued [ServerOperation]s.
+   */
+  bool get isEmpty {
+    return _queues.every((queue) => queue.isEmpty);
+  }
+
+  /**
+   * Returns the next operation to perform or `null` if empty.
+   */
+  ServerOperation take() {
+    // try to find a priority analysis operarion
+    for (ServerOperationPriority priority in _analysisPriorities) {
+      Queue<ServerOperation> queue = _queues[priority.ordinal];
+      for (PerformAnalysisOperation operation in queue) {
+        if (_server.isPriorityContext(operation.context)) {
+          queue.remove(operation);
+          return operation;
+        }
+      }
+    }
+    // non-priority operations
+    for (Queue<ServerOperation> queue in _queues) {
+      if (!queue.isEmpty) {
+        return queue.removeFirst();
+      }
+    }
+    // empty
+    return null;
+  }
+}
+
diff --git a/pkg/analysis_server/lib/src/protocol.dart b/pkg/analysis_server/lib/src/protocol.dart
index 07f4008..9efbf64 100644
--- a/pkg/analysis_server/lib/src/protocol.dart
+++ b/pkg/analysis_server/lib/src/protocol.dart
@@ -365,6 +365,41 @@
     }
     return datum;
   }
+
+  /**
+   * Determine if the datum is a map whose values are all string lists.
+   *
+   * Note: we can safely assume that the keys are all strings, since JSON maps
+   * cannot have any other key type.
+   */
+  bool isStringListMap() {
+    if (datum is! Map) {
+      return false;
+    }
+    for (var value in datum.values) {
+      if (value is! List) {
+        return false;
+      }
+      for (var listItem in value) {
+        if (listItem is! String) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Validate that the datum is a map from strings to string listss, and return
+   * it.
+   */
+  Map<String, List<String>> asStringListMap() {
+    if (!isStringListMap()) {
+      throw new RequestFailure(new Response.invalidParameter(request, path,
+          "be a string list map"));
+    }
+    return datum;
+  }
 }
 
 /**
@@ -466,6 +501,14 @@
     : this(requestId, new RequestError(-9, message));
 
   /**
+   * Initialize a newly created instance to represent an error condition caused
+   * by a `analysis.setSubscriptions` [request] that includes an unknown
+   * analysis service name.
+   */
+  Response.unknownAnalysisService(Request request, String name)
+    : this(request.id, new RequestError(-10, 'Unknown analysis service: "$name"'));
+
+  /**
    * Initialize a newly created instance based upon the given JSON data
    */
   factory Response.fromJson(Map<String, Object> json) {
diff --git a/pkg/analysis_server/lib/src/resource.dart b/pkg/analysis_server/lib/src/resource.dart
index b8b6c3c..e3df8af 100644
--- a/pkg/analysis_server/lib/src/resource.dart
+++ b/pkg/analysis_server/lib/src/resource.dart
@@ -80,6 +80,11 @@
    * Return the [Resource] that corresponds to the given [path].
    */
   Resource getResource(String path);
+
+  /**
+   * Get the path context used by this resource provider.
+   */
+  Context get pathContext;
 }
 
 
@@ -347,6 +352,9 @@
     _pathToTimestamp.remove(path);
     _notifyWatchers(path, ChangeType.REMOVE);
   }
+
+  @override
+  Context get pathContext => posix;
 }
 
 
@@ -442,4 +450,7 @@
       return new _PhysicalFile(file);
     }
   }
+
+  @override
+  Context get pathContext => io.Platform.isWindows ? windows : posix;
 }
diff --git a/pkg/analysis_server/lib/src/socket_server.dart b/pkg/analysis_server/lib/src/socket_server.dart
index 59b5a9b..7d673b4 100644
--- a/pkg/analysis_server/lib/src/socket_server.dart
+++ b/pkg/analysis_server/lib/src/socket_server.dart
@@ -7,7 +7,6 @@
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/channel.dart';
 import 'package:analysis_server/src/domain_analysis.dart';
-import 'package:analysis_server/src/domain_context.dart';
 import 'package:analysis_server/src/domain_server.dart';
 import 'package:analysis_server/src/protocol.dart';
 import 'package:analysis_server/src/resource.dart';
@@ -40,7 +39,8 @@
     }
     analysisServer = new AnalysisServer(
         serverChannel,
-        PhysicalResourceProvider.INSTANCE);
+        PhysicalResourceProvider.INSTANCE,
+        rethrowExceptions: false);
     _initializeHandlers(analysisServer);
   }
 
@@ -51,7 +51,6 @@
     server.handlers = [
         new ServerDomainHandler(server),
         new AnalysisDomainHandler(server),
-        new ContextDomainHandler(server),
     ];
   }
 
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
index 7b68188..eb003a9 100644
--- a/pkg/analysis_server/pubspec.yaml
+++ b/pkg/analysis_server/pubspec.yaml
@@ -11,6 +11,7 @@
   args: any
   logging: any
   path: any
+  typed_mock: any
   watcher: any
 dev_dependencies:
   mock: '>=0.10.0 <0.11.0'
diff --git a/pkg/analysis_server/test/analysis_abstract_test.dart b/pkg/analysis_server/test/analysis_abstract_test.dart
new file mode 100644
index 0000000..bc26d3e
--- /dev/null
+++ b/pkg/analysis_server/test/analysis_abstract_test.dart
@@ -0,0 +1,284 @@
+// 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.domain.analysis.abstract;
+
+import 'dart:async';
+
+import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/domain_analysis.dart';
+import 'package:analysis_server/src/constants.dart';
+import 'package:analysis_server/src/protocol.dart';
+import 'package:analysis_server/src/resource.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:unittest/unittest.dart';
+
+import 'mocks.dart';
+
+
+main() {
+}
+
+
+/**
+ * An abstract base for all 'analysis' domain tests.
+ */
+class AbstractAnalysisTest {
+  MockServerChannel serverChannel;
+  MemoryResourceProvider resourceProvider;
+  AnalysisServer server;
+  AnalysisDomainHandler handler;
+
+  Map<String, List<String>> analysisSubscriptions = {};
+
+  String projectPath = '/project';
+  String testFile = '/project/bin/test.dart';
+  String testCode;
+
+//  Map<String, List<AnalysisError>> filesErrors = {};
+//  Map<String, List<Map<String, Object>>> filesHighlights = {};
+//  Map<String, List<Map<String, Object>>> filesNavigation = {};
+
+
+  AbstractAnalysisTest() {
+  }
+
+  void setUp() {
+    serverChannel = new MockServerChannel();
+    resourceProvider = new MemoryResourceProvider();
+    server = new AnalysisServer(serverChannel, resourceProvider);
+    handler = new AnalysisDomainHandler(server);
+    // listen for notifications
+    Stream<Notification> notificationStream = serverChannel.notificationController.stream;
+    notificationStream.listen((Notification notification) {
+      processNotification(notification);
+    });
+    // create an empty project
+    _createEmptyProject();
+  }
+
+  void addAnalysisSubscription(AnalysisService service, String file) {
+    // add file to subscription
+    var files = analysisSubscriptions[service.name];
+    if (files == null) {
+      files = <String>[];
+      analysisSubscriptions[service.name] = files;
+    }
+    files.add(file);
+    // set subscriptions
+    Request request = new Request('0', METHOD_SET_ANALYSIS_SUBSCRIPTIONS);
+    request.setParameter(SUBSCRIPTIONS, analysisSubscriptions);
+    handleSuccessfulRequest(request);
+  }
+
+  void tearDown() {
+    server.done();
+    handler = null;
+    server = null;
+    resourceProvider = null;
+    serverChannel = null;
+  }
+
+  void processNotification(Notification notification) {
+//    if (notification.event == NOTIFICATION_ERRORS) {
+//      String file = notification.getParameter(FILE);
+//      List<Map<String, Object>> errorMaps = notification.getParameter(ERRORS);
+//      filesErrors[file] = errorMaps.map(jsonToAnalysisError).toList();
+//    }
+//    if (notification.event == NOTIFICATION_HIGHLIGHTS) {
+//      String file = notification.getParameter(FILE);
+//      filesHighlights[file] = notification.getParameter(REGIONS);
+//    }
+//    if (notification.event == NOTIFICATION_NAVIGATION) {
+//      String file = notification.getParameter(FILE);
+//      filesNavigation[file] = notification.getParameter(REGIONS);
+//    }
+  }
+
+  /**
+   * Returns a [Future] that completes when the [AnalysisServer] finishes
+   * all its scheduled tasks.
+   */
+  Future waitForTasksFinished() {
+    return waitForServerOperationsPerformed(server);
+  }
+
+  /**
+   * Returns the offset of [search] in [testCode].
+   * Fails if not found.
+   */
+  int findFileOffset(String path, String search) {
+    File file = resourceProvider.getResource(path) as File;
+    String code = file.createSource(UriKind.FILE_URI).contents.data;
+    int offset = code.indexOf(search);
+    expect(offset, isNot(-1), reason: '"$search" in\n$code');
+    return offset;
+  }
+
+  /**
+   * Returns the offset of [search] in [testCode].
+   * Fails if not found.
+   */
+  int findOffset(String search) {
+    int offset = testCode.indexOf(search);
+    expect(offset, isNot(-1));
+    return offset;
+  }
+
+//  /**
+//   * Returns [AnalysisError]s recorded for the given [file].
+//   * May be empty, but not `null`.
+//   */
+//  List<AnalysisError> getErrors(String file) {
+//    List<AnalysisError> errors = filesErrors[file];
+//    if (errors != null) {
+//      return errors;
+//    }
+//    return <AnalysisError>[];
+//  }
+//
+//  /**
+//   * Returns highlights recorded for the given [file].
+//   * May be empty, but not `null`.
+//   */
+//  List<Map<String, Object>> getHighlights(String file) {
+//    List<Map<String, Object>> highlights = filesHighlights[file];
+//    if (highlights != null) {
+//      return highlights;
+//    }
+//    return [];
+//  }
+//
+//  /**
+//   * Returns navigation regions recorded for the given [file].
+//   * May be empty, but not `null`.
+//   */
+//  List<Map<String, Object>> getNavigation(String file) {
+//    List<Map<String, Object>> navigation = filesNavigation[file];
+//    if (navigation != null) {
+//      return navigation;
+//    }
+//    return [];
+//  }
+//
+//  /**
+//   * Returns [AnalysisError]s recorded for the [testFile].
+//   * May be empty, but not `null`.
+//   */
+//  List<AnalysisError> getTestErrors() {
+//    return getErrors(testFile);
+//  }
+//
+//  /**
+//   * Returns highlights recorded for the given [testFile].
+//   * May be empty, but not `null`.
+//   */
+//  List<Map<String, Object>> getTestHighlights() {
+//    return getHighlights(testFile);
+//  }
+//
+//  /**
+//   * Returns navigation information recorded for the given [testFile].
+//   * May be empty, but not `null`.
+//   */
+//  List<Map<String, Object>> getTestNavigation() {
+//    return getNavigation(testFile);
+//  }
+
+  /**
+   * Creates an empty project `/project/`.
+   */
+  void _createEmptyProject() {
+    resourceProvider.newFolder(projectPath);
+    Request request = new Request('0', METHOD_SET_ANALYSIS_ROOTS);
+    request.setParameter(INCLUDED, [projectPath]);
+    request.setParameter(EXCLUDED, []);
+    handleSuccessfulRequest(request);
+  }
+
+//  /**
+//   * Creates a project with a single Dart file `/project/bin/test.dart` with
+//   * the given [code].
+//   */
+//  void createSingleFileProject(code) {
+//    this.testCode = _getCodeString(code);
+//    resourceProvider.newFolder('/project');
+//    resourceProvider.newFile(testFile, testCode);
+//    Request request = new Request('0', METHOD_SET_ANALYSIS_ROOTS);
+//    request.setParameter(INCLUDED, ['/project']);
+//    request.setParameter(EXCLUDED, []);
+//    handleSuccessfulRequest(request);
+//  }
+
+  String addFile(String path, String content) {
+    resourceProvider.newFile(path, content);
+    return path;
+  }
+
+  String addTestFile(String content) {
+    addFile(testFile, content);
+    this.testCode = content;
+    return testFile;
+  }
+
+  /**
+   * Validates that the given [request] is handled successfully.
+   */
+  void handleSuccessfulRequest(Request request) {
+    Response response = handler.handleRequest(request);
+    expect(response, isResponseSuccess('0'));
+  }
+
+  static String _getCodeString(code) {
+    if (code is List<String>) {
+      code = code.join('\n');
+    }
+    return code as String;
+  }
+}
+
+
+
+class AnalysisError {
+  final String file;
+  final String errorCode;
+  final int offset;
+  final int length;
+  final String message;
+  final String correction;
+  AnalysisError(this.file, this.errorCode, this.offset, this.length,
+      this.message, this.correction);
+
+  @override
+  String toString() {
+    return 'NotificationError(file=$file; errorCode=$errorCode; '
+        'offset=$offset; length=$length; message=$message)';
+  }
+}
+
+
+AnalysisError _jsonToAnalysisError(Map<String, Object> json) {
+  return new AnalysisError(
+      json['file'],
+      json['errorCode'],
+      json['offset'],
+      json['length'],
+      json['message'],
+      json['correction']);
+}
+
+
+int findIdentifierLength(String search) {
+  int length = 0;
+  while (length < search.length) {
+    int c = search.codeUnitAt(length);
+    if (!(c >= 'a'.codeUnitAt(0) && c <= 'z'.codeUnitAt(0) ||
+          c >= 'A'.codeUnitAt(0) && c <= 'Z'.codeUnitAt(0) ||
+          c >= '0'.codeUnitAt(0) && c <= '9'.codeUnitAt(0))) {
+      break;
+    }
+    length++;
+  }
+  return length;
+}
diff --git a/pkg/analysis_server/test/analysis_notification_navigation_test.dart b/pkg/analysis_server/test/analysis_notification_navigation_test.dart
new file mode 100644
index 0000000..0268147
--- /dev/null
+++ b/pkg/analysis_server/test/analysis_notification_navigation_test.dart
@@ -0,0 +1,420 @@
+// 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.domain.analysis.notification.navigation;
+
+import 'dart:async';
+
+import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/constants.dart';
+import 'package:analysis_server/src/protocol.dart';
+import 'package:unittest/unittest.dart';
+
+import 'analysis_abstract_test.dart';
+import 'reflective_tests.dart';
+
+
+@ReflectiveTestCase()
+class AnalysisNotificationNavigationTest extends AbstractAnalysisTest {
+  List<Map<String, Object>> regions;
+  Map<String, Object> testRegion;
+  List<Map<String, Object>> testTargets;
+
+  void processNotification(Notification notification) {
+    if (notification.event == NOTIFICATION_NAVIGATION) {
+      String file = notification.getParameter(FILE);
+      if (file == testFile) {
+        regions = notification.getParameter(REGIONS);
+      }
+    }
+  }
+
+  Future prepareNavigation(then()) {
+    addAnalysisSubscription(AnalysisService.NAVIGATION, testFile);
+    return waitForTasksFinished().then((_) {
+      then();
+    });
+  }
+
+  /**
+   * Finds the navigation region with the given [offset] and [length].
+   * If [length] is `-1`, then it is ignored.
+   *
+   * If [exists] is `true`, then fails if such region does not exist.
+   * Otherwise remembers this it into [testRegion].
+   * Also fills [testTargets] with its targets.
+   *
+   * If [exists] is `false`, then fails if such region exists.
+   */
+  void findRegion(int offset, int length, [bool exists]) {
+    for (Map<String, Object> region in regions) {
+      if (region['offset'] == offset &&
+          (length == -1 || region['length'] == length)) {
+        if (exists == false) {
+          fail('Not expected to find (offset=$offset; length=$length) in\n'
+               '${regions.join('\n')}');
+        }
+        testRegion = region;
+        testTargets = region['targets'];
+        return;
+      }
+    }
+    if (exists == true) {
+      fail('Expected to find (offset=$offset; length=$length) in\n'
+           '${regions.join('\n')}');
+    }
+  }
+
+  /**
+   * Validates that there is a region at the offset of [search] in [testFile].
+   * If [length] is not specified explicitly, then length of an identifier
+   * from [search] is used.
+   */
+  void assertHasRegion(String search, [int length = -1]) {
+    int offset = findOffset(search);
+    if (length == -1) {
+      length = findIdentifierLength(search);
+    }
+    findRegion(offset, length, true);
+  }
+
+  /**
+   * Validates that there is a region at the offset of [search] in [testFile]
+   * with the length of [search].
+   */
+  void assertHasRegionString(String search) {
+    int offset = findOffset(search);
+    int length = search.length;
+    findRegion(offset, length, true);
+  }
+
+  /**
+   * Validates that there is a target in [testTargets]  with [testFile], at the
+   * offset of [search] in [testFile], and with the given [length] or the length
+   * of an leading identifier in [search].
+   */
+  void assertHasTarget(String search, [int length = -1]) {
+    int offset = findOffset(search);
+    if (length == -1) {
+      length = findIdentifierLength(search);
+    }
+    for (Map<String, Object> target in testTargets) {
+      if (target['file'] == testFile &&
+          target['offset'] == offset &&
+          target['length'] == length) {
+        return;
+      }
+    }
+    fail('Expected to find target (offset=$offset; length=$length) in\n'
+         '${testRegion} in\n'
+         '${regions.join('\n')}');
+  }
+
+  /**
+   * Validates that there is a target in [testTargets]  with [file], at [offset]
+   * and with the given [length].
+   */
+  void assertHasFileTarget(String file, int offset, int length) {
+    for (Map<String, Object> target in testTargets) {
+      if (target['file'] == file &&
+          target['offset'] == offset &&
+          target['length'] == length) {
+        return;
+      }
+    }
+    fail('Expected to find target (file=$file; offset=$offset; length=$length) in\n'
+         '${testRegion} in\n'
+         '${regions.join('\n')}');
+  }
+
+  /**
+   * Validates that there is an identifier region at [regionSearch] with target
+   * at [targetSearch].
+   */
+  void assertHasRegionTarget(String regionSearch, String targetSearch) {
+    assertHasRegion(regionSearch);
+    assertHasTarget(targetSearch);
+  }
+
+  void assertHasOperatorRegion(String regionSearch, int regionLength,
+                               String targetSearch, int targetLength) {
+    assertHasRegion(regionSearch, regionLength);
+    assertHasTarget(targetSearch, targetLength);
+  }
+
+  /**
+   * Validates that there is no a region at [search] and with the given
+   * [length].
+   */
+  void assertNoRegion(String search, int length) {
+    int offset = findOffset(search);
+    findRegion(offset, length, false);
+  }
+
+  /**
+   * Validates that there is no a region at [search] with any length.
+   */
+  void assertNoRegionAt(String search) {
+    int offset = findOffset(search);
+    findRegion(offset, -1, false);
+  }
+
+  /**
+   * Validates that there is no a region for [search] string.
+   */
+  void assertNoRegionString(String search) {
+    int offset = findOffset(search);
+    int length = search.length;
+    findRegion(offset, length, false);
+  }
+
+  test_constructor_named() {
+    addTestFile('''
+class A {
+  A.named(BBB p) {}
+}
+class BBB {}
+''');
+    return prepareNavigation(() {
+      // has region for complete "A.named"
+      assertHasRegionString('A.named');
+      assertHasTarget('named(BBB');
+      // no separate regions for "A" and "named"
+      assertNoRegion('A.named(', 'A'.length);
+      assertNoRegion('named(', 'named'.length);
+      // validate that we don't forget to resolve parameters
+      assertHasRegionTarget('BBB p', 'BBB {}');
+    });
+  }
+
+  test_constructor_unnamed() {
+    addTestFile('''
+class A {
+  A(BBB p) {}
+}
+class BBB {}
+''');
+    return prepareNavigation(() {
+      // has region for complete "A.named"
+      assertHasRegion("A(BBB");
+      assertHasTarget("A(BBB", 0);
+      // validate that we don't forget to resolve parameters
+      assertHasRegionTarget('BBB p', 'BBB {}');
+    });
+  }
+
+  test_fieldFormalParameter() {
+    addTestFile('''
+class AAA {
+  int fff = 123;
+  AAA(this.fff);
+}
+''');
+    return prepareNavigation(() {
+      assertHasRegionTarget('fff);', 'fff = 123');
+    });
+  }
+
+  test_identifier_resolved() {
+    addTestFile('''
+class AAA {}
+main() {
+  AAA aaa = null;
+  print(aaa);
+}
+''');
+    return prepareNavigation(() {
+      assertHasRegionTarget('AAA aaa', 'AAA {}');
+      assertHasRegionTarget('aaa);', 'aaa = null');
+      assertHasRegionTarget('main() {', 'main() {');
+    });
+  }
+
+  test_identifier_unresolved() {
+    addTestFile('''
+main() {
+  print(vvv);
+}
+''');
+    return prepareNavigation(() {
+      assertNoRegionString('vvv');
+    });
+  }
+
+  test_instanceCreation_named() {
+    addTestFile('''
+class A {
+  A.named() {}
+}
+main() {
+  new A.named();
+}
+''');
+    return prepareNavigation(() {
+      assertHasRegionString('new A.named');
+      assertHasTarget('named() {}');
+    });
+  }
+
+  test_instanceCreation_unnamed() {
+    addTestFile('''
+class A {
+  A() {}
+}
+main() {
+  new A();
+}
+''');
+    return prepareNavigation(() {
+      assertHasRegionString('new A');
+      assertHasTarget("A() {}", 0);
+    });
+  }
+
+  test_operator_arithmetic() {
+    addTestFile('''
+class A {
+  A operator +(other) => null;
+  A operator -() => null;
+  A operator -(other) => null;
+  A operator *(other) => null;
+  A operator /(other) => null;
+}
+main() {
+  var a = new A();
+  a - 1;
+  a + 2;
+  -a; // unary
+  --a;
+  ++a;
+  a--; // mm
+  a++; // pp
+  a -= 3;
+  a += 4;
+  a *= 5;
+  a /= 6;
+}
+''');
+    return prepareNavigation(() {
+      assertHasOperatorRegion('- 1', 1, '-(other) => null', 1);
+      assertHasOperatorRegion('+ 2', 1, '+(other) => null', 1);
+      assertHasOperatorRegion('-a; // unary', 1, '-() => null', 1);
+      assertHasOperatorRegion('--a;', 2, '-(other) => null', 1);
+      assertHasOperatorRegion('++a;', 2, '+(other) => null', 1);
+      assertHasOperatorRegion('--; // mm', 2, '-(other) => null', 1);
+      assertHasOperatorRegion('++; // pp', 2, '+(other) => null', 1);
+      assertHasOperatorRegion('-= 3', 2, '-(other) => null', 1);
+      assertHasOperatorRegion('+= 4', 2, '+(other) => null', 1);
+      assertHasOperatorRegion('*= 5', 2, '*(other) => null', 1);
+      assertHasOperatorRegion('/= 6', 2, '/(other) => null', 1);
+    });
+  }
+
+  test_operator_index() {
+    addTestFile('''
+class A {
+  A operator +(other) => null;
+}
+class B {
+  A operator [](index) => null;
+  operator []=(index, A value) {}
+}
+main() {
+  var b = new B();
+  b[0] // [];
+  b[1] = 1; // []=;
+  b[2] += 2;
+}
+''');
+    return prepareNavigation(() {
+      assertHasOperatorRegion('] // []', 1, '[](index)', 2);
+      assertHasOperatorRegion('] = 1;', 1, '[]=(index,', 3);
+      assertHasOperatorRegion('] += 2;', 1, '[]=(index,', 3);
+      assertHasOperatorRegion('+= 2;', 2, '+(other)', 1);
+    });
+  }
+
+  test_partOf() {
+    var libCode = 'library lib; part "test.dart";';
+    var libFile = addFile('$projectPath/bin/lib.dart', libCode);
+    addTestFile('part of lib;');
+    return prepareNavigation(() {
+      assertHasRegionString('part of lib');
+      assertHasFileTarget(libFile, libCode.indexOf('lib;'), 'lib'.length);
+    });
+  }
+
+  test_string_export() {
+    var libCode = 'library lib;';
+    var libFile = addFile('$projectPath/bin/lib.dart', libCode);
+    addTestFile('export "lib.dart";');
+    return prepareNavigation(() {
+      assertHasRegionString('export "lib.dart"');
+      assertHasFileTarget(libFile, libCode.indexOf('lib;'), 'lib'.length);
+    });
+  }
+
+  test_string_export_unresolvedUri() {
+    addTestFile('export "no.dart";');
+    return prepareNavigation(() {
+      assertNoRegionString('export "no.dart"');
+    });
+  }
+
+  test_string_import() {
+    var libCode = 'library lib;';
+    var libFile = addFile('$projectPath/bin/lib.dart', libCode);
+    addTestFile('import "lib.dart";');
+    return prepareNavigation(() {
+      assertHasRegionString('import "lib.dart"');
+      assertHasFileTarget(libFile, libCode.indexOf('lib;'), 'lib'.length);
+    });
+  }
+
+  test_string_import_noUri() {
+    addTestFile('import ;');
+    return prepareNavigation(() {
+      assertNoRegionAt('import ;');
+    });
+  }
+
+  test_string_import_unresolvedUri() {
+    addTestFile('import "no.dart";');
+    return prepareNavigation(() {
+      assertNoRegionString('import "no.dart"');
+    });
+  }
+
+  test_string_part() {
+    var unitCode = 'part of lib;  f() {}';
+    var unitFile = addFile('$projectPath/bin/test_unit.dart', unitCode);
+    addTestFile('''
+library lib;
+part "test_unit.dart";
+''');
+    return prepareNavigation(() {
+      assertHasRegionString('part "test_unit.dart"');
+      assertHasFileTarget(unitFile, 0, 0);
+    });
+  }
+
+  test_string_part_unresolvedUri() {
+    // TODO(scheglov) why do we throw MemoryResourceException here?
+    // This Source/File does not exist.
+//    addTestFile('''
+//library lib;
+//part "test_unit.dart";
+//''');
+//    return prepareNavigation(() {
+//      assertNoRegionString('part "test_unit.dart"');
+//    });
+  }
+}
+
+
+main() {
+  group('notification.navigation', () {
+    runReflectiveTests(AnalysisNotificationNavigationTest);
+  });
+}
\ No newline at end of file
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index dd4807b..b3c11f6 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -4,11 +4,12 @@
 
 library test.analysis_server;
 
-import 'dart:async';
-
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/src/generated/source.dart';
 import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/domain_server.dart';
 import 'package:analysis_server/src/protocol.dart';
 import 'package:analysis_server/src/resource.dart';
@@ -16,214 +17,95 @@
 import 'package:unittest/unittest.dart';
 
 import 'mocks.dart';
+import 'package:analysis_server/src/operation/operation.dart';
+
+class AnalysisServerTestHelper {
+  MockServerChannel channel;
+  AnalysisServer server;
+
+  AnalysisServerTestHelper({bool rethrowExceptions: true}) {
+    channel = new MockServerChannel();
+    server = new AnalysisServer(channel, PhysicalResourceProvider.INSTANCE,
+        rethrowExceptions: rethrowExceptions);
+  }
+}
 
 main() {
   group('AnalysisServer', () {
-    setUp(AnalysisServerTest.setUp);
-    test('addContextToWorkQueue_twice',
-        AnalysisServerTest.addContextToWorkQueue_twice);
-    test('addContextToWorkQueue_whenNotRunning',
-        AnalysisServerTest.addContextToWorkQueue_whenNotRunning);
-    // TODO(scheglov) remove or move to the 'analysis' domain
-//    test('addContextToWorkQueue_whenRunning',
-//        AnalysisServerTest.addContextToWorkQueue_whenRunning);
-//    test('createContext', AnalysisServerTest.createContext);
-    test('echo', AnalysisServerTest.echo);
-    test('errorToJson_formattingApplied',
-        AnalysisServerTest.errorToJson_formattingApplied);
-    test('errorToJson_noCorrection',
-        AnalysisServerTest.errorToJson_noCorrection);
-    test('errorToJson_withCorrection',
-        AnalysisServerTest.errorToJson_withCorrection);
-    test('performTask_whenNotRunning',
-        AnalysisServerTest.performTask_whenNotRunning);
-    test('shutdown', AnalysisServerTest.shutdown);
-    test('unknownRequest', AnalysisServerTest.unknownRequest);
+    test('server.status notifications', () {
+      AnalysisServerTestHelper helper = new AnalysisServerTestHelper();
+      MockAnalysisContext context = new MockAnalysisContext();
+      MockSource source = new MockSource();
+      source.when(callsTo('get fullName')).alwaysReturn('foo.dart');
+      source.when(callsTo('get isInSystemLibrary')).alwaysReturn(false);
+      ChangeNoticeImpl notice = new ChangeNoticeImpl(source);
+      notice.setErrors([], new LineInfo([0]));
+      AnalysisResult firstResult = new AnalysisResult([notice], 0, '', 0);
+      AnalysisResult lastResult = new AnalysisResult(null, 1, '', 1);
+      context.when(callsTo("performAnalysisTask"))
+        ..thenReturn(firstResult, 3)
+        ..thenReturn(lastResult);
+      helper.server.schedulePerformAnalysisOperation(context);
+      // Pump the event queue to make sure the server has finished any
+      // analysis.
+      return pumpEventQueue().then((_) {
+        List<Notification> notifications = helper.channel.notificationsReceived;
+        expect(notifications, isNot(isEmpty));
+        Notification notification = notifications[notifications.length - 1];
+        Map analysisStatus = notification.params['analysis'];
+        expect(analysisStatus['analyzing'], isFalse);
+      });
+    });
+
+    test('echo', () {
+      AnalysisServerTestHelper helper = new AnalysisServerTestHelper();
+      helper.server.handlers = [new EchoHandler()];
+      var request = new Request('my22', 'echo');
+      return helper.channel.sendRequest(request)
+          .then((Response response) {
+            expect(response.id, equals('my22'));
+            expect(response.error, isNull);
+          });
+    });
+
+    test('shutdown', () {
+      AnalysisServerTestHelper helper = new AnalysisServerTestHelper();
+      helper.server.handlers = [new ServerDomainHandler(helper.server)];
+      var request = new Request('my28', METHOD_SHUTDOWN);
+      return helper.channel.sendRequest(request)
+          .then((Response response) {
+            expect(response.id, equals('my28'));
+            expect(response.error, isNull);
+          });
+    });
+
+    test('unknownRequest', () {
+      AnalysisServerTestHelper helper = new AnalysisServerTestHelper();
+      helper.server.handlers = [new EchoHandler()];
+      var request = new Request('my22', 'randomRequest');
+      return helper.channel.sendRequest(request)
+          .then((Response response) {
+            expect(response.id, equals('my22'));
+            expect(response.error, isNotNull);
+          });
+    });
+
+    test('rethrow exceptions', () {
+      AnalysisServerTestHelper helper = new AnalysisServerTestHelper();
+      Exception exceptionToThrow = new Exception('test exception');
+      MockServerOperation operation = new MockServerOperation(
+          ServerOperationPriority.ANALYSIS, (_) { throw exceptionToThrow; });
+      helper.server.operationQueue.add(operation);
+      try {
+        helper.server.performOperation();
+        fail('exception not rethrown');
+      } on AnalysisException catch (exception) {
+        expect(exception.cause.exception, equals(exceptionToThrow));
+      }
+    });
   });
 }
 
-class AnalysisServerTest {
-  static MockServerChannel channel;
-  static AnalysisServer server;
-  static MockAnalysisLogger logger;
-
-  static void setUp() {
-    channel = new MockServerChannel();
-    server = new AnalysisServer(channel, PhysicalResourceProvider.INSTANCE);
-    logger = new MockAnalysisLogger();
-    AnalysisEngine.instance.logger = logger;
-  }
-
-  static Future addContextToWorkQueue_whenNotRunning() {
-    server.running = false;
-    MockAnalysisContext context = new MockAnalysisContext();
-    server.addContextToWorkQueue(context);
-    // Pump the event queue to make sure the server doesn't try to do any
-    // analysis.
-    return pumpEventQueue();
-  }
-
-  // TODO(scheglov) remove after implementing "setAnalysisRoots" API
-//  static Future addContextToWorkQueue_whenRunning() {
-//    MockAnalysisContext context = new MockAnalysisContext();
-//    server.addContextToWorkQueue(context);
-//    server.contextIdMap[context] = 'context-27';
-//    MockSource source = new MockSource();
-//    source.when(callsTo('get encoding')).alwaysReturn('foo.dart');
-//    ChangeNoticeImpl changeNoticeImpl = new ChangeNoticeImpl(source);
-//    LineInfo lineInfo = new LineInfo([0]);
-//    AnalysisError analysisError = new AnalysisError.con1(source,
-//        CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER, ['Foo']);
-//    changeNoticeImpl.setErrors([analysisError], lineInfo);
-//    context.when(callsTo('performAnalysisTask')).thenReturn(
-//        new AnalysisResult([changeNoticeImpl], 0, 'myClass', 0));
-//    context.when(callsTo('performAnalysisTask')).thenReturn(
-//        new AnalysisResult(null, 0, null, 0));
-//    return pumpEventQueue().then((_) {
-//      context.getLogs(callsTo('performAnalysisTask')).verify(happenedExactly(2));
-//      List<Notification> notifications = channel.notificationsReceived;
-//      expect(notifications, hasLength(4));
-//
-//      expect(notifications[0].event, equals('server.connected'));
-//
-//      assertStatusNotification(notifications[1], true);
-//
-//      expect(notifications[2].event, equals('context.errors'));
-//      expect(notifications[2].params['source'], equals('foo.dart'));
-//      expect(notifications[2].params['contextId'], equals('context-27'));
-//      List<AnalysisError> errors = notifications[2].params['errors'];
-//      expect(errors, hasLength(1));
-//      expect(errors[0], equals(AnalysisServer.errorToJson(analysisError)));
-//
-//      assertStatusNotification(notifications[3], false);
-//    });
-//  }
-//
-//  static void assertStatusNotification(Notification notification, bool expectAnalyzing) {
-//    expect(notification.event, equals('server.status'));
-//    Map<String, Object> analysis = notification.params['analysis'];
-//    expect(analysis['analyzing'], expectAnalyzing);
-//    expect(analysis.containsKey('analysisTarget'), expectAnalyzing);
-//    if (expectAnalyzing) {
-//      var analysisTarget = analysis['analysisTarget'];
-//      expect((analysisTarget is String), isTrue);
-//      expect(analysisTarget.length > 0, isTrue);
-//    }
-//  }
-
-  static Future addContextToWorkQueue_twice() {
-    // TODO(scheglov) remove after implementing "setAnalysisRoots" API
-    return new Future.value();
-//    // The context should only be asked to perform its analysis task once.
-//    MockAnalysisContext context = new MockAnalysisContext();
-//    server.addContextToWorkQueue(context);
-//    server.addContextToWorkQueue(context);
-//    context.when(callsTo('performAnalysisTask')).thenReturn(
-//        new AnalysisResult(null, 0, null, 0));
-//    return pumpEventQueue().then((_) =>
-//        context.getLogs(callsTo('performAnalysisTask')).verify(happenedExactly(1)));
-  }
-
-  // TODO(scheglov) remove or move to the 'analysis' domain
-//  static Future createContext() {
-//    server.handlers = [new ServerDomainHandler(server)];
-//    var request = new Request('my27', ServerDomainHandler.CREATE_CONTEXT_METHOD);
-//    request.setParameter(ServerDomainHandler.SDK_DIRECTORY_PARAM, sdkPath);
-//    request.setParameter(AnalysisServer.CONTEXT_ID_PARAM, 'ctx');
-//    return channel.sendRequest(request)
-//        .then((Response response) {
-//          expect(response.id, equals('my27'));
-//          expect(response.error, isNull);
-//        });
-//  }
-
-  static Future echo() {
-    server.handlers = [new EchoHandler()];
-    var request = new Request('my22', 'echo');
-    return channel.sendRequest(request)
-        .then((Response response) {
-          expect(response.id, equals('my22'));
-          expect(response.error, isNull);
-        });
-  }
-
-  static void errorToJson_formattingApplied() {
-    MockSource source = new MockSource();
-    source.when(callsTo('get encoding')).alwaysReturn('foo.dart');
-    CompileTimeErrorCode errorCode = CompileTimeErrorCode.AMBIGUOUS_EXPORT;
-    AnalysisError analysisError =
-        new AnalysisError.con1(source, errorCode, ['foo', 'bar', 'baz']);
-    Map<String, Object> json = AnalysisServer.errorToJson(analysisError);
-
-    expect(json['message'],
-        equals("The name 'foo' is defined in the libraries 'bar' and 'baz'"));
-  }
-
-  static void errorToJson_noCorrection() {
-    MockSource source = new MockSource();
-    source.when(callsTo('get fullName')).alwaysReturn('foo.dart');
-    CompileTimeErrorCode errorCode =
-        CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER;
-    AnalysisError analysisError =
-        new AnalysisError.con2(source, 10, 5, errorCode, ['Foo']);
-    Map<String, Object> json = AnalysisServer.errorToJson(analysisError);
-    expect(json, hasLength(5));
-    expect(json['file'], equals('foo.dart'));
-    expect(json['errorCode'], 'CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER');
-    expect(json['offset'], equals(analysisError.offset));
-    expect(json['length'], equals(analysisError.length));
-    expect(json['message'], equals(errorCode.message.replaceAll('%s', 'Foo')));
-  }
-
-  static void errorToJson_withCorrection() {
-    MockSource source = new MockSource();
-    source.when(callsTo('get encoding')).alwaysReturn('foo.dart');
-
-    // TODO(paulberry): in principle we should test an error or hint that uses
-    // %s formatting in its correction string.  But no such errors or hints
-    // currently exist!
-    HintCode errorCode = HintCode.MISSING_RETURN;
-
-    AnalysisError analysisError =
-        new AnalysisError.con2(source, 10, 5, errorCode, ['int']);
-    Map<String, Object> json = AnalysisServer.errorToJson(analysisError);
-    expect(json['correction'], equals(errorCode.correction));
-  }
-
-  static Future performTask_whenNotRunning() {
-    // If the server is shut down while there is analysis still pending,
-    // performTask() should notice that the server is no longer running and
-    // do no analysis.
-    MockAnalysisContext context = new MockAnalysisContext();
-    server.addContextToWorkQueue(context);
-    server.running = false;
-    // Pump the event queue to make sure the server doesn't try to do any
-    // analysis.
-    return pumpEventQueue();
-  }
-
-  static Future shutdown() {
-    server.handlers = [new ServerDomainHandler(server)];
-    var request = new Request('my28', ServerDomainHandler.SHUTDOWN_METHOD);
-    return channel.sendRequest(request)
-        .then((Response response) {
-          expect(response.id, equals('my28'));
-          expect(response.error, isNull);
-        });
-  }
-
-  static Future unknownRequest() {
-    server.handlers = [new EchoHandler()];
-    var request = new Request('my22', 'randomRequest');
-    return channel.sendRequest(request)
-        .then((Response response) {
-          expect(response.id, equals('my22'));
-          expect(response.error, isNotNull);
-        });
-  }
-}
-
-
 class EchoHandler implements RequestHandler {
   @override
   Response handleRequest(Request request) {
diff --git a/pkg/analysis_server/test/context_directory_manager_test.dart b/pkg/analysis_server/test/context_directory_manager_test.dart
index f9d359e..283dd63 100644
--- a/pkg/analysis_server/test/context_directory_manager_test.dart
+++ b/pkg/analysis_server/test/context_directory_manager_test.dart
@@ -97,6 +97,23 @@
       expect(filePaths, contains(filePath));
     });
 
+    test('ignore files in packages dir', () {
+      String projPath = '/my/proj';
+      provider.newFolder(projPath);
+      String pubspecPath = posix.join(projPath, 'pubspec.yaml');
+      provider.newFile(pubspecPath, 'pubspec');
+      String filePath1 = posix.join(projPath, 'packages', 'file1.dart');
+      provider.newFile(filePath1, 'contents');
+      manager.setRoots(<String>[projPath], <String>[]);
+      Set<String> filePaths = manager.currentContextFilePaths[projPath];
+      expect(filePaths, hasLength(0));
+      String filePath2 = posix.join(projPath, 'packages', 'file2.dart');
+      provider.newFile(filePath2, 'contents');
+      return pumpEventQueue().then((_) {
+        expect(filePaths, hasLength(0));
+      });
+    });
+
     group('detect context modifications', () {
       String projPath;
 
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart
index 2a4d8d2..4e1fa97 100644
--- a/pkg/analysis_server/test/domain_analysis_test.dart
+++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -7,6 +7,8 @@
 import 'dart:async';
 
 import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/constants.dart';
+import 'package:analysis_server/src/computers.dart';
 import 'package:analysis_server/src/domain_analysis.dart';
 import 'package:analysis_server/src/protocol.dart';
 import 'package:analysis_server/src/resource.dart';
@@ -30,22 +32,25 @@
   });
 
   group('notification.errors', testNotificationErrors);
+  group('notification.highlights', testNotificationHighlights);
+  group('notification.navigation', testNotificationNavigation);
   group('updateContent', testUpdateContent);
+  group('setSubscriptions', test_setSubscriptions);
 
   group('AnalysisDomainHandler', () {
     test('getFixes', () {
-      var request = new Request('0', AnalysisDomainHandler.GET_FIXES_METHOD);
-      request.setParameter(AnalysisDomainHandler.ERRORS_PARAM, []);
+      var request = new Request('0', METHOD_GET_FIXES);
+      request.setParameter(ERRORS, []);
       var response = handler.handleRequest(request);
       // TODO(scheglov) implement
       expect(response, isNull);
     });
 
     test('getMinorRefactorings', () {
-      var request = new Request('0', AnalysisDomainHandler.GET_MINOR_REFACTORINGS_METHOD);
-      request.setParameter(AnalysisDomainHandler.FILE_PARAM, 'test.dart');
-      request.setParameter(AnalysisDomainHandler.OFFSET_PARAM, 10);
-      request.setParameter(AnalysisDomainHandler.LENGTH_PARAM, 20);
+      var request = new Request('0', METHOD_GET_MINOR_REFACTORINGS);
+      request.setParameter(FILE, 'test.dart');
+      request.setParameter(OFFSET, 10);
+      request.setParameter(LENGTH, 20);
       var response = handler.handleRequest(request);
       // TODO(scheglov) implement
       expect(response, isNull);
@@ -55,13 +60,13 @@
       Request request;
 
       setUp(() {
-        request = new Request('0', AnalysisDomainHandler.SET_ANALYSIS_ROOTS_METHOD);
-        request.setParameter(AnalysisDomainHandler.INCLUDED_PARAM, []);
-        request.setParameter(AnalysisDomainHandler.EXCLUDED_PARAM, []);
+        request = new Request('0', METHOD_SET_ANALYSIS_ROOTS);
+        request.setParameter(INCLUDED, []);
+        request.setParameter(EXCLUDED, []);
       });
 
       test('excluded', () {
-        request.setParameter(AnalysisDomainHandler.EXCLUDED_PARAM, ['foo']);
+        request.setParameter(EXCLUDED, ['foo']);
         // TODO(scheglov) implement
         var response = handler.handleRequest(request);
         expect(response, isResponseFailure('0'));
@@ -73,13 +78,13 @@
           resourceProvider.newFile('/project/pubspec.yaml', 'name: project');
           resourceProvider.newFile('/project/bin/test.dart', 'main() {}');
           request.setParameter(
-              AnalysisDomainHandler.INCLUDED_PARAM,
+              INCLUDED,
               ['/project']);
           var response = handler.handleRequest(request);
           var serverRef = server;
           expect(response, isResponseSuccess('0'));
           // verify that unit is resolved eventually
-          return waitForServerTasksFinished(server).then((_) {
+          return waitForServerOperationsPerformed(server).then((_) {
             var unit = serverRef.test_getResolvedCompilationUnit('/project/bin/test.dart');
             expect(unit, isNotNull);
           });
@@ -88,33 +93,19 @@
     });
 
     test('setPriorityFiles', () {
-      var request = new Request('0', AnalysisDomainHandler.SET_PRIORITY_FILES_METHOD);
+      var request = new Request('0', METHOD_SET_PRIORITY_FILES);
       request.setParameter(
-          AnalysisDomainHandler.FILES_PARAM,
+          FILES,
           ['projectA/aa.dart', 'projectB/ba.dart']);
       var response = handler.handleRequest(request);
       // TODO(scheglov) implement
       expect(response, isNull);
     });
 
-    test('setSubscriptions', () {
-      var request = new Request('0', AnalysisDomainHandler.SET_SUBSCRIPTIONS_METHOD);
-      request.setParameter(
-          AnalysisDomainHandler.SUBSCRIPTIONS_PARAM,
-          {
-            AnalysisService.HIGHLIGHTS : ['project/a.dart', 'project/b.dart'],
-            AnalysisService.NAVIGATION : ['project/c.dart'],
-            AnalysisService.OUTLINE : ['project/d.dart', 'project/e.dart']
-          });
-      var response = handler.handleRequest(request);
-      // TODO(scheglov) implement
-      expect(response, isNull);
-    });
-
     test('updateOptions', () {
-      var request = new Request('0', AnalysisDomainHandler.UPDATE_OPTIONS_METHOD);
+      var request = new Request('0', METHOD_UPDATE_OPTIONS);
       request.setParameter(
-          AnalysisDomainHandler.OPTIONS_PARAM,
+          OPTIONS,
           {
             'analyzeAngular' : true,
             'enableDeferredLoading': true,
@@ -126,14 +117,14 @@
     });
 
     test('updateSdks', () {
-      var request = new Request('0', AnalysisDomainHandler.UPDATE_SDKS_METHOD);
+      var request = new Request('0', METHOD_UPDATE_SDKS);
       request.setParameter(
-          AnalysisDomainHandler.ADDED_PARAM,
+          ADDED,
           ['/dart/sdk-1.3', '/dart/sdk-1.4']);
       request.setParameter(
-          AnalysisDomainHandler.REMOVED_PARAM,
+          REMOVED,
           ['/dart/sdk-1.2']);
-      request.setParameter(AnalysisDomainHandler.DEFAULT_PARAM, '/dart/sdk-1.4');
+      request.setParameter(DEFAULT, '/dart/sdk-1.4');
       var response = handler.handleRequest(request);
       // TODO(scheglov) implement
       expect(response, isNull);
@@ -142,6 +133,35 @@
 }
 
 
+class AnalysisError {
+  final String file;
+  final String errorCode;
+  final int offset;
+  final int length;
+  final String message;
+  final String correction;
+  AnalysisError(this.file, this.errorCode, this.offset, this.length,
+      this.message, this.correction);
+
+  @override
+  String toString() {
+    return 'NotificationError(file=$file; errorCode=$errorCode; '
+        'offset=$offset; length=$length; message=$message)';
+  }
+}
+
+
+AnalysisError jsonToAnalysisError(Map<String, Object> json) {
+  return new AnalysisError(
+      json['file'],
+      json['errorCode'],
+      json['offset'],
+      json['length'],
+      json['message'],
+      json['correction']);
+}
+
+
 /**
  * A helper to test 'analysis.*' requests.
  */
@@ -151,7 +171,11 @@
   AnalysisServer server;
   AnalysisDomainHandler handler;
 
+  Map<String, List<String>> analysisSubscriptions = {};
+
   Map<String, List<AnalysisError>> filesErrors = {};
+  Map<String, List<Map<String, Object>>> filesHighlights = {};
+  Map<String, List<Map<String, Object>>> filesNavigation = {};
 
   String testFile = '/project/bin/test.dart';
   String testCode;
@@ -164,20 +188,60 @@
     // listen for notifications
     Stream<Notification> notificationStream = serverChannel.notificationController.stream;
     notificationStream.listen((Notification notification) {
-      if (notification.event == AnalysisDomainHandler.ERRORS_NOTIFICATION) {
-        String file = notification.getParameter(AnalysisServer.FILE_PARAM);
-        List<Map<String, Object>> errorMaps = notification.getParameter(AnalysisServer.ERRORS_PARAM);
+      if (notification.event == NOTIFICATION_ERRORS) {
+        String file = notification.getParameter(FILE);
+        List<Map<String, Object>> errorMaps = notification.getParameter(ERRORS);
         filesErrors[file] = errorMaps.map(jsonToAnalysisError).toList();
       }
+      if (notification.event == NOTIFICATION_HIGHLIGHTS) {
+        String file = notification.getParameter(FILE);
+        filesHighlights[file] = notification.getParameter(REGIONS);
+      }
+      if (notification.event == NOTIFICATION_NAVIGATION) {
+        String file = notification.getParameter(FILE);
+        filesNavigation[file] = notification.getParameter(REGIONS);
+      }
     });
   }
 
+  void addAnalysisSubscriptionHighlights(String file) {
+    addAnalysisSubscription(AnalysisService.HIGHLIGHTS, file);
+  }
+
+  void addAnalysisSubscriptionNavigation(String file) {
+    addAnalysisSubscription(AnalysisService.NAVIGATION, file);
+  }
+
+  void addAnalysisSubscription(AnalysisService service, String file) {
+    // add file to subscription
+    var files = analysisSubscriptions[service.name];
+    if (files == null) {
+      files = <String>[];
+      analysisSubscriptions[service.name] = files;
+    }
+    files.add(file);
+    // set subscriptions
+    Request request = new Request('0', METHOD_SET_ANALYSIS_SUBSCRIPTIONS);
+    request.setParameter(SUBSCRIPTIONS, analysisSubscriptions);
+    handleSuccessfulRequest(request);
+  }
+
   /**
    * Returns a [Future] that completes when this this helper finished all its
    * scheduled tasks.
    */
-  Future waitForTasksFinished() {
-    return waitForServerTasksFinished(server);
+  Future waitForOperationsFinished() {
+    return waitForServerOperationsPerformed(server);
+  }
+
+  /**
+   * Returns the offset of [search] in [testCode].
+   * Fails if not found.
+   */
+  int findOffset(String search) {
+    int offset = testCode.indexOf(search);
+    expect(offset, isNot(-1));
+    return offset;
   }
 
   /**
@@ -193,6 +257,30 @@
   }
 
   /**
+   * Returns highlights recorded for the given [file].
+   * May be empty, but not `null`.
+   */
+  List<Map<String, Object>> getHighlights(String file) {
+    List<Map<String, Object>> highlights = filesHighlights[file];
+    if (highlights != null) {
+      return highlights;
+    }
+    return [];
+  }
+
+  /**
+   * Returns navigation regions recorded for the given [file].
+   * May be empty, but not `null`.
+   */
+  List<Map<String, Object>> getNavigation(String file) {
+    List<Map<String, Object>> navigation = filesNavigation[file];
+    if (navigation != null) {
+      return navigation;
+    }
+    return [];
+  }
+
+  /**
    * Returns [AnalysisError]s recorded for the [testFile].
    * May be empty, but not `null`.
    */
@@ -201,20 +289,51 @@
   }
 
   /**
+   * Returns highlights recorded for the given [testFile].
+   * May be empty, but not `null`.
+   */
+  List<Map<String, Object>> getTestHighlights() {
+    return getHighlights(testFile);
+  }
+
+  /**
+   * Returns navigation information recorded for the given [testFile].
+   * May be empty, but not `null`.
+   */
+  List<Map<String, Object>> getTestNavigation() {
+    return getNavigation(testFile);
+  }
+
+  /**
+   * Creates an empty project `/project`.
+   */
+  void createEmptyProject() {
+    resourceProvider.newFolder('/project');
+    Request request = new Request('0', METHOD_SET_ANALYSIS_ROOTS);
+    request.setParameter(INCLUDED, ['/project']);
+    request.setParameter(EXCLUDED, []);
+    handleSuccessfulRequest(request);
+  }
+
+  /**
    * Creates a project with a single Dart file `/project/bin/test.dart` with
    * the given [code].
    */
   void createSingleFileProject(code) {
     this.testCode = _getCodeString(code);
     resourceProvider.newFolder('/project');
-    resourceProvider.newFile('/project/pubspec.yaml', 'name: project');
     resourceProvider.newFile(testFile, testCode);
-    Request request = new Request('0', AnalysisDomainHandler.SET_ANALYSIS_ROOTS_METHOD);
-    request.setParameter(AnalysisDomainHandler.INCLUDED_PARAM, ['/project']);
-    request.setParameter(AnalysisDomainHandler.EXCLUDED_PARAM, []);
+    Request request = new Request('0', METHOD_SET_ANALYSIS_ROOTS);
+    request.setParameter(INCLUDED, ['/project']);
+    request.setParameter(EXCLUDED, []);
     handleSuccessfulRequest(request);
   }
 
+  String setFileContent(String path, String content) {
+    resourceProvider.newFile(path, content);
+    return path;
+  }
+
   /**
    * Validates that the given [request] is handled successfully.
    */
@@ -248,7 +367,7 @@
 
   test('ParserErrorCode', () {
     helper.createSingleFileProject('library lib');
-    return helper.waitForTasksFinished().then((_) {
+    return helper.waitForOperationsFinished().then((_) {
       List<AnalysisError> errors = helper.getTestErrors();
       expect(errors, hasLength(1));
       AnalysisError error = errors[0];
@@ -265,7 +384,7 @@
       'main() {',
       '  print(unknown);',
       '}']);
-    return helper.waitForTasksFinished().then((_) {
+    return helper.waitForOperationsFinished().then((_) {
       List<AnalysisError> errors = helper.getTestErrors();
       expect(errors, hasLength(1));
       AnalysisError error = errors[0];
@@ -275,27 +394,1167 @@
 }
 
 
+class NotificationHighlightHelper extends AnalysisTestHelper {
+  List<Map<String, Object>> regions;
+
+  Future prepareRegions(then()) {
+    addAnalysisSubscriptionHighlights(testFile);
+    return waitForOperationsFinished().then((_) {
+      regions = getTestHighlights();
+      then();
+    });
+  }
+
+  void assertHasRawRegion(HighlightType type, int offset, int length) {
+    for (Map<String, Object> region in regions) {
+      if (region['offset'] == offset && region['length'] == length
+          && region['type'] == type.name) {
+        return;
+      }
+    }
+    fail('Expected to find (offset=$offset; length=$length; type=$type) in\n'
+         '${regions.join('\n')}');
+  }
+
+  void assertNoRawRegion(HighlightType type, int offset, int length) {
+    for (Map<String, Object> region in regions) {
+      if (region['offset'] == offset && region['length'] == length
+          && region['type'] == type.name) {
+        fail('Not expected to find (offset=$offset; length=$length; type=$type) in\n'
+             '${regions.join('\n')}');
+      }
+    }
+  }
+
+  void assertHasRegion(HighlightType type, String search, [int length = -1]) {
+    int offset = testCode.indexOf(search);
+    expect(offset, isNot(-1));
+    length = findRegionLength(search, length);
+    assertHasRawRegion(type, offset, length);
+  }
+
+  void assertNoRegion(HighlightType type, String search, [int length = -1]) {
+    int offset = testCode.indexOf(search);
+    expect(offset, isNot(-1));
+    length = findRegionLength(search, length);
+    assertNoRawRegion(type, offset, length);
+  }
+
+  int findRegionLength(String search, int length) {
+    if (length == -1) {
+      length = 0;
+      while (length < search.length) {
+        int c = search.codeUnitAt(length);
+        if (length == 0 && c == '@'.codeUnitAt(0)) {
+          length++;
+          continue;
+        }
+        if (!(c >= 'a'.codeUnitAt(0) && c <= 'z'.codeUnitAt(0) ||
+              c >= 'A'.codeUnitAt(0) && c <= 'Z'.codeUnitAt(0) ||
+              c >= '0'.codeUnitAt(0) && c <= '9'.codeUnitAt(0))) {
+          break;
+        }
+        length++;
+      }
+    }
+    return length;
+  }
+}
+
+
+testNotificationHighlights() {
+  Future testRegions(String code, then(NotificationHighlightHelper helper)) {
+    var helper = new NotificationHighlightHelper();
+    helper.createSingleFileProject(code);
+    return helper.prepareRegions(() {
+      then(helper);
+    });
+  }
+
+  group('ANNOTATION', () {
+    test('no arguments', () {
+      var code = '''
+const AAA = 42;
+@AAA main() {}
+''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.ANNOTATION, '@AAA');
+      });
+    });
+
+    test('has arguments', () {
+      var code = '''
+class AAA {
+  const AAA(a, b, c);
+}
+@AAA(1, 2, 3) main() {}
+''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.ANNOTATION, '@AAA(', '@AAA('.length);
+        helper.assertHasRegion(HighlightType.ANNOTATION, ') main', ')'.length);
+      });
+    });
+  });
+
+  group('BUILT_IN', () {
+    test('abstract', () {
+      var code = '''
+abstract class A {};
+main() {
+  var abstract = 42;
+}''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'abstract class');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'abstract = 42');
+      });
+    });
+
+    test('as', () {
+      var code = '''
+import 'dart:math' as math;
+main() {
+  p as int;
+  var as = 42;
+}''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'as math');
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'as int');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'as = 42');
+      });
+    });
+
+    test('deferred', () {
+      var code = '''
+import 'dart:math' deferred as math;
+main() {
+  var deferred = 42;
+}''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'deferred as math');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'deferred = 42');
+      });
+    });
+
+    test('export', () {
+      var code = '''
+export "dart:math";
+main() {
+  var export = 42;
+}''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'export "dart:');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'export = 42');
+      });
+    });
+
+    test('external', () {
+      var code = '''
+class A {
+  external A();
+  external aaa();
+}
+external main() {
+  var external = 42;
+}''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'external A()');
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'external aaa()');
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'external main()');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'external = 42');
+      });
+    });
+
+    test('factory', () {
+      var code = '''
+class A {
+  factory A() => null;
+}
+main() {
+  var factory = 42;
+}''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'factory A()');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'factory = 42');
+      });
+    });
+
+    test('get', () {
+      var code = '''
+get aaa => 1;
+class A {
+  get bbb => 2;
+}
+main() {
+  var get = 42;
+}''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'get aaa =>');
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'get bbb =>');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'get = 42');
+      });
+    });
+
+    test('hide', () {
+      var code = '''
+import 'foo.dart' hide Foo;
+main() {
+  var hide = 42;
+}''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'hide Foo');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'hide = 42');
+      });
+    });
+
+    test('implements', () {
+      var code = '''
+class A {}
+class B implements A {}
+main() {
+  var implements = 42;
+}''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'implements A {}');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'implements = 42');
+      });
+    });
+
+    test('import', () {
+      var code = '''
+import "foo.dart";
+main() {
+  var import = 42;
+}''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'import "');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'import = 42');
+      });
+    });
+
+    test('library', () {
+      var code = '''
+library lib;
+main() {
+  var library = 42;
+}''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'library lib;');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'library = 42');
+      });
+    });
+
+    test('native', () {
+      var code = '''
+class A native "A_native" {}
+class B {
+  bbb() native "bbb_native";
+}
+main() {
+  var native = 42;
+}''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'native "A_');
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'native "bbb_');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'native = 42');
+      });
+    });
+
+    test('on', () {
+      var code = '''
+main() {
+  try {
+  } on int catch (e) {
+  }
+  var on = 42;
+}''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'on int');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'on = 42');
+      });
+    });
+
+    test('operator', () {
+      var code = '''
+class A {
+  operator +(x) => null;
+}
+main() {
+  var operator = 42;
+}''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'operator +(');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'operator = 42');
+      });
+    });
+
+    test('part', () {
+      var helper = new NotificationHighlightHelper();
+      var code = '''
+part "my_part.dart";
+main() {
+  var part = 42;
+}''';
+      helper.createSingleFileProject(code);
+      helper.setFileContent('/project/bin/my_part.dart', 'part of lib;');
+      return helper.prepareRegions(() {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'part "my_');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'part = 42');
+      });
+    });
+
+    test('part', () {
+      var helper = new NotificationHighlightHelper();
+      var code = '''
+part of lib;
+main() {
+  var part = 1;
+  var of = 2;
+}''';
+      helper.createSingleFileProject(code);
+      helper.setFileContent('/project/bin/lib.dart', '''
+library lib;
+part 'test.dart';
+''');
+      return helper.prepareRegions(() {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'part of', 'part of'.length);
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'part = 1');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'of = 2');
+      });
+    });
+
+    test('set', () {
+      var code = '''
+set aaa(x) {}
+class A
+  set bbb(x) {}
+}
+main() {
+  var set = 42;
+}''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'set aaa(');
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'set bbb(');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'set = 42');
+      });
+    });
+
+    test('show', () {
+      var code = '''
+import 'foo.dart' show Foo;
+main() {
+  var show = 42;
+}''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'show Foo');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'show = 42');
+      });
+    });
+
+    test('static', () {
+      var code = '''
+class A {
+  static aaa;
+  static bbb() {}
+}
+main() {
+  var static = 42;
+}''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'static aaa;');
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'static bbb()');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'static = 42');
+      });
+    });
+
+    test('typedef', () {
+      var code = '''
+typedef A();
+main() {
+  var typedef = 42;
+}''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.BUILT_IN, 'typedef A();');
+        helper.assertNoRegion(HighlightType.BUILT_IN, 'typedef = 42');
+      });
+    });
+  });
+
+  group('CLASS', () {
+    test('CLASS', () {
+      var code = '''
+class AAA {}
+AAA aaa;
+''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertHasRegion(HighlightType.CLASS, 'AAA {}');
+        helper.assertHasRegion(HighlightType.CLASS, 'AAA aaa');
+      });
+    });
+
+    test('not dynamic', () {
+      var code = '''
+dynamic f() {}
+''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertNoRegion(HighlightType.CLASS, 'dynamic f()');
+      });
+    });
+
+    test('not void', () {
+      var code = '''
+void f() {}
+''';
+      return testRegions(code, (NotificationHighlightHelper helper) {
+        helper.assertNoRegion(HighlightType.CLASS, 'void f()');
+      });
+    });
+  });
+
+  test('CONSTRUCTOR', () {
+    var code = '''
+class AAA {
+  AAA() {}
+  AAA.name(p) {}
+}
+main() {
+  new AAA();
+  new AAA.name(42);
+}
+''';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.CONSTRUCTOR, 'name(p)');
+      helper.assertHasRegion(HighlightType.CONSTRUCTOR, 'name(42)');
+      helper.assertNoRegion(HighlightType.CONSTRUCTOR, 'AAA() {}');
+      helper.assertNoRegion(HighlightType.CONSTRUCTOR, 'AAA();');
+    });
+  });
+
+  test('DYNAMIC_TYPE', () {
+    var code = '''
+f() {}
+main(p) {
+  print(p);
+  var v1 = f();
+  int v2;
+  var v3 = v2;
+}
+''';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.DYNAMIC_TYPE, 'p)');
+      helper.assertHasRegion(HighlightType.DYNAMIC_TYPE, 'v1 =');
+      helper.assertNoRegion(HighlightType.DYNAMIC_TYPE, 'v2;');
+      helper.assertNoRegion(HighlightType.DYNAMIC_TYPE, 'v3 =');
+    });
+  });
+
+  test('FIELD', () {
+    var code = '''
+class A {
+  int aaa = 1;
+  int bbb = 2;
+  A([this.bbb = 3]);
+}
+main(A a) {
+  a.aaa = 4;
+  a.bbb = 5;
+}
+''';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.FIELD, 'aaa = 1');
+      helper.assertHasRegion(HighlightType.FIELD, 'bbb = 2');
+      helper.assertHasRegion(HighlightType.FIELD, 'bbb = 3');
+      helper.assertHasRegion(HighlightType.FIELD, 'aaa = 4');
+      helper.assertHasRegion(HighlightType.FIELD, 'bbb = 5');
+    });
+  });
+
+  test('FIELD_STATIC', () {
+    var code = '''
+class A {
+  static aaa = 1;
+  static get bbb => null;
+  static set ccc(x) {}
+}
+main() {
+  A.aaa = 2;
+  A.bbb;
+  A.ccc = 3;
+}
+''';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.FIELD_STATIC, 'aaa = 1');
+      helper.assertHasRegion(HighlightType.FIELD_STATIC, 'aaa = 2');
+      helper.assertHasRegion(HighlightType.FIELD_STATIC, 'bbb;');
+      helper.assertHasRegion(HighlightType.FIELD_STATIC, 'ccc = 3');
+    });
+  });
+
+  test('FUNCTION', () {
+    var code = '''
+fff(p) {}
+main() {
+  fff(42);
+}
+''';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.FUNCTION_DECLARATION, 'fff(p) {}');
+      helper.assertHasRegion(HighlightType.FUNCTION, 'fff(42)');
+    });
+  });
+
+  test('FUNCTION_TYPE_ALIAS', () {
+    var code = '''
+typedef FFF(p);
+main(FFF fff) {
+}
+''';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.FUNCTION_TYPE_ALIAS, 'FFF(p)');
+      helper.assertHasRegion(HighlightType.FUNCTION_TYPE_ALIAS, 'FFF fff)');
+    });
+  });
+
+  test('GETTER_DECLARATION', () {
+    var code = '''
+get aaa => null;
+class A {
+  get bbb => null;
+}
+main(A a) {
+  aaa;
+  a.bbb;
+}
+''';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.GETTER_DECLARATION, 'aaa => null');
+      helper.assertHasRegion(HighlightType.GETTER_DECLARATION, 'bbb => null');
+      helper.assertHasRegion(HighlightType.FIELD_STATIC, 'aaa;');
+      helper.assertHasRegion(HighlightType.FIELD, 'bbb;');
+    });
+  });
+
+  test('IDENTIFIER_DEFAULT', () {
+    var code = '''
+main() {
+  aaa = 42;
+  bbb(84);
+  CCC ccc;
+}
+''';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.IDENTIFIER_DEFAULT, 'aaa = 42');
+      helper.assertHasRegion(HighlightType.IDENTIFIER_DEFAULT, 'bbb(84)');
+      helper.assertHasRegion(HighlightType.IDENTIFIER_DEFAULT, 'CCC ccc');
+    });
+  });
+
+  test('IMPORT_PREFIX', () {
+    var code = '''
+import 'dart:math' as ma;
+main() {
+  ma.max(1, 2);
+}
+''';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.IMPORT_PREFIX, 'ma;');
+      helper.assertHasRegion(HighlightType.IMPORT_PREFIX, 'ma.max');
+    });
+  });
+
+  test('KEYWORD void', () {
+    var code = '''
+void main() {
+}
+''';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.KEYWORD, 'void main()');
+    });
+  });
+
+  test('LITERAL_BOOLEAN', () {
+    var code = 'var V = true;';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.LITERAL_BOOLEAN, 'true;');
+    });
+  });
+
+  test('LITERAL_DOUBLE', () {
+    var code = 'var V = 4.2;';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.LITERAL_DOUBLE, '4.2;', '4.2'.length);
+    });
+  });
+
+  test('LITERAL_INTEGER', () {
+    var code = 'var V = 42;';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.LITERAL_INTEGER, '42;');
+    });
+  });
+
+  test('LITERAL_STRING', () {
+    var code = 'var V = "abc";';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.LITERAL_STRING, '"abc";', '"abc"'.length);
+    });
+  });
+
+  test('LOCAL_VARIABLE', () {
+    var code = '''
+main() {
+  int vvv = 0;
+  vvv;
+  vvv = 1;
+}
+''';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.LOCAL_VARIABLE_DECLARATION, 'vvv = 0');
+      helper.assertHasRegion(HighlightType.LOCAL_VARIABLE, 'vvv;');
+      helper.assertHasRegion(HighlightType.LOCAL_VARIABLE, 'vvv = 1;');
+    });
+  });
+
+  test('METHOD', () {
+    var code = '''
+class A {
+  aaa() {}
+  static bbb() {}
+}
+main(A a) {
+  a.aaa();
+  a.aaa;
+  A.bbb();
+  A.bbb;
+}
+''';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.METHOD_DECLARATION, 'aaa() {}');
+      helper.assertHasRegion(HighlightType.METHOD_DECLARATION_STATIC, 'bbb() {}');
+      helper.assertHasRegion(HighlightType.METHOD, 'aaa();');
+      helper.assertHasRegion(HighlightType.METHOD, 'aaa;');
+      helper.assertHasRegion(HighlightType.METHOD_STATIC, 'bbb();');
+      helper.assertHasRegion(HighlightType.METHOD_STATIC, 'bbb;');
+    });
+  });
+
+  test('METHOD best type', () {
+    var code = '''
+main(p) {
+  if (p is List) {
+    p.add(null);
+  }
+}
+''';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.METHOD, 'add(null)');
+    });
+  });
+
+  test('PARAMETER', () {
+    var code = '''
+main(int p) {
+  p;
+  p = 42;
+}
+''';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.PARAMETER, 'p) {');
+      helper.assertHasRegion(HighlightType.PARAMETER, 'p;');
+      helper.assertHasRegion(HighlightType.PARAMETER, 'p = 42');
+    });
+  });
+
+  test('SETTER_DECLARATION', () {
+    var code = '''
+set aaa(x) {}
+class A {
+  set bbb(x) {}
+}
+main(A a) {
+  aaa = 1;
+  a.bbb = 2;
+}
+''';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.SETTER_DECLARATION, 'aaa(x)');
+      helper.assertHasRegion(HighlightType.SETTER_DECLARATION, 'bbb(x)');
+      helper.assertHasRegion(HighlightType.FIELD_STATIC, 'aaa = 1');
+      helper.assertHasRegion(HighlightType.FIELD, 'bbb = 2');
+    });
+  });
+
+  test('TOP_LEVEL_VARIABLE', () {
+    var code = '''
+var VVV = 0;
+main() {
+  print(VVV);
+  VVV = 1;
+}
+''';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.TOP_LEVEL_VARIABLE, 'VVV = 0');
+      helper.assertHasRegion(HighlightType.FIELD_STATIC, 'VVV);');
+      helper.assertHasRegion(HighlightType.FIELD_STATIC, 'VVV = 1');
+    });
+  });
+
+  test('TYPE_NAME_DYNAMIC', () {
+    var code = '''
+dynamic main() {
+  dynamic = 42;
+}
+''';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.TYPE_NAME_DYNAMIC, 'dynamic main()');
+      helper.assertNoRegion(HighlightType.IDENTIFIER_DEFAULT, 'dynamic main()');
+      helper.assertNoRegion(HighlightType.TYPE_NAME_DYNAMIC, 'dynamic = 42');
+    });
+  });
+
+  test('TYPE_PARAMETER', () {
+    var code = '''
+class A<T> {
+  T fff;
+  T mmm(T p) => null;
+}
+''';
+    return testRegions(code, (NotificationHighlightHelper helper) {
+      helper.assertHasRegion(HighlightType.TYPE_PARAMETER, 'T> {');
+      helper.assertHasRegion(HighlightType.TYPE_PARAMETER, 'T fff;');
+      helper.assertHasRegion(HighlightType.TYPE_PARAMETER, 'T mmm(');
+      helper.assertHasRegion(HighlightType.TYPE_PARAMETER, 'T p)');
+    });
+  });
+}
+
+
+
+
+class NotificationNavigationHelper extends AnalysisTestHelper {
+  List<Map<String, Object>> regions;
+
+  Future prepareRegions(then()) {
+    addAnalysisSubscriptionNavigation(testFile);
+    return waitForOperationsFinished().then((_) {
+      regions = getTestNavigation();
+      then();
+    });
+  }
+
+  void assertHasRegion(String regionSearch, String targetSearch) {
+    var regionOffset = findOffset(regionSearch);
+    int regionLength = findIdentifierLength(regionSearch);
+    var targetOffset = findOffset(targetSearch);
+    var targetLength = findIdentifierLength(targetSearch);
+    asserHasRegionInts(regionOffset, regionLength, targetOffset, targetLength);
+  }
+
+  void asserHasOperatorRegion(String search, int regionLength, int targetLength) {
+    var regionOffset = findOffset(search);
+    var region = asserHasRegionInts(regionOffset, regionLength, -1, 0);
+    if (targetLength != -1) {
+      expect(region['targets'][0]['length'], targetLength);
+    }
+  }
+
+  asserHasRegionInts(int regionOffset, int regionLength,
+                          int targetOffset, int targetLength) {
+    Map<String, Object> region = findRegion(regionOffset, regionLength);
+    if (region != null) {
+      List<Map<String, Object>> targets = region['targets'];
+      if (targetOffset == -1) {
+        return region;
+      }
+      var target = findTarget(targets, testFile, targetOffset, targetLength);
+      if (target != null) {
+        return target;
+      }
+    }
+    fail('Expected to find (offset=$regionOffset; length=$regionLength) => '
+         '(offset=$targetOffset; length=$targetLength) in\n'
+         '${regions.join('\n')}');
+  }
+
+  Map<String, Object> findRegionString(String search, [bool notNull]) {
+    int offset = findOffset(search);
+    int length = search.length;
+    return findRegion(offset, length, notNull);
+  }
+
+  Map<String, Object> findRegionAt(String search, [bool notNull]) {
+    int offset = findOffset(search);
+    for (Map<String, Object> region in regions) {
+      if (region['offset'] == offset) {
+        if (notNull == false) {
+          fail('Not expected to find at offset=$offset in\n'
+               '${regions.join('\n')}');
+        }
+        return region;
+      }
+    }
+    if (notNull == true) {
+      fail('Expected to find at offset=$offset in\n'
+           '${regions.join('\n')}');
+    }
+    return null;
+  }
+
+  Map<String, Object> findRegionIdentifier(String search, [bool notNull]) {
+    int offset = findOffset(search);
+    int length = findIdentifierLength(search);
+    return findRegion(offset, length, notNull);
+  }
+
+  Map<String, Object> findRegion(int offset, int length, [bool notNull]) {
+    for (Map<String, Object> region in regions) {
+      if (region['offset'] == offset && region['length'] == length) {
+        if (notNull == false) {
+          fail('Not expected to find (offset=$offset; length=$length) in\n'
+               '${regions.join('\n')}');
+        }
+        return region;
+      }
+    }
+    if (notNull == true) {
+      fail('Expected to find (offset=$offset; length=$length) in\n'
+           '${regions.join('\n')}');
+    }
+    return null;
+  }
+
+  Map<String, Object> findTarget(List<Map<String, Object>> targets,
+                                 String file, int offset, int length) {
+    for (Map<String, Object> target in targets) {
+      if (target['file'] == file &&
+          target['offset'] == offset &&
+          target['length'] == length) {
+        return target;
+      }
+    }
+    return null;
+  }
+
+  void assertNoRegion(String regionSearch) {
+    var regionOffset = findOffset(regionSearch);
+    var regionLength = findIdentifierLength(regionSearch);
+    for (Map<String, Object> region in regions) {
+      if (region['offset'] == regionOffset && region['length'] == regionLength) {
+        fail('Unexpected (offset=$regionOffset; length=$regionLength) in\n'
+             '${regions.join('\n')}');
+      }
+    }
+  }
+}
+
+
+int findIdentifierLength(String search) {
+  int length = 0;
+  while (length < search.length) {
+    int c = search.codeUnitAt(length);
+    if (!(c >= 'a'.codeUnitAt(0) && c <= 'z'.codeUnitAt(0) ||
+          c >= 'A'.codeUnitAt(0) && c <= 'Z'.codeUnitAt(0) ||
+          c >= '0'.codeUnitAt(0) && c <= '9'.codeUnitAt(0))) {
+      break;
+    }
+    length++;
+  }
+  return length;
+}
+
+
+testNotificationNavigation() {
+  Future testNavigation(String code, then(NotificationNavigationHelper helper)) {
+    var helper = new NotificationNavigationHelper();
+    helper.createSingleFileProject(code);
+    return helper.prepareRegions(() {
+      then(helper);
+    });
+  }
+
+  group('constructor', () {
+    test('named', () {
+      var code = '''
+class A {
+  A.named(int p) {}
+}
+''';
+      return testNavigation(code, (NotificationNavigationHelper helper) {
+        // has region for complete "A.named"
+        helper.asserHasRegionInts(
+            helper.findOffset('A.named'), 'A.named'.length,
+            helper.findOffset('named(int'), 'named'.length);
+        // no separate regions for "A" and "named"
+        helper.assertNoRegion('A.named(');
+        helper.assertNoRegion('named(');
+        // validate that we don't forget to resolve parameters
+        helper.asserHasRegionInts(
+            helper.findOffset('int p'), 'int'.length,
+            -1, 0);
+      });
+    });
+
+    test('unnamed', () {
+      var code = '''
+class A {
+  A(int p) {}
+}
+''';
+      return testNavigation(code, (NotificationNavigationHelper helper) {
+        // has constructor region for "A()"
+        helper.asserHasRegionInts(
+            helper.findOffset('A(int p)'), 'A'.length,
+            helper.findOffset('A(int p)'), 0);
+        // validate that we don't forget to resolve parameters
+        helper.asserHasRegionInts(
+            helper.findOffset('int p'), 'int'.length,
+            -1, 0);
+      });
+    });
+  });
+
+  group('identifier', () {
+    test('resolved', () {
+      var code = '''
+class AAA {}
+main() {
+  AAA aaa = null;
+  print(aaa);
+}
+''';
+      return testNavigation(code, (NotificationNavigationHelper helper) {
+        helper.assertHasRegion('AAA aaa', 'AAA {}');
+        helper.assertHasRegion('aaa);', 'aaa = null');
+        helper.assertHasRegion('main() {', 'main() {');
+      });
+    });
+
+    test('unresolved', () {
+      var code = '''
+main() {
+  print(noo);
+}
+''';
+      return testNavigation(code, (NotificationNavigationHelper helper) {
+        helper.assertNoRegion('noo);');
+      });
+    });
+  });
+
+  test('fieldFormalParameter', () {
+    var code = '''
+class A {
+  int fff = 123;
+  A(this.fff);
+}
+''';
+    return testNavigation(code, (NotificationNavigationHelper helper) {
+      helper.assertHasRegion('fff);', 'fff = 123');
+    });
+  });
+
+  group('instanceCreation', () {
+    test('named', () {
+      var code = '''
+class A {
+  A.named() {}
+}
+main() {
+  new A.named();
+}
+''';
+      return testNavigation(code, (NotificationNavigationHelper helper) {
+        helper.asserHasRegionInts(
+            helper.findOffset('new A.named'), 'new A.named'.length,
+            helper.findOffset('named()'), 'named'.length);
+      });
+    });
+
+    test('unnamed', () {
+      var code = '''
+class A {
+  A() {}
+}
+main() {
+  new A();
+}
+''';
+      return testNavigation(code, (NotificationNavigationHelper helper) {
+        helper.asserHasRegionInts(
+            helper.findOffset('new A'), 'new A'.length,
+            helper.findOffset('A()'), ''.length);
+      });
+    });
+  });
+
+  group('operator', () {
+    test('int', () {
+      var code = '''
+main() {
+  var v = 0;
+  v - 1;
+  v + 2;
+  -v; // unary
+  --v;
+  ++v;
+  v--; // mm
+  v++; // pp
+  v -= 3;
+  v += 4;
+  v *= 5;
+  v /= 6;
+}
+''';
+      return testNavigation(code, (NotificationNavigationHelper helper) {
+        helper.asserHasOperatorRegion('- 1;', 1, 1);
+        helper.asserHasOperatorRegion('+ 2;', 1, 1);
+        helper.asserHasOperatorRegion('-v; // unary', 1, -1);
+        helper.asserHasOperatorRegion('--v;', 2, 1);
+        helper.asserHasOperatorRegion('++v;', 2, 1);
+        helper.asserHasOperatorRegion('--; // mm', 2, 1);
+        helper.asserHasOperatorRegion('++; // pp', 2, 1);
+        helper.asserHasOperatorRegion('-= 3;', 2, 1);
+        helper.asserHasOperatorRegion('+= 4;', 2, 1);
+        helper.asserHasOperatorRegion('*= 5;', 2, 1);
+        helper.asserHasOperatorRegion('/= 6;', 2, 1);
+      });
+    });
+
+    test('list', () {
+      var code = '''
+main() {
+  List<int> v = [1, 2, 3];
+  v[0]; // []
+  v[1] = 1; // []=
+  v[2] += 2;
+}
+''';
+      return testNavigation(code, (NotificationNavigationHelper helper) {
+        helper.asserHasOperatorRegion(']; // []', 1, 2);
+        helper.asserHasOperatorRegion('] = 1', 1, 3);
+        helper.asserHasOperatorRegion('] += 2', 1, 3);
+        helper.asserHasOperatorRegion('+= 2', 2, 1);
+      });
+    });
+  });
+
+  test('partOf', () {
+    var helper = new NotificationNavigationHelper();
+    var code = '''
+part of lib;
+''';
+    helper.createSingleFileProject(code);
+    var libPath = helper.setFileContent('/project/bin/lib.dart', '''
+library lib;
+part 'test.dart';
+''');
+    return helper.prepareRegions(() {
+      var region = helper.findRegionString('part of lib', true);
+      var target = region['targets'][0];
+      expect(target['file'], libPath);
+    });
+  });
+
+  group('string', () {
+    test('export', () {
+      var code = '''
+export "dart:math";
+''';
+      return testNavigation(code, (NotificationNavigationHelper helper) {
+        helper.findRegionString('export "dart:math"', true);
+      });
+    });
+
+    test('export unresolved URI', () {
+      var code = '''
+export 'no.dart';
+''';
+      return testNavigation(code, (NotificationNavigationHelper helper) {
+        helper.findRegionAt('export ', false);
+      });
+    });
+
+    test('import', () {
+      var code = '''
+import "dart:math" as m;
+''';
+      return testNavigation(code, (NotificationNavigationHelper helper) {
+        helper.findRegionString('import "dart:math"', true);
+      });
+    });
+
+    test('import no URI', () {
+      var code = '''
+import ;
+''';
+      return testNavigation(code, (NotificationNavigationHelper helper) {
+        helper.findRegionAt('import ', false);
+      });
+    });
+
+    test('import unresolved URI', () {
+      var code = '''
+import 'no.dart';
+''';
+      return testNavigation(code, (NotificationNavigationHelper helper) {
+        helper.findRegionAt('import ', false);
+      });
+    });
+
+    test('part', () {
+      var helper = new NotificationNavigationHelper();
+      var code = '''
+library lib;
+part "my_part.dart";
+''';
+      helper.createSingleFileProject(code);
+      var unitPath = helper.setFileContent('/project/bin/my_part.dart', '''
+part of lib;
+''');
+      return helper.prepareRegions(() {
+        var region = helper.findRegionString('part "my_part.dart"', true);
+        var target = region['targets'][0];
+        expect(target['file'], unitPath);
+      });
+    });
+
+    test('part unresolved URI', () {
+      // TODO(scheglov) why do we throw MemoryResourceException here?
+      // This Source/File does not exist.
+//      var helper = new NotificationNavigationHelper();
+//      var code = '''
+//library lib;
+//part "my_part.dart";
+//''';
+//      helper.createSingleFileProject(code);
+//      return helper.prepareRegions(() {
+//        helper.findRegionAt('part ', false);
+//      });
+    });
+  });
+}
+
+
 testUpdateContent() {
   test('full content', () {
     AnalysisTestHelper helper = new AnalysisTestHelper();
     helper.createSingleFileProject('// empty');
-    return helper.waitForTasksFinished().then((_) {
+    return helper.waitForOperationsFinished().then((_) {
       // no errors initially
       List<AnalysisError> errors = helper.getTestErrors();
       expect(errors, isEmpty);
       // update code
       {
-        Request request = new Request('0', AnalysisDomainHandler.UPDATE_CONTENT_METHOD);
+        Request request = new Request('0', METHOD_UPDATE_CONTENT);
         request.setParameter('files',
             {
               helper.testFile : {
-                AnalysisDomainHandler.CONTENT_PARAM : 'library lib'
+                CONTENT : 'library lib'
               }
             });
         helper.handleSuccessfulRequest(request);
       }
       // wait, there is an error
-      helper.waitForTasksFinished().then((_) {
+      return helper.waitForOperationsFinished().then((_) {
         List<AnalysisError> errors = helper.getTestErrors();
         expect(errors, hasLength(1));
       });
@@ -305,26 +1564,26 @@
   test('incremental', () {
     AnalysisTestHelper helper = new AnalysisTestHelper();
     helper.createSingleFileProject('library A;');
-    return helper.waitForTasksFinished().then((_) {
+    return helper.waitForOperationsFinished().then((_) {
       // no errors initially
       List<AnalysisError> errors = helper.getTestErrors();
       expect(errors, isEmpty);
       // update code
       {
-        Request request = new Request('0', AnalysisDomainHandler.UPDATE_CONTENT_METHOD);
+        Request request = new Request('0', METHOD_UPDATE_CONTENT);
         request.setParameter('files',
             {
               helper.testFile : {
-                AnalysisDomainHandler.CONTENT_PARAM : 'library lib',
-                AnalysisDomainHandler.OFFSET_PARAM : 'library '.length,
-                AnalysisDomainHandler.OLD_LENGTH_PARAM : 'A;'.length,
-                AnalysisDomainHandler.NEW_LENGTH_PARAM : 'lib'.length,
+                CONTENT : 'library lib',
+                OFFSET : 'library '.length,
+                OLD_LENGTH : 'A;'.length,
+                NEW_LENGTH : 'lib'.length,
               }
             });
         helper.handleSuccessfulRequest(request);
       }
       // wait, there is an error
-      helper.waitForTasksFinished().then((_) {
+      return helper.waitForOperationsFinished().then((_) {
         List<AnalysisError> errors = helper.getTestErrors();
         expect(errors, hasLength(1));
       });
@@ -333,30 +1592,35 @@
 }
 
 
-class AnalysisError {
-  final String file;
-  final String errorCode;
-  final int offset;
-  final int length;
-  final String message;
-  final String correction;
-  AnalysisError(this.file, this.errorCode, this.offset, this.length,
-      this.message, this.correction);
+void test_setSubscriptions() {
+  test('before analysis', () {
+    AnalysisTestHelper helper = new AnalysisTestHelper();
+    // subscribe
+    helper.addAnalysisSubscriptionHighlights(helper.testFile);
+    // create project
+    helper.createSingleFileProject('int V = 42;');
+    // wait, there are highlight regions
+    helper.waitForOperationsFinished().then((_) {
+      var highlights = helper.getHighlights(helper.testFile);
+      expect(highlights, isNot(isEmpty));
+    });
+  });
 
-  @override
-  String toString() {
-    return 'NotificationError(file=$file; errorCode=$errorCode; '
-        'offset=$offset; length=$length; message=$message)';
-  }
-}
-
-
-AnalysisError jsonToAnalysisError(Map<String, Object> json) {
-  return new AnalysisError(
-      json['file'],
-      json['errorCode'],
-      json['offset'],
-      json['length'],
-      json['message'],
-      json['correction']);
+  test('after analysis', () {
+    AnalysisTestHelper helper = new AnalysisTestHelper();
+    // create project
+    helper.createSingleFileProject('int V = 42;');
+    // wait, no regions initially
+    return helper.waitForOperationsFinished().then((_) {
+      var highlights = helper.getHighlights(helper.testFile);
+      expect(highlights, isEmpty);
+      // subscribe
+      helper.addAnalysisSubscriptionHighlights(helper.testFile);
+      // wait, has regions
+      return helper.waitForOperationsFinished().then((_) {
+        var highlights = helper.getHighlights(helper.testFile);
+        expect(highlights, isNot(isEmpty));
+      });
+    });
+  });
 }
diff --git a/pkg/analysis_server/test/domain_context_test.dart b/pkg/analysis_server/test/domain_context_test.dart
deleted file mode 100644
index adaf6f9..0000000
--- a/pkg/analysis_server/test/domain_context_test.dart
+++ /dev/null
@@ -1,154 +0,0 @@
-// 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.domain.context;
-
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/source_io.dart';
-import 'package:analysis_server/src/analysis_server.dart';
-import 'package:analysis_server/src/domain_context.dart';
-import 'package:analysis_server/src/protocol.dart';
-import 'package:analysis_server/src/resource.dart';
-import 'package:unittest/unittest.dart';
-
-import 'mocks.dart';
-
-main() {
-  group('ContextDomainHandlerTest', () {
-    // TODO(scheglov) remove or move to the 'analysis' domain
-//    test('applyChanges', ContextDomainHandlerTest.applyChanges);
-    test('createChangeSet', ContextDomainHandlerTest.createChangeSet);
-    test('createChangeSet_onlyAdded', ContextDomainHandlerTest.createChangeSet_onlyAdded);
-    // TODO(scheglov) remove or move to the 'analysis' domain
-//    test('setOptions', ContextDomainHandlerTest.setOptions);
-//    test('setPrioritySources_empty', ContextDomainHandlerTest.setPrioritySources_empty);
-//    test('setPrioritySources_nonEmpty', ContextDomainHandlerTest.setPrioritySources_nonEmpty);
-  });
-}
-
-class ContextDomainHandlerTest {
-  static int contextIdCounter = 0;
-
-  // TODO(scheglov) remove or move to the 'analysis' domain
-//  static void applyChanges() {
-//    AnalysisServer server = new AnalysisServer(new MockServerChannel());
-//    String contextId = _createContext(server);
-//    ChangeSet changeSet = new ChangeSet();
-//    ContextDomainHandler handler = new ContextDomainHandler(server);
-//
-//    Request request = new Request('0', ContextDomainHandler.APPLY_CHANGES_NAME);
-//    request.setParameter(ContextDomainHandler.CONTEXT_ID_PARAM, contextId);
-//    request.setParameter(ContextDomainHandler.SOURCES_PARAM, []);
-//    request.setParameter(ContextDomainHandler.CHANGES_PARAM, {
-//      ContextDomainHandler.ADDED_PARAM : ['ffile:/one.dart'],
-//      ContextDomainHandler.MODIFIED_PARAM : ['ffile:/two.dart'],
-//      ContextDomainHandler.REMOVED_PARAM : ['ffile:/three.dart']
-//    });
-//    expect(server.contextWorkQueue, isEmpty);
-//    Response response = handler.handleRequest(request);
-//    expect(server.contextWorkQueue, hasLength(1));
-//    expect(response.toJson(), equals({
-//      Response.ID: '0'
-//    }));
-//  }
-
-  static void createChangeSet() {
-    AnalysisServer server = new AnalysisServer(
-        new MockServerChannel(),
-        PhysicalResourceProvider.INSTANCE);
-    Request request = new Request('0', ContextDomainHandler.APPLY_CHANGES_NAME);
-    ContextDomainHandler handler = new ContextDomainHandler(server);
-    SourceFactory sourceFactory = new SourceFactory([new FileUriResolver()]);
-    ChangeSet changeSet = handler.createChangeSet(request, sourceFactory,
-        new RequestDatum(request, ContextDomainHandler.CHANGES_PARAM, {
-      ContextDomainHandler.ADDED_PARAM: ['ffile:/one.dart'],
-      ContextDomainHandler.MODIFIED_PARAM: [],
-      ContextDomainHandler.REMOVED_PARAM: ['ffile:/two.dart',
-          'ffile:/three.dart']
-    }));
-    expect(changeSet.addedSources, hasLength(equals(1)));
-    expect(changeSet.changedSources, hasLength(equals(0)));
-    expect(changeSet.removedSources, hasLength(equals(2)));
-  }
-
-  static void createChangeSet_onlyAdded() {
-    AnalysisServer server = new AnalysisServer(
-        new MockServerChannel(),
-        PhysicalResourceProvider.INSTANCE);
-    Request request = new Request('0', ContextDomainHandler.APPLY_CHANGES_NAME);
-    ContextDomainHandler handler = new ContextDomainHandler(server);
-    SourceFactory sourceFactory = new SourceFactory([new FileUriResolver()]);
-    ChangeSet changeSet = handler.createChangeSet(request, sourceFactory,
-        new RequestDatum(request, ContextDomainHandler.CHANGES_PARAM, {
-      ContextDomainHandler.ADDED_PARAM: ['ffile:/one.dart'],
-    }));
-    expect(changeSet.addedSources, hasLength(equals(1)));
-    expect(changeSet.changedSources, hasLength(equals(0)));
-    expect(changeSet.removedSources, hasLength(equals(0)));
-  }
-
-  // TODO(scheglov) remove or move to the 'analysis' domain
-//  static void setOptions() {
-//    AnalysisServer server = new AnalysisServer(new MockServerChannel());
-//    String contextId = _createContext(server);
-//    Map<String, Object> options = new Map<String, Object>();
-//    ContextDomainHandler handler = new ContextDomainHandler(server);
-//
-//    Request request = new Request('0', ContextDomainHandler.SET_OPTIONS_NAME);
-//    request.setParameter(ContextDomainHandler.CONTEXT_ID_PARAM, contextId);
-//    request.setParameter(ContextDomainHandler.OPTIONS_PARAM, options);
-//    Response response = handler.handleRequest(request);
-//    expect(response.toJson(), equals({
-//      Response.ID: '0'
-//    }));
-//  }
-
-  // TODO(scheglov) remove or move to the 'analysis' domain
-//  static void setPrioritySources_empty() {
-//    AnalysisServer server = new AnalysisServer(new MockServerChannel());
-//    String contextId = _createContext(server);
-//    List<String> sources = new List<String>();
-//    ContextDomainHandler handler = new ContextDomainHandler(server);
-//
-//    Request request = new Request('0', ContextDomainHandler.SET_PRIORITY_SOURCES_NAME);
-//    request.setParameter(ContextDomainHandler.CONTEXT_ID_PARAM, contextId);
-//    request.setParameter(ContextDomainHandler.SOURCES_PARAM, sources);
-//    Response response = handler.handleRequest(request);
-//    expect(response.toJson(), equals({
-//      Response.ID: '0'
-//    }));
-//  }
-
-  // TODO(scheglov) remove or move to the 'analysis' domain
-//  static void setPrioritySources_nonEmpty() {
-//    AnalysisServer server = new AnalysisServer(new MockServerChannel());
-//    String contextId = _createContext(server);
-//    List<String> sources = new List<String>();
-//    sources.add("foo.dart");
-//    ContextDomainHandler handler = new ContextDomainHandler(server);
-//
-//    Request request = new Request('0', ContextDomainHandler.SET_PRIORITY_SOURCES_NAME);
-//    request.setParameter(ContextDomainHandler.CONTEXT_ID_PARAM, contextId);
-//    request.setParameter(ContextDomainHandler.SOURCES_PARAM, sources);
-//    Response response = handler.handleRequest(request);
-//    expect(response.toJson(), equals({
-//      Response.ID: '0'
-//    }));
-//  }
-
-  // TODO(scheglov) remove or move to the 'analysis' domain
-//  static String _createContext(AnalysisServer server) {
-//    String contextId = "context${contextIdCounter++}";
-//    ServerDomainHandler handler = new ServerDomainHandler(server);
-//    Request request = new Request('0', ServerDomainHandler.CREATE_CONTEXT_METHOD);
-//    request.setParameter(ServerDomainHandler.SDK_DIRECTORY_PARAM, sdkPath);
-//    request.setParameter(AnalysisServer.CONTEXT_ID_PARAM, contextId);
-//    Response response = handler.handleRequest(request);
-//    if (response.error != null) {
-//      fail('Unexpected error: ${response.error.toJson()}');
-//    }
-//    return contextId;
-//  }
-}
diff --git a/pkg/analysis_server/test/domain_server_test.dart b/pkg/analysis_server/test/domain_server_test.dart
index 3ac3eb0..cb726d4 100644
--- a/pkg/analysis_server/test/domain_server_test.dart
+++ b/pkg/analysis_server/test/domain_server_test.dart
@@ -5,6 +5,7 @@
 library test.domain.server;
 
 import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/domain_server.dart';
 import 'package:analysis_server/src/protocol.dart';
 import 'package:analysis_server/src/resource.dart';
@@ -25,12 +26,12 @@
 
   group('ServerDomainHandler', () {
     test('getVersion', () {
-      var request = new Request('0', ServerDomainHandler.GET_VERSION_METHOD);
+      var request = new Request('0', METHOD_GET_VERSION);
       var response = handler.handleRequest(request);
       expect(response.toJson(), equals({
         Response.ID: '0',
         Response.RESULT: {
-          ServerDomainHandler.VERSION_RESULT: '0.0.1'
+          VERSION: '0.0.1'
         }
       }));
     });
@@ -38,12 +39,12 @@
     group('setSubscriptions', () {
       Request request;
       setUp(() {
-        request = new Request('0', ServerDomainHandler.SET_SUBSCRIPTIONS_METHOD);
+        request = new Request('0', METHOD_SET_SERVER_SUBSCRIPTIONS);
       });
 
       test('invalid service name', () {
         request.setParameter(
-            ServerDomainHandler.SUBSCRIPTIONS_PARAMETER,
+            SUBSCRIPTIONS,
             ['noSuchService']);
         var response = handler.handleRequest(request);
         expect(response, isResponseFailure('0'));
@@ -53,7 +54,7 @@
         expect(server.serverServices, isEmpty);
         // send request
         request.setParameter(
-            ServerDomainHandler.SUBSCRIPTIONS_PARAMETER,
+            SUBSCRIPTIONS,
             [ServerService.STATUS.name]);
         var response = handler.handleRequest(request);
         expect(response, isResponseSuccess('0'));
@@ -65,7 +66,7 @@
     test('shutdown', () {
       expect(server.running, isTrue);
       // send request
-      var request = new Request('0', ServerDomainHandler.SHUTDOWN_METHOD);
+      var request = new Request('0', METHOD_SHUTDOWN);
       var response = handler.handleRequest(request);
       expect(response, isResponseSuccess('0'));
       // server is down
diff --git a/pkg/analysis_server/test/mocks.dart b/pkg/analysis_server/test/mocks.dart
index 8f90993..f8f3f9a 100644
--- a/pkg/analysis_server/test/mocks.dart
+++ b/pkg/analysis_server/test/mocks.dart
@@ -12,13 +12,14 @@
 
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analysis_server/src/analysis_logger.dart';
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/channel.dart';
 import 'package:analysis_server/src/protocol.dart';
 import 'package:matcher/matcher.dart';
 import 'package:mock/mock.dart';
 import 'package:unittest/unittest.dart';
+import 'package:analysis_server/src/operation/operation_analysis.dart';
+import 'package:analysis_server/src/operation/operation.dart';
 
 /**
  * Answer the absolute path the the SDK relative to the currently running
@@ -54,8 +55,8 @@
  * Returns a [Future] that completes when the given [AnalysisServer] finished
  * all its scheduled tasks.
  */
-Future waitForServerTasksFinished(AnalysisServer server) {
-  if (server.test_areTasksFinished()) {
+Future waitForServerOperationsPerformed(AnalysisServer server) {
+  if (server.test_areOperationsFinished()) {
     return new Future.value();
   }
   // We use a delayed future to allow microtask events to finish. The
@@ -63,7 +64,7 @@
   // would therefore not wait for microtask callbacks that are scheduled after
   // invoking this method.
   return new Future.delayed(Duration.ZERO,
-      () => waitForServerTasksFinished(server));
+      () => waitForServerOperationsPerformed(server));
 }
 
 /**
@@ -124,7 +125,7 @@
 class MockServerChannel implements ServerCommunicationChannel {
   StreamController<Request> requestController = new StreamController<Request>();
   StreamController<Response> responseController = new StreamController<Response>();
-  StreamController<Notification> notificationController = new StreamController<Notification>();
+  StreamController<Notification> notificationController = new StreamController<Notification>(sync: true);
 
   List<Response> responsesReceived = [];
   List<Notification> notificationsReceived = [];
@@ -141,7 +142,9 @@
   void sendNotification(Notification notification) {
     notificationsReceived.add(notification);
     // Wrap send notification in future to simulate websocket
-    new Future(() => notificationController.add(notification));
+    // TODO(scheglov) ask Dan why and decide what to do
+//    new Future(() => notificationController.add(notification));
+    notificationController.add(notification);
   }
 
   /**
@@ -171,41 +174,6 @@
 }
 
 /**
- * Exception thrown when an unexpected function call is made on a mock.
- */
-class UnexpectedMockCall extends Error {
-  UnexpectedMockCall(this.functionName);
-
-  final String functionName;
-
-  String toString() => "Unexpected call to $functionName";
-}
-
-/**
- * Shorthand function for throwing an UnexpectedMockCall exception.
- */
-_unexpected(String functionName) {
-  throw new UnexpectedMockCall(functionName);
-}
-
-/**
- * A mock [AnalysisLogger] that treats all errors and warnings as unexpected.
- */
-@proxy
-class MockAnalysisLogger extends Logger {
-
-  void logError(String message) {
-    print(message);
-    _unexpected('MockAnalysisLogger.logError');
-  }
-
-  noSuchMethod(Invocation invocation) {
-    var name = MirrorSystem.getName(invocation.memberName);
-    return _unexpected("MockAnalysisLogger.$name");
-  }
-}
-
-/**
  * A mock [AnalysisContext] for testing [AnalysisServer].
  */
 class MockAnalysisContext extends Mock implements AnalysisContext {
@@ -220,6 +188,31 @@
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
 
+typedef void MockServerOperationPerformFunction(AnalysisServer server);
+
+/**
+ * A mock [ServerOperation] for testing [AnalysisServer].
+ */
+class MockServerOperation implements PerformAnalysisOperation {
+  final ServerOperationPriority priority;
+  final MockServerOperationPerformFunction _perform;
+
+  MockServerOperation(this.priority, this._perform);
+
+  @override
+  void perform(AnalysisServer server) => this._perform(server);
+
+  @override
+  AnalysisContext get context => null;
+
+  @override
+  bool get isContinue => false;
+
+  @override
+  void sendNotices(AnalysisServer server, List<ChangeNotice> notices) {
+  }
+}
+
 
 /**
  * A [Matcher] that check that the given [Response] has an expected identifier
diff --git a/pkg/analysis_server/test/operation/operation_analysis_test.dart b/pkg/analysis_server/test/operation/operation_analysis_test.dart
new file mode 100644
index 0000000..4e5d2b4
--- /dev/null
+++ b/pkg/analysis_server/test/operation/operation_analysis_test.dart
@@ -0,0 +1,76 @@
+// 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.operation.analysis;
+
+import 'package:analysis_server/src/operation/operation_analysis.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:typed_mock/typed_mock.dart';
+import 'package:unittest/unittest.dart';
+
+import '../reflective_tests.dart';
+
+main() {
+  groupSep = ' | ';
+
+  group('errorToJson', () {
+    runReflectiveTests(Test_errorToJson);
+  });
+}
+
+
+@ReflectiveTestCase()
+class Test_errorToJson {
+  Source source = new SourceMock();
+  AnalysisError analysisError = new AnalysisErrorMock();
+
+  setUp() {
+    // prepare Source
+    when(source.fullName).thenReturn('foo.dart');
+    // prepare AnalysisError
+    when(analysisError.source).thenReturn(source);
+    when(analysisError.errorCode).thenReturn(CompileTimeErrorCode.AMBIGUOUS_EXPORT);
+    when(analysisError.message).thenReturn('my message');
+    when(analysisError.offset).thenReturn(10);
+    when(analysisError.length).thenReturn(20);
+  }
+
+  tearDown() {
+    source = null;
+    analysisError = null;
+  }
+
+  test_noCorrection() {
+    when(analysisError.correction).thenReturn('my correction');
+    Map<String, Object> json = errorToJson(analysisError);
+    expect(json, {
+      'file': 'foo.dart',
+      'errorCode': 'CompileTimeErrorCode.AMBIGUOUS_EXPORT',
+      'offset': 10,
+      'length': 20,
+      'message': 'my message',
+      'correction': 'my correction'});
+  }
+
+  test_withCorrection() {
+    Map<String, Object> json = errorToJson(analysisError);
+    expect(json, {
+      'file': 'foo.dart',
+      'errorCode': 'CompileTimeErrorCode.AMBIGUOUS_EXPORT',
+      'offset': 10,
+      'length': 20,
+      'message': 'my message'});
+  }
+}
+
+
+class SourceMock extends TypedMock implements Source {
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+
+class AnalysisErrorMock extends TypedMock implements AnalysisError {
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
diff --git a/pkg/analysis_server/test/operation/operation_queue_test.dart b/pkg/analysis_server/test/operation/operation_queue_test.dart
new file mode 100644
index 0000000..2b05e14
--- /dev/null
+++ b/pkg/analysis_server/test/operation/operation_queue_test.dart
@@ -0,0 +1,123 @@
+// 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.operation.queue;
+
+import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/operation/operation_analysis.dart';
+import 'package:analysis_server/src/operation/operation.dart';
+import 'package:analysis_server/src/operation/operation_queue.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:typed_mock/typed_mock.dart';
+import 'package:unittest/unittest.dart';
+
+main() {
+  groupSep = ' | ';
+
+  group('ServerOperationQueue', () {
+    AnalysisServer server;
+    ServerOperationQueue queue;
+
+    setUp(() {
+      server = new AnalysisServerMock();
+      queue = new ServerOperationQueue(server);
+    });
+
+    test('clear', () {
+      var operationA = mockOperation(ServerOperationPriority.SEARCH);
+      var operationB = mockOperation(ServerOperationPriority.REFACTORING);
+      queue.add(operationA);
+      queue.add(operationB);
+      // there are some operations
+      expect(queue.isEmpty, false);
+      // clear - no operations
+      queue.clear();
+      expect(queue.isEmpty, true);
+    });
+
+    group('isEmpty', () {
+      test('true', () {
+        expect(queue.isEmpty, isTrue);
+      });
+
+      test('false', () {
+        var operation = mockOperation(ServerOperationPriority.SEARCH);
+        queue.add(operation);
+        expect(queue.isEmpty, isFalse);
+      });
+    });
+
+    group('take', () {
+      test('empty', () {
+        expect(queue.take(), isNull);
+      });
+
+      test('use operation priorities', () {
+        // TODO(scheglov) update 'typed_mock' to make 'any*' fields dynamic
+        when(server.isPriorityContext(anyObject as dynamic)).thenReturn(false);
+        var analysisContext = new AnalysisContextMock();
+        var operationA = mockOperation(ServerOperationPriority.SEARCH);
+        var operationB = mockOperation(ServerOperationPriority.REFACTORING);
+        var operationC = new PerformAnalysisOperation(analysisContext, false);
+        queue.add(operationA);
+        queue.add(operationB);
+        queue.add(operationC);
+        expect(queue.take(), operationC);
+        expect(queue.take(), operationA);
+        expect(queue.take(), operationB);
+        expect(queue.take(), isNull);
+      });
+
+      test('continue analysis first', () {
+        // TODO(scheglov) update 'typed_mock' to make 'any*' fields dynamic
+        when(server.isPriorityContext(anyObject as dynamic)).thenReturn(false);
+        var analysisContext = new AnalysisContextMock();
+        var operationA = new PerformAnalysisOperation(analysisContext, false);
+        var operationB = new PerformAnalysisOperation(analysisContext, true);
+        queue.add(operationA);
+        queue.add(operationB);
+        expect(queue.take(), operationB);
+        expect(queue.take(), operationA);
+        expect(queue.take(), isNull);
+      });
+
+      test('priority context first', () {
+        var analysisContextA = new AnalysisContextMock();
+        var analysisContextB = new AnalysisContextMock();
+        var operationA = new PerformAnalysisOperation(analysisContextA, false);
+        var operationB = new PerformAnalysisOperation(analysisContextB, false);
+        queue.add(operationA);
+        queue.add(operationB);
+        when(server.isPriorityContext(analysisContextA)).thenReturn(false);
+        when(server.isPriorityContext(analysisContextB)).thenReturn(true);
+        expect(queue.take(), operationB);
+        expect(queue.take(), operationA);
+        expect(queue.take(), isNull);
+      });
+    });
+  });
+}
+
+
+/**
+ *  Return a [ServerOperation] mock with the given priority.
+ */
+ServerOperation mockOperation(ServerOperationPriority priority) {
+  ServerOperation operation = new ServerOperationMock();
+  when(operation.priority).thenReturn(priority);
+  return operation;
+}
+
+
+class AnalysisContextMock extends TypedMock implements AnalysisContext {
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+class ServerOperationMock extends TypedMock implements ServerOperation {
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+class AnalysisServerMock extends TypedMock implements AnalysisServer {
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
diff --git a/pkg/analysis_server/test/operation/operation_test.dart b/pkg/analysis_server/test/operation/operation_test.dart
new file mode 100644
index 0000000..4797ded
--- /dev/null
+++ b/pkg/analysis_server/test/operation/operation_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 test.operation;
+
+import 'package:analysis_server/src/operation/operation.dart';
+import 'package:unittest/unittest.dart';
+
+main() {
+  groupSep = ' | ';
+
+  group('ServerOperationPriority', () {
+    test('toString', () {
+      expect(ServerOperationPriority.SEARCH.toString(), 'SEARCH');
+    });
+  });
+}
diff --git a/pkg/analysis_server/test/operation/test_all.dart b/pkg/analysis_server/test/operation/test_all.dart
new file mode 100644
index 0000000..4a0d39b
--- /dev/null
+++ b/pkg/analysis_server/test/operation/test_all.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.
+
+import 'package:unittest/unittest.dart';
+
+import 'operation_analysis_test.dart' as analysis_operation_test;
+import 'operation_queue_test.dart' as operation_queue_test;
+import 'operation_test.dart' as operation_test;
+
+/**
+ * Utility for manually running all tests.
+ */
+main() {
+  groupSep = ' | ';
+  group('operation', () {
+    analysis_operation_test.main();
+    operation_queue_test.main();
+    operation_test.main();
+  });
+}
\ No newline at end of file
diff --git a/pkg/analysis_server/test/physical_resource_provider_test.dart b/pkg/analysis_server/test/physical_resource_provider_test.dart
index 00f6ca7..f2af810 100644
--- a/pkg/analysis_server/test/physical_resource_provider_test.dart
+++ b/pkg/analysis_server/test/physical_resource_provider_test.dart
@@ -7,10 +7,7 @@
 import 'dart:async';
 import 'dart:io' as io;
 
-import 'mocks.dart';
-
 import 'package:analysis_server/src/resource.dart';
-import 'package:analyzer/src/generated/engine.dart' show TimestampedData;
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:path/path.dart';
 import 'package:unittest/unittest.dart';
diff --git a/pkg/analysis_server/test/protocol_test.dart b/pkg/analysis_server/test/protocol_test.dart
index 61ec2b6..79c394b 100644
--- a/pkg/analysis_server/test/protocol_test.dart
+++ b/pkg/analysis_server/test/protocol_test.dart
@@ -425,6 +425,32 @@
     }).asStringMap(), _throwsInvalidParameter);
     expect(() => makeDatum([]).asStringMap(), _throwsInvalidParameter);
   }
+
+  @runTest
+  static void asStringListMap() {
+    setUp();
+    {
+      var map = {
+        'key1': ['value11', 'value12'],
+        'key2': ['value21', 'value22']
+      };
+      expect(makeDatum(map).asStringListMap(), map);
+    }
+    {
+      var map = {
+        'key1': 10,
+        'key2': 20
+      };
+      expect(() => makeDatum(map).asStringListMap(), _throwsInvalidParameter);
+    }
+    {
+      var map = {
+        'key1': [11, 12],
+        'key2': [21, 22]
+      };
+      expect(() => makeDatum(map).asStringListMap(), _throwsInvalidParameter);
+    }
+  }
 }
 
 class ResponseTest {
diff --git a/pkg/analysis_server/test/reflective_tests.dart b/pkg/analysis_server/test/reflective_tests.dart
new file mode 100644
index 0000000..107812e
--- /dev/null
+++ b/pkg/analysis_server/test/reflective_tests.dart
@@ -0,0 +1,74 @@
+// 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 reflective.tests;
+
+import 'dart:async';
+
+@MirrorsUsed(metaTargets: 'ReflectiveTestCase')
+import 'dart:mirrors';
+
+import 'package:unittest/unittest.dart';
+
+
+/**
+ * A marker annotation used to instruct dart2js to keep reflection information
+ * for the annotated classes.
+ */
+class ReflectiveTestCase {
+  const ReflectiveTestCase();
+}
+
+
+/**
+ * Runs test methods existing in the given [type].
+ *
+ * Methods with names starting with `test` are run using [test] function.
+ * Methods with names starting with `solo_test` are run using [solo_test] function.
+ *
+ * Each method is run with a new instance of [type].
+ * So, [type] should have a default constructor.
+ *
+ * If [type] declares method `setUp`, it methods will be invoked before any test
+ * method invocation.
+ *
+ * If [type] declares method `tearDown`, it will be invoked after any test
+ * method invocation. If method returns [Future] to test some asyncronous
+ * behavior, then `tearDown` will be invoked in `Future.complete`.
+ */
+void runReflectiveTests(Type type) {
+  ClassMirror classMirror = reflectClass(type);
+  classMirror.instanceMembers.forEach((symbol, memberMirror) {
+    // we need only methods
+    if (memberMirror is! MethodMirror || !memberMirror.isRegularMethod) {
+      return;
+    }
+    // check name
+    String memberName = MirrorSystem.getName(symbol);
+    if (memberName.startsWith('test_')) {
+      String testName = memberName.substring('test_'.length);
+      test(testName, () {
+        InstanceMirror instanceMirror = classMirror.newInstance(new Symbol(''), []);
+        _invokeSymbolIfExists(instanceMirror, #setUp);
+        var testReturn = instanceMirror.invoke(symbol, []).reflectee;
+        if (testReturn is Future) {
+          return testReturn.whenComplete(() {
+            _invokeSymbolIfExists(instanceMirror, #tearDown);
+          });
+        } else {
+          _invokeSymbolIfExists(instanceMirror, #tearDown);
+          return testReturn;
+        }
+      });
+    }
+  });
+}
+
+
+void _invokeSymbolIfExists(InstanceMirror instanceMirror, Symbol symbol) {
+  try {
+    instanceMirror.invoke(symbol, []);
+  } on NoSuchMethodError catch (e) {
+  }
+}
diff --git a/pkg/analysis_server/test/resource_test.dart b/pkg/analysis_server/test/resource_test.dart
index a7b58bf..a7e2b47 100644
--- a/pkg/analysis_server/test/resource_test.dart
+++ b/pkg/analysis_server/test/resource_test.dart
@@ -5,7 +5,6 @@
 library test.resource;
 
 import 'dart:async';
-import 'dart:io' as io;
 
 import 'mocks.dart';
 
diff --git a/pkg/analysis_server/test/socket_server_test.dart b/pkg/analysis_server/test/socket_server_test.dart
index fbc1512..0f9c083 100644
--- a/pkg/analysis_server/test/socket_server_test.dart
+++ b/pkg/analysis_server/test/socket_server_test.dart
@@ -8,8 +8,7 @@
 
 import 'mocks.dart';
 
-import 'package:analysis_server/src/analysis_server.dart';
-import 'package:analysis_server/src/domain_server.dart';
+import 'package:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/protocol.dart';
 import 'package:analysis_server/src/socket_server.dart';
 import 'package:unittest/unittest.dart';
@@ -29,11 +28,11 @@
     MockServerChannel channel = new MockServerChannel();
     server.createAnalysisServer(channel);
     channel.expectMsgCount(notificationCount: 1);
-    expect(channel.notificationsReceived[0].event, equals(
-        AnalysisServer.CONNECTED_NOTIFICATION));
+    expect(channel.notificationsReceived[0].event, NOTIFICATION_CONNECTED);
     expect(channel.notificationsReceived[0].params, isEmpty);
-    return channel.sendRequest(new Request('0',
-        ServerDomainHandler.SHUTDOWN_METHOD)).then((Response response) {
+    return channel.sendRequest(
+        new Request('0', METHOD_SHUTDOWN)
+    ).then((Response response) {
       expect(response.id, equals('0'));
       expect(response.error, isNull);
       channel.expectMsgCount(responseCount: 1, notificationCount: 1);
@@ -45,8 +44,7 @@
     MockServerChannel channel1 = new MockServerChannel();
     MockServerChannel channel2 = new MockServerChannel();
     server.createAnalysisServer(channel1);
-    expect(channel1.notificationsReceived[0].event, equals(
-        AnalysisServer.CONNECTED_NOTIFICATION));
+    expect(channel1.notificationsReceived[0].event, NOTIFICATION_CONNECTED);
     expect(channel1.notificationsReceived[0].params, isEmpty);
     server.createAnalysisServer(channel2);
     channel1.expectMsgCount(notificationCount: 1);
@@ -55,8 +53,7 @@
     expect(channel2.responsesReceived[0].error, isNotNull);
     expect(channel2.responsesReceived[0].error.code, equals(
         RequestError.CODE_SERVER_ALREADY_STARTED));
-    channel2.sendRequest(new Request('0', ServerDomainHandler.SHUTDOWN_METHOD)
-        ).then((Response response) {
+    channel2.sendRequest(new Request('0', METHOD_SHUTDOWN)).then((Response response) {
       expect(response.id, equals('0'));
       expect(response.error, isNotNull);
       expect(response.error.code, equals(
diff --git a/pkg/analysis_server/test/test_all.dart b/pkg/analysis_server/test/test_all.dart
index b7c5df6..42cf5a9 100644
--- a/pkg/analysis_server/test/test_all.dart
+++ b/pkg/analysis_server/test/test_all.dart
@@ -4,11 +4,12 @@
 
 import 'package:unittest/unittest.dart';
 
+import 'analysis_notification_navigation_test.dart' as analysis_notification_navigation_test;
 import 'analysis_server_test.dart' as analysis_server_test;
 import 'channel_test.dart' as channel_test;
 import 'domain_analysis_test.dart' as domain_analysis_test;
-import 'domain_context_test.dart' as domain_context_test;
 import 'domain_server_test.dart' as domain_server_test;
+import 'operation/test_all.dart' as operation_test;
 import 'protocol_test.dart' as protocol_test;
 import 'resource_test.dart' as resource_test;
 import 'socket_server_test.dart' as socket_server_test;
@@ -19,11 +20,12 @@
 main() {
   groupSep = ' | ';
   group('analysis_server', () {
+    analysis_notification_navigation_test.main();
     analysis_server_test.main();
     channel_test.main();
     domain_analysis_test.main();
-    domain_context_test.main();
     domain_server_test.main();
+    operation_test.main();
     protocol_test.main();
     resource_test.main();
     socket_server_test.main();
diff --git a/pkg/analyzer/lib/analyzer.dart b/pkg/analyzer/lib/analyzer.dart
index fc9cfa1..dc0b647 100644
--- a/pkg/analyzer/lib/analyzer.dart
+++ b/pkg/analyzer/lib/analyzer.dart
@@ -52,6 +52,9 @@
 ///
 /// If [name] is passed, it's used in error messages as the name of the code
 /// being parsed.
+///
+/// Throws an [AnalyzerErrorGroup] if any errors occurred, unless
+/// [suppressErrors] is `true`, in which case any errors are discarded.
 CompilationUnit parseCompilationUnit(String contents,
     {String name, bool suppressErrors: false}) {
   if (name == null) name = '<unknown source>';
@@ -69,6 +72,33 @@
   return unit;
 }
 
+/// Parses the script tag and directives in a string of Dart code into an AST.
+///
+/// Stops parsing when the first non-directive is encountered. The rest of the
+/// string will not be parsed.
+///
+/// If [name] is passed, it's used in error messages as the name of the code
+/// being parsed.
+///
+/// Throws an [AnalyzerErrorGroup] if any errors occurred, unless
+/// [suppressErrors] is `true`, in which case any errors are discarded.
+CompilationUnit parseDirectives(String contents,
+    {String name, bool suppressErrors: false}) {
+  if (name == null) name = '<unknown source>';
+  var source = new StringSource(contents, name);
+  var errorCollector = new _ErrorCollector();
+  var reader = new CharSequenceReader(contents);
+  var scanner = new Scanner(source, reader, errorCollector);
+  var token = scanner.tokenize();
+  var parser = new Parser(source, errorCollector);
+  var unit = parser.parseDirectives(token);
+  unit.lineInfo = new LineInfo(scanner.lineStarts);
+
+  if (errorCollector.hasErrors && !suppressErrors) throw errorCollector.group;
+
+  return unit;
+}
+
 /// Converts an AST node representing a string literal into a [String].
 String stringLiteralToString(StringLiteral literal) {
   return literal.stringValue;
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 1f452ed..caa0f1c 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.15.5
+version: 0.15.6-dev
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: http://www.dartlang.org
diff --git a/pkg/barback/pubspec.yaml b/pkg/barback/pubspec.yaml
index bbfd90b..53666e3 100644
--- a/pkg/barback/pubspec.yaml
+++ b/pkg/barback/pubspec.yaml
@@ -24,7 +24,7 @@
 dependencies:
   path: ">=0.9.0 <2.0.0"
   source_maps: ">=0.9.0 <0.10.0"
-  stack_trace: ">=0.9.1 <0.10.0"
+  stack_trace: ">=0.9.1 <2.0.0"
   collection: ">=0.9.1 <0.10.0"
 dev_dependencies:
   scheduled_test: ">=0.9.0 <0.11.0"
diff --git a/pkg/docgen/pubspec.yaml b/pkg/docgen/pubspec.yaml
index 63a90a5..dd37a0a 100644
--- a/pkg/docgen/pubspec.yaml
+++ b/pkg/docgen/pubspec.yaml
@@ -7,7 +7,7 @@
   logging: '>=0.9.0 <0.10.0'
   markdown: 0.7.0
   path: '>=0.9.0 <2.0.0'
-  yaml: '>=0.9.0 <0.10.0'
+  yaml: '>=0.9.0 <2.0.0'
 dev_dependencies:
   scheduled_test: '>=0.10.0 <0.12.0'
   unittest: '>=0.9.0 <0.11.0'
diff --git a/pkg/http/CHANGELOG.md b/pkg/http/CHANGELOG.md
index ac6a0cf..8d6e3c8 100644
--- a/pkg/http/CHANGELOG.md
+++ b/pkg/http/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.11.1+1
+
+* Widen the version constraint for `stack_trace`.
+
 ## 0.11.1
 
 * Expose the `IOClient` class which wraps a `dart:io` `HttpClient`.
diff --git a/pkg/http/pubspec.yaml b/pkg/http/pubspec.yaml
index 077d277..abb241d 100644
--- a/pkg/http/pubspec.yaml
+++ b/pkg/http/pubspec.yaml
@@ -1,12 +1,12 @@
 name: http
-version: 0.11.1
+version: 0.11.1+1
 author: "Dart Team <misc@dartlang.org>"
 homepage: https://pub.dartlang.org/packages/http
 description: A composable, Future-based API for making HTTP requests.
 dependencies:
   http_parser: ">=0.0.1 <0.1.0"
   path: ">=0.9.0 <2.0.0"
-  stack_trace: ">=0.9.1 <0.10.0"
+  stack_trace: ">=0.9.1 <2.0.0"
 dev_dependencies:
   unittest: ">=0.9.0 <0.11.0"
 environment:
diff --git a/pkg/http_parser/CHANGELOG.md b/pkg/http_parser/CHANGELOG.md
index 48073a4..328e779 100644
--- a/pkg/http_parser/CHANGELOG.md
+++ b/pkg/http_parser/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.0.2+3
+
+* Fix a library name conflict.
+
 ## 0.0.2+2
 
 * Fixes for HTTP date formatting.
diff --git a/pkg/http_parser/lib/src/http_date.dart b/pkg/http_parser/lib/src/http_date.dart
index ff7c710..0626c72 100644
--- a/pkg/http_parser/lib/src/http_date.dart
+++ b/pkg/http_parser/lib/src/http_date.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library http_parser;
+library http_parser.http_date;
 
 import 'package:string_scanner/string_scanner.dart';
 
diff --git a/pkg/http_parser/pubspec.yaml b/pkg/http_parser/pubspec.yaml
index d473759..af1a192 100644
--- a/pkg/http_parser/pubspec.yaml
+++ b/pkg/http_parser/pubspec.yaml
@@ -1,5 +1,5 @@
 name: http_parser
-version: 0.0.2+2
+version: 0.0.2+3
 author: "Dart Team <misc@dartlang.org>"
 homepage: http://www.dartlang.org
 description: >
diff --git a/pkg/json_rpc_2/CHANGELOG.md b/pkg/json_rpc_2/CHANGELOG.md
index 3b0694e..ba15fb3 100644
--- a/pkg/json_rpc_2/CHANGELOG.md
+++ b/pkg/json_rpc_2/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.0.2+3
+
+* Widen the version constraint for `stack_trace`.
+
 ## 0.0.2+2
 
 * Fix error response to include data from `RpcException` when not a map.
diff --git a/pkg/json_rpc_2/pubspec.yaml b/pkg/json_rpc_2/pubspec.yaml
index b340db3..2cf1bc8 100644
--- a/pkg/json_rpc_2/pubspec.yaml
+++ b/pkg/json_rpc_2/pubspec.yaml
@@ -1,11 +1,11 @@
 name: json_rpc_2
-version: 0.0.2+2
+version: 0.0.2+3
 author: Dart Team <misc@dartlang.org>
 description: An implementation of the JSON-RPC 2.0 spec.
 homepage: http://www.dartlang.org
 documentation: http://api.dartlang.org/docs/pkg/json_rpc_2
 dependencies:
-  stack_trace: '>=0.9.1 <0.10.0'
+  stack_trace: '>=0.9.1 <2.0.0'
 dev_dependencies:
   unittest: ">=0.9.0 <0.10.0"
 environment:
diff --git a/pkg/mime/lib/mime.dart b/pkg/mime/lib/mime.dart
index 11b2ca9..dce6774 100644
--- a/pkg/mime/lib/mime.dart
+++ b/pkg/mime/lib/mime.dart
@@ -15,4 +15,5 @@
 library mime;
 
 export 'src/mime_multipart_transformer.dart';
+export 'src/mime_shared.dart';
 export 'src/mime_type.dart';
diff --git a/pkg/mime/lib/src/bound_multipart_stream.dart b/pkg/mime/lib/src/bound_multipart_stream.dart
new file mode 100644
index 0000000..d470034
--- /dev/null
+++ b/pkg/mime/lib/src/bound_multipart_stream.dart
@@ -0,0 +1,375 @@
+// 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 mime.bound_multipart_stream;
+
+import 'dart:async';
+import 'dart:convert';
+
+import 'mime_shared.dart';
+import 'char_code.dart';
+
+// Bytes for '()<>@,;:\\"/[]?={} \t'.
+const _SEPARATORS = const [40, 41, 60, 62, 64, 44, 59, 58, 92, 34, 47, 91, 93,
+                           63, 61, 123, 125, 32, 9];
+
+bool _isTokenChar(int byte) {
+  return byte > 31 && byte < 128 && _SEPARATORS.indexOf(byte) == -1;
+}
+
+int _toLowerCase(int byte) {
+  const delta = CharCode.LOWER_A - CharCode.UPPER_A;
+  return (CharCode.UPPER_A <= byte && byte <= CharCode.UPPER_Z) ?
+      byte + delta : byte;
+}
+
+void _expectByteValue(int val1, int val2) {
+  if (val1 != val2) {
+    throw new MimeMultipartException("Failed to parse multipart mime 1");
+  }
+}
+
+void _expectWhitespace(int byte) {
+  if (byte != CharCode.SP && byte != CharCode.HT) {
+    throw new MimeMultipartException("Failed to parse multipart mime 2");
+  }
+}
+
+class _MimeMultipart extends MimeMultipart {
+  final Map<String, String> headers;
+  final Stream<List<int>> _stream;
+
+  _MimeMultipart(this.headers, this._stream);
+
+  StreamSubscription<List<int>> listen(void onData(List<int> data),
+                                       {void onDone(),
+                                        Function onError,
+                                        bool cancelOnError}) {
+    return _stream.listen(onData,
+                          onDone: onDone,
+                          onError: onError,
+                          cancelOnError: cancelOnError);
+  }
+}
+
+class BoundMultipartStream {
+   static const int _START = 0;
+   static const int _FIRST_BOUNDARY_ENDING = 111;
+   static const int _FIRST_BOUNDARY_END = 112;
+   static const int _BOUNDARY_ENDING = 1;
+   static const int _BOUNDARY_END = 2;
+   static const int _HEADER_START = 3;
+   static const int _HEADER_FIELD = 4;
+   static const int _HEADER_VALUE_START = 5;
+   static const int _HEADER_VALUE = 6;
+   static const int _HEADER_VALUE_FOLDING_OR_ENDING = 7;
+   static const int _HEADER_VALUE_FOLD_OR_END = 8;
+   static const int _HEADER_ENDING = 9;
+   static const int _CONTENT = 10;
+   static const int _LAST_BOUNDARY_DASH2 = 11;
+   static const int _LAST_BOUNDARY_ENDING = 12;
+   static const int _LAST_BOUNDARY_END = 13;
+   static const int _DONE = 14;
+   static const int _FAIL = 15;
+
+   final List<int> _boundary;
+   final List<int> _headerField = [];
+   final List<int> _headerValue = [];
+
+   StreamController _controller;
+
+   Stream<MimeMultipart> get stream => _controller.stream;
+
+   StreamSubscription _subscription;
+
+   StreamController _multipartController;
+   Map<String, String> _headers;
+
+   int _state = _START;
+   int _boundaryIndex = 2;
+
+   // Current index in the data buffer. If index is negative then it
+   // is the index into the artificial prefix of the boundary string.
+   int _index;
+   List<int> _buffer;
+
+   BoundMultipartStream(this._boundary, Stream<List<int>> stream) {
+     _controller = new StreamController(
+         sync: true,
+         onPause: _pauseStream,
+         onResume:_resumeStream,
+         onCancel: () {
+           _subscription.cancel();
+         },
+         onListen: () {
+           _subscription = stream.listen(
+               (data) {
+                 assert(_buffer == null);
+                 _pauseStream();
+                 _buffer = data;
+                 _index = 0;
+                 _parse();
+               },
+               onDone: () {
+                 if (_state != _DONE) {
+                   _controller.addError(
+                       new MimeMultipartException("Bad multipart ending"));
+                 }
+                 _controller.close();
+               },
+               onError: _controller.addError);
+         });
+   }
+
+   void _resumeStream() {
+     _subscription.resume();
+   }
+
+   void _pauseStream() {
+     _subscription.pause();
+   }
+
+
+   void _parse() {
+     // Number of boundary bytes to artificially place before the supplied data.
+     int boundaryPrefix = 0;
+     // Position where content starts. Will be null if no known content
+     // start exists. Will be negative of the content starts in the
+     // boundary prefix. Will be zero or position if the content starts
+     // in the current buffer.
+     int contentStartIndex;
+
+     // Function to report content data for the current part. The data
+     // reported is from the current content start index up til the
+     // current index. As the data can be artificially prefixed with a
+     // prefix of the boundary both the content start index and index
+     // can be negative.
+     void reportData() {
+       if (contentStartIndex < 0) {
+         var contentLength = boundaryPrefix + _index - _boundaryIndex;
+         if (contentLength <= boundaryPrefix) {
+           _multipartController.add(
+               _boundary.sublist(0, contentLength));
+         } else {
+           _multipartController.add(
+               _boundary.sublist(0, boundaryPrefix));
+           _multipartController.add(
+               _buffer.sublist(0, contentLength - boundaryPrefix));
+         }
+       } else {
+         var contentEndIndex = _index - _boundaryIndex;
+         _multipartController.add(
+             _buffer.sublist(contentStartIndex, contentEndIndex));
+       }
+     }
+
+     if (_state == _CONTENT && _boundaryIndex == 0) {
+       contentStartIndex = 0;
+     } else {
+       contentStartIndex = null;
+     }
+     // The data to parse might be "artificially" prefixed with a
+     // partial match of the boundary.
+     boundaryPrefix = _boundaryIndex;
+
+     while ((_index < _buffer.length) && _state != _FAIL && _state != _DONE) {
+       if (_multipartController != null && _multipartController.isPaused) {
+         return;
+       }
+       int byte;
+       if (_index < 0) {
+         byte = _boundary[boundaryPrefix + _index];
+       } else {
+         byte = _buffer[_index];
+       }
+       switch (_state) {
+         case _START:
+           if (byte == _boundary[_boundaryIndex]) {
+             _boundaryIndex++;
+             if (_boundaryIndex == _boundary.length) {
+               _state = _FIRST_BOUNDARY_ENDING;
+               _boundaryIndex = 0;
+             }
+           } else {
+             // Restart matching of the boundary.
+             _index = _index - _boundaryIndex;
+             _boundaryIndex = 0;
+           }
+           break;
+
+         case _FIRST_BOUNDARY_ENDING:
+           if (byte == CharCode.CR) {
+             _state = _FIRST_BOUNDARY_END;
+           } else {
+             _expectWhitespace(byte);
+           }
+           break;
+
+         case _FIRST_BOUNDARY_END:
+           _expectByteValue(byte, CharCode.LF);
+           _state = _HEADER_START;
+           break;
+
+         case _BOUNDARY_ENDING:
+           if (byte == CharCode.CR) {
+             _state = _BOUNDARY_END;
+           } else if (byte == CharCode.DASH) {
+             _state = _LAST_BOUNDARY_DASH2;
+           } else {
+             _expectWhitespace(byte);
+           }
+           break;
+
+         case _BOUNDARY_END:
+           _expectByteValue(byte, CharCode.LF);
+           _multipartController.close();
+           _multipartController = null;
+           _state = _HEADER_START;
+           break;
+
+         case _HEADER_START:
+           _headers = new Map<String, String>();
+           if (byte == CharCode.CR) {
+             _state = _HEADER_ENDING;
+           } else {
+             // Start of new header field.
+             _headerField.add(_toLowerCase(byte));
+             _state = _HEADER_FIELD;
+           }
+           break;
+
+         case _HEADER_FIELD:
+           if (byte == CharCode.COLON) {
+             _state = _HEADER_VALUE_START;
+           } else {
+             if (!_isTokenChar(byte)) {
+               throw new MimeMultipartException("Invalid header field name");
+             }
+             _headerField.add(_toLowerCase(byte));
+           }
+           break;
+
+         case _HEADER_VALUE_START:
+           if (byte == CharCode.CR) {
+             _state = _HEADER_VALUE_FOLDING_OR_ENDING;
+           } else if (byte != CharCode.SP && byte != CharCode.HT) {
+             // Start of new header value.
+             _headerValue.add(byte);
+             _state = _HEADER_VALUE;
+           }
+           break;
+
+         case _HEADER_VALUE:
+           if (byte == CharCode.CR) {
+             _state = _HEADER_VALUE_FOLDING_OR_ENDING;
+           } else {
+             _headerValue.add(byte);
+           }
+           break;
+
+         case _HEADER_VALUE_FOLDING_OR_ENDING:
+           _expectByteValue(byte, CharCode.LF);
+           _state = _HEADER_VALUE_FOLD_OR_END;
+           break;
+
+         case _HEADER_VALUE_FOLD_OR_END:
+           if (byte == CharCode.SP || byte == CharCode.HT) {
+             _state = _HEADER_VALUE_START;
+           } else {
+             String headerField = UTF8.decode(_headerField);
+             String headerValue = UTF8.decode(_headerValue);
+             _headers[headerField.toLowerCase()] = headerValue;
+             _headerField.clear();
+             _headerValue.clear();
+             if (byte == CharCode.CR) {
+               _state = _HEADER_ENDING;
+             } else {
+               // Start of new header field.
+               _headerField.add(_toLowerCase(byte));
+               _state = _HEADER_FIELD;
+             }
+           }
+           break;
+
+         case _HEADER_ENDING:
+           _expectByteValue(byte, CharCode.LF);
+           _multipartController = new StreamController(
+               sync: true,
+               onPause: () {
+                 _pauseStream();
+               },
+               onResume: () {
+                 _resumeStream();
+                 _parse();
+               });
+           _controller.add(
+               new _MimeMultipart(_headers, _multipartController.stream));
+           _headers = null;
+           _state = _CONTENT;
+           contentStartIndex = _index + 1;
+           break;
+
+         case _CONTENT:
+           if (byte == _boundary[_boundaryIndex]) {
+             _boundaryIndex++;
+             if (_boundaryIndex == _boundary.length) {
+               if (contentStartIndex != null) {
+                 _index++;
+                 reportData();
+                 _index--;
+               }
+               _multipartController.close();
+               _boundaryIndex = 0;
+               _state = _BOUNDARY_ENDING;
+             }
+           } else {
+             // Restart matching of the boundary.
+             _index = _index - _boundaryIndex;
+             if (contentStartIndex == null) contentStartIndex = _index;
+             _boundaryIndex = 0;
+           }
+           break;
+
+         case _LAST_BOUNDARY_DASH2:
+           _expectByteValue(byte, CharCode.DASH);
+           _state = _LAST_BOUNDARY_ENDING;
+           break;
+
+         case _LAST_BOUNDARY_ENDING:
+           if (byte == CharCode.CR) {
+             _state = _LAST_BOUNDARY_END;
+           } else {
+             _expectWhitespace(byte);
+           }
+           break;
+
+         case _LAST_BOUNDARY_END:
+           _expectByteValue(byte, CharCode.LF);
+           _multipartController.close();
+           _multipartController = null;
+           _state = _DONE;
+           break;
+
+         default:
+           // Should be unreachable.
+           assert(false);
+           break;
+       }
+
+       // Move to the next byte.
+       _index++;
+     }
+
+     // Report any known content.
+     if (_state == _CONTENT && contentStartIndex != null) {
+       reportData();
+     }
+
+     // Resume if at end.
+     if (_index == _buffer.length) {
+       _buffer = null;
+       _index = null;
+       _resumeStream();
+     }
+   }
+}
diff --git a/pkg/mime/lib/src/char_code.dart b/pkg/mime/lib/src/char_code.dart
new file mode 100644
index 0000000..f455e68
--- /dev/null
+++ b/pkg/mime/lib/src/char_code.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 mime.char_code;
+
+class CharCode {
+  static const int HT = 9;
+  static const int LF = 10;
+  static const int CR = 13;
+  static const int SP = 32;
+  static const int DASH = 45;
+  static const int COLON = 58;
+  static const int UPPER_A = 65;
+  static const int UPPER_Z = 90;
+  static const int LOWER_A = 97;
+}
diff --git a/pkg/mime/lib/src/mime_multipart_transformer.dart b/pkg/mime/lib/src/mime_multipart_transformer.dart
index 75d10ff..3afff2d 100644
--- a/pkg/mime/lib/src/mime_multipart_transformer.dart
+++ b/pkg/mime/lib/src/mime_multipart_transformer.dart
@@ -1,45 +1,28 @@
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-
 library mime.multipart_transformer;
 
 import 'dart:async';
-import 'dart:convert';
 import 'dart:typed_data';
 
-/**
- * A Mime Multipart class representing each part parsed by
- * [MimeMultipartTransformer]. The data is streamed in as it become available.
- */
-abstract class MimeMultipart extends Stream<List<int>> {
-  Map<String, String> get headers;
-}
+import 'bound_multipart_stream.dart';
+import 'mime_shared.dart';
+import 'char_code.dart';
 
-class _MimeMultipart extends MimeMultipart {
-  final Map<String, String> headers;
-  final Stream<List<int>> _stream;
 
-  _MimeMultipart(this.headers, this._stream);
+Uint8List _getBoundary(String boundary) {
+  var charCodes = boundary.codeUnits;
 
-  StreamSubscription<List<int>> listen(void onData(List<int> data),
-                                       {void onDone(),
-                                        Function onError,
-                                        bool cancelOnError}) {
-    return _stream.listen(onData,
-                          onDone: onDone,
-                          onError: onError,
-                          cancelOnError: cancelOnError);
-  }
-}
-
-class _CharCode {
-  static const int HT = 9;
-  static const int LF = 10;
-  static const int CR = 13;
-  static const int SP = 32;
-  static const int DASH = 45;
-  static const int COLON = 58;
+  var boundaryList = new Uint8List(4 + charCodes.length);
+  // Set-up the matching boundary preceding it with CRLF and two
+  // dashes.
+  boundaryList[0] = CharCode.CR;
+  boundaryList[1] = CharCode.LF;
+  boundaryList[2] = CharCode.DASH;
+  boundaryList[3] = CharCode.DASH;
+  boundaryList.setRange(4, 4 + charCodes.length, charCodes);
+  return boundaryList;
 }
 
 /**
@@ -49,373 +32,18 @@
  */
 class MimeMultipartTransformer
     implements StreamTransformer<List<int>, MimeMultipart> {
-  static const int _START = 0;
-  static const int _FIRST_BOUNDARY_ENDING = 111;
-  static const int _FIRST_BOUNDARY_END = 112;
-  static const int _BOUNDARY_ENDING = 1;
-  static const int _BOUNDARY_END = 2;
-  static const int _HEADER_START = 3;
-  static const int _HEADER_FIELD = 4;
-  static const int _HEADER_VALUE_START = 5;
-  static const int _HEADER_VALUE = 6;
-  static const int _HEADER_VALUE_FOLDING_OR_ENDING = 7;
-  static const int _HEADER_VALUE_FOLD_OR_END = 8;
-  static const int _HEADER_ENDING = 9;
-  static const int _CONTENT = 10;
-  static const int _LAST_BOUNDARY_DASH2 = 11;
-  static const int _LAST_BOUNDARY_ENDING = 12;
-  static const int _LAST_BOUNDARY_END = 13;
-  static const int _DONE = 14;
-  static const int _FAILURE = 15;
 
-  // Bytes for '()<>@,;:\\"/[]?={} \t'.
-  static const _SEPARATORS = const [40, 41, 60, 62, 64, 44, 59, 58, 92, 34, 47,
-                                   91, 93, 63, 61, 123, 125, 32, 9];
-
-  StreamController _controller;
-  StreamSubscription _subscription;
-
-  StreamController _multipartController;
-  Map<String, String> _headers;
-
-  List<int> _boundary;
-  int _state = _START;
-  int _boundaryIndex = 2;
-
-  // Current index in the data buffer. If index is negative then it
-  // is the index into the artificial prefix of the boundary string.
-  int _index;
-  List<int> _buffer;
-
-  List<int> _headerField = [];
-  List<int> _headerValue = [];
+  final List<int> _boundary;
 
   /**
    * Construct a new MIME multipart parser with the boundary
    * [boundary]. The boundary should be as specified in the content
    * type parameter, that is without the -- prefix.
    */
-  MimeMultipartTransformer(String boundary) {
-    List<int> charCodes = boundary.codeUnits;
-    _boundary = new Uint8List(4 + charCodes.length);
-    // Set-up the matching boundary preceding it with CRLF and two
-    // dashes.
-    _boundary[0] = _CharCode.CR;
-    _boundary[1] = _CharCode.LF;
-    _boundary[2] = _CharCode.DASH;
-    _boundary[3] = _CharCode.DASH;
-    _boundary.setRange(4, 4 + charCodes.length, charCodes);
-  }
-
-  void _resumeStream() {
-    _subscription.resume();
-  }
-
-  void _pauseStream() {
-    _subscription.pause();
-  }
+  MimeMultipartTransformer(String boundary)
+      : _boundary = _getBoundary(boundary);
 
   Stream<MimeMultipart> bind(Stream<List<int>> stream) {
-    _controller = new StreamController(
-        sync: true,
-        onPause: _pauseStream,
-        onResume:_resumeStream,
-        onCancel: () {
-          _subscription.cancel();
-        },
-        onListen: () {
-          _subscription = stream.listen(
-              (data) {
-                assert(_buffer == null);
-                _pauseStream();
-                _buffer = data;
-                _index = 0;
-                _parse();
-              },
-              onDone: () {
-                if (_state != _DONE) {
-                  _controller.addError(
-                      new MimeMultipartException("Bad multipart ending"));
-                }
-                _controller.close();
-              },
-              onError: _controller.addError);
-        });
-    return _controller.stream;
+    return new BoundMultipartStream(_boundary, stream).stream;
   }
-
-  void _parse() {
-    // Number of boundary bytes to artificially place before the supplied data.
-    int boundaryPrefix = 0;
-    // Position where content starts. Will be null if no known content
-    // start exists. Will be negative of the content starts in the
-    // boundary prefix. Will be zero or position if the content starts
-    // in the current buffer.
-    int contentStartIndex;
-
-    // Function to report content data for the current part. The data
-    // reported is from the current content start index up til the
-    // current index. As the data can be artificially prefixed with a
-    // prefix of the boundary both the content start index and index
-    // can be negative.
-    void reportData() {
-      if (contentStartIndex < 0) {
-        var contentLength = boundaryPrefix + _index - _boundaryIndex;
-        if (contentLength <= boundaryPrefix) {
-          _multipartController.add(
-              _boundary.sublist(0, contentLength));
-        } else {
-          _multipartController.add(
-              _boundary.sublist(0, boundaryPrefix));
-          _multipartController.add(
-              _buffer.sublist(0, contentLength - boundaryPrefix));
-        }
-      } else {
-        var contentEndIndex = _index - _boundaryIndex;
-        _multipartController.add(
-            _buffer.sublist(contentStartIndex, contentEndIndex));
-      }
-    }
-
-    if (_state == _CONTENT && _boundaryIndex == 0) {
-      contentStartIndex = 0;
-    } else {
-      contentStartIndex = null;
-    }
-    // The data to parse might be "artificially" prefixed with a
-    // partial match of the boundary.
-    boundaryPrefix = _boundaryIndex;
-
-    while ((_index < _buffer.length) && _state != _FAILURE && _state != _DONE) {
-      if (_multipartController != null && _multipartController.isPaused) {
-        return;
-      }
-      int byte;
-      if (_index < 0) {
-        byte = _boundary[boundaryPrefix + _index];
-      } else {
-        byte = _buffer[_index];
-      }
-      switch (_state) {
-        case _START:
-          if (byte == _boundary[_boundaryIndex]) {
-            _boundaryIndex++;
-            if (_boundaryIndex == _boundary.length) {
-              _state = _FIRST_BOUNDARY_ENDING;
-              _boundaryIndex = 0;
-            }
-          } else {
-            // Restart matching of the boundary.
-            _index = _index - _boundaryIndex;
-            _boundaryIndex = 0;
-          }
-          break;
-
-        case _FIRST_BOUNDARY_ENDING:
-          if (byte == _CharCode.CR) {
-            _state = _FIRST_BOUNDARY_END;
-          } else {
-            _expectWS(byte);
-          }
-          break;
-
-        case _FIRST_BOUNDARY_END:
-          _expect(byte, _CharCode.LF);
-          _state = _HEADER_START;
-          break;
-
-        case _BOUNDARY_ENDING:
-          if (byte == _CharCode.CR) {
-            _state = _BOUNDARY_END;
-          } else if (byte == _CharCode.DASH) {
-            _state = _LAST_BOUNDARY_DASH2;
-          } else {
-            _expectWS(byte);
-          }
-          break;
-
-        case _BOUNDARY_END:
-          _expect(byte, _CharCode.LF);
-          _multipartController.close();
-          _multipartController = null;
-          _state = _HEADER_START;
-          break;
-
-        case _HEADER_START:
-          _headers = new Map<String, String>();
-          if (byte == _CharCode.CR) {
-            _state = _HEADER_ENDING;
-          } else {
-            // Start of new header field.
-            _headerField.add(_toLowerCase(byte));
-            _state = _HEADER_FIELD;
-          }
-          break;
-
-        case _HEADER_FIELD:
-          if (byte == _CharCode.COLON) {
-            _state = _HEADER_VALUE_START;
-          } else {
-            if (!_isTokenChar(byte)) {
-              throw new MimeMultipartException("Invalid header field name");
-            }
-            _headerField.add(_toLowerCase(byte));
-          }
-          break;
-
-        case _HEADER_VALUE_START:
-          if (byte == _CharCode.CR) {
-            _state = _HEADER_VALUE_FOLDING_OR_ENDING;
-          } else if (byte != _CharCode.SP && byte != _CharCode.HT) {
-            // Start of new header value.
-            _headerValue.add(byte);
-            _state = _HEADER_VALUE;
-          }
-          break;
-
-        case _HEADER_VALUE:
-          if (byte == _CharCode.CR) {
-            _state = _HEADER_VALUE_FOLDING_OR_ENDING;
-          } else {
-            _headerValue.add(byte);
-          }
-          break;
-
-        case _HEADER_VALUE_FOLDING_OR_ENDING:
-          _expect(byte, _CharCode.LF);
-          _state = _HEADER_VALUE_FOLD_OR_END;
-          break;
-
-        case _HEADER_VALUE_FOLD_OR_END:
-          if (byte == _CharCode.SP || byte == _CharCode.HT) {
-            _state = _HEADER_VALUE_START;
-          } else {
-            String headerField = UTF8.decode(_headerField);
-            String headerValue = UTF8.decode(_headerValue);
-            _headers[headerField.toLowerCase()] = headerValue;
-            _headerField = [];
-            _headerValue = [];
-            if (byte == _CharCode.CR) {
-              _state = _HEADER_ENDING;
-            } else {
-              // Start of new header field.
-              _headerField.add(_toLowerCase(byte));
-              _state = _HEADER_FIELD;
-            }
-          }
-          break;
-
-        case _HEADER_ENDING:
-          _expect(byte, _CharCode.LF);
-          _multipartController = new StreamController(
-              sync: true,
-              onPause: () {
-                _pauseStream();
-              },
-              onResume: () {
-                _resumeStream();
-                _parse();
-              });
-          _controller.add(
-              new _MimeMultipart(_headers, _multipartController.stream));
-          _headers = null;
-          _state = _CONTENT;
-          contentStartIndex = _index + 1;
-          break;
-
-        case _CONTENT:
-          if (byte == _boundary[_boundaryIndex]) {
-            _boundaryIndex++;
-            if (_boundaryIndex == _boundary.length) {
-              if (contentStartIndex != null) {
-                _index++;
-                reportData();
-                _index--;
-              }
-              _multipartController.close();
-              _boundaryIndex = 0;
-              _state = _BOUNDARY_ENDING;
-            }
-          } else {
-            // Restart matching of the boundary.
-            _index = _index - _boundaryIndex;
-            if (contentStartIndex == null) contentStartIndex = _index;
-            _boundaryIndex = 0;
-          }
-          break;
-
-        case _LAST_BOUNDARY_DASH2:
-          _expect(byte, _CharCode.DASH);
-          _state = _LAST_BOUNDARY_ENDING;
-          break;
-
-        case _LAST_BOUNDARY_ENDING:
-          if (byte == _CharCode.CR) {
-            _state = _LAST_BOUNDARY_END;
-          } else {
-            _expectWS(byte);
-          }
-          break;
-
-        case _LAST_BOUNDARY_END:
-          _expect(byte, _CharCode.LF);
-          _multipartController.close();
-          _multipartController = null;
-          _state = _DONE;
-          break;
-
-        default:
-          // Should be unreachable.
-          assert(false);
-          break;
-      }
-
-      // Move to the next byte.
-      _index++;
-    }
-
-    // Report any known content.
-    if (_state == _CONTENT && contentStartIndex != null) {
-      reportData();
-    }
-
-    // Resume if at end.
-    if (_index == _buffer.length) {
-      _buffer = null;
-      _index = null;
-      _resumeStream();
-    }
-  }
-
-  bool _isTokenChar(int byte) {
-    return byte > 31 && byte < 128 && _SEPARATORS.indexOf(byte) == -1;
-  }
-
-  int _toLowerCase(int byte) {
-    final int aCode = "A".codeUnitAt(0);
-    final int zCode = "Z".codeUnitAt(0);
-    final int delta = "a".codeUnitAt(0) - aCode;
-    return (aCode <= byte && byte <= zCode) ? byte + delta : byte;
-  }
-
-  void _expect(int val1, int val2) {
-    if (val1 != val2) {
-      throw new MimeMultipartException("Failed to parse multipart mime 1");
-    }
-  }
-
-  void _expectWS(int byte) {
-    if (byte != _CharCode.SP && byte != _CharCode.HT) {
-      throw new MimeMultipartException("Failed to parse multipart mime 2");
-    }
-  }
-}
-
-
-class MimeMultipartException implements Exception {
-  final String message;
-
-  const MimeMultipartException([String this.message = ""]);
-
-  String toString() => "MimeMultipartException: $message";
 }
diff --git a/pkg/mime/lib/src/mime_shared.dart b/pkg/mime/lib/src/mime_shared.dart
new file mode 100644
index 0000000..6d14e0a
--- /dev/null
+++ b/pkg/mime/lib/src/mime_shared.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.
+library mime.shared;
+
+import 'dart:async';
+
+class MimeMultipartException implements Exception {
+  final String message;
+
+  const MimeMultipartException([String this.message = ""]);
+
+  String toString() => "MimeMultipartException: $message";
+}
+
+/**
+ * A Mime Multipart class representing each part parsed by
+ * [MimeMultipartTransformer]. The data is streamed in as it become available.
+ */
+abstract class MimeMultipart extends Stream<List<int>> {
+  Map<String, String> get headers;
+}
diff --git a/pkg/mime/pubspec.yaml b/pkg/mime/pubspec.yaml
index 54dc5a8..7051582 100644
--- a/pkg/mime/pubspec.yaml
+++ b/pkg/mime/pubspec.yaml
@@ -1,9 +1,9 @@
 name: mime
-version: 0.9.0+2
+version: 0.9.0+3
 author: Dart Team <misc@dartlang.org>
 description: Helper-package for working with MIME.
 homepage: http://www.dartlang.org
 environment:
   sdk: '>=1.0.0 <2.0.0'
 dev_dependencies:
-  unittest: '>=0.9.0 <0.11.0'
+  unittest: '>=0.9.0 <0.12.0'
diff --git a/pkg/observe/CHANGELOG.md b/pkg/observe/CHANGELOG.md
index f51ca6a..7337b98 100644
--- a/pkg/observe/CHANGELOG.md
+++ b/pkg/observe/CHANGELOG.md
@@ -3,7 +3,7 @@
 This file contains highlights of what changes on each version of the observe
 package.
 
-#### Pub version 0.10.0-dev
+#### Pub version 0.10.0
   * package:observe no longer declares @MirrorsUsed. The package uses mirrors
     for development time, but assumes frameworks (like polymer) and apps that
     use it directly will either generate code that replaces the use of mirrors,
diff --git a/pkg/observe/pubspec.yaml b/pkg/observe/pubspec.yaml
index 4161d8af..408a285 100644
--- a/pkg/observe/pubspec.yaml
+++ b/pkg/observe/pubspec.yaml
@@ -1,5 +1,5 @@
 name: observe
-version: 0.10.0-pre.4
+version: 0.10.0
 author: Polymer.dart Authors <web-ui-dev@dartlang.org>
 description: >
   Observable properties and objects for use in template_binding.
@@ -13,7 +13,7 @@
   barback: '>=0.9.0 <0.15.0'
   logging: '>=0.9.0 <0.10.0'
   path: '>=0.9.0 <2.0.0'
-  smoke: '>=0.1.0-pre.0 <0.2.0'
+  smoke: '>=0.1.0 <0.2.0'
   source_maps: '>=0.9.0 <0.10.0'
 dev_dependencies:
   unittest: '>=0.10.0 <0.11.0'
diff --git a/pkg/path/CHANGELOG.md b/pkg/path/CHANGELOG.md
index 22fc34f..f1d2485 100644
--- a/pkg/path/CHANGELOG.md
+++ b/pkg/path/CHANGELOG.md
@@ -1,3 +1,11 @@
+# 1.2.1
+
+* Many members on `Style` that provided access to patterns and functions used
+  internally for parsing paths have been deprecated.
+
+* Manually parse paths (rather than using RegExps to do so) for better
+  performance.
+
 # 1.2.0
 
 * Added `path.prettyUri`, which produces a human-readable representation of a
diff --git a/pkg/path/lib/src/characters.dart b/pkg/path/lib/src/characters.dart
new file mode 100644
index 0000000..ff196a6
--- /dev/null
+++ b/pkg/path/lib/src/characters.dart
@@ -0,0 +1,19 @@
+// 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.
+
+/// This library contains character-code definitions.
+library path.characters;
+
+const PLUS = 0x2b;
+const MINUS = 0x2d;
+const PERIOD = 0x2e;
+const SLASH = 0x2f;
+const ZERO = 0x30;
+const NINE = 0x39;
+const COLON = 0x3a;
+const UPPER_A = 0x41;
+const UPPER_Z = 0x5a;
+const LOWER_A = 0x61;
+const LOWER_Z = 0x7a;
+const BACKSLASH = 0x5c;
diff --git a/pkg/path/lib/src/context.dart b/pkg/path/lib/src/context.dart
index 88ca61f..823e0c2 100644
--- a/pkg/path/lib/src/context.dart
+++ b/pkg/path/lib/src/context.dart
@@ -4,6 +4,7 @@
 
 library path.context;
 
+import 'internal_style.dart';
 import 'style.dart';
 import 'parsed_path.dart';
 import 'path_exception.dart';
@@ -30,7 +31,12 @@
       }
     }
 
-    if (style == null) style = Style.platform;
+    if (style == null) {
+      style = Style.platform;
+    } else if (style is! InternalStyle) {
+      throw new ArgumentError("Only styles defined by the path package are "
+          "allowed.");
+    }
 
     return new Context._(style, current);
   }
@@ -38,7 +44,7 @@
   Context._(this.style, this.current);
 
   /// The style of path that this context works with.
-  final Style style;
+  final InternalStyle style;
 
   /// The current directory that relative paths will be relative to.
   final String current;
@@ -213,7 +219,7 @@
         // replaces the path after it.
         var parsed = _parse(part);
         parsed.root = this.rootPrefix(buffer.toString());
-        if (parsed.root.contains(style.needsSeparatorPattern)) {
+        if (style.needsSeparator(parsed.root)) {
           parsed.separators[0] = style.separator;
         }
         buffer.clear();
@@ -224,7 +230,7 @@
         buffer.clear();
         buffer.write(part);
       } else {
-        if (part.length > 0 && part[0].contains(style.separatorPattern)) {
+        if (part.length > 0 && style.containsSeparator(part[0])) {
           // The part starts with a separator, so we don't need to add one.
         } else if (needsSeparator) {
           buffer.write(separator);
@@ -235,7 +241,7 @@
 
       // Unless this part ends with a separator, we'll need to add one before
       // the next part.
-      needsSeparator = part.contains(style.needsSeparatorPattern);
+      needsSeparator = style.needsSeparator(part);
     }
 
     return buffer.toString();
diff --git a/pkg/path/lib/src/internal_style.dart b/pkg/path/lib/src/internal_style.dart
new file mode 100644
index 0000000..67b5d34
--- /dev/null
+++ b/pkg/path/lib/src/internal_style.dart
@@ -0,0 +1,54 @@
+// 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 path.internal_style;
+
+import 'context.dart';
+import 'style.dart';
+
+/// The internal interface for the [Style] type.
+///
+/// Users should be able to pass around instances of [Style] like an enum, but
+/// the members that [Context] uses should be hidden from them. Those members
+/// are defined on this class instead.
+abstract class InternalStyle extends Style {
+  /// The default path separator for this style.
+  ///
+  /// On POSIX, this is `/`. On Windows, it's `\`.
+  String get separator;
+
+  /// Returns whether [path] contains a separator.
+  bool containsSeparator(String path);
+
+  /// Returns whether [codeUnit] is the character code of a separator.
+  bool isSeparator(int codeUnit);
+
+  /// Returns whether this path component needs a separator after it.
+  ///
+  /// Windows and POSIX styles just need separators when the previous component
+  /// doesn't already end in a separator, but the URL always needs to place a
+  /// separator between the root and the first component, even if the root
+  /// already ends in a separator character. For example, to join "file://" and
+  /// "usr", an additional "/" is needed (making "file:///usr").
+  bool needsSeparator(String path);
+
+  /// Gets the root prefix of [path] if path is absolute. If [path] is relative,
+  /// returns `null`.
+  String getRoot(String path);
+
+  /// Gets the root prefix of [path] if it's root-relative.
+  ///
+  /// If [path] is relative or absolute and not root-relative, returns `null`.
+  String getRelativeRoot(String path);
+
+  /// Returns the path represented by [uri] in this style.
+  String pathFromUri(Uri uri);
+
+  /// Returns the URI that represents the relative path made of [parts].
+  Uri relativePathToUri(String path) =>
+      new Uri(pathSegments: context.split(path));
+
+  /// Returns the URI that represents [path], which is assumed to be absolute.
+  Uri absolutePathToUri(String path);
+}
diff --git a/pkg/path/lib/src/parsed_path.dart b/pkg/path/lib/src/parsed_path.dart
index 5356b44..57773ee 100644
--- a/pkg/path/lib/src/parsed_path.dart
+++ b/pkg/path/lib/src/parsed_path.dart
@@ -4,12 +4,12 @@
 
 library path.parsed_path;
 
+import 'internal_style.dart';
 import 'style.dart';
 
-// TODO(rnystrom): Make this public?
 class ParsedPath {
-  /// The [Style] that was used to parse this path.
-  Style style;
+  /// The [InternalStyle] that was used to parse this path.
+  InternalStyle style;
 
   /// The absolute root portion of the path, or `null` if the path is relative.
   /// On POSIX systems, this will be `null` or "/". On Windows, it can be
@@ -40,7 +40,7 @@
   /// `true` if this is an absolute path.
   bool get isAbsolute => root != null;
 
-  factory ParsedPath.parse(String path, Style style) {
+  factory ParsedPath.parse(String path, InternalStyle style) {
     var before = path;
 
     // Remove the root prefix, if any.
@@ -52,19 +52,21 @@
     var parts = [];
     var separators = [];
 
-    var firstSeparator = style.separatorPattern.matchAsPrefix(path);
-    if (firstSeparator != null) {
-      separators.add(firstSeparator[0]);
-      path = path.substring(firstSeparator[0].length);
+    var start = 0;
+
+    if (path.isNotEmpty && style.isSeparator(path.codeUnitAt(0))) {
+      separators.add(path[0]);
+      start = 1;
     } else {
       separators.add('');
     }
 
-    var start = 0;
-    for (var match in style.separatorPattern.allMatches(path)) {
-      parts.add(path.substring(start, match.start));
-      separators.add(match[0]);
-      start = match.end;
+    for (var i = start; i < path.length; i++) {
+      if (style.isSeparator(path.codeUnitAt(i))) {
+        parts.add(path.substring(start, i));
+        separators.add(path[i]);
+        start = i + 1;
+      }
     }
 
     // Add the final part, if any.
@@ -133,8 +135,7 @@
     var newSeparators = new List.generate(
         newParts.length, (_) => style.separator, growable: true);
     newSeparators.insert(0,
-        isAbsolute && newParts.length > 0 &&
-                root.contains(style.needsSeparatorPattern) ?
+        isAbsolute && newParts.length > 0 && style.needsSeparator(root) ?
             style.separator : '');
 
     parts = newParts;
diff --git a/pkg/path/lib/src/style.dart b/pkg/path/lib/src/style.dart
index 9da4b43..a94ec68 100644
--- a/pkg/path/lib/src/style.dart
+++ b/pkg/path/lib/src/style.dart
@@ -51,67 +51,37 @@
   /// The name of this path style. Will be "posix" or "windows".
   String get name;
 
-  /// The path separator for this style. On POSIX, this is `/`. On Windows,
-  /// it's `\`.
-  String get separator;
-
-  /// The [Pattern] that can be used to match a separator for a path in this
-  /// style. Windows allows both "/" and "\" as path separators even though "\"
-  /// is the canonical one.
-  Pattern get separatorPattern;
-
-  /// The [Pattern] that matches path components that need a separator after
-  /// them.
-  ///
-  /// Windows and POSIX styles just need separators when the previous component
-  /// doesn't already end in a separator, but the URL always needs to place a
-  /// separator between the root and the first component, even if the root
-  /// already ends in a separator character. For example, to join "file://" and
-  /// "usr", an additional "/" is needed (making "file:///usr").
-  Pattern get needsSeparatorPattern;
-
-  /// The [Pattern] that can be used to match the root prefix of an absolute
-  /// path in this style.
-  Pattern get rootPattern;
-
-  /// The [Pattern] that can be used to match the root prefix of a root-relative
-  /// path in this style.
-  ///
-  /// This can be null to indicate that this style doesn't support root-relative
-  /// paths.
-  final Pattern relativeRootPattern = null;
-
   /// A [Context] that uses this style.
   Context get context => new Context(style: this);
 
-  /// Gets the root prefix of [path] if path is absolute. If [path] is relative,
-  /// returns `null`.
-  String getRoot(String path) {
-    // TODO(rnystrom): Use firstMatch() when #7080 is fixed.
-    var matches = rootPattern.allMatches(path);
-    if (matches.isNotEmpty) return matches.first[0];
-    return getRelativeRoot(path);
-  }
+  @Deprecated("Most Style members will be removed in path 2.0.")
+  String get separator;
 
-  /// Gets the root prefix of [path] if it's root-relative.
-  ///
-  /// If [path] is relative or absolute and not root-relative, returns `null`.
-  String getRelativeRoot(String path) {
-    if (relativeRootPattern == null) return null;
-    // TODO(rnystrom): Use firstMatch() when #7080 is fixed.
-    var matches = relativeRootPattern.allMatches(path);
-    if (matches.isEmpty) return null;
-    return matches.first[0];
-  }
+  @Deprecated("Most Style members will be removed in path 2.0.")
+  Pattern get separatorPattern;
 
-  /// Returns the path represented by [uri] in this style.
+  @Deprecated("Most Style members will be removed in path 2.0.")
+  Pattern get needsSeparatorPattern;
+
+  @Deprecated("Most Style members will be removed in path 2.0.")
+  Pattern get rootPattern;
+
+  @Deprecated("Most Style members will be removed in path 2.0.")
+  Pattern get relativeRootPattern;
+
+  @Deprecated("Most style members will be removed in path 2.0.")
+  String getRoot(String path);
+
+  @Deprecated("Most style members will be removed in path 2.0.")
+  String getRelativeRoot(String path);
+
+  @Deprecated("Most style members will be removed in path 2.0.")
   String pathFromUri(Uri uri);
 
-  /// Returns the URI that represents the relative path made of [parts].
-  Uri relativePathToUri(String path) =>
-      new Uri(pathSegments: context.split(path));
+  @Deprecated("Most style members will be removed in path 2.0.")
+  Uri relativePathToUri(String path);
 
-  /// Returns the URI that represents [path], which is assumed to be absolute.
+  @Deprecated("Most style members will be removed in path 2.0.")
   Uri absolutePathToUri(String path);
 
   String toString() => name;
diff --git a/pkg/path/lib/src/style/posix.dart b/pkg/path/lib/src/style/posix.dart
index 72e7044..b8b82b4 100644
--- a/pkg/path/lib/src/style/posix.dart
+++ b/pkg/path/lib/src/style/posix.dart
@@ -4,18 +4,38 @@
 
 library path.style.posix;
 
+import '../characters.dart' as chars;
 import '../parsed_path.dart';
-import '../style.dart';
+import '../internal_style.dart';
 
 /// The style for POSIX paths.
-class PosixStyle extends Style {
+class PosixStyle extends InternalStyle {
   PosixStyle();
 
   final name = 'posix';
   final separator = '/';
+  final separators = const ['/'];
+
+  // Deprecated properties.
+
   final separatorPattern = new RegExp(r'/');
   final needsSeparatorPattern = new RegExp(r'[^/]$');
   final rootPattern = new RegExp(r'^/');
+  final relativeRootPattern = null;
+
+  bool containsSeparator(String path) => path.contains('/');
+
+  bool isSeparator(int codeUnit) => codeUnit == chars.SLASH;
+
+  bool needsSeparator(String path) =>
+      path.isNotEmpty && !isSeparator(path.codeUnitAt(path.length - 1));
+
+  String getRoot(String path) {
+    if (path.isNotEmpty && isSeparator(path.codeUnitAt(0))) return '/';
+    return null;
+  }
+
+  String getRelativeRoot(String path) => null;
 
   String pathFromUri(Uri uri) {
     if (uri.scheme == '' || uri.scheme == 'file') {
diff --git a/pkg/path/lib/src/style/url.dart b/pkg/path/lib/src/style/url.dart
index 4a7003d..f383923 100644
--- a/pkg/path/lib/src/style/url.dart
+++ b/pkg/path/lib/src/style/url.dart
@@ -4,22 +4,85 @@
 
 library path.style.url;
 
-import '../style.dart';
+import '../characters.dart' as chars;
+import '../internal_style.dart';
+import '../utils.dart';
 
 /// The style for URL paths.
-class UrlStyle extends Style {
+class UrlStyle extends InternalStyle {
   UrlStyle();
 
   final name = 'url';
   final separator = '/';
+  final separators = const ['/'];
+
+  // Deprecated properties.
+
   final separatorPattern = new RegExp(r'/');
   final needsSeparatorPattern = new RegExp(
       r"(^[a-zA-Z][-+.a-zA-Z\d]*://|[^/])$");
   final rootPattern = new RegExp(r"[a-zA-Z][-+.a-zA-Z\d]*://[^/]*");
   final relativeRootPattern = new RegExp(r"^/");
 
+  bool containsSeparator(String path) => path.contains('/');
+
+  bool isSeparator(int codeUnit) => codeUnit == chars.SLASH;
+
+  bool needsSeparator(String path) {
+    if (path.isEmpty) return false;
+
+    // A URL that doesn't end in "/" always needs a separator.
+    if (!isSeparator(path.codeUnitAt(path.length - 1))) return true;
+
+    // A URI that's just "scheme://" needs an extra separator, despite ending
+    // with "/".
+    var root = _getRoot(path);
+    return root != null && root.endsWith('://');
+  }
+
+  String getRoot(String path) {
+    var root = _getRoot(path);
+    return root == null ? getRelativeRoot(path) : root;
+  }
+
+  String getRelativeRoot(String path) {
+    if (path.isEmpty) return null;
+    return isSeparator(path.codeUnitAt(0)) ? "/" : null;
+  }
+
   String pathFromUri(Uri uri) => uri.toString();
 
   Uri relativePathToUri(String path) => Uri.parse(path);
   Uri absolutePathToUri(String path) => Uri.parse(path);
+
+  // A helper method for [getRoot] that doesn't handle relative roots.
+  String _getRoot(String path) {
+    if (path.isEmpty) return null;
+
+    // We aren't using a RegExp for this because they're slow (issue 19090). If
+    // we could, we'd match against r"[a-zA-Z][-+.a-zA-Z\d]*://[^/]*".
+
+    if (!isAlphabetic(path.codeUnitAt(0))) return null;
+    var start = 1;
+    for (; start < path.length; start++) {
+      var char = path.codeUnitAt(start);
+      if (isAlphabetic(char)) continue;
+      if (isNumeric(char)) continue;
+      if (char == chars.MINUS || char == chars.PLUS || char == chars.PERIOD) {
+        continue;
+      }
+
+      break;
+    }
+
+    if (start + 3 > path.length) return null;
+    if (path.substring(start, start + 3) != '://') return null;
+    start += 3;
+
+    // A URL root can end with a non-"/" prefix.
+    while (start < path.length && !isSeparator(path.codeUnitAt(start))) {
+      start++;
+    }
+    return path.substring(0, start);
+  }
 }
diff --git a/pkg/path/lib/src/style/windows.dart b/pkg/path/lib/src/style/windows.dart
index 1750578..2965f1e 100644
--- a/pkg/path/lib/src/style/windows.dart
+++ b/pkg/path/lib/src/style/windows.dart
@@ -4,20 +4,48 @@
 
 library path.style.windows;
 
+import '../characters.dart' as chars;
+import '../internal_style.dart';
 import '../parsed_path.dart';
-import '../style.dart';
+import '../utils.dart';
 
 /// The style for Windows paths.
-class WindowsStyle extends Style {
+class WindowsStyle extends InternalStyle {
   WindowsStyle();
 
   final name = 'windows';
   final separator = '\\';
+  final separators = const ['/', '\\'];
+
+  // Deprecated properties.
+
   final separatorPattern = new RegExp(r'[/\\]');
   final needsSeparatorPattern = new RegExp(r'[^/\\]$');
   final rootPattern = new RegExp(r'^(\\\\[^\\]+\\[^\\/]+|[a-zA-Z]:[/\\])');
   final relativeRootPattern = new RegExp(r"^[/\\](?![/\\])");
 
+  bool containsSeparator(String path) => path.contains('/');
+
+  bool isSeparator(int codeUnit) =>
+      codeUnit == chars.SLASH || codeUnit == chars.BACKSLASH;
+
+  bool needsSeparator(String path) {
+    if (path.isEmpty) return false;
+    return !isSeparator(path.codeUnitAt(path.length - 1));
+  }
+
+  String getRoot(String path) {
+    var root = _getRoot(path);
+    return root == null ? getRelativeRoot(path) : root;
+  }
+
+  String getRelativeRoot(String path) {
+    if (path.isEmpty) return null;
+    if (!isSeparator(path.codeUnitAt(0))) return null;
+    if (path.length > 1 && isSeparator(path.codeUnitAt(1))) return null;
+    return path[0];
+  }
+
   String pathFromUri(Uri uri) {
     if (uri.scheme != '' && uri.scheme != 'file') {
       throw new ArgumentError("Uri $uri must have scheme 'file:'.");
@@ -66,9 +94,45 @@
 
       // Get rid of the trailing "\" in "C:\" because the URI constructor will
       // add a separator on its own.
-      parsed.parts.insert(0, parsed.root.replaceAll(separatorPattern, ""));
+      parsed.parts.insert(0,
+          parsed.root.replaceAll("/", "").replaceAll("\\", ""));
 
       return new Uri(scheme: 'file', pathSegments: parsed.parts);
     }
   }
+
+  // A helper method for [getRoot] that doesn't handle relative roots.
+  String _getRoot(String path) {
+    if (path.length < 3) return null;
+
+    // We aren't using a RegExp for this because they're slow (issue 19090). If
+    // we could, we'd match against r'^(\\\\[^\\]+\\[^\\/]+|[a-zA-Z]:[/\\])'.
+
+    // Try roots like "C:\".
+    if (isAlphabetic(path.codeUnitAt(0))) {
+      if (path.codeUnitAt(1) != chars.COLON) return null;
+      if (!isSeparator(path.codeUnitAt(2))) return null;
+      return path.substring(0, 3);
+    }
+
+    // Try roots like "\\server\share".
+    if (!path.startsWith('\\\\')) return null;
+
+    var start = 2;
+    // The server is one or more non-"\" characters.
+    while (start < path.length && path.codeUnitAt(start) != chars.BACKSLASH) {
+      start++;
+    }
+    if (start == 2 || start == path.length) return null;
+
+    // The share is one or more non-"\" characters.
+    start += 1;
+    if (path.codeUnitAt(start) == chars.BACKSLASH) return null;
+    start += 1;
+    while (start < path.length && path.codeUnitAt(start) != chars.BACKSLASH) {
+      start++;
+    }
+
+    return path.substring(0, start);
+  }
 }
\ No newline at end of file
diff --git a/pkg/path/lib/src/utils.dart b/pkg/path/lib/src/utils.dart
new file mode 100644
index 0000000..0636261
--- /dev/null
+++ b/pkg/path/lib/src/utils.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 path.utils;
+
+import 'characters.dart' as chars;
+
+/// Returns whether [char] is the code for an ASCII letter (uppercase or
+/// lowercase).
+bool isAlphabetic(int char) =>
+    (char >= chars.UPPER_A && char <= chars.UPPER_Z) ||
+    (char >= chars.LOWER_A && char <= chars.LOWER_Z);
+
+/// Returns whether [char] is the code for an ASCII digit.
+bool isNumeric(int char) => char >= chars.ZERO && char <= chars.NINE;
diff --git a/pkg/path/pubspec.yaml b/pkg/path/pubspec.yaml
index f21ac50..7bc83bff 100644
--- a/pkg/path/pubspec.yaml
+++ b/pkg/path/pubspec.yaml
@@ -1,5 +1,5 @@
 name: path
-version: 1.2.0
+version: 1.2.1
 author: Dart Team <misc@dartlang.org>
 description: >
  A string-based path manipulation library. All of the path operations you know
diff --git a/pkg/pkg.status b/pkg/pkg.status
index f9f3244..f7e1cff 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -52,7 +52,6 @@
 code_transformers/test/resolver_test: Pass, Timeout
 docgen/test/*: Skip # Slow
 polymer/test/build/all_phases_test: Skip # Slow
-polymer_expressions/test/globals_test: Pass, Timeout
 smoke/test/codegen/end_to_end_test: Pass, Timeout
 smoke/test/codegen/recorder_test: Pass, Timeout
 template_binding/test/template_binding_test: Pass, Timeout
@@ -81,6 +80,9 @@
 [ $compiler == dart2js && $checked ]
 crypto/test/base64_test: Slow, Pass
 
+[ $compiler == dart2js && $checked && $runtime == drt ]
+polymer/test/event_handlers_test: RuntimeError # Issue 19190
+
 [ $compiler == dart2js && $checked && $runtime == ie9 ]
 crypto/test/base64_test: Timeout # Issue 12486
 collection/test/priority_queue_test: Pass, Slow # Issue 16426
@@ -157,6 +159,7 @@
 [ $ie ]
 polymer/test/noscript_test: RuntimeError, Pass # Issue 13260
 intl/test/date_time_format_http_request_test: Fail # Issue 8983
+polymer_expressions/test/syntax_test: Fail, Timeout, Pass # Issue 19138
 
 [ $runtime == ie10 ]
 typed_data/test/typed_buffers_test/none: Fail # Issue   17607 (I put this here explicitly, since this is not the same as on ie9)
@@ -344,10 +347,6 @@
 third_party/html5lib/test/browser/browser_test: Skip
 http/test/html/*: Skip
 
-[ $runtime == safari || $runtime == safarimobilesim || $ie ]
-polymer_expressions/test/globals_test: Fail # Issue 16568
-polymer_expressions/test/bindings_test: Fail # Issue 16568
-
 [ $browser ]
 docgen/test/*: Skip  # Uses dart:io
 scheduled_test/test/scheduled_server_test: Skip # Uses dart:io
diff --git a/pkg/polymer/CHANGELOG.md b/pkg/polymer/CHANGELOG.md
index 6aa0a4c..a1fb57e 100644
--- a/pkg/polymer/CHANGELOG.md
+++ b/pkg/polymer/CHANGELOG.md
@@ -1,22 +1,19 @@
 # changelog
 
 This file contains highlights of what changes on each version of the polymer
-package. We will also note important changes to the polyfill packages if they
-impact polymer: custom_element, html_import, observe, shadow_dom,
-and template_binding.
+package. We will also note important changes to the polyfill packages (observe,
+web_components, and template_binding) if they impact polymer.
 
-#### Pub version 0.10.0-dev
-  * initPolymer is now deprecated: no need to call it or to include init.dart,
-    instead include `<link rel="import" href="packages/polymer/polymer.html">`
-  * Mime-type of script tags needs to change to prepare for upcoming breaking
-    change in Dartium: use `<script type="application/dart;component=1">`.
-  * The output of pub-build no longer uses mirrors. We replace all uses of
-    mirrors with code generation.
+#### Pub version 0.10.0
   * Interop with polymer-js elements now works.
   * Polymer polyfills are now consolidated in package:web_components, which is
     identical to platform.js from http://polymer-project.org.
-  * Breaking change: "noscript" polymer-elements are created by polymer.js, and
-    therefore cannot be extended (subtyped) in Dart. They can still be used
+  * The output of pub-build no longer uses mirrors. We replace all uses of
+    mirrors with code generation.
+  * **breaking change**: Declaring a polymer app requires an extra import to
+    `<link rel="import" href="packages/polymer/polymer.html">`
+  * **breaking change**: "noscript" polymer-elements are created by polymer.js,
+    and therefore cannot be extended (subtyped) in Dart. They can still be used
     by Dart elements or applications, however.
   * New feature: `@ObserveProperty('foo bar.baz') myMethod() {...}` will cause
     myMethod to be called when "foo" or "bar.baz" changes.
diff --git a/pkg/polymer/README.md b/pkg/polymer/README.md
index a940c3e..c71bb2ab 100644
--- a/pkg/polymer/README.md
+++ b/pkg/polymer/README.md
@@ -40,7 +40,7 @@
 
 ```yaml
 dependencies:
-  polymer: ">=0.9.0 <0.10.0"
+  polymer: ">=0.10.0 <0.11.0"
 ```
 
 Instead of using `any`, we recommend using version ranges to avoid getting your
diff --git a/pkg/polymer/pubspec.yaml b/pkg/polymer/pubspec.yaml
index 590cd14..a0a7820 100644
--- a/pkg/polymer/pubspec.yaml
+++ b/pkg/polymer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: polymer
-version: 0.10.0-pre.14.dev
+version: 0.10.0
 author: Polymer.dart Authors <web-ui-dev@dartlang.org>
 description: >
   Polymer.dart is a new type of library for the web, built on top of Web
@@ -14,14 +14,14 @@
   code_transformers: '>=0.1.0 <0.2.0'
   html5lib: '>=0.11.0 <0.12.0'
   logging: '>=0.9.0 <0.10.0'
-  observe: '>=0.10.0-pre.0 <0.11.0'
+  observe: '>=0.10.0 <0.11.0'
   path: '>=0.9.0 <2.0.0'
-  polymer_expressions: '>=0.10.0-pre.1 <0.11.0'
-  smoke: '>=0.1.0-pre.5 <0.2.0'
+  polymer_expressions: '>=0.10.0 <0.11.0'
+  smoke: '>=0.1.0 <0.2.0'
   source_maps: '>=0.9.0 <0.10.0'
-  template_binding: '>=0.10.0-pre.1 <0.11.0'
+  template_binding: '>=0.10.0 <0.11.0'
   web_components: '>=0.3.3 <0.4.0'
-  yaml: '>=0.9.0 <0.10.0'
+  yaml: '>=0.9.0 <2.0.0'
 dev_dependencies:
   unittest: '>=0.10.0 <0.11.0'
 transformers:
diff --git a/pkg/polymer/test/nested_binding_test.dart b/pkg/polymer/test/nested_binding_test.dart
index c6ab7ef..9118bb1e 100644
--- a/pkg/polymer/test/nested_binding_test.dart
+++ b/pkg/polymer/test/nested_binding_test.dart
@@ -18,14 +18,10 @@
 
   MyTest.created() : super.created();
 
-  _runTest(_) {
+  ready() {
     expect($['fruit'].text.trim(), 'Short name: [pears]');
     _testDone.complete();
   }
-
-  ready() {
-    onMutation($['fruit']).then(_runTest);
-  }
 }
 
 main() => initPolymer().run(() {
diff --git a/pkg/polymer_expressions/CHANGELOG.md b/pkg/polymer_expressions/CHANGELOG.md
index 8b2cb5c..451cd00 100644
--- a/pkg/polymer_expressions/CHANGELOG.md
+++ b/pkg/polymer_expressions/CHANGELOG.md
@@ -3,7 +3,7 @@
 This file contains highlights of what changes on each version of the
 polymer_expressions package.
 
-#### Pub version 0.10.0-dev
+#### Pub version 0.10.0
   * package:polymer_expressions no longer declares @MirrosUsed. The package uses
     mirrors at development time, but assumes frameworks like polymer will
     generate code that replaces the use of mirrors. If you use this directly,
@@ -16,3 +16,13 @@
     trap some errors and report them in a Logger, and we would let other errors
     halt the rendering process. Now all errors are caught, but they are reported
     asynchornously so they are visible even when logging is not set up.
+
+  * Fixed several bugs, including:
+      * propagating list changes ([18749][]).
+      * precedence of ternary operators ([17805][]).
+      * two-way bindings ([18410][] and [18792][]).
+
+[17805]: https://code.google.com/p/dart/issues/detail?id=17805
+[18410]: https://code.google.com/p/dart/issues/detail?id=18410
+[18749]: https://code.google.com/p/dart/issues/detail?id=18749
+[18792]: https://code.google.com/p/dart/issues/detail?id=18792
diff --git a/pkg/polymer_expressions/lib/eval.dart b/pkg/polymer_expressions/lib/eval.dart
index a33abeb..625bca2 100644
--- a/pkg/polymer_expressions/lib/eval.dart
+++ b/pkg/polymer_expressions/lib/eval.dart
@@ -20,6 +20,7 @@
   '-':  (a, b) => a - b,
   '*':  (a, b) => a * b,
   '/':  (a, b) => a / b,
+  '%':  (a, b) => a % b,
   '==': (a, b) => a == b,
   '!=': (a, b) => a != b,
   '>':  (a, b) => a > b,
@@ -60,7 +61,7 @@
  * [ExpressionObsserver].
  */
 ExpressionObserver observe(Expression expr, Scope scope) {
-  var observer = new ObserverBuilder(scope).visit(expr);
+  var observer = new ObserverBuilder().visit(expr);
   return observer;
 }
 
@@ -80,10 +81,8 @@
  * operators or function invocations, and any index operations must use a
  * literal index.
  */
-Object assign(Expression expr, Object value, Scope scope) {
-
-  notAssignable() =>
-      throw new EvalException("Expression is not assignable: $expr");
+Object assign(Expression expr, Object value, Scope scope,
+    {bool checkAssignability: true}) {
 
   Expression expression;
   var property;
@@ -101,42 +100,43 @@
 
   if (expr is Identifier) {
     expression = empty();
-    Identifier ident = expr;
-    property = ident.value;
+    property = expr.value;
   } else if (expr is Index) {
-    if (expr.argument is! Literal) notAssignable();
     expression = expr.receiver;
-    Literal l = expr.argument;
-    property = l.value;
+    property = expr.argument;
     isIndex = true;
   } else if (expr is Getter) {
     expression = expr.receiver;
     property = expr.name;
-  } else if (expr is Invoke) {
-    expression = expr.receiver;
-    if (expr.method != null) {
-      if (expr.arguments != null) notAssignable();
-      property = expr.method;
-    } else {
-      notAssignable();
-    }
   } else {
-    notAssignable();
+    if (checkAssignability) {
+      throw new EvalException("Expression is not assignable: $expr");
+    }
+    return null;
   }
 
   // transform the values backwards through the filters
   for (var filterExpr in filters) {
     var filter = eval(filterExpr, scope);
     if (filter is! Transformer) {
-      throw new EvalException("filter must implement Transformer: $filterExpr");
+      if (checkAssignability) {
+        throw new EvalException("filter must implement Transformer to be "
+            "assignable: $filterExpr");
+      } else {
+        return null;
+      }
     }
     value = filter.reverse(value);
   }
-  // make the assignment
+  // evaluate the receiver
   var o = eval(expression, scope);
-  if (o == null) throw new EvalException("Can't assign to null: $expression");
+
+  // can't assign to a property on a null LHS object. Silently fail.
+  if (o == null) return null;
+
   if (isIndex) {
-    o[property] = value;
+    var index = eval(property, scope);
+    o[index] = value;
   } else {
     smoke.write(o, smoke.nameToSymbol(property), value);
   }
@@ -152,6 +152,9 @@
  * and then finally looks up the name as a property in the model.
  */
 abstract class Scope implements Indexable<String, Object> {
+  static int __seq = 1;
+  final int _seq = __seq++;
+
   Scope._();
 
   /** Create a scope containing a [model] and all of [variables]. */
@@ -185,6 +188,9 @@
   /** Create a new scope extending this scope with an additional variable. */
   Scope childScope(String name, Object value) =>
       new _LocalVariableScope(name, value, this);
+
+  String toString() => 'Scope(seq: $_seq model: $model)';
+
 }
 
 /**
@@ -208,6 +214,8 @@
   }
 
   Object _isModelProperty(String name) => name != 'this';
+
+  String toString() => "[model: $model]";
 }
 
 /**
@@ -239,6 +247,8 @@
     if (varName == name) return false;
     return parent == null ? false : parent._isModelProperty(name);
   }
+
+  String toString() => "$parent > [local: $varName]";
 }
 
 /** A scope that holds a reference to a global variables. */
@@ -264,6 +274,8 @@
     if (variables.containsKey(name)) return false;
     return parent == null ? false : parent._isModelProperty(name);
   }
+
+  String toString() => "$parent > [global: ${variables.keys}]";
 }
 
 Object _convert(v) => v is Stream ? new StreamBinding(v) : v;
@@ -323,18 +335,12 @@
   visitExpression(ExpressionObserver e) {
     e._observe(scope);
   }
-
-  visitInExpression(InObserver c) {
-    visit(c.right);
-    visitExpression(c);
-  }
 }
 
 class ObserverBuilder extends Visitor {
-  final Scope scope;
   final Queue parents = new Queue();
 
-  ObserverBuilder(this.scope);
+  ObserverBuilder();
 
   visitEmptyExpression(EmptyExpression e) => new EmptyObserver(e);
 
@@ -422,13 +428,11 @@
   }
 
   visitInExpression(InExpression i) {
-    // don't visit the left. It's an identifier, but we don't want to evaluate
-    // it, we just want to add it to the comprehension object
-    var left = visit(i.left);
-    var right = visit(i.right);
-    var inexpr = new InObserver(i, left, right);
-    right._parent = inexpr;
-    return inexpr;
+    throw new UnsupportedError("can't eval an 'in' expression");
+  }
+
+  visitAsExpression(AsExpression i) {
+    throw new UnsupportedError("can't eval an 'as' expression");
   }
 }
 
@@ -508,7 +512,6 @@
 
   _updateSelf(Scope scope) {
     _value = scope[value];
-
     if (!scope._isModelProperty(value)) return;
     var model = scope.model;
     if (model is! Observable) return;
@@ -711,47 +714,8 @@
   accept(Visitor v) => v.visitInvoke(this);
 }
 
-class InObserver extends ExpressionObserver<InExpression>
-    implements InExpression {
-  IdentifierObserver left;
-  ExpressionObserver right;
-
-  InObserver(Expression expr, this.left, this.right) : super(expr);
-
-  _updateSelf(Scope scope) {
-    Identifier identifier = left;
-    var iterable = right._value;
-
-    if (iterable is! Iterable && iterable != null) {
-      throw new EvalException("right side of 'in' is not an iterator");
-    }
-
-    if (iterable is ObservableList) {
-      _subscription = iterable.listChanges.listen((_) => _invalidate(scope));
-    }
-
-    // TODO: make Comprehension observable and update it
-    _value = new Comprehension(identifier.value, iterable);
-  }
-
-  accept(Visitor v) => v.visitInExpression(this);
-}
-
 _toBool(v) => (v == null) ? false : v;
 
-/**
- * A comprehension declaration ("a in b"). [identifier] is the loop variable
- * that's added to the scope during iteration. [iterable] is the set of
- * objects to iterate over.
- */
-class Comprehension {
-  final String identifier;
-  final Iterable iterable;
-
-  Comprehension(this.identifier, Iterable iterable)
-      : iterable = (iterable != null) ? iterable : const [];
-}
-
 class EvalException implements Exception {
   final String message;
   EvalException(this.message);
diff --git a/pkg/polymer_expressions/lib/expression.dart b/pkg/polymer_expressions/lib/expression.dart
index 54adfd7..ac36c8b 100644
--- a/pkg/polymer_expressions/lib/expression.dart
+++ b/pkg/polymer_expressions/lib/expression.dart
@@ -24,6 +24,7 @@
 Invoke invoke(Expression e, String m, List<Expression> a) =>
     new Invoke(e, m, a);
 InExpression inExpr(Expression l, Expression r) => new InExpression(l, r);
+AsExpression asExpr(Expression l, Expression r) => new AsExpression(l, r);
 TernaryOperator ternary(Expression c, Expression t, Expression f) =>
     new TernaryOperator(c, t, f);
 
@@ -59,6 +60,8 @@
       new Invoke(e, m, a);
 
   InExpression inExpr(Expression l, Expression r) => new InExpression(l, r);
+
+  AsExpression asExpr(Expression l, Expression r) => new AsExpression(l, r);
 }
 
 /// Base class for all expressions
@@ -67,6 +70,11 @@
   accept(Visitor v);
 }
 
+abstract class HasIdentifier {
+  String get identifier;
+  Expression get expr;
+}
+
 class EmptyExpression extends Expression {
   const EmptyExpression();
   accept(Visitor v) => v.visitEmptyExpression(this);
@@ -212,14 +220,18 @@
       trueExpr.hashCode, falseExpr.hashCode);
 }
 
-class InExpression extends Expression {
-  final Expression left;
+class InExpression extends Expression implements HasIdentifier {
+  final Identifier left;
   final Expression right;
 
   InExpression(this.left, this.right);
 
   accept(Visitor v) => v.visitInExpression(this);
 
+  String get identifier => left.value;
+
+  Expression get expr => right;
+
   String toString() => '($left in $right)';
 
   bool operator ==(o) => o is InExpression && o.left == left
@@ -228,6 +240,26 @@
   int get hashCode => _JenkinsSmiHash.hash2(left.hashCode, right.hashCode);
 }
 
+class AsExpression extends Expression implements HasIdentifier {
+  final Expression left;
+  final Identifier right;
+
+  AsExpression(this.left, this.right);
+
+  accept(Visitor v) => v.visitAsExpression(this);
+
+  String get identifier => right.value;
+
+  Expression get expr => left;
+
+  String toString() => '($left as $right)';
+
+  bool operator ==(o) => o is AsExpression && o.left == left
+      && o.right == right;
+
+  int get hashCode => _JenkinsSmiHash.hash2(left.hashCode, right.hashCode);
+}
+
 class Index extends Expression {
   final Expression receiver;
   final Expression argument;
diff --git a/pkg/polymer_expressions/lib/parser.dart b/pkg/polymer_expressions/lib/parser.dart
index 411c7ae..4d0de87 100644
--- a/pkg/polymer_expressions/lib/parser.dart
+++ b/pkg/polymer_expressions/lib/parser.dart
@@ -64,8 +64,14 @@
         _advance();
         var right = _parseUnary();
         left = _makeInvokeOrGetter(left, right);
-      } else if (_token.kind == KEYWORD_TOKEN && _token.value == 'in') {
-        left = _parseComprehension(left);
+      } else if (_token.kind == KEYWORD_TOKEN) {
+        if (_token.value == 'in') {
+          left = _parseInExpression(left);
+        } else if (_token.value == 'as') {
+          left = _parseAsExpression(left);
+        } else {
+          break;
+        }
       } else if (_token.kind == OPERATOR_TOKEN
           && _token.precedence >= precedence) {
         left = _token.value == '?' ? _parseTernary(left) : _parseBinary(left);
@@ -141,8 +147,8 @@
           _advance();
           // TODO(justin): return keyword node
           return _astFactory.identifier('this');
-        } else if (keyword == 'in') {
-          return null;
+        } else if (KEYWORDS.contains(keyword)) {
+          throw new ParseException('invalid keyword: $keyword');
         }
         throw new ArgumentError('unrecognized keyword: $keyword');
       case IDENTIFIER_TOKEN:
@@ -204,7 +210,7 @@
     return _astFactory.mapLiteralEntry(key, value);
   }
 
-  InExpression _parseComprehension(Expression left) {
+  InExpression _parseInExpression(Expression left) {
     assert(_token.value == 'in');
     if (left is! Identifier) {
       throw new ParseException(
@@ -215,6 +221,17 @@
     return _astFactory.inExpr(left, right);
   }
 
+  AsExpression _parseAsExpression(Expression left) {
+    assert(_token.value == 'as');
+    _advance();
+    var right = _parseExpression();
+    if (right is! Identifier) {
+      throw new ParseException(
+          "as... statements must end with an identifier");
+    }
+    return _astFactory.asExpr(left, right);
+  }
+
   Expression _parseInvokeOrIdentifier() {
     if (_token.value == 'true') {
       _advance();
diff --git a/pkg/polymer_expressions/lib/polymer_expressions.dart b/pkg/polymer_expressions/lib/polymer_expressions.dart
index ac939d8..fa03dee 100644
--- a/pkg/polymer_expressions/lib/polymer_expressions.dart
+++ b/pkg/polymer_expressions/lib/polymer_expressions.dart
@@ -38,7 +38,6 @@
 import 'parser.dart';
 import 'src/globals.dart';
 
-// TODO(justin): Investigate XSS protection
 Object _classAttributeConverter(v) =>
     (v is Map) ? v.keys.where((k) => v[k] == true).join(' ') :
     (v is Iterable) ? v.join(' ') :
@@ -53,68 +52,229 @@
   /** The default [globals] to use for Polymer expressions. */
   static const Map DEFAULT_GLOBALS = const { 'enumerate': enumerate };
 
+  final ScopeFactory _scopeFactory;
   final Map<String, Object> globals;
 
+  // allows access to scopes created for template instances
+  final Expando<Scope> _scopes = new Expando<Scope>();
+  // allows access to scope identifiers (for "in" and "as")
+  final Expando<String> _scopeIdents = new Expando<String>();
+
   /**
    * Creates a new binding delegate for Polymer expressions, with the provided
    * variables used as [globals]. If no globals are supplied, a copy of the
    * [DEFAULT_GLOBALS] will be used.
    */
-  PolymerExpressions({Map<String, Object> globals})
+  PolymerExpressions({Map<String, Object> globals,
+      ScopeFactory scopeFactory: const ScopeFactory()})
       : globals = globals == null ?
-          new Map<String, Object>.from(DEFAULT_GLOBALS) : globals;
+          new Map<String, Object>.from(DEFAULT_GLOBALS) : globals,
+          _scopeFactory = scopeFactory;
 
-  prepareBinding(String path, name, node) {
+  @override
+  PrepareBindingFunction prepareBinding(String path, name, Node boundNode) {
     if (path == null) return null;
     var expr = new Parser(path).parse();
 
-    // For template bind/repeat to an empty path, just pass through the model.
-    // We don't want to unwrap the Scope.
-    // TODO(jmesserly): a custom element extending <template> could notice this
-    // behavior. An alternative is to associate the Scope with the node via an
-    // Expando, which is what the JavaScript PolymerExpressions does.
-    if (isSemanticTemplate(node) && (name == 'bind' || name == 'repeat') &&
-        expr is EmptyExpression) {
-      return null;
+    if (isSemanticTemplate(boundNode) && (name == 'bind' || name == 'repeat')) {
+      if (expr is HasIdentifier) {
+        var identifier = expr.identifier;
+        var bindExpr = expr.expr;
+        return (model, Node node, bool oneTime) {
+          _scopeIdents[node] = identifier;
+          // model may not be a Scope if it was assigned directly via
+          // template.model = x; In that case, prepareInstanceModel will
+          // be called _after_ prepareBinding and will lookup this scope from
+          // _scopes
+          var scope = _scopes[node] = (model is Scope)
+              ? model
+              : _scopeFactory.modelScope(model: model, variables: globals);
+          return new _Binding(bindExpr, scope);
+        };
+      } else {
+        return (model, Node node, bool oneTime) {
+          var scope = _scopes[node] = (model is Scope)
+              ? model
+              : _scopeFactory.modelScope(model: model, variables: globals);
+          if (oneTime) {
+            return _Binding._oneTime(expr, scope, null);
+          }
+          return new _Binding(expr, scope);
+        };
+      }
     }
 
-    return (model, node, oneTime) {
-      if (model is! Scope) {
-        model = new Scope(model: model, variables: globals);
-      }
-      var converter = null;
-      if (node is Element && name == "class") {
-        converter = _classAttributeConverter;
-      }
-      if (node is Element && name == "style") {
-        converter = _styleAttributeConverter;
-      }
+    // For regular bindings, not bindings on a template, the model is always
+    // a Scope created by prepareInstanceModel
+    _Converter converter = null;
+    if (boundNode is Element && name == 'class') {
+      converter = _classAttributeConverter;
+    } else if (boundNode is Element && name == 'style') {
+      converter = _styleAttributeConverter;
+    }
 
+    return (model, Node node, bool oneTime) {
+      var scope = _getScopeForModel(node, model);
       if (oneTime) {
-        return _Binding._oneTime(expr, model, converter);
+        return _Binding._oneTime(expr, scope, converter);
       }
-
-      return new _Binding(expr, model, converter);
+      return new _Binding(expr, scope, converter);
     };
   }
 
-  prepareInstanceModel(Element template) => (model) =>
-      model is Scope ? model : new Scope(model: model, variables: globals);
+  prepareInstanceModel(Element template) {
+    var ident = _scopeIdents[template];
+
+    if (ident == null) {
+      return (model) {
+        var existingScope = _scopes[template];
+        // TODO (justinfagnani): make template binding always call
+        // prepareInstanceModel first and get rid of this check
+        if (existingScope != null) {
+          // If there's an existing scope, we created it in prepareBinding
+          // If it has the same model, then we can reuse it, otherwise it's
+          // a repeat with no identifier and we create new scope to occlude
+          // the outer one
+          if (model == existingScope.model) return existingScope;
+          return _scopeFactory.modelScope(model: model, variables: globals);
+        } else {
+          return _getScopeForModel(template, model);
+        }
+      };
+    }
+
+    // We have an ident, so it's a bind/as or repeat/in expression
+    assert(templateBind(template).templateInstance == null);
+    return (model) {
+      var existingScope = _scopes[template];
+      if (existingScope != null) {
+        // This only happens when a model has been assigned programatically
+        // and prepareBinding is called _before_ prepareInstanceModel.
+        // The scope assigned in prepareBinding wraps the model and is the
+        // scope of the expression. That should be the parent of the templates
+        // scope in the case of bind/as or repeat/in bindings.
+        return _scopeFactory.childScope(existingScope, ident, model);
+      } else {
+        // If there's not an existing scope then we have a bind/as or
+        // repeat/in binding enclosed in an outer scope, so we use that as
+        // the parent
+        var parentScope = _getParentScope(template);
+        return _scopeFactory.childScope(parentScope, ident, model);
+      }
+    };
+  }
+
+  /**
+   * Gets an existing scope for use as a parent, but does not create a new one.
+   */
+  Scope _getParentScope(Node node) {
+    var parent = node.parentNode;
+    if (parent == null) return null;
+
+    if (isSemanticTemplate(node)) {
+      var templateExtension = templateBind(node);
+      var templateInstance = templateExtension.templateInstance;
+      var model = templateInstance == null
+          ? templateExtension.model
+          : templateInstance.model;
+      if (model is Scope) {
+        return model;
+      } else {
+        // A template with a bind binding might have a non-Scope model
+        return _scopes[node];
+      }
+    }
+    if (parent != null) return _getParentScope(parent);
+    return null;
+  }
+
+  /**
+   * Returns the Scope to be used to evaluate expressions in the template
+   * containing [node]. Since all expressions in the same template evaluate
+   * against the same model, [model] is passed in and checked against the
+   * template model to make sure they agree.
+   *
+   * For nested templates, we might have a binding on the nested template that
+   * should be evaluated in the context of the parent template. All scopes are
+   * retreived from an ancestor of [node], since node may be establishing a new
+   * Scope.
+   */
+  Scope _getScopeForModel(Node node, model) {
+    // This only happens in bindings_test because it calls prepareBinding()
+    // directly. Fix the test and throw if node is null?
+    if (node == null) {
+      return _scopeFactory.modelScope(model: model, variables: globals);
+    }
+
+    var id = node is Element ? node.id : '';
+    if (model is Scope) {
+      return model;
+    }
+    if (_scopes[node] != null) {
+      var scope = _scopes[node];
+      assert(scope.model == model);
+      return _scopes[node];
+    } else if (node.parentNode != null) {
+      return _getContainingScope(node.parentNode, model);
+    } else {
+      // here we should be at a top-level template, so there's no parent to
+      // look for a Scope on.
+      if (!isSemanticTemplate(node)) {
+        throw "expected a template instead of $node";
+      }
+      return _getContainingScope(node, model);
+    }
+  }
+
+  Scope _getContainingScope(Node node, model) {
+    if (isSemanticTemplate(node)) {
+      var templateExtension = templateBind(node);
+      var templateInstance = templateExtension.templateInstance;
+      var templateModel = templateInstance == null
+          ? templateExtension.model
+          : templateInstance.model;
+      assert(templateModel == model);
+      var scope = _scopes[node];
+      assert(scope != null);
+      assert(scope.model == model);
+      return scope;
+    } else if (node.parent == null) {
+      var scope = _scopes[node];
+      if (scope != null) {
+        assert(scope.model == model);
+      } else {
+        // only happens in bindings_test
+        scope = _scopeFactory.modelScope(model: model, variables: globals);
+      }
+      return scope;
+    } else {
+      return _getContainingScope(node.parentNode, model);
+    }
+  }
+
 }
 
+typedef Object _Converter(Object);
+
 class _Binding extends Bindable {
+  static int __seq = 1;
+
+  final int _seq = __seq++;
+
   final Scope _scope;
-  final _converter;
-  Expression _expr;
+  final _Converter _converter;
+  final Expression _expr;
   Function _callback;
   StreamSubscription _sub;
   var _value;
 
-  _Binding(this._expr, this._scope, [this._converter]);
+  _Binding(this._expr, this._scope, [converter])
+      : _converter = converter == null ? _identity : converter;
 
-  static _oneTime(Expression expr, Scope scope, [converter]) {
+  static Object _oneTime(Expression expr, Scope scope, _Converter converter) {
     try {
-      return _convertValue(eval(expr, scope), scope, converter);
+      var value = eval(expr, scope);
+      return (converter == null) ? value : converter(value);
     } catch (e, s) {
       new Completer().completeError(
           "Error evaluating expression '$expr': $e", s);
@@ -122,51 +282,45 @@
     return null;
   }
 
-  _setValue(v) {
+  _check(v, {bool skipChanges: false}) {
     var oldValue = _value;
-    _value = _convertValue(v, _scope, _converter);
-    if (_callback != null && oldValue != _value) _callback(_value);
-  }
-
-  static _convertValue(v, scope, converter) {
-    if (v is Comprehension) {
-      // convert the Comprehension into a list of scopes with the loop
-      // variable added to the scope
-      return v.iterable.map((i) => scope.childScope(v.identifier, i))
-          .toList(growable: false);
-    } else {
-      return converter == null ? v : converter(v);
+    _value = _converter(v);
+    if (!skipChanges && _callback != null && oldValue != _value) {
+      _callback(_value);
     }
   }
 
   get value {
+    // if there's a callback, then _value has been set, if not we need to
+    // force an evaluation
     if (_callback != null) return _value;
     return _oneTime(_expr, _scope, _converter);
   }
 
   set value(v) {
     try {
-      var newValue = assign(_expr, v, _scope);
-      _value = _convertValue(newValue, _scope, _converter);
+      var newValue = assign(_expr, v, _scope, checkAssignability: false);
+      _check(newValue, skipChanges: true);
     } catch (e, s) {
       new Completer().completeError(
           "Error evaluating expression '$_expr': $e", s);
     }
   }
 
-  open(callback(value)) {
+  Object open(callback(value)) {
     if (_callback != null) throw new StateError('already open');
 
     _callback = callback;
     final expr = observe(_expr, _scope);
-    _expr = expr;
-    _sub = expr.onUpdate.listen(_setValue)..onError((e, s) {
+//    _expr = expr;
+    _sub = expr.onUpdate.listen(_check)..onError((e, s) {
       new Completer().completeError(
           "Error evaluating expression '$expr': $e", s);
     });
     try {
+      // this causes a call to _updateValue with the new value
       update(expr, _scope);
-      _value = _convertValue(expr.currentValue, _scope, _converter);
+      _check(expr.currentValue, skipChanges: true);
     } catch (e, s) {
       new Completer().completeError(
           "Error evaluating expression '$expr': $e", s);
@@ -179,7 +333,20 @@
 
     _sub.cancel();
     _sub = null;
-    _expr = (_expr as ExpressionObserver).expression;
     _callback = null;
   }
 }
+
+_identity(x) => x;
+
+/**
+ * Factory function used for testing.
+ */
+class ScopeFactory {
+  const ScopeFactory();
+  modelScope({Object model, Map<String, Object> variables}) =>
+      new Scope(model: model, variables: variables);
+
+  childScope(Scope parent, String name, Object value) =>
+      parent.childScope(name, value);
+}
diff --git a/pkg/polymer_expressions/lib/tokenizer.dart b/pkg/polymer_expressions/lib/tokenizer.dart
index fb66087..d63f2b4 100644
--- a/pkg/polymer_expressions/lib/tokenizer.dart
+++ b/pkg/polymer_expressions/lib/tokenizer.dart
@@ -59,7 +59,7 @@
 
 const _TWO_CHAR_OPS = const ['==', '!=', '<=', '>=', '||', '&&'];
 
-const _KEYWORDS = const ['in', 'this'];
+const KEYWORDS = const ['as', 'in', 'this'];
 
 const _PRECEDENCE = const {
   '!':  0,
@@ -218,7 +218,7 @@
       _advance();
     }
     var value = _sb.toString();
-    if (_KEYWORDS.contains(value)) {
+    if (KEYWORDS.contains(value)) {
       _tokens.add(new Token(KEYWORD_TOKEN, value));
     } else {
       _tokens.add(new Token(IDENTIFIER_TOKEN, value));
diff --git a/pkg/polymer_expressions/lib/visitor.dart b/pkg/polymer_expressions/lib/visitor.dart
index 8c4118d..7bf8053 100644
--- a/pkg/polymer_expressions/lib/visitor.dart
+++ b/pkg/polymer_expressions/lib/visitor.dart
@@ -22,6 +22,7 @@
   visitUnaryOperator(UnaryOperator o);
   visitTernaryOperator(TernaryOperator o);
   visitInExpression(InExpression c);
+  visitAsExpression(AsExpression c);
 }
 
 class RecursiveVisitor extends Visitor {
@@ -123,4 +124,10 @@
     visit(c.right);
     visitExpression(c);
   }
+
+  visitAsExpression(AsExpression c) {
+    visit(c.left);
+    visit(c.right);
+    visitExpression(c);
+  }
 }
diff --git a/pkg/polymer_expressions/pubspec.yaml b/pkg/polymer_expressions/pubspec.yaml
index 213acac..c41cd8e 100644
--- a/pkg/polymer_expressions/pubspec.yaml
+++ b/pkg/polymer_expressions/pubspec.yaml
@@ -1,12 +1,12 @@
 name: polymer_expressions
-version: 0.10.0-pre.3
+version: 0.10.0
 author: Polymer.dart Authors <web-ui-dev@dartlang.org>
 description: An expressive custom binding syntax for HTML templates
 homepage: http://www.dartlang.org/polymer-dart/
 dependencies:
   browser: ">=0.10.0 <0.11.0"
-  observe: ">=0.10.0-pre.0 <0.11.0"
-  template_binding: ">=0.10.0-pre.0 <0.11.0"
+  observe: ">=0.10.0 <0.11.0"
+  template_binding: ">=0.10.0 <0.11.0"
 dev_dependencies:
   unittest: ">=0.10.0 <0.11.0"
   benchmark_harness: ">=1.0.0 <2.0.0"
diff --git a/pkg/polymer_expressions/test/bindings_test.dart b/pkg/polymer_expressions/test/bindings_test.dart
index 3aac607..3664bee 100644
--- a/pkg/polymer_expressions/test/bindings_test.dart
+++ b/pkg/polymer_expressions/test/bindings_test.dart
@@ -11,16 +11,20 @@
 import 'package:observe/mirrors_used.dart'; // make test smaller.
 import 'package:observe/src/dirty_check.dart' show dirtyCheckZone;
 import 'package:polymer_expressions/polymer_expressions.dart';
-import 'package:template_binding/template_binding.dart' show templateBind;
+import 'package:smoke/mirrors.dart' as smoke;
+import 'package:template_binding/template_binding.dart' show
+    TemplateBindExtension, templateBind;
 import 'package:unittest/html_config.dart';
+
 import 'package:unittest/unittest.dart';
 
+var testDiv;
+
 main() => dirtyCheckZone().run(() {
   useHtmlConfiguration();
 
   group('bindings', () {
     var stop = null;
-    var testDiv;
     setUp(() {
       document.body.append(testDiv = new DivElement());
     });
@@ -43,8 +47,10 @@
 
     test('should update text content when data changes', () {
       var model = new NotifyModel('abcde');
-      var template = templateBind(new Element.html(
-          '<template><span>{{x}}</span></template>'));
+      var tag = new Element.html(
+      '<template><span>{{x}}</span></template>');
+      TemplateBindExtension.bootstrap(tag);
+      var template = templateBind(tag);
       testDiv.append(template.createInstance(model, new PolymerExpressions()));
 
       var el;
@@ -63,8 +69,10 @@
       var model = new NotifyModel('abcde');
       var completer = new Completer();
       runZoned(() {
-        var template = templateBind(new Element.html(
-            '<template><span>{{foo}}</span></template>'));
+        var tag = new Element.html(
+        '<template><span>{{foo}}</span></template>');
+        TemplateBindExtension.bootstrap(tag);
+        var template = templateBind(tag);
         testDiv.append(template.createInstance(model,
             new PolymerExpressions()));
 
@@ -76,64 +84,13 @@
       return completer.future;
     });
 
-    test('should preserve the cursor position', () {
-      var model = new NotifyModel('abcde');
-      var template = templateBind(new Element.html(
-          '<template><input id="i1" value={{x}}></template>'));
-      testDiv.append(template.createInstance(model, new PolymerExpressions()));
-
-      var el;
-      return new Future(() {
-        el = testDiv.query("#i1");
-        var subscription = el.onInput.listen(expectAsync((_) {}, count: 1));
-        el.focus();
-
-        expect(el.value, 'abcde');
-        expect(model.x, 'abcde');
-
-        el.selectionStart = 3;
-        el.selectionEnd = 3;
-        expect(el.selectionStart, 3);
-        expect(el.selectionEnd, 3);
-
-        el.value = 'abc de';
-        // Updating the input value programatically (even to the same value in
-        // Chrome) loses the selection position.
-        expect(el.selectionStart, 6);
-        expect(el.selectionEnd, 6);
-
-        el.selectionStart = 4;
-        el.selectionEnd = 4;
-
-        expect(model.x, 'abcde');
-        el.dispatchEvent(new Event('input'));
-        expect(model.x, 'abc de');
-        expect(el.value, 'abc de');
-
-        // But propagating observable values through reassign the value and
-        // selection will be preserved.
-        expect(el.selectionStart, 4);
-        expect(el.selectionEnd, 4);
-        subscription.cancel();
-      }).then(_nextMicrotask).then((_) {
-        // Nothing changes on the next micro task.
-        expect(el.selectionStart, 4);
-        expect(el.selectionEnd, 4);
-      }).then((_) => window.animationFrame).then((_) {
-        // ... or on the next animation frame.
-        expect(el.selectionStart, 4);
-        expect(el.selectionEnd, 4);
-      }).then(_afterTimeout).then((_) {
-        // ... or later.
-        expect(el.selectionStart, 4);
-        expect(el.selectionEnd, 4);
-      });
-    });
-
     test('detects changes to ObservableList', () {
       var list = new ObservableList.from([1, 2, 3]);
-      var template = templateBind(new Element.html(
-          '<template>{{x[1]}}</template>'));
+
+      var tag = new Element.html('<template>{{x[1]}}</template>');
+      TemplateBindExtension.bootstrap(tag);
+      var template = templateBind(tag);
+
       var model = new NotifyModel(list);
       testDiv.append(template.createInstance(model, new PolymerExpressions()));
 
@@ -160,9 +117,13 @@
 
     test('detects changes to ObservableMap keys/values', () {
       var map = new ObservableMap.from({'a': 1, 'b': 2});
-      var template = templateBind(new Element.html('<template>'
+
+      var tag = new Element.html('<template>'
           '<template repeat="{{k in x.keys}}">{{k}}:{{x[k]}},</template>'
-          '</template>'));
+          '</template>');
+      TemplateBindExtension.bootstrap(tag);
+      var template = templateBind(tag);
+
       var model = new NotifyModel(map);
       testDiv.append(template.createInstance(model, new PolymerExpressions()));
 
@@ -177,19 +138,165 @@
         expect(testDiv.text, 'a:4,c:3,');
       });
     });
+
+    // TODO(sigmund): enable this test (issue 19105)
+    // _cursorPositionTest(false);
+    _cursorPositionTest(true);
+
+    // Regression tests for issue 18792.
+    for (var usePolymer in [true, false]) {
+      // We run these tests both with PolymerExpressions and with the default
+      // delegate to ensure the results are consistent. The expressions on these
+      // tests use syntax common to both delegates.
+      var name = usePolymer ? 'polymer-expressions' : 'default';
+      group('$name delegate', () {
+        // Use <option template repeat="{{y}}" value="{{}}">item {{}}
+        _initialSelectTest('{{y}}', '{{}}', usePolymer);
+        _updateSelectTest('{{y}}', '{{}}', usePolymer);
+      });
+    }
+
+    group('polymer-expressions delegate, polymer syntax', () {
+        // Use <option template repeat="{{i in y}}" value="{{i}}">item {{i}}
+      _initialSelectTest('{{i in y}}', '{{i}}', true);
+      _updateSelectTest('{{i in y}}', '{{i}}', true);
+    });
   });
 });
 
+
+_cursorPositionTest(bool usePolymer) {
+  test('should preserve the cursor position', () {
+    var model = new NotifyModel('abcde');
+
+    var tag = new Element.html(
+        '<template><input id="i1" value={{x}}></template>');
+    TemplateBindExtension.bootstrap(tag);
+    var template = templateBind(tag);
+
+    var delegate = usePolymer ? new PolymerExpressions() : null;
+    testDiv.append(template.createInstance(model, delegate));
+
+    var el;
+    return new Future(() {
+      el = testDiv.query("#i1");
+      var subscription = el.onInput.listen(expectAsync((_) {}, count: 1));
+      el.focus();
+
+      expect(el.value, 'abcde');
+      expect(model.x, 'abcde');
+
+      el.selectionStart = 3;
+      el.selectionEnd = 3;
+      expect(el.selectionStart, 3);
+      expect(el.selectionEnd, 3);
+
+      el.value = 'abc de';
+      // Updating the input value programatically (even to the same value in
+      // Chrome) loses the selection position.
+      expect(el.selectionStart, 6);
+      expect(el.selectionEnd, 6);
+
+      el.selectionStart = 4;
+      el.selectionEnd = 4;
+
+      expect(model.x, 'abcde');
+      el.dispatchEvent(new Event('input'));
+      expect(model.x, 'abc de');
+      expect(el.value, 'abc de');
+
+      // But propagating observable values through reassign the value and
+      // selection will be preserved.
+      expect(el.selectionStart, 4);
+      expect(el.selectionEnd, 4);
+      subscription.cancel();
+    }).then(_nextMicrotask).then((_) {
+      // Nothing changes on the next micro task.
+      expect(el.selectionStart, 4);
+      expect(el.selectionEnd, 4);
+    }).then((_) => window.animationFrame).then((_) {
+      // ... or on the next animation frame.
+      expect(el.selectionStart, 4);
+      expect(el.selectionEnd, 4);
+    }).then(_afterTimeout).then((_) {
+      // ... or later.
+      expect(el.selectionStart, 4);
+      expect(el.selectionEnd, 4);
+    });
+  });
+}
+
+_initialSelectTest(String repeatExp, String valueExp, bool usePolymer) {
+  test('initial select value is set correctly', () {
+    var list = const ['a', 'b'];
+
+    var tag = new Element.html('<template>'
+        '<select value="{{x}}">'
+        '<option template repeat="$repeatExp" value="$valueExp">item $valueExp'
+        '</option></select></template>',
+        treeSanitizer: _nullTreeSanitizer);
+    TemplateBindExtension.bootstrap(tag);
+    var template = templateBind(tag);
+
+    var model = new NotifyModel('b', list);
+    var delegate = usePolymer ? new PolymerExpressions() : null;
+    testDiv.append(template.createInstance(model, delegate));
+
+    expect(testDiv.querySelector('select').value, 'b');
+    return new Future(() {
+      expect(model.x, 'b');
+      expect(testDiv.querySelector('select').value, 'b');
+    });
+  });
+}
+
+_updateSelectTest(String repeatExp, String valueExp, bool usePolymer) {
+  test('updates to select value propagate correctly', () {
+    var list = const ['a', 'b'];
+
+    var tag = new Element.html('<template>'
+        '<select value="{{x}}">'
+        '<option template repeat="$repeatExp" value="$valueExp">item $valueExp'
+        '</option></select></template>',
+        treeSanitizer: _nullTreeSanitizer);
+    TemplateBindExtension.bootstrap(tag);
+    var template = templateBind(tag);
+
+    var model = new NotifyModel('a', list);
+    var delegate = usePolymer ? new PolymerExpressions() : null;
+    testDiv.append(template.createInstance(model, delegate));
+
+    expect(testDiv.querySelector('select').value, 'a');
+    return new Future(() {
+      expect(testDiv.querySelector('select').value, 'a');
+      model.x = 'b';
+    }).then(_nextMicrotask).then((_) {
+      expect(testDiv.querySelector('select').value, 'b');
+    });
+  });
+}
+
 _nextMicrotask(_) => new Future(() {});
 _afterTimeout(_) => new Future.delayed(new Duration(milliseconds: 30), () {});
 
 @reflectable
 class NotifyModel extends ChangeNotifier {
   var _x;
-  NotifyModel([this._x]);
+  var _y;
+  NotifyModel([this._x, this._y]);
 
   get x => _x;
   set x(value) {
     _x = notifyPropertyChange(#x, _x, value);
   }
+
+  get y => _y;
+  set y(value) {
+    _y = notifyPropertyChange(#y, _y, value);
+  }
 }
+
+class _NullTreeSanitizer implements NodeTreeSanitizer {
+  void sanitizeTree(Node node) {}
+}
+final _nullTreeSanitizer = new _NullTreeSanitizer();
diff --git a/pkg/polymer_expressions/test/eval_test.dart b/pkg/polymer_expressions/test/eval_test.dart
index 2181215..a73e037 100644
--- a/pkg/polymer_expressions/test/eval_test.dart
+++ b/pkg/polymer_expressions/test/eval_test.dart
@@ -81,6 +81,9 @@
       expectEval('2 - 1', 1);
       expectEval('4 / 2', 2);
       expectEval('2 * 3', 6);
+      expectEval('5 % 2', 1);
+      expectEval('5 % -2', 1);
+      expectEval('-5 % 2', 1);
 
       expectEval('1 == 1', true);
       expectEval('1 == 2', false);
@@ -216,24 +219,8 @@
       expectEval('a || b', false, null, {'a': null, 'b': null});
     });
 
-    test('should evaluate an "in" expression', () {
-      var scope = new Scope(variables: {'items': [1, 2, 3]});
-      var comprehension = eval(parse('item in items'), scope);
-      expect(comprehension.iterable, orderedEquals([1, 2, 3]));
-    });
-
-    test('should evaluate complex "in" expressions', () {
-      var holder = new ListHolder([1, 2, 3]);
-      var scope = new Scope(variables: {'holder': holder});
-      var comprehension = eval(parse('item in holder.items'), scope);
-      expect(comprehension.iterable, orderedEquals([1, 2, 3]));
-    });
-
-    test('should handle null iterators in "in" expressions', () {
-      var scope = new Scope(variables: {'items': null});
-      var comprehension = eval(parse('item in items'), scope);
-      expect(comprehension, isNotNull);
-      expect(comprehension.iterable, []);
+    test('should not evaluate "in" expressions', () {
+      expect(() => eval(parse('item in items'), null), throws);
     });
 
   });
@@ -257,6 +244,15 @@
       var foo = new Foo(items: [1, 2, 3]);
       assign(parse('items[0]'), 4, new Scope(model: foo));
       expect(foo.items[0], 4);
+      assign(parse('items[a]'), 5, new Scope(model: foo, variables: {'a': 0}));
+      expect(foo.items[0], 5);
+    });
+
+    test('should assign with a function call subexpression', () {
+      var child = new Foo();
+      var foo = new Foo(items: [1, 2, 3], child: child);
+      assign(parse('getChild().name'), 'child', new Scope(model: foo));
+      expect(child.name, 'child');
     });
 
     test('should assign through transformers', () {
@@ -273,6 +269,36 @@
       expect(foo.name, '19');
     });
 
+    test('should not throw on assignments to properties on null', () {
+      assign(parse('name'), 'b', new Scope(model: null));
+    });
+
+    test('should throw on assignments to non-assignable expressions', () {
+      var foo = new Foo(name: 'a');
+      var scope = new Scope(model: foo);
+      expect(() => assign(parse('name + 1'), 1, scope),
+          throwsA(new isInstanceOf<EvalException>()));
+      expect(() => assign(parse('toString()'), 1, scope),
+          throwsA(new isInstanceOf<EvalException>()));
+      expect(() => assign(parse('name | filter'), 1, scope),
+          throwsA(new isInstanceOf<EvalException>()));
+    });
+
+    test('should not throw on assignments to non-assignable expressions if '
+        'checkAssignability is false', () {
+      var foo = new Foo(name: 'a');
+      var scope = new Scope(model: foo);
+      expect(
+          assign(parse('name + 1'), 1, scope, checkAssignability: false),
+          null);
+      expect(
+          assign(parse('toString()'), 1, scope, checkAssignability: false),
+          null);
+      expect(
+          assign(parse('name | filter'), 1, scope, checkAssignability: false),
+          null);
+    });
+
   });
 
   group('scope', () {
@@ -340,19 +366,6 @@
       );
     });
 
-    test('should observe an comprehension', () {
-      var items = new ObservableList();
-      var foo = new Foo(name: 'foo');
-      return expectObserve('item in items',
-          variables: {'items': items},
-          beforeMatcher: (c) => c.iterable.isEmpty,
-          mutate: () {
-            items.add(foo);
-          },
-          afterMatcher: (c) => c.iterable.contains(foo)
-      );
-    });
-
   });
 
 }
@@ -372,6 +385,10 @@
   Foo({name, this.age, this.child, this.items}) : _name = name;
 
   int x() => age * age;
+
+  getChild() => child;
+
+  filter(i) => i;
 }
 
 @reflectable
diff --git a/pkg/polymer_expressions/test/globals_test.dart b/pkg/polymer_expressions/test/globals_test.dart
index 433cd08..8fdbc17 100644
--- a/pkg/polymer_expressions/test/globals_test.dart
+++ b/pkg/polymer_expressions/test/globals_test.dart
@@ -26,6 +26,7 @@
               </template>
             </template>
           </div>''');
+      TemplateBindExtension.bootstrap(testDiv);
       document.body.nodes.add(testDiv);
     });
 
diff --git a/pkg/polymer_expressions/test/parser_test.dart b/pkg/polymer_expressions/test/parser_test.dart
index 09de5d6..04f2ee7 100644
--- a/pkg/polymer_expressions/test/parser_test.dart
+++ b/pkg/polymer_expressions/test/parser_test.dart
@@ -64,10 +64,9 @@
 
     test('should give multiply higher associativity than plus', () {
       expectParse('a + b * c',
-          binary(
-              ident('a'),
-              '+',
-              binary(ident('b'), '*', ident('c'))));
+          binary(ident('a'), '+', binary(ident('b'), '*', ident('c'))));
+      expectParse('a * b + c',
+          binary(binary(ident('a'), '*', ident('b')), '+', ident('c')));
     });
 
     test('should parse a dot operator', () {
@@ -181,7 +180,7 @@
           '|', ident('c')));
     });
 
-    test('should parse comprehension', () {
+    test('should parse "in" expression', () {
       expectParse('a in b', inExpr(ident('a'), ident('b')));
       expectParse('a in b.c',
           inExpr(ident('a'), getter(ident('b'), 'c')));
@@ -193,8 +192,15 @@
       expect(() => parse('a + 1 in b'), throwsException);
     });
 
-    test('should reject keywords as identifiers', () {
-      expect(() => parse('a.in'), throwsException);
+    test('should parse "as" expressions', () {
+      expectParse('a as b', asExpr(ident('a'), ident('b')));
+    });
+
+    skip_test('should reject keywords as identifiers', () {
+      expect(() => parse('a.in'), throws);
+      expect(() => parse('a.as'), throws);
+      // TODO: re-enable when 'this' is a keyword
+//      expect(() => parse('a.this'), throws);
     });
 
     test('should parse map literals', () {
diff --git a/pkg/polymer_expressions/test/syntax_test.dart b/pkg/polymer_expressions/test/syntax_test.dart
index 5d15e17..d4f8d9e 100644
--- a/pkg/polymer_expressions/test/syntax_test.dart
+++ b/pkg/polymer_expressions/test/syntax_test.dart
@@ -8,105 +8,602 @@
 import 'package:observe/observe.dart';
 import 'package:observe/mirrors_used.dart'; // make test smaller.
 import 'package:polymer_expressions/polymer_expressions.dart';
+import 'package:polymer_expressions/eval.dart';
 import 'package:template_binding/template_binding.dart';
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
+import 'package:smoke/mirrors.dart' as smoke;
+
+class TestScopeFactory implements ScopeFactory {
+  int scopeCount = 0;
+
+  modelScope({Object model, Map<String, Object> variables}) {
+    scopeCount++;
+    return new Scope(model: model, variables: variables);
+  }
+
+  childScope(Scope parent, String name, Object value) {
+    scopeCount++;
+    return parent.childScope(name, value);
+  }
+}
 
 main() {
   useHtmlConfiguration();
+  smoke.useMirrors();
 
   group('PolymerExpressions', () {
-    var testDiv;
+    DivElement testDiv;
+    TestScopeFactory testScopeFactory;
 
     setUp(() {
       document.body.append(testDiv = new DivElement());
+      testScopeFactory = new TestScopeFactory();
     });
 
     tearDown(() {
-      testDiv.firstChild.remove();
+      testDiv.children.clear();
       testDiv = null;
     });
 
-    test('should make two-way bindings to inputs', () {
-      testDiv.nodes.add(new Element.html('''
-          <template id="test" bind>
-            <input id="input" value="{{ firstName }}">
-          </template>'''));
-      var person = new Person('John', 'Messerly', ['A', 'B', 'C']);
-      templateBind(querySelector('#test'))
-          ..bindingDelegate = new PolymerExpressions()
-          ..model = person;
-      return new Future(() {}).then((_) {
-        InputElement input = querySelector('#input');
-        expect(input.value, 'John');
-        input.focus();
-        input.value = 'Justin';
-        input.blur();
-        var event = new Event('change');
-        // TODO(justin): figure out how to trigger keyboard events to test
-        // two-way bindings
+    Future<Element> setUpTest(String html, {model, Map globals}) {
+      var tag = new Element.html(html,
+          treeSanitizer: new NullNodeTreeSanitizer());
+
+      // make sure templates behave in the polyfill
+      TemplateBindExtension.bootstrap(tag);
+
+      templateBind(tag)
+        ..bindingDelegate = new PolymerExpressions(globals: globals,
+            scopeFactory: testScopeFactory)
+        ..model = model;
+      testDiv.children.clear();
+      testDiv.append(tag);
+      return waitForChange(testDiv);
+    }
+
+    group('scope creation', () {
+      // These tests are sensitive to some internals of the implementation that
+      // might not be visible to applications, but are useful for verifying that
+      // that we're not creating too many Scopes.
+
+      // The reason that we create two Scopes in the cases with one binding is
+      // that <template bind> has one scope for the context to evaluate the bind
+      // binding in, and another scope for the bindings inside the template.
+
+      // We could try to optimize the outer scope away in cases where the
+      // expression is empty, but there are a lot of special cases in the
+      // syntax code already.
+      test('should create one scope for a single binding', () =>
+        setUpTest('''
+            <template id="test" bind>
+              <div>{{ data }}</div>
+            </template>''',
+            model: new Model('a'))
+        .then((_) {
+          expect(testDiv.children.length, 2);
+          expect(testDiv.children[1].text, 'a');
+          expect(testScopeFactory.scopeCount, 1);
+        }));
+
+      test('should only create a single scope for two bindings', () =>
+        setUpTest('''
+            <template id="test" bind>
+              <div>{{ data }}</div>
+              <div>{{ data }}</div>
+            </template>''',
+            model: new Model('a'))
+        .then((_) {
+          expect(testDiv.children.length, 3);
+          expect(testDiv.children[1].text, 'a');
+          expect(testDiv.children[2].text, 'a');
+          expect(testScopeFactory.scopeCount, 1);
+        }));
+
+      test('should create a new scope for a bind/as binding', () {
+        return setUpTest('''
+            <template id="test" bind>
+              <div>{{ data }}</div>
+              <template bind="{{ data as a }}" id="inner">
+                <div>{{ a }}</div>
+                <div>{{ data }}</div>
+              </template>
+            </template>''',
+            model: new Model('foo'))
+        .then((_) {
+          expect(testDiv.children.length, 5);
+          expect(testDiv.children[1].text, 'foo');
+          expect(testDiv.children[3].text, 'foo');
+          expect(testDiv.children[4].text, 'foo');
+          expect(testScopeFactory.scopeCount, 2);
+        });
+      });
+
+      test('should create scopes for a repeat/in binding', () {
+        return setUpTest('''
+            <template id="test" bind>
+              <div>{{ data }}</div>
+              <template repeat="{{ i in items }}" id="inner">
+                <div>{{ i }}</div>
+                <div>{{ data }}</div>
+              </template>
+            </template>''',
+            model: new Model('foo'), globals: {'items': ['a', 'b', 'c']})
+        .then((_) {
+          expect(testDiv.children.length, 9);
+          expect(testDiv.children[1].text, 'foo');
+          expect(testDiv.children[3].text, 'a');
+          expect(testDiv.children[4].text, 'foo');
+          expect(testDiv.children[5].text, 'b');
+          expect(testDiv.children[6].text, 'foo');
+          expect(testDiv.children[7].text, 'c');
+          expect(testDiv.children[8].text, 'foo');
+          // 1 scopes for <template bind>, 1 for each repeat
+          expect(testScopeFactory.scopeCount, 4);
+        });
+      });
+
+
+    });
+
+    group('with template bind', () {
+
+      test('should show a simple binding on the model', () =>
+        setUpTest('''
+            <template id="test" bind>
+              <div>{{ data }}</div>
+            </template>''',
+            model: new Model('a'))
+        .then((_) {
+          expect(testDiv.children.length, 2);
+          expect(testDiv.children[1].text, 'a');
+        }));
+
+      test('should handle an empty binding on the model', () =>
+        setUpTest('''
+            <template id="test" bind>
+              <div>{{ }}</div>
+            </template>''',
+            model: 'a')
+        .then((_) {
+          expect(testDiv.children.length, 2);
+          expect(testDiv.children[1].text, 'a');
+        }));
+
+      test('should show a simple binding to a global', () =>
+        setUpTest('''
+            <template id="test" bind>
+              <div>{{ a }}</div>
+            </template>''',
+            globals: {'a': '123'})
+        .then((_) {
+          expect(testDiv.children.length, 2);
+          expect(testDiv.children[1].text, '123');
+        }));
+
+      test('should show an expression binding', () =>
+        setUpTest('''
+            <template id="test" bind>
+              <div>{{ data + 'b' }}</div>
+            </template>''',
+            model: new Model('a'))
+        .then((_) {
+          expect(testDiv.children.length, 2);
+          expect(testDiv.children[1].text, 'ab');
+        }));
+
+      test('should handle an expression in the bind attribute', () =>
+        setUpTest('''
+            <template id="test" bind="{{ data }}">
+              <div>{{ this }}</div>
+            </template>''',
+            model: new Model('a'))
+        .then((_) {
+          expect(testDiv.children.length, 2);
+          expect(testDiv.children[1].text, 'a');
+        }));
+
+      test('should handle a nested template with an expression in the bind '
+          'attribute', () =>
+        setUpTest('''
+            <template id="test" bind>
+              <template id="inner" bind="{{ data }}">
+                <div>{{ this }}</div>
+              </template>
+            </template>''',
+            model: new Model('a'))
+        .then((_) {
+          expect(testDiv.children.length, 3);
+          expect(testDiv.children[2].text, 'a');
+        }));
+
+
+      test('should handle an "as" expression in the bind attribute', () =>
+        setUpTest('''
+            <template id="test" bind="{{ data as a }}">
+              <div>{{ data }}b</div>
+              <div>{{ a }}c</div>
+            </template>''',
+            model: new Model('a'))
+        .then((_) {
+          expect(testDiv.children.length, 3);
+          expect(testDiv.children[1].text, 'ab');
+          expect(testDiv.children[2].text, 'ac');
+        }));
+
+      // passes safari
+      test('should not resolve names in the outer template from within a nested'
+          ' template with a bind binding', () {
+        var completer = new Completer();
+        var bindingErrorHappened = false;
+        var templateRendered = false;
+        maybeComplete() {
+          if (bindingErrorHappened && templateRendered) {
+            completer.complete(true);
+          }
+        }
+        runZoned(() {
+          setUpTest('''
+              <template id="test" bind>
+                <div>{{ data }}</div>
+                <div>{{ b }}</div>
+                <template id="inner" bind="{{ b }}">
+                  <div>{{ data }}</div>
+                  <div>{{ b }}</div>
+                  <div>{{ this }}</div>
+                </template>
+              </template>''',
+              model: new Model('foo'), globals: {'b': 'bbb'})
+          .then((_) {
+            expect(testDiv.children[0].text, '');
+            expect(testDiv.children[1].text, 'foo');
+            expect(testDiv.children[2].text, 'bbb');
+            // Something very strage is happening in the template bindings
+            // polyfill, and the template is being stamped out, inside the
+            // template tag (which shouldn't happen), and outside the template
+            //expect(testDiv.children[3].text, '');
+            expect(testDiv.children[3].tagName.toLowerCase(), 'template');
+            expect(testDiv.children[4].text, '');
+            expect(testDiv.children[5].text, 'bbb');
+            expect(testDiv.children[6].text, 'bbb');
+            templateRendered = true;
+            maybeComplete();
+          });
+        }, onError: (e, s) {
+          expect('$e', contains('data'));
+          bindingErrorHappened = true;
+          maybeComplete();
+        });
+        return completer.future;
+      });
+
+      // passes safari
+      test('should shadow names in the outer template from within a nested '
+          'template', () =>
+          setUpTest('''
+            <template id="test" bind>
+              <div>{{ a }}</div>
+              <div>{{ b }}</div>
+              <template bind="{{ b as a }}">
+                <div>{{ a }}</div>
+                <div>{{ b }}</div>
+              </template>
+            </template>''',
+            globals: {'a': 'aaa', 'b': 'bbb'})
+        .then((_) {
+          expect(testDiv.children[0].text, '');
+          expect(testDiv.children[1].text, 'aaa');
+          expect(testDiv.children[2].text, 'bbb');
+          expect(testDiv.children[3].tagName.toLowerCase(), 'template');
+          expect(testDiv.children[4].text, 'bbb');
+          expect(testDiv.children[5].text, 'bbb');
+        }));
+
+    });
+
+    group('with template repeat', () {
+
+      // passes safari
+      test('should not resolve names in the outer template from within a nested'
+          ' template with a repeat binding', () {
+        var completer = new Completer();
+        var bindingErrorHappened = false;
+        var templateRendered = false;
+        maybeComplete() {
+          if (bindingErrorHappened && templateRendered) {
+            completer.complete(true);
+          }
+        }
+        runZoned(() {
+          setUpTest('''
+              <template id="test" bind>
+                <div>{{ data }}</div>
+                <template repeat="{{ items }}">
+                  <div>{{ }}{{ data }}</div>
+                </template>
+              </template>''',
+              globals: {'items': [1, 2, 3]},
+              model: new Model('a'))
+          .then((_) {
+            expect(testDiv.children[0].text, '');
+            expect(testDiv.children[1].text, 'a');
+            expect(testDiv.children[2].tagName.toLowerCase(), 'template');
+            expect(testDiv.children[3].text, '1');
+            expect(testDiv.children[4].text, '2');
+            expect(testDiv.children[5].text, '3');
+            templateRendered = true;
+            maybeComplete();
+          });
+        }, onError: (e, s) {
+          expect('$e', contains('data'));
+          bindingErrorHappened = true;
+          maybeComplete();
+        });
+        return completer.future;
+      });
+
+      test('should handle repeat/in bindings', () =>
+        setUpTest('''
+            <template id="test" bind>
+              <div>{{ data }}</div>
+              <template repeat="{{ item in items }}">
+                <div>{{ item }}{{ data }}</div>
+              </template>
+            </template>''',
+            globals: {'items': [1, 2, 3]},
+            model: new Model('a'))
+        .then((_) {
+          // expect 6 children: two templates, a div and three instances
+          expect(testDiv.children[0].text, '');
+          expect(testDiv.children[1].text, 'a');
+          expect(testDiv.children[2].tagName.toLowerCase(), 'template');
+          expect(testDiv.children[3].text, '1a');
+          expect(testDiv.children[4].text, '2a');
+          expect(testDiv.children[5].text, '3a');
+//          expect(testDiv.children.map((c) => c.text),
+//              ['', 'a', '', '1a', '2a', '3a']);
+        }));
+
+      test('should observe changes to lists in repeat bindings', () {
+        var items = new ObservableList.from([1, 2, 3]);
+        return setUpTest('''
+            <template id="test" bind>
+              <template repeat="{{ items }}">
+                <div>{{ }}</div>
+              </template>
+            </template>''',
+            globals: {'items': items},
+            model: new Model('a'))
+        .then((_) {
+          expect(testDiv.children[0].text, '');
+          expect(testDiv.children[1].tagName.toLowerCase(), 'template');
+          expect(testDiv.children[2].text, '1');
+          expect(testDiv.children[3].text, '2');
+          expect(testDiv.children[4].text, '3');
+//          expect(testDiv.children.map((c) => c.text),
+//              ['', '', '1', '2', '3']);
+          items.add(4);
+          return waitForChange(testDiv);
+        }).then((_) {
+          expect(testDiv.children[0].text, '');
+          expect(testDiv.children[1].tagName.toLowerCase(), 'template');
+          expect(testDiv.children[2].text, '1');
+          expect(testDiv.children[3].text, '2');
+          expect(testDiv.children[4].text, '3');
+          expect(testDiv.children[5].text, '4');
+//          expect(testDiv.children.map((c) => c.text),
+//              ['', '', '1', '2', '3', '4']);
+        });
+      });
+
+      test('should observe changes to lists in repeat/in bindings', () {
+        var items = new ObservableList.from([1, 2, 3]);
+        return setUpTest('''
+            <template id="test" bind>
+              <template repeat="{{ item in items }}">
+                <div>{{ item }}</div>
+              </template>
+            </template>''',
+            globals: {'items': items},
+            model: new Model('a'))
+        .then((_) {
+          expect(testDiv.children[0].text, '');
+          expect(testDiv.children[1].tagName.toLowerCase(), 'template');
+          expect(testDiv.children[2].text, '1');
+          expect(testDiv.children[3].text, '2');
+          expect(testDiv.children[4].text, '3');
+//          expect(testDiv.children.map((c) => c.text),
+//              ['', '', '1', '2', '3']);
+          items.add(4);
+          return waitForChange(testDiv);
+        }).then((_) {
+          expect(testDiv.children[0].text, '');
+          expect(testDiv.children[1].tagName.toLowerCase(), 'template');
+          expect(testDiv.children[2].text, '1');
+          expect(testDiv.children[3].text, '2');
+          expect(testDiv.children[4].text, '3');
+          expect(testDiv.children[5].text, '4');
+//          expect(testDiv.children.map((c) => c.text),
+//              ['', '', '1', '2', '3', '4']);
+        });
       });
     });
 
-    test('should handle null collections in "in" expressions', () {
-      testDiv.nodes.add(new Element.html('''
-          <template id="test" bind>
-            <template repeat="{{ item in items }}">
-              {{ item }}
-            </template>
-          </template>'''));
-      templateBind(querySelector('#test')).bindingDelegate =
-          new PolymerExpressions(globals: {'items': null});
-      // the template should be the only node
-      expect(testDiv.nodes.length, 1);
-      expect(testDiv.nodes[0].id, 'test');
+    group('with template if', () {
+
+      Future doTest(value, bool shouldRender) =>
+        setUpTest('''
+            <template id="test" bind>
+              <div>{{ data }}</div>
+              <template if="{{ show }}">
+                <div>{{ data }}</div>
+              </template>
+            </template>''',
+            globals: {'show': value},
+            model: new Model('a'))
+        .then((_) {
+          if (shouldRender) {
+            expect(testDiv.children.length, 4);
+            expect(testDiv.children[1].text, 'a');
+            expect(testDiv.children[3].text, 'a');
+          } else {
+            expect(testDiv.children.length, 3);
+            expect(testDiv.children[1].text, 'a');
+          }
+        });
+
+      test('should render for a true expression',
+          () => doTest(true, true));
+
+      test('should treat a non-null expression as truthy',
+          () => doTest('a', true));
+
+      test('should treat an empty list as truthy',
+          () => doTest([], true));
+
+      test('should handle a false expression',
+          () => doTest(false, false));
+
+      test('should treat null as falsey',
+          () => doTest(null, false));
     });
 
-    test('should silently handle bad variable names', () {
-      var completer = new Completer();
-      runZoned(() {
-        testDiv.nodes.add(new Element.html('''
-            <template id="test" bind>{{ foo }}</template>'''));
-        templateBind(querySelector('#test'))
-            ..bindingDelegate = new PolymerExpressions()
-            ..model = [];
-        return new Future(() {});
-      }, onError: (e, s) {
-        expect('$e', contains('foo'));
-        completer.complete(true);
+    group('error handling', () {
+
+      test('should silently handle bad variable names', () {
+        var completer = new Completer();
+        runZoned(() {
+          testDiv.nodes.add(new Element.html('''
+              <template id="test" bind>{{ foo }}</template>'''));
+          templateBind(query('#test'))
+              ..bindingDelegate = new PolymerExpressions()
+              ..model = [];
+          return new Future(() {});
+        }, onError: (e, s) {
+          expect('$e', contains('foo'));
+          completer.complete(true);
+        });
+        return completer.future;
       });
-      return completer.future;
+
+      test('should handle null collections in "in" expressions', () =>
+        setUpTest('''
+            <template id="test" bind>
+              <template repeat="{{ item in items }}">
+                {{ item }}
+              </template>
+            </template>''',
+            globals: {'items': null})
+        .then((_) {
+          expect(testDiv.children.length, 2);
+          expect(testDiv.children[0].id, 'test');
+        }));
+
     });
+
+    group('special bindings', () {
+
+      test('should handle class attributes with lists', ()  =>
+        setUpTest('''
+            <template id="test" bind>
+              <div class="{{ classes }}">
+            </template>''',
+            globals: {'classes': ['a', 'b']})
+        .then((_) {
+          expect(testDiv.children.length, 2);
+          expect(testDiv.children[1].attributes['class'], 'a b');
+          expect(testDiv.children[1].classes, ['a', 'b']);
+        }));
+
+      test('should handle class attributes with maps', ()  =>
+        setUpTest('''
+            <template id="test" bind>
+              <div class="{{ classes }}">
+            </template>''',
+            globals: {'classes': {'a': true, 'b': false, 'c': true}})
+        .then((_) {
+          expect(testDiv.children.length, 2);
+          expect(testDiv.children[1].attributes['class'], 'a c');
+          expect(testDiv.children[1].classes, ['a', 'c']);
+        }));
+
+      test('should handle style attributes with lists', () =>
+        setUpTest('''
+            <template id="test" bind>
+              <div style="{{ styles }}">
+            </template>''',
+            globals: {'styles': ['display: none', 'color: black']})
+        .then((_) {
+          expect(testDiv.children.length, 2);
+          expect(testDiv.children[1].attributes['style'],
+              'display: none;color: black');
+        }));
+
+      test('should handle style attributes with maps', ()  =>
+        setUpTest('''
+            <template id="test" bind>
+              <div style="{{ styles }}">
+            </template>''',
+            globals: {'styles': {'display': 'none', 'color': 'black'}})
+        .then((_) {
+          expect(testDiv.children.length, 2);
+          expect(testDiv.children[1].attributes['style'],
+              'display: none;color: black');
+        }));
+    });
+
+    group('regression tests', () {
+
+      test('should bind to literals', () =>
+        setUpTest('''
+            <template id="test" bind>
+              <div>{{ 123 }}</div>
+              <div>{{ 123.456 }}</div>
+              <div>{{ "abc" }}</div>
+              <div>{{ true }}</div>
+              <div>{{ null }}</div>
+            </template>''',
+            globals: {'items': null})
+        .then((_) {
+          expect(testDiv.children.length, 6);
+          expect(testDiv.children[1].text, '123');
+          expect(testDiv.children[2].text, '123.456');
+          expect(testDiv.children[3].text, 'abc');
+          expect(testDiv.children[4].text, 'true');
+          expect(testDiv.children[5].text, '');
+        }));
+
+      });
+
   });
 }
 
-@reflectable
-class Person extends ChangeNotifier {
-  String _firstName;
-  String _lastName;
-  List<String> _items;
-
-  Person(this._firstName, this._lastName, this._items);
-
-  String get firstName => _firstName;
-
-  void set firstName(String value) {
-    _firstName = notifyPropertyChange(#firstName, _firstName, value);
-  }
-
-  String get lastName => _lastName;
-
-  void set lastName(String value) {
-    _lastName = notifyPropertyChange(#lastName, _lastName, value);
-  }
-
-  String getFullName() => '$_firstName $_lastName';
-
-  List<String> get items => _items;
-
-  void set items(List<String> value) {
-    _items = notifyPropertyChange(#items, _items, value);
-  }
-
-  String toString() => "Person(firstName: $_firstName, lastName: $_lastName)";
+Future<Element> waitForChange(Element e) {
+  var completer = new Completer<Element>();
+  new MutationObserver((mutations, observer) {
+    observer.disconnect();
+    completer.complete(e);
+  }).observe(e, childList: true);
+  return completer.future.timeout(new Duration(seconds: 1));
 }
+
+@reflectable
+class Model extends ChangeNotifier {
+  String _data;
+
+  Model(this._data);
+
+  String get data => _data;
+
+  void set data(String value) {
+    _data = notifyPropertyChange(#data, _data, value);
+  }
+
+  String toString() => "Model(data: $_data)";
+}
+
+class NullNodeTreeSanitizer implements NodeTreeSanitizer {
+
+  @override
+  void sanitizeTree(Node node) {}
+}
\ No newline at end of file
diff --git a/pkg/polymer_expressions/test/tokenizer_test.dart b/pkg/polymer_expressions/test/tokenizer_test.dart
index a93dce7..9689b86 100644
--- a/pkg/polymer_expressions/test/tokenizer_test.dart
+++ b/pkg/polymer_expressions/test/tokenizer_test.dart
@@ -67,15 +67,23 @@
           t(IDENTIFIER_TOKEN, 'c')]);
     });
 
-    test('should tokenize an iterate expression with "in" keyword', () {
+    test('should tokenize "in" expressions', () {
       expectTokens('item in items', [
           t(IDENTIFIER_TOKEN, 'item'),
           t(KEYWORD_TOKEN, 'in'),
           t(IDENTIFIER_TOKEN, 'items')]);
     });
 
+    test('should takenize an "as" expression', () {
+      expectTokens('a as b', [
+          t(IDENTIFIER_TOKEN, 'a'),
+          t(KEYWORD_TOKEN, 'as'),
+          t(IDENTIFIER_TOKEN, 'b')]);
+    });
+
     test('should tokenize keywords', () {
       expectTokens('in', [t(KEYWORD_TOKEN, 'in')]);
+      expectTokens('as', [t(KEYWORD_TOKEN, 'as')]);
       expectTokens('this', [t(KEYWORD_TOKEN, 'this')]);
     });
 
diff --git a/pkg/scheduled_test/CHANGELOG.md b/pkg/scheduled_test/CHANGELOG.md
index fe09dd6..a745c63 100644
--- a/pkg/scheduled_test/CHANGELOG.md
+++ b/pkg/scheduled_test/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.11.0+5
+
+* Widen the version constraint for `stack_trace`.
+
 ## 0.11.0+4
 
 * Added `README.md` with content from `lib/scheduled_test.dart`.
diff --git a/pkg/scheduled_test/pubspec.yaml b/pkg/scheduled_test/pubspec.yaml
index d96db15..9eb8ec1 100644
--- a/pkg/scheduled_test/pubspec.yaml
+++ b/pkg/scheduled_test/pubspec.yaml
@@ -1,5 +1,5 @@
 name: scheduled_test
-version: 0.11.0+4
+version: 0.11.0+5
 author: Dart Team <misc@dartlang.org>
 description: >
   A package for writing readable tests of asynchronous behavior.
@@ -15,5 +15,5 @@
   http: '>=0.9.0 <0.12.0'
   path: '>=0.9.0 <2.0.0'
   shelf: '>=0.4.0 <0.6.0'
-  stack_trace: '>=0.9.1 <0.10.0'
+  stack_trace: '>=0.9.1 <2.0.0'
   unittest: '>=0.9.0 <0.12.0'
diff --git a/pkg/shelf/CHANGELOG.md b/pkg/shelf/CHANGELOG.md
index 538153e..2926976 100644
--- a/pkg/shelf/CHANGELOG.md
+++ b/pkg/shelf/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.5.4+1
+
+* Widen the version constraint for `stack_trace`.
+
 ## 0.5.4
 
 * The `shelf_io` adapter now sends the `Date` HTTP header by default.
diff --git a/pkg/shelf/pubspec.yaml b/pkg/shelf/pubspec.yaml
index 712ad4a..b6e13fb 100644
--- a/pkg/shelf/pubspec.yaml
+++ b/pkg/shelf/pubspec.yaml
@@ -1,5 +1,5 @@
 name: shelf
-version: 0.5.4
+version: 0.5.4+1
 author: Dart Team <misc@dartlang.org>
 description: Web Server Middleware for Dart
 homepage: http://www.dartlang.org
@@ -10,7 +10,7 @@
   collection: '>=0.9.1 <0.10.0'
   http_parser: '>=0.0.0 <0.1.0'
   path: '>=1.0.0 <2.0.0'
-  stack_trace: '>=0.9.2 <0.10.0'
+  stack_trace: '>=0.9.2 <2.0.0'
 dev_dependencies:
   http: '>=0.9.2 <0.12.0'
   scheduled_test: '>=0.10.0 <0.12.0'
diff --git a/pkg/smoke/CHANGELOG.md b/pkg/smoke/CHANGELOG.md
index 3ceed16..287fcc2 100644
--- a/pkg/smoke/CHANGELOG.md
+++ b/pkg/smoke/CHANGELOG.md
@@ -2,5 +2,8 @@
 
 This file contains highlights of what changes on each version of this package.
 
-#### Pub version 0.1.0-dev
-  * First version of this package. Initial API and mirror based implementation.
+#### Pub version 0.1.0
+  * Initial release: introduces the smoke API, a mirror based implementation, a
+    statically configured implementation that can be declared by hand or be
+    generated by tools, and libraries that help generate the static
+    configurations.
diff --git a/pkg/smoke/README.md b/pkg/smoke/README.md
index 1889574..685e1c5 100644
--- a/pkg/smoke/README.md
+++ b/pkg/smoke/README.md
@@ -31,7 +31,10 @@
 Code Generation
 ===============
 
-TBD. We envision we'll have a base transformer class that can be tailored to
-create a transformer for your framework.
+Use `package:smoke/codegen/generator.dart` and
+`package:smoke/codegen/recorder.dart` in your transformer to create a static
+initialization that can be used by smoke. The test under
+`test/codegen/end_to_end_test.dart` is a good illustrating example to learn how
+to use these APIs.
 
 [MirrorsUsed]: https://api.dartlang.org/apidocs/channels/stable/#dart-mirrors.MirrorsUsed
diff --git a/pkg/smoke/pubspec.yaml b/pkg/smoke/pubspec.yaml
index be94b9e..6dfe5b5 100644
--- a/pkg/smoke/pubspec.yaml
+++ b/pkg/smoke/pubspec.yaml
@@ -1,5 +1,5 @@
 name: smoke
-version: 0.1.0-pre.6.dev
+version: 0.1.0
 author: Polymer.dart Authors <web-ui-dev@dartlang.org>
 homepage: "https://api.dartlang.org/apidocs/channels/be/#smoke"
 description: >
diff --git a/pkg/stack_trace/CHANGELOG.md b/pkg/stack_trace/CHANGELOG.md
index 36c7d3c..0b3553f 100644
--- a/pkg/stack_trace/CHANGELOG.md
+++ b/pkg/stack_trace/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.0
+
+* No API changes, just declared stable.
+
 ## 0.9.3+2
 
 * Update the dependency on path.
diff --git a/pkg/stack_trace/pubspec.yaml b/pkg/stack_trace/pubspec.yaml
index e75d338..ddad7f9 100644
--- a/pkg/stack_trace/pubspec.yaml
+++ b/pkg/stack_trace/pubspec.yaml
@@ -1,5 +1,5 @@
 name: stack_trace
-version: 0.9.3+2
+version: 1.0.0
 author: "Dart Team <misc@dartlang.org>"
 homepage: http://www.dartlang.org
 description: >
diff --git a/pkg/template_binding/CHANGELOG.md b/pkg/template_binding/CHANGELOG.md
index a8f1aa9..0f299d7 100644
--- a/pkg/template_binding/CHANGELOG.md
+++ b/pkg/template_binding/CHANGELOG.md
@@ -3,13 +3,11 @@
 This file contains highlights of what changes on each version of the
 template_binding package.
 
-#### Pub version 0.10.0-pre.1.dev
+#### Pub version 0.10.0
   * Applied patch to throw errors asycnhronously if property path evaluation
     fails.
   * Applied patch matching commit [51df59][] (fix parser to avoid allocating
     PropertyPath if there is a non-null delegateFn).
-
-#### Pub version 0.10.0-pre.0
   * Ported JS code as of commit [fcb7a5][] 
 
 [fcb7a5]: https://github.com/Polymer/TemplateBinding/commit/fcb7a502794f19544f2d4b77c96eebb70830591d
diff --git a/pkg/template_binding/pubspec.yaml b/pkg/template_binding/pubspec.yaml
index b23462f..e12fb39 100644
--- a/pkg/template_binding/pubspec.yaml
+++ b/pkg/template_binding/pubspec.yaml
@@ -1,13 +1,12 @@
 name: template_binding
-version: 0.10.0-pre.1
+version: 0.10.0
 author: Polymer.dart Team <web-ui-dev@dartlang.org>
 description: >
   Extends the capabilities of the HTML Template Element by enabling it to
   create, manage, and remove instances of content bound to data defined in Dart.
 homepage: https://www.dartlang.org/polymer-dart/
 dependencies:
-  logging: ">=0.9.0 <0.10.0"
-  observe: ">=0.10.0-pre.3 <0.11.0"
+  observe: ">=0.10.0 <0.11.0"
 dev_dependencies:
   web_components: ">=0.3.1 <0.4.0"
   unittest: ">=0.10.0 <0.11.0"
diff --git a/pkg/typed_mock/lib/typed_mock.dart b/pkg/typed_mock/lib/typed_mock.dart
index 3cde9a6..eb9ae73 100644
--- a/pkg/typed_mock/lib/typed_mock.dart
+++ b/pkg/typed_mock/lib/typed_mock.dart
@@ -115,7 +115,7 @@
       if (argument is ArgumentMatcher) {
         matcher = argument;
       } else {
-        matcher = equals(argument);
+        matcher = new _ArgumentMatcher_equals(argument);
       }
       _matchers.add(matcher);
     });
@@ -380,11 +380,6 @@
   }
 }
 
-/// Matches an argument that is equal to the given [expected] value.
-equals(expected) {
-  return new _ArgumentMatcher_equals(expected);
-}
-
 
 class _ArgumentMatcher_anyBool extends ArgumentMatcher {
   @override
@@ -394,7 +389,7 @@
 }
 
 /// Matches any [bool] value.
-final anyBool = new _ArgumentMatcher_anyBool();
+final anyBool = new _ArgumentMatcher_anyBool() as dynamic;
 
 
 class _ArgumentMatcher_anyInt extends ArgumentMatcher {
@@ -405,7 +400,7 @@
 }
 
 /// Matches any [int] value.
-final anyInt = new _ArgumentMatcher_anyInt();
+final anyInt = new _ArgumentMatcher_anyInt() as dynamic;
 
 
 class _ArgumentMatcher_anyObject extends ArgumentMatcher {
@@ -416,7 +411,7 @@
 }
 
 /// Matches any [Object] (or subclass) value.
-final anyObject = new _ArgumentMatcher_anyObject();
+final anyObject = new _ArgumentMatcher_anyObject() as dynamic;
 
 
 class _ArgumentMatcher_anyString extends ArgumentMatcher {
@@ -427,4 +422,4 @@
 }
 
 /// Matches any [String] value.
-final anyString = new _ArgumentMatcher_anyString();
+final anyString = new _ArgumentMatcher_anyString() as dynamic;
diff --git a/pkg/typed_mock/pubspec.yaml b/pkg/typed_mock/pubspec.yaml
index c2e2cdc..209860c 100644
--- a/pkg/typed_mock/pubspec.yaml
+++ b/pkg/typed_mock/pubspec.yaml
@@ -1,5 +1,5 @@
 name: typed_mock
-version: 0.0.1
+version: 0.0.2
 author: Dart Team <misc@dartlang.org>
 description: A library for mocking classes using Mockito-like syntax
 homepage: http://www.dartlang.org
diff --git a/pkg/typed_mock/test/typed_mock_test.dart b/pkg/typed_mock/test/typed_mock_test.dart
index 76add8e..c2dc907 100644
--- a/pkg/typed_mock/test/typed_mock_test.dart
+++ b/pkg/typed_mock/test/typed_mock_test.dart
@@ -2,8 +2,7 @@
 
 import 'package:unittest/unittest.dart';
 
-import 'package:typed_mock/typed_mock.dart' hide equals;
-import 'package:typed_mock/typed_mock.dart' as typed_mocks show equals;
+import 'package:typed_mock/typed_mock.dart';
 
 
 abstract class TestInterface {
@@ -36,13 +35,6 @@
   });
 
   group('Matchers', () {
-    test('equals', () {
-      expect(typed_mocks.equals(10).matches(10), true);
-      expect(typed_mocks.equals(10).matches(20), false);
-      expect(typed_mocks.equals('abc').matches('abc'), true);
-      expect(typed_mocks.equals('abc').matches('xyz'), false);
-    });
-
     test('anyBool', () {
       expect(anyBool.matches(true), true);
       expect(anyBool.matches(false), true);
diff --git a/pkg/unittest/CHANGELOG.md b/pkg/unittest/CHANGELOG.md
index bc09b95..b9c36f2 100644
--- a/pkg/unittest/CHANGELOG.md
+++ b/pkg/unittest/CHANGELOG.md
@@ -1,3 +1,7 @@
+##0.11.1+1
+
+* Widen the version constraint for `stack_trace`.
+
 ##0.11.0
 
 * Deprecated methods have been removed:
diff --git a/pkg/unittest/pubspec.yaml b/pkg/unittest/pubspec.yaml
index b7fa187..fc05836 100644
--- a/pkg/unittest/pubspec.yaml
+++ b/pkg/unittest/pubspec.yaml
@@ -1,5 +1,5 @@
 name: unittest
-version: 0.11.0
+version: 0.11.0+1
 author: Dart Team <misc@dartlang.org>
 description: A library for writing dart unit tests.
 homepage: http://www.dartlang.org
@@ -8,4 +8,4 @@
 documentation: http://api.dartlang.org/docs/pkg/unittest
 dependencies:
   matcher: '>=0.10.0 <0.11.0'
-  stack_trace: '>=0.9.0 <0.10.0'
+  stack_trace: '>=0.9.0 <2.0.0'
diff --git a/pkg/watcher/pubspec.yaml b/pkg/watcher/pubspec.yaml
index 1045bc5..51ba562 100644
--- a/pkg/watcher/pubspec.yaml
+++ b/pkg/watcher/pubspec.yaml
@@ -7,7 +7,7 @@
   notifies you when files have been added, removed, or modified.
 dependencies:
   path: ">=0.9.0 <2.0.0"
-  stack_trace: ">=0.9.1 <0.10.0"
+  stack_trace: ">=0.9.1 <2.0.0"
 dev_dependencies:
   scheduled_test: ">=0.9.3-dev <0.11.0"
   unittest: ">=0.9.2 <0.10.0"
diff --git a/pkg/yaml/CHANGELOG.md b/pkg/yaml/CHANGELOG.md
index 7d1fafd..261a666 100644
--- a/pkg/yaml/CHANGELOG.md
+++ b/pkg/yaml/CHANGELOG.md
@@ -1,3 +1,26 @@
+## 1.0.0+1
+
+* Fix a variable name typo.
+
+## 1.0.0
+
+* **Backwards incompatibility**: The data structures returned by `loadYaml` and
+  `loadYamlStream` are now immutable.
+
+* **Backwards incompatibility**: The interface of the `YamlMap` class has
+  changed substantially in numerous ways. External users may no longer construct
+  their own instances.
+
+* Maps and lists returned by `loadYaml` and `loadYamlStream` now contain
+  information about their source locations.
+
+* A new `loadYamlNode` function returns the source location of top-level scalars
+  as well.
+
+## 0.10.0
+
+* Improve error messages when a file fails to parse.
+
 ## 0.9.0+2
 
 * Ensure that maps are order-independent when used as map keys.
diff --git a/pkg/yaml/lib/src/composer.dart b/pkg/yaml/lib/src/composer.dart
index 3178096..1a23bc6 100644
--- a/pkg/yaml/lib/src/composer.dart
+++ b/pkg/yaml/lib/src/composer.dart
@@ -45,13 +45,13 @@
   /// Currently this only supports the YAML core type schema.
   Node visitScalar(ScalarNode scalar) {
     if (scalar.tag.name == "!") {
-      return setAnchor(scalar, parseString(scalar.content));
+      return setAnchor(scalar, parseString(scalar));
     } else if (scalar.tag.name == "?") {
       for (var fn in [parseNull, parseBool, parseInt, parseFloat]) {
-        var result = fn(scalar.content);
+        var result = fn(scalar);
         if (result != null) return result;
       }
-      return setAnchor(scalar, parseString(scalar.content));
+      return setAnchor(scalar, parseString(scalar));
     }
 
     var result = _parseByTag(scalar);
@@ -62,11 +62,11 @@
 
   ScalarNode _parseByTag(ScalarNode scalar) {
     switch (scalar.tag.name) {
-      case "null": return parseNull(scalar.content);
-      case "bool": return parseBool(scalar.content);
-      case "int": return parseInt(scalar.content);
-      case "float": return parseFloat(scalar.content);
-      case "str": return parseString(scalar.content);
+      case "null": return parseNull(scalar);
+      case "bool": return parseBool(scalar);
+      case "int": return parseInt(scalar);
+      case "float": return parseFloat(scalar);
+      case "str": return parseString(scalar);
     }
     throw new YamlException('Undefined tag: ${scalar.tag}.');
   }
@@ -78,7 +78,8 @@
       throw new YamlException("Invalid tag for sequence: ${seq.tag}.");
     }
 
-    var result = setAnchor(seq, new SequenceNode(Tag.yaml('seq'), null));
+    var result = setAnchor(seq,
+        new SequenceNode(Tag.yaml('seq'), null, seq.span));
     result.content = super.visitSequence(seq);
     return result;
   }
@@ -90,7 +91,8 @@
       throw new YamlException("Invalid tag for mapping: ${map.tag}.");
     }
 
-    var result = setAnchor(map, new MappingNode(Tag.yaml('map'), null));
+    var result = setAnchor(map,
+        new MappingNode(Tag.yaml('map'), null, map.span));
     result.content = super.visitMapping(map);
     return result;
   }
@@ -105,36 +107,40 @@
   }
 
   /// Parses a null scalar.
-  ScalarNode parseNull(String content) {
-    if (!new RegExp(r"^(null|Null|NULL|~|)$").hasMatch(content)) return null;
-    return new ScalarNode(Tag.yaml("null"), value: null);
+  ScalarNode parseNull(ScalarNode scalar) {
+    if (new RegExp(r"^(null|Null|NULL|~|)$").hasMatch(scalar.content)) {
+      return new ScalarNode(Tag.yaml("null"), scalar.span, value: null);
+    } else {
+      return null;
+    }
   }
 
   /// Parses a boolean scalar.
-  ScalarNode parseBool(String content) {
+  ScalarNode parseBool(ScalarNode scalar) {
     var match = new RegExp(r"^(?:(true|True|TRUE)|(false|False|FALSE))$").
-      firstMatch(content);
+        firstMatch(scalar.content);
     if (match == null) return null;
-    return new ScalarNode(Tag.yaml("bool"), value: match.group(1) != null);
+    return new ScalarNode(Tag.yaml("bool"), scalar.span,
+        value: match.group(1) != null);
   }
 
   /// Parses an integer scalar.
-  ScalarNode parseInt(String content) {
-    var match = new RegExp(r"^[-+]?[0-9]+$").firstMatch(content);
+  ScalarNode parseInt(ScalarNode scalar) {
+    var match = new RegExp(r"^[-+]?[0-9]+$").firstMatch(scalar.content);
     if (match != null) {
-      return new ScalarNode(Tag.yaml("int"),
+      return new ScalarNode(Tag.yaml("int"), scalar.span,
           value: int.parse(match.group(0)));
     }
 
-    match = new RegExp(r"^0o([0-7]+)$").firstMatch(content);
+    match = new RegExp(r"^0o([0-7]+)$").firstMatch(scalar.content);
     if (match != null) {
       int n = int.parse(match.group(1), radix: 8);
-      return new ScalarNode(Tag.yaml("int"), value: n);
+      return new ScalarNode(Tag.yaml("int"), scalar.span, value: n);
     }
 
-    match = new RegExp(r"^0x[0-9a-fA-F]+$").firstMatch(content);
+    match = new RegExp(r"^0x[0-9a-fA-F]+$").firstMatch(scalar.content);
     if (match != null) {
-      return new ScalarNode(Tag.yaml("int"),
+      return new ScalarNode(Tag.yaml("int"), scalar.span,
           value: int.parse(match.group(0)));
     }
 
@@ -142,33 +148,33 @@
   }
 
   /// Parses a floating-point scalar.
-  ScalarNode parseFloat(String content) {
+  ScalarNode parseFloat(ScalarNode scalar) {
     var match = new RegExp(
-        r"^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$").
-      firstMatch(content);
+          r"^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$").
+        firstMatch(scalar.content);
     if (match != null) {
       // YAML allows floats of the form "0.", but Dart does not. Fix up those
       // floats by removing the trailing dot.
       var matchStr = match.group(0).replaceAll(new RegExp(r"\.$"), "");
-      return new ScalarNode(Tag.yaml("float"),
+      return new ScalarNode(Tag.yaml("float"), scalar.span,
           value: double.parse(matchStr));
     }
 
-    match = new RegExp(r"^([+-]?)\.(inf|Inf|INF)$").firstMatch(content);
+    match = new RegExp(r"^([+-]?)\.(inf|Inf|INF)$").firstMatch(scalar.content);
     if (match != null) {
       var value = match.group(1) == "-" ? -double.INFINITY : double.INFINITY;
-      return new ScalarNode(Tag.yaml("float"), value: value);
+      return new ScalarNode(Tag.yaml("float"), scalar.span, value: value);
     }
 
-    match = new RegExp(r"^\.(nan|NaN|NAN)$").firstMatch(content);
+    match = new RegExp(r"^\.(nan|NaN|NAN)$").firstMatch(scalar.content);
     if (match != null) {
-      return new ScalarNode(Tag.yaml("float"), value: double.NAN);
+      return new ScalarNode(Tag.yaml("float"), scalar.span, value: double.NAN);
     }
 
     return null;
   }
 
   /// Parses a string scalar.
-  ScalarNode parseString(String content) =>
-    new ScalarNode(Tag.yaml("str"), value: content);
+  ScalarNode parseString(ScalarNode scalar) =>
+    new ScalarNode(Tag.yaml("str"), scalar.span, value: scalar.content);
 }
diff --git a/pkg/yaml/lib/src/constructor.dart b/pkg/yaml/lib/src/constructor.dart
index 116809d..5cf23c7 100644
--- a/pkg/yaml/lib/src/constructor.dart
+++ b/pkg/yaml/lib/src/constructor.dart
@@ -4,9 +4,10 @@
 
 library yaml.constructor;
 
+import 'equality.dart';
 import 'model.dart';
 import 'visitor.dart';
-import 'yaml_map.dart';
+import 'yaml_node.dart';
 
 /// Takes a parsed and composed YAML document (what the spec calls the
 /// "representation graph") and creates native Dart objects that represent that
@@ -16,43 +17,54 @@
   final Node _root;
 
   /// Map from anchor names to the most recent Dart node with that anchor.
-  final _anchors = <String, dynamic>{};
+  final _anchors = <String, YamlNode>{};
 
   Constructor(this._root);
 
   /// Runs the Constructor to produce a Dart object.
-  construct() => _root.visit(this);
+  YamlNode construct() => _root.visit(this);
 
   /// Returns the value of a scalar.
-  visitScalar(ScalarNode scalar) => scalar.value;
+  YamlScalar visitScalar(ScalarNode scalar) =>
+      new YamlScalar(scalar.value, scalar.span);
 
   /// Converts a sequence into a List of Dart objects.
-  visitSequence(SequenceNode seq) {
+  YamlList visitSequence(SequenceNode seq) {
     var anchor = getAnchor(seq);
     if (anchor != null) return anchor;
-    var dartSeq = setAnchor(seq, []);
-    dartSeq.addAll(super.visitSequence(seq));
+    var nodes = [];
+    var dartSeq = setAnchor(seq, new YamlList(nodes, seq.span));
+    nodes.addAll(super.visitSequence(seq));
     return dartSeq;
   }
 
-  /// Converts a mapping into a Map of Dart objects.
-  visitMapping(MappingNode map) {
+  /// Converts a mapping into a [Map] of Dart objects.
+  YamlMap visitMapping(MappingNode map) {
     var anchor = getAnchor(map);
     if (anchor != null) return anchor;
-    var dartMap = setAnchor(map, new YamlMap());
-    super.visitMapping(map).forEach((k, v) { dartMap[k] = v; });
+    var nodes = deepEqualsMap();
+    var dartMap = setAnchor(map, new YamlMap(nodes, map.span));
+    super.visitMapping(map).forEach((k, v) => nodes[k] = v);
     return dartMap;
   }
 
-  /// Returns the Dart object that already represents [anchored], if such a
-  /// thing exists.
-  getAnchor(Node anchored) {
+  /// Returns a new Dart object wrapping the object that already represents
+  /// [anchored], if such a thing exists.
+  YamlNode getAnchor(Node anchored) {
     if (anchored.anchor == null) return null;
-    if (_anchors.containsKey(anchored.anchor)) return _anchors[anchored.anchor];
+    var value = _anchors[anchored.anchor];
+    if (value == null) return null;
+
+    // Re-wrap [value]'s contents so that it's associated with the span of the
+    // anchor rather than its original definition.
+    if (value is YamlMap) return new YamlMap(value.nodes, anchored.span);
+    if (value is YamlList) return new YamlList(value.nodes, anchored.span);
+    assert(value is YamlScalar);
+    return new YamlScalar(value.value, anchored.span);
   }
 
   /// Records that [value] is the Dart object representing [anchored].
-  setAnchor(Node anchored, value) {
+  YamlNode setAnchor(Node anchored, YamlNode value) {
     if (anchored.anchor == null) return value;
     _anchors[anchored.anchor] = value;
     return value;
diff --git a/pkg/yaml/lib/src/deep_equals.dart b/pkg/yaml/lib/src/deep_equals.dart
deleted file mode 100644
index 68fb236..0000000
--- a/pkg/yaml/lib/src/deep_equals.dart
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library yaml.deep_equals;
-
-/// Returns whether two objects are structurally equivalent.
-///
-/// This considers `NaN` values to be equivalent. It also handles
-/// self-referential structures.
-bool deepEquals(obj1, obj2) => new _DeepEquals().equals(obj1, obj2);
-
-/// A class that provides access to the list of parent objects used for loop
-/// detection.
-class _DeepEquals {
-  final _parents1 = [];
-  final _parents2 = [];
-
-  /// Returns whether [obj1] and [obj2] are structurally equivalent.
-  bool equals(obj1, obj2) {
-    // _parents1 and _parents2 are guaranteed to be the same size.
-    for (var i = 0; i < _parents1.length; i++) {
-      var loop1 = identical(obj1, _parents1[i]);
-      var loop2 = identical(obj2, _parents2[i]);
-      // If both structures loop in the same place, they're equal at that point
-      // in the structure. If one loops and the other doesn't, they're not
-      // equal.
-      if (loop1 && loop2) return true;
-      if (loop1 || loop2) return false;
-    }
-
-    _parents1.add(obj1);
-    _parents2.add(obj2);
-    try {
-      if (obj1 is List && obj2 is List) {
-        return _listEquals(obj1, obj2);
-      } else if (obj1 is Map && obj2 is Map) {
-        return _mapEquals(obj1, obj2);
-      } else if (obj1 is num && obj2 is num) {
-        return _numEquals(obj1, obj2);
-      } else {
-        return obj1 == obj2;
-      }
-    } finally {
-      _parents1.removeLast();
-      _parents2.removeLast();
-    }
-  }
-
-  /// Returns whether [list1] and [list2] are structurally equal. 
-  bool _listEquals(List list1, List list2) {
-    if (list1.length != list2.length) return false;
-
-    for (var i = 0; i < list1.length; i++) {
-      if (!equals(list1[i], list2[i])) return false;
-    }
-
-    return true;
-  }
-
-  /// Returns whether [map1] and [map2] are structurally equal. 
-  bool _mapEquals(Map map1, Map map2) {
-    if (map1.length != map2.length) return false;
-
-    for (var key in map1.keys) {
-      if (!map2.containsKey(key)) return false;
-      if (!equals(map1[key], map2[key])) return false;
-    }
-
-    return true;
-  }
-
-  /// Returns whether two numbers are equivalent.
-  ///
-  /// This differs from `n1 == n2` in that it considers `NaN` to be equal to
-  /// itself.
-  bool _numEquals(num n1, num n2) {
-    if (n1.isNaN && n2.isNaN) return true;
-    return n1 == n2;
-  }
-}
diff --git a/pkg/yaml/lib/src/equality.dart b/pkg/yaml/lib/src/equality.dart
new file mode 100644
index 0000000..5408135
--- /dev/null
+++ b/pkg/yaml/lib/src/equality.dart
@@ -0,0 +1,126 @@
+// 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 yaml.equality;
+
+import 'dart:collection';
+
+import 'package:collection/collection.dart';
+
+import 'yaml_node.dart';
+
+/// Returns a [Map] that compares its keys based on [deepEquals].
+Map deepEqualsMap() => new HashMap(equals: deepEquals, hashCode: deepHashCode);
+
+/// Returns whether two objects are structurally equivalent.
+///
+/// This considers `NaN` values to be equivalent, handles self-referential
+/// structures, and considers [YamlScalar]s to be equal to their values.
+bool deepEquals(obj1, obj2) => new _DeepEquals().equals(obj1, obj2);
+
+/// A class that provides access to the list of parent objects used for loop
+/// detection.
+class _DeepEquals {
+  final _parents1 = [];
+  final _parents2 = [];
+
+  /// Returns whether [obj1] and [obj2] are structurally equivalent.
+  bool equals(obj1, obj2) {
+    if (obj1 is YamlScalar) obj1 = obj1.value;
+    if (obj2 is YamlScalar) obj2 = obj2.value;
+
+    // _parents1 and _parents2 are guaranteed to be the same size.
+    for (var i = 0; i < _parents1.length; i++) {
+      var loop1 = identical(obj1, _parents1[i]);
+      var loop2 = identical(obj2, _parents2[i]);
+      // If both structures loop in the same place, they're equal at that point
+      // in the structure. If one loops and the other doesn't, they're not
+      // equal.
+      if (loop1 && loop2) return true;
+      if (loop1 || loop2) return false;
+    }
+
+    _parents1.add(obj1);
+    _parents2.add(obj2);
+    try {
+      if (obj1 is List && obj2 is List) {
+        return _listEquals(obj1, obj2);
+      } else if (obj1 is Map && obj2 is Map) {
+        return _mapEquals(obj1, obj2);
+      } else if (obj1 is num && obj2 is num) {
+        return _numEquals(obj1, obj2);
+      } else {
+        return obj1 == obj2;
+      }
+    } finally {
+      _parents1.removeLast();
+      _parents2.removeLast();
+    }
+  }
+
+  /// Returns whether [list1] and [list2] are structurally equal. 
+  bool _listEquals(List list1, List list2) {
+    if (list1.length != list2.length) return false;
+
+    for (var i = 0; i < list1.length; i++) {
+      if (!equals(list1[i], list2[i])) return false;
+    }
+
+    return true;
+  }
+
+  /// Returns whether [map1] and [map2] are structurally equal. 
+  bool _mapEquals(Map map1, Map map2) {
+    if (map1.length != map2.length) return false;
+
+    for (var key in map1.keys) {
+      if (!map2.containsKey(key)) return false;
+      if (!equals(map1[key], map2[key])) return false;
+    }
+
+    return true;
+  }
+
+  /// Returns whether two numbers are equivalent.
+  ///
+  /// This differs from `n1 == n2` in that it considers `NaN` to be equal to
+  /// itself.
+  bool _numEquals(num n1, num n2) {
+    if (n1.isNaN && n2.isNaN) return true;
+    return n1 == n2;
+  }
+}
+
+/// Returns a hash code for [obj] such that structurally equivalent objects
+/// will have the same hash code.
+///
+/// This supports deep equality for maps and lists, including those with
+/// self-referential structures, and returns the same hash code for
+/// [YamlScalar]s and their values.
+int deepHashCode(obj) {
+  var parents = [];
+
+  _deepHashCode(value) {
+    if (parents.any((parent) => identical(parent, value))) return -1;
+
+    parents.add(value);
+    try {
+      if (value is Map) {
+        var equality = const UnorderedIterableEquality();
+        return equality.hash(value.keys.map(_deepHashCode)) ^
+            equality.hash(value.values.map(_deepHashCode));
+      } else if (value is Iterable) {
+        return const IterableEquality().hash(value.map(deepHashCode));
+      } else if (value is YamlScalar) {
+        return value.value.hashCode;
+      } else {
+        return value.hashCode;
+      }
+    } finally {
+      parents.removeLast();
+    }
+  }
+
+  return _deepHashCode(obj);
+}
diff --git a/pkg/yaml/lib/src/model.dart b/pkg/yaml/lib/src/model.dart
index 564cac6..f0e839c 100644
--- a/pkg/yaml/lib/src/model.dart
+++ b/pkg/yaml/lib/src/model.dart
@@ -7,8 +7,10 @@
 /// representation graph.
 library yaml.model;
 
+import 'package:source_maps/source_maps.dart';
+
+import 'equality.dart';
 import 'parser.dart';
-import 'utils.dart';
 import 'visitor.dart';
 import 'yaml_exception.dart';
 
@@ -80,14 +82,17 @@
   /// Any YAML node can have an anchor associated with it.
   String anchor;
 
-  Node(this.tag, [this.anchor]);
+  /// The source span for this node.
+  Span span;
+
+  Node(this.tag, this.span, [this.anchor]);
 
   bool operator ==(other) {
     if (other is! Node) return false;
     return tag == other.tag;
   }
 
-  int get hashCode => hashCodeFor([tag, anchor]);
+  int get hashCode => tag.hashCode ^ anchor.hashCode;
 
   visit(Visitor v);
 }
@@ -97,8 +102,8 @@
   /// The nodes in the sequence.
   List<Node> content;
 
-  SequenceNode(String tagName, this.content)
-    : super(new Tag.sequence(tagName));
+  SequenceNode(String tagName, this.content, Span span)
+    : super(new Tag.sequence(tagName), span);
 
   /// Two sequences are equal if their tags and contents are equal.
   bool operator ==(other) {
@@ -113,14 +118,15 @@
 
   String toString() => '$tag [${content.map((e) => '$e').join(', ')}]';
 
-  int get hashCode => super.hashCode ^ hashCodeFor(content);
+  int get hashCode => super.hashCode ^ deepHashCode(content);
 
   visit(Visitor v) => v.visitSequence(this);
 }
 
 /// An alias node is a reference to an anchor.
 class AliasNode extends Node {
-  AliasNode(String anchor) : super(new Tag.scalar(Tag.yaml("str")), anchor);
+  AliasNode(String anchor, Span span)
+      : super(new Tag.scalar(Tag.yaml("str")), span, anchor);
 
   visit(Visitor v) => v.visitAlias(this);
 }
@@ -139,9 +145,9 @@
   /// be specified for a newly-parsed scalar that hasn't yet been composed.
   /// Value should be specified for a composed scalar, although `null` is a
   /// valid value.
-  ScalarNode(String tagName, {String content, this.value})
+  ScalarNode(String tagName, Span span, {String content, this.value})
    : _content = content,
-     super(new Tag.scalar(tagName));
+     super(new Tag.scalar(tagName), span);
 
   /// Two scalars are equal if their string representations are equal.
   bool operator ==(other) {
@@ -225,8 +231,8 @@
   /// The node map.
   Map<Node, Node> content;
 
-  MappingNode(String tagName, this.content)
-    : super(new Tag.mapping(tagName));
+  MappingNode(String tagName, this.content, Span span)
+    : super(new Tag.mapping(tagName), span);
 
   /// Two mappings are equal if their tags and contents are equal.
   bool operator ==(other) {
@@ -247,7 +253,7 @@
     return '$tag {$strContent}';
   }
 
-  int get hashCode => super.hashCode ^ hashCodeFor(content);
+  int get hashCode => super.hashCode ^ deepHashCode(content);
 
   visit(Visitor v) => v.visitMapping(this);
 }
diff --git a/pkg/yaml/lib/src/parser.dart b/pkg/yaml/lib/src/parser.dart
index d1e20ff..b42638f 100644
--- a/pkg/yaml/lib/src/parser.dart
+++ b/pkg/yaml/lib/src/parser.dart
@@ -6,9 +6,12 @@
 
 import 'dart:collection';
 
+import 'package:source_maps/source_maps.dart';
+import 'package:string_scanner/string_scanner.dart';
+
+import 'equality.dart';
 import 'model.dart';
-import 'yaml_exception.dart';
-import 'yaml_map.dart';
+import 'utils.dart';
 
 /// Translates a string of characters into a YAML serialization tree.
 ///
@@ -116,48 +119,28 @@
   static const CHOMPING_KEEP = 1;
   static const CHOMPING_CLIP = 2;
 
-  /// The source string being parsed.
-  final String _s;
-
-  /// The current position in the source string.
-  int _pos = 0;
-
-  /// The length of the string being parsed.
-  final int _len;
-
-  /// The current (0-based) line in the source string.
-  int _line = 0;
-
-  /// The current (0-based) column in the source string.
-  int _column = 0;
+  /// The scanner that's used to scan through the document.
+  final SpanScanner _scanner;
 
   /// Whether we're parsing a bare document (that is, one that doesn't begin
   /// with `---`). Bare documents don't allow `%` immediately following
   /// newlines.
   bool _inBareDocument = false;
 
-  /// The line number of the farthest position that has been parsed successfully
-  /// before backtracking. Used for error reporting.
-  int _farthestLine = 0;
-
-  /// The column number of the farthest position that has been parsed
-  /// successfully before backtracking. Used for error reporting.
-  int _farthestColumn = 0;
-
-  /// The farthest position in the source string that has been parsed
-  /// successfully before backtracking. Used for error reporting.
-  int _farthestPos = 0;
+  /// The state of the scanner when it was the farthest in the document it's
+  /// been.
+  LineScannerState _farthestState;
 
   /// The name of the context of the farthest position that has been parsed
   /// successfully before backtracking. Used for error reporting.
   String _farthestContext = "document";
 
   /// A stack of the names of parse contexts. Used for error reporting.
-  List<String> _contextStack;
+  final _contextStack = <String>["document"];
 
   /// Annotations attached to ranges of the source string that add extra
   /// information to any errors that occur in the annotated range.
-  _RangeMap<String> _errorAnnotations;
+  final _errorAnnotations = new _RangeMap<String>();
 
   /// The buffer containing the string currently being captured.
   StringBuffer _capturedString;
@@ -168,46 +151,18 @@
   /// Whether the current string capture is being overridden.
   bool _capturingAs = false;
 
-  Parser(String s)
-    : this._s = s,
-      _len = s.length,
-      _contextStack = <String>["document"],
-      _errorAnnotations = new _RangeMap();
-
-  /// Return the character at the current position, then move that position
-  /// forward one character. Also updates the current line and column numbers.
-  int next() {
-    if (_pos == _len) return -1;
-    var char = _s.codeUnitAt(_pos++);
-    if (isBreak(char)) {
-      _line++;
-      _column = 0;
-    } else {
-      _column++;
-    }
-
-    if (_farthestLine < _line) {
-      _farthestLine = _line;
-      _farthestColumn = _column;
-      _farthestContext = _contextStack.last;
-    } else if (_farthestLine == _line && _farthestColumn < _column) {
-      _farthestColumn = _column;
-      _farthestContext = _contextStack.last;
-    }
-    _farthestPos = _pos;
-
-    return char;
+  Parser(String yaml, String sourceName)
+      : _scanner = new SpanScanner(yaml, sourceName) {
+    _farthestState = _scanner.state;
   }
 
+  /// Returns the character at the current position, then moves that position
+  /// forward one character.
+  int next() => _scanner.readChar();
+
   /// Returns the code unit at the current position, or the character [i]
   /// characters after the current position.
-  ///
-  /// Returns -1 if this would return a character after the end or before the
-  /// beginning of the input string.
-  int peek([int i = 0]) {
-    var peekPos = _pos + i;
-    return (peekPos >= _len || peekPos < 0) ? -1 : _s.codeUnitAt(peekPos);
-  }
+  int peek([int i = 0]) => _scanner.peekChar(i);
 
   /// The truthiness operator. Returns `false` if [obj] is `null` or `false`,
   /// `true` otherwise.
@@ -249,11 +204,11 @@
   /// Conceptually, repeats a production any number of times.
   List zeroOrMore(consumer()) {
     var out = [];
-    var oldPos = _pos;
+    var oldPos = _scanner.position;
     while (true) {
       var el = consumer();
-      if (!truth(el) || oldPos == _pos) return out;
-      oldPos = _pos;
+      if (!truth(el) || oldPos == _scanner.position) return out;
+      oldPos = _scanner.position;
       out.add(el);
     }
     return null; // Unreachable.
@@ -276,18 +231,15 @@
   /// Calls [consumer] and returns its result, but rolls back the parser state
   /// if [consumer] returns a falsey value.
   transaction(consumer()) {
-    var oldPos = _pos;
-    var oldLine = _line;
-    var oldColumn = _column;
+    var oldState = _scanner.state;
     var oldCaptureStart = _captureStart;
     String capturedSoFar = _capturedString == null ? null :
       _capturedString.toString();
     var res = consumer();
+    _refreshFarthestState();
     if (truth(res)) return res;
 
-    _pos = oldPos;
-    _line = oldLine;
-    _column = oldColumn;
+    _scanner.state = oldState;
     _captureStart = oldCaptureStart;
     _capturedString = capturedSoFar == null ? null :
       new StringBuffer(capturedSoFar);
@@ -324,7 +276,7 @@
     // captureString calls may not be nested
     assert(_capturedString == null);
 
-    _captureStart = _pos;
+    _captureStart = _scanner.position;
     _capturedString = new StringBuffer();
     var res = transaction(consumer);
     if (!truth(res)) {
@@ -353,18 +305,20 @@
     _capturingAs = false;
     if (!truth(res)) return res;
 
-    _capturedString.write(transformation(_s.substring(_captureStart, _pos)));
-    _captureStart = _pos;
+    _capturedString.write(transformation(
+        _scanner.string.substring(_captureStart, _scanner.position)));
+    _captureStart = _scanner.position;
     return res;
   }
 
   void flushCapture() {
-    _capturedString.write(_s.substring(_captureStart, _pos));
-    _captureStart = _pos;
+    _capturedString.write(_scanner.string.substring(
+        _captureStart, _scanner.position));
+    _captureStart = _scanner.position;
   }
 
   /// Adds a tag and an anchor to [node], if they're defined.
-  Node addProps(Node node, _Pair<Tag, String> props) {
+  Node addProps(Node node, Pair<Tag, String> props) {
     if (props == null || node == null) return node;
     if (truth(props.first)) node.tag = props.first;
     if (truth(props.last)) node.anchor = props.last;
@@ -372,10 +326,10 @@
   }
 
   /// Creates a MappingNode from [pairs].
-  MappingNode map(List<_Pair<Node, Node>> pairs) {
+  MappingNode map(List<Pair<Node, Node>> pairs, Span span) {
     var content = new Map<Node, Node>();
     pairs.forEach((pair) => content[pair.first] = pair.last);
-    return new MappingNode("?", content);
+    return new MappingNode("?", content, span);
   }
 
   /// Runs [fn] in a context named [name]. Used for error reporting.
@@ -393,22 +347,19 @@
   /// current position and the position of the cursor after running [fn]. The
   /// cursor is reset after [fn] is run.
   annotateError(String message, fn()) {
-    var start = _pos;
+    var start = _scanner.position;
     var end;
     transaction(() {
       fn();
-      end = _pos;
+      end = _scanner.position;
       return false;
     });
     _errorAnnotations[new _Range(start, end)] = message;
   }
 
   /// Throws an error with additional context information.
-  error(String message) {
-    // Line and column should be one-based.
-    throw new SyntaxError(_line + 1, _column + 1,
-        "$message (in $_farthestContext).");
-  }
+  void error(String message) =>
+      _scanner.error("$message (in $_farthestContext).");
 
   /// If [result] is falsey, throws an error saying that [expected] was
   /// expected.
@@ -417,14 +368,24 @@
     error("Expected $expected");
   }
 
-  /// Throws an error saying that the parse failed. Uses [_farthestLine],
-  /// [_farthestColumn], and [_farthestContext] to provide additional
+  /// Throws an error saying that the parse failed.
+  ///
+  /// Uses [_farthestState] and [_farthestContext] to provide additional
   /// information.
   parseFailed() {
     var message = "Invalid YAML in $_farthestContext";
-    var extraError = _errorAnnotations[_farthestPos];
+    _refreshFarthestState();
+    _scanner.state = _farthestState;
+
+    var extraError = _errorAnnotations[_scanner.position];
     if (extraError != null) message = "$message ($extraError)";
-    throw new SyntaxError(_farthestLine + 1, _farthestColumn + 1, "$message.");
+    _scanner.error("$message.");
+  }
+
+  /// Update [_farthestState] if the scanner is farther than it's been before.
+  void _refreshFarthestState() {
+    if (_scanner.position <= _farthestState.position) return;
+    _farthestState = _scanner.state;
   }
 
   /// Returns the number of spaces after the current position.
@@ -439,15 +400,11 @@
     if (!header.autoDetectIndent) return header.additionalIndent;
 
     var maxSpaces = 0;
-    var maxSpacesLine = 0;
     var spaces = 0;
     transaction(() {
       do {
         spaces = captureString(() => zeroOrMore(() => consumeChar(SP))).length;
-        if (spaces > maxSpaces) {
-          maxSpaces = spaces;
-          maxSpacesLine = _line;
-        }
+        if (spaces > maxSpaces) maxSpaces = spaces;
       } while (b_break());
       return false;
     });
@@ -460,19 +417,15 @@
     // It's an error for a leading empty line to be indented more than the first
     // non-empty line.
     if (maxSpaces > spaces) {
-      throw new SyntaxError(maxSpacesLine + 1, maxSpaces,
-          "Leading empty lines may not be indented more than the first "
-          "non-empty line.");
+      _scanner.error("Leading empty lines may not be indented more than the "
+          "first non-empty line.");
     }
 
     return spaces - indent;
   }
 
   /// Returns whether the current position is at the beginning of a line.
-  bool get atStartOfLine => _column == 0;
-
-  /// Returns whether the current position is at the end of the input.
-  bool get atEndOfFile => _pos == _len;
+  bool get atStartOfLine => _scanner.column == 0;
 
   /// Given an indicator character, returns the type of that indicator (or null
   /// if the indicator isn't found.
@@ -504,6 +457,7 @@
 
   // 1
   bool isPrintable(int char) {
+    if (char == null) return false;
     return char == TAB ||
       char == LF ||
       char == CR ||
@@ -515,7 +469,8 @@
   }
 
   // 2
-  bool isJson(int char) => char == TAB || (char >= SP && char <= 0x10FFFF);
+  bool isJson(int char) => char != null &&
+      (char == TAB || (char >= SP && char <= 0x10FFFF));
 
   // 22
   bool c_indicator(int type) => consume((c) => indicatorType(c) == type);
@@ -558,10 +513,12 @@
   bool isNonSpace(int char) => isNonBreak(char) && !isSpace(char);
 
   // 35
-  bool isDecDigit(int char) => char >= NUMBER_0 && char <= NUMBER_9;
+  bool isDecDigit(int char) => char != null && char >= NUMBER_0 &&
+      char <= NUMBER_9;
 
   // 36
   bool isHexDigit(int char) {
+    if (char == null) return false;
     return isDecDigit(char) ||
       (char >= LETTER_A && char <= LETTER_F) ||
       (char >= LETTER_CAP_A && char <= LETTER_CAP_F);
@@ -754,7 +711,7 @@
   }
 
   // 76
-  bool b_comment() => atEndOfFile || b_nonContent();
+  bool b_comment() => _scanner.isDone || b_nonContent();
 
   // 77
   bool s_b_comment() {
@@ -803,7 +760,7 @@
   bool l_directive() => false; // TODO(nweiz): implement
 
   // 96
-  _Pair<Tag, String> c_ns_properties(int indent, int ctx) {
+  Pair<Tag, String> c_ns_properties(int indent, int ctx) {
     var tag, anchor;
     tag = c_ns_tagProperty();
     if (truth(tag)) {
@@ -811,7 +768,7 @@
         if (!truth(s_separate(indent, ctx))) return null;
         return c_ns_anchorProperty();
       });
-      return new _Pair<Tag, String>(tag, anchor);
+      return new Pair<Tag, String>(tag, anchor);
     }
 
     anchor = c_ns_anchorProperty();
@@ -820,7 +777,7 @@
         if (!truth(s_separate(indent, ctx))) return null;
         return c_ns_tagProperty();
       });
-      return new _Pair<Tag, String>(tag, anchor);
+      return new Pair<Tag, String>(tag, anchor);
     }
 
     return null;
@@ -841,13 +798,14 @@
 
   // 104
   Node c_ns_aliasNode() {
+    var start = _scanner.state;
     if (!truth(c_indicator(C_ALIAS))) return null;
     var name = expect(ns_anchorName(), 'anchor name');
-    return new AliasNode(name);
+    return new AliasNode(name, _scanner.spanFrom(start));
   }
 
   // 105
-  ScalarNode e_scalar() => new ScalarNode("?", content: "");
+  ScalarNode e_scalar() => new ScalarNode("?", _scanner.emptySpan, content: "");
 
   // 106
   ScalarNode e_node() => e_scalar();
@@ -864,10 +822,11 @@
   // 109
   Node c_doubleQuoted(int indent, int ctx) => context('string', () {
     return transaction(() {
+      var start = _scanner.state;
       if (!truth(c_indicator(C_DOUBLE_QUOTE))) return null;
       var contents = nb_doubleText(indent, ctx);
       if (!truth(c_indicator(C_DOUBLE_QUOTE))) return null;
-      return new ScalarNode("!", content: contents);
+      return new ScalarNode("!", _scanner.spanFrom(start), content: contents);
     });
   });
 
@@ -952,10 +911,11 @@
   // 120
   Node c_singleQuoted(int indent, int ctx) => context('string', () {
     return transaction(() {
+      var start = _scanner.state;
       if (!truth(c_indicator(C_SINGLE_QUOTE))) return null;
       var contents = nb_singleText(indent, ctx);
       if (!truth(c_indicator(C_SINGLE_QUOTE))) return null;
-      return new ScalarNode("!", content: contents);
+      return new ScalarNode("!", _scanner.spanFrom(start), content: contents);
     });
   });
 
@@ -1119,11 +1079,13 @@
 
   // 137
   SequenceNode c_flowSequence(int indent, int ctx) => transaction(() {
+    var start = _scanner.state;
     if (!truth(c_indicator(C_SEQUENCE_START))) return null;
     zeroOrOne(() => s_separate(indent, ctx));
     var content = zeroOrOne(() => ns_s_flowSeqEntries(indent, inFlow(ctx)));
     if (!truth(c_indicator(C_SEQUENCE_END))) return null;
-    return new SequenceNode("?", new List<Node>.from(content));
+    return new SequenceNode("?", new List<Node>.from(content),
+        _scanner.spanFrom(start));
   });
 
   // 138
@@ -1152,17 +1114,18 @@
 
   // 140
   Node c_flowMapping(int indent, int ctx) {
+    var start = _scanner.state;
     if (!truth(c_indicator(C_MAPPING_START))) return null;
     zeroOrOne(() => s_separate(indent, ctx));
     var content = zeroOrOne(() => ns_s_flowMapEntries(indent, inFlow(ctx)));
     if (!truth(c_indicator(C_MAPPING_END))) return null;
-    return new MappingNode("?", content);
+    return new MappingNode("?", content, _scanner.spanFrom(start));
   }
 
   // 141
-  YamlMap ns_s_flowMapEntries(int indent, int ctx) {
+  Map ns_s_flowMapEntries(int indent, int ctx) {
     var first = ns_flowMapEntry(indent, ctx);
-    if (!truth(first)) return new YamlMap();
+    if (!truth(first)) return deepEqualsMap();
     zeroOrOne(() => s_separate(indent, ctx));
 
     var rest;
@@ -1171,7 +1134,7 @@
       rest = ns_s_flowMapEntries(indent, ctx);
     }
 
-    if (rest == null) rest = new YamlMap();
+    if (rest == null) rest = deepEqualsMap();
 
     // TODO(nweiz): Duplicate keys should be an error. This includes keys with
     // different representations but the same value (e.g. 10 vs 0xa). To make
@@ -1183,7 +1146,7 @@
   }
 
   // 142
-  _Pair<Node, Node> ns_flowMapEntry(int indent, int ctx) => or([
+  Pair<Node, Node> ns_flowMapEntry(int indent, int ctx) => or([
     () => transaction(() {
       if (!truth(c_indicator(C_MAPPING_KEY))) return false;
       if (!truth(s_separate(indent, ctx))) return false;
@@ -1193,20 +1156,20 @@
   ]);
 
   // 143
-  _Pair<Node, Node> ns_flowMapExplicitEntry(int indent, int ctx) => or([
+  Pair<Node, Node> ns_flowMapExplicitEntry(int indent, int ctx) => or([
     () => ns_flowMapImplicitEntry(indent, ctx),
-    () => new _Pair<Node, Node>(e_node(), e_node())
+    () => new Pair<Node, Node>(e_node(), e_node())
   ]);
 
   // 144
-  _Pair<Node, Node> ns_flowMapImplicitEntry(int indent, int ctx) => or([
+  Pair<Node, Node> ns_flowMapImplicitEntry(int indent, int ctx) => or([
     () => ns_flowMapYamlKeyEntry(indent, ctx),
     () => c_ns_flowMapEmptyKeyEntry(indent, ctx),
     () => c_ns_flowMapJsonKeyEntry(indent, ctx)
   ]);
 
   // 145
-  _Pair<Node, Node> ns_flowMapYamlKeyEntry(int indent, int ctx) {
+  Pair<Node, Node> ns_flowMapYamlKeyEntry(int indent, int ctx) {
     var key = ns_flowYamlNode(indent, ctx);
     if (!truth(key)) return null;
     var value = or([
@@ -1216,14 +1179,14 @@
       }),
       e_node
     ]);
-    return new _Pair<Node, Node>(key, value);
+    return new Pair<Node, Node>(key, value);
   }
 
   // 146
-  _Pair<Node, Node> c_ns_flowMapEmptyKeyEntry(int indent, int ctx) {
+  Pair<Node, Node> c_ns_flowMapEmptyKeyEntry(int indent, int ctx) {
     var value = c_ns_flowMapSeparateValue(indent, ctx);
     if (!truth(value)) return null;
-    return new _Pair<Node, Node>(e_node(), value);
+    return new Pair<Node, Node>(e_node(), value);
   }
 
   // 147
@@ -1241,7 +1204,7 @@
   });
 
   // 148
-  _Pair<Node, Node> c_ns_flowMapJsonKeyEntry(int indent, int ctx) {
+  Pair<Node, Node> c_ns_flowMapJsonKeyEntry(int indent, int ctx) {
     var key = c_flowJsonNode(indent, ctx);
     if (!truth(key)) return null;
     var value = or([
@@ -1251,7 +1214,7 @@
       }),
       e_node
     ]);
-    return new _Pair<Node, Node>(key, value);
+    return new Pair<Node, Node>(key, value);
   }
 
   // 149
@@ -1268,6 +1231,7 @@
 
   // 150
   Node ns_flowPair(int indent, int ctx) {
+    var start = _scanner.state;
     var pair = or([
       () => transaction(() {
         if (!truth(c_indicator(C_MAPPING_KEY))) return null;
@@ -1278,34 +1242,34 @@
     ]);
     if (!truth(pair)) return null;
 
-    return map([pair]);
+    return map([pair], _scanner.spanFrom(start));
   }
 
   // 151
-  _Pair<Node, Node> ns_flowPairEntry(int indent, int ctx) => or([
+  Pair<Node, Node> ns_flowPairEntry(int indent, int ctx) => or([
     () => ns_flowPairYamlKeyEntry(indent, ctx),
     () => c_ns_flowMapEmptyKeyEntry(indent, ctx),
     () => c_ns_flowPairJsonKeyEntry(indent, ctx)
   ]);
 
   // 152
-  _Pair<Node, Node> ns_flowPairYamlKeyEntry(int indent, int ctx) =>
+  Pair<Node, Node> ns_flowPairYamlKeyEntry(int indent, int ctx) =>
     transaction(() {
       var key = ns_s_implicitYamlKey(FLOW_KEY);
       if (!truth(key)) return null;
       var value = c_ns_flowMapSeparateValue(indent, ctx);
       if (!truth(value)) return null;
-      return new _Pair<Node, Node>(key, value);
+      return new Pair<Node, Node>(key, value);
     });
 
   // 153
-  _Pair<Node, Node> c_ns_flowPairJsonKeyEntry(int indent, int ctx) =>
+  Pair<Node, Node> c_ns_flowPairJsonKeyEntry(int indent, int ctx) =>
     transaction(() {
       var key = c_s_implicitJsonKey(FLOW_KEY);
       if (!truth(key)) return null;
       var value = c_ns_flowMapAdjacentValue(indent, ctx);
       if (!truth(value)) return null;
-      return new _Pair<Node, Node>(key, value);
+      return new Pair<Node, Node>(key, value);
     });
 
   // 154
@@ -1332,9 +1296,10 @@
 
   // 156
   Node ns_flowYamlContent(int indent, int ctx) {
+    var start = _scanner.state;
     var str = ns_plain(indent, ctx);
     if (!truth(str)) return null;
-    return new ScalarNode("?", content: str);
+    return new ScalarNode("?", _scanner.spanFrom(start), content: str);
   }
 
   // 157
@@ -1428,7 +1393,7 @@
 
   // 165
   bool b_chompedLast(int chomping) {
-    if (atEndOfFile) return true;
+    if (_scanner.isDone) return true;
     switch (chomping) {
     case CHOMPING_STRIP:
       return b_nonContent();
@@ -1481,6 +1446,7 @@
 
   // 170
   Node c_l_literal(int indent) => transaction(() {
+    var start = _scanner.state;
     if (!truth(c_indicator(C_LITERAL))) return null;
     var header = c_b_blockHeader();
     if (!truth(header)) return null;
@@ -1489,7 +1455,7 @@
     var content = l_literalContent(indent + additionalIndent, header.chomping);
     if (!truth(content)) return null;
 
-    return new ScalarNode("!", content: content);
+    return new ScalarNode("!", _scanner.spanFrom(start), content: content);
   });
 
   // 171
@@ -1518,6 +1484,7 @@
 
   // 174
   Node c_l_folded(int indent) => transaction(() {
+    var start = _scanner.state;
     if (!truth(c_indicator(C_FOLDED))) return null;
     var header = c_b_blockHeader();
     if (!truth(header)) return null;
@@ -1526,7 +1493,7 @@
     var content = l_foldedContent(indent + additionalIndent, header.chomping);
     if (!truth(content)) return null;
 
-    return new ScalarNode("!", content: content);
+    return new ScalarNode("!", _scanner.spanFrom(start), content: content);
   });
 
   // 175
@@ -1606,13 +1573,14 @@
     var additionalIndent = countIndentation() - indent;
     if (additionalIndent <= 0) return null;
 
+    var start = _scanner.state;
     var content = oneOrMore(() => transaction(() {
       if (!truth(s_indent(indent + additionalIndent))) return null;
       return c_l_blockSeqEntry(indent + additionalIndent);
     }));
     if (!truth(content)) return null;
 
-    return new SequenceNode("?", content);
+    return new SequenceNode("?", content, _scanner.spanFrom(start));
   });
 
   // 184
@@ -1639,6 +1607,7 @@
 
   // 186
   Node ns_l_compactSequence(int indent) => context('sequence', () {
+    var start = _scanner.state;
     var first = c_l_blockSeqEntry(indent);
     if (!truth(first)) return null;
 
@@ -1648,7 +1617,7 @@
       }));
     content.insert(0, first);
 
-    return new SequenceNode("?", content);
+    return new SequenceNode("?", content, _scanner.spanFrom(start));
   });
 
   // 187
@@ -1656,23 +1625,24 @@
     var additionalIndent = countIndentation() - indent;
     if (additionalIndent <= 0) return null;
 
+    var start = _scanner.state;
     var pairs = oneOrMore(() => transaction(() {
       if (!truth(s_indent(indent + additionalIndent))) return null;
       return ns_l_blockMapEntry(indent + additionalIndent);
     }));
     if (!truth(pairs)) return null;
 
-    return map(pairs);
+    return map(pairs, _scanner.spanFrom(start));
   });
 
   // 188
-  _Pair<Node, Node> ns_l_blockMapEntry(int indent) => or([
+  Pair<Node, Node> ns_l_blockMapEntry(int indent) => or([
     () => c_l_blockMapExplicitEntry(indent),
     () => ns_l_blockMapImplicitEntry(indent)
   ]);
 
   // 189
-  _Pair<Node, Node> c_l_blockMapExplicitEntry(int indent) {
+  Pair<Node, Node> c_l_blockMapExplicitEntry(int indent) {
     var key = c_l_blockMapExplicitKey(indent);
     if (!truth(key)) return null;
 
@@ -1681,7 +1651,7 @@
       e_node
     ]);
 
-    return new _Pair<Node, Node>(key, value);
+    return new Pair<Node, Node>(key, value);
   }
 
   // 190
@@ -1698,10 +1668,10 @@
   });
 
   // 192
-  _Pair<Node, Node> ns_l_blockMapImplicitEntry(int indent) => transaction(() {
+  Pair<Node, Node> ns_l_blockMapImplicitEntry(int indent) => transaction(() {
     var key = or([ns_s_blockMapImplicitKey, e_node]);
     var value = c_l_blockMapImplicitValue(indent);
-    return truth(value) ? new _Pair<Node, Node>(key, value) : null;
+    return truth(value) ? new Pair<Node, Node>(key, value) : null;
   });
 
   // 193
@@ -1722,6 +1692,7 @@
 
   // 195
   Node ns_l_compactMapping(int indent) => context('mapping', () {
+    var start = _scanner.state;
     var first = ns_l_blockMapEntry(indent);
     if (!truth(first)) return null;
 
@@ -1731,7 +1702,7 @@
       }));
     pairs.insert(0, first);
 
-    return map(pairs);
+    return map(pairs, _scanner.spanFrom(start));
   });
 
   // 196
@@ -1810,7 +1781,7 @@
     transaction(() {
       if (!truth(or([c_directivesEnd, c_documentEnd]))) return;
       var char = peek();
-      forbidden = isBreak(char) || isSpace(char) || atEndOfFile;
+      forbidden = isBreak(char) || isSpace(char) || _scanner.isDone;
       return;
     });
     return forbidden;
@@ -1851,7 +1822,8 @@
     or([l_directiveDocument, l_explicitDocument, l_bareDocument]);
 
   // 211
-  List<Node> l_yamlStream() {
+  Pair<List<Node>, Span> l_yamlStream() {
+    var start = _scanner.state;
     var docs = [];
     zeroOrMore(l_documentPrefix);
     var first = zeroOrOne(l_anyDocument);
@@ -1871,31 +1843,11 @@
       return doc;
     });
 
-    if (!atEndOfFile) parseFailed();
-    return docs;
+    if (!_scanner.isDone) parseFailed();
+    return new Pair(docs, _scanner.spanFrom(start));
   }
 }
 
-class SyntaxError extends YamlException {
-  final int _line;
-  final int _column;
-
-  SyntaxError(this._line, this._column, String msg) : super(msg);
-
-  String toString() => "Syntax error on line $_line, column $_column: "
-      "${super.toString()}";
-}
-
-/// A pair of values.
-class _Pair<E, F> {
-  E first;
-  F last;
-
-  _Pair(this.first, this.last);
-
-  String toString() => '($first, $last)';
-}
-
 /// The information in the header for a block scalar.
 class _BlockHeader {
   final int additionalIndent;
@@ -1926,7 +1878,7 @@
 /// expensive.
 class _RangeMap<E> {
   /// The ranges and their associated elements.
-  final List<_Pair<_Range, E>> _contents = <_Pair<_Range, E>>[];
+  final List<Pair<_Range, E>> _contents = <Pair<_Range, E>>[];
 
   _RangeMap();
 
@@ -1944,5 +1896,5 @@
 
   /// Associates [value] with [range].
   operator[]=(_Range range, E value) =>
-    _contents.add(new _Pair<_Range, E>(range, value));
+    _contents.add(new Pair<_Range, E>(range, value));
 }
diff --git a/pkg/yaml/lib/src/utils.dart b/pkg/yaml/lib/src/utils.dart
index 463af70..84c1113 100644
--- a/pkg/yaml/lib/src/utils.dart
+++ b/pkg/yaml/lib/src/utils.dart
@@ -4,33 +4,12 @@
 
 library yaml.utils;
 
-import 'package:collection/collection.dart';
+/// A pair of values.
+class Pair<E, F> {
+  final E first;
+  final F last;
 
-/// Returns a hash code for [obj] such that structurally equivalent objects
-/// will have the same hash code.
-///
-/// This supports deep equality for maps and lists, including those with
-/// self-referential structures.
-int hashCodeFor(obj) {
-  var parents = [];
+  Pair(this.first, this.last);
 
-  _hashCodeFor(value) {
-    if (parents.any((parent) => identical(parent, value))) return -1;
-
-    parents.add(value);
-    try {
-      if (value is Map) {
-        var equality = const UnorderedIterableEquality();
-        return equality.hash(value.keys.map(_hashCodeFor)) ^
-            equality.hash(value.values.map(_hashCodeFor));
-      } else if (value is Iterable) {
-        return const IterableEquality().hash(value.map(hashCodeFor));
-      }
-      return value.hashCode;
-    } finally {
-      parents.removeLast();
-    }
-  }
-
-  return _hashCodeFor(obj);
+  String toString() => '($first, $last)';
 }
diff --git a/pkg/yaml/lib/src/visitor.dart b/pkg/yaml/lib/src/visitor.dart
index 7095268..3f4c455 100644
--- a/pkg/yaml/lib/src/visitor.dart
+++ b/pkg/yaml/lib/src/visitor.dart
@@ -4,8 +4,8 @@
 
 library yaml.visitor;
 
+import 'equality.dart';
 import 'model.dart';
-import 'yaml_map.dart';
 
 /// The visitor pattern for YAML documents.
 class Visitor {
@@ -21,7 +21,7 @@
 
   /// Visits each key and value in [map] and returns a map of the results.
   visitMapping(MappingNode map) {
-    var out = new YamlMap();
+    var out = deepEqualsMap();
     for (var key in map.content.keys) {
       out[key.visit(this)] = map.content[key].visit(this);
     }
diff --git a/pkg/yaml/lib/src/yaml_map.dart b/pkg/yaml/lib/src/yaml_map.dart
deleted file mode 100644
index ff3da36..0000000
--- a/pkg/yaml/lib/src/yaml_map.dart
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library yaml.map;
-
-import 'dart:collection';
-
-import 'package:collection/collection.dart';
-
-import 'deep_equals.dart';
-import 'utils.dart';
-
-/// This class behaves almost identically to the normal Dart [Map]
-/// implementation, with the following differences:
-///
-///  *  It allows NaN, list, and map keys.
-///  *  It defines `==` structurally. That is, `yamlMap1 == yamlMap2` if they
-///     have the same contents.
-///  *  It has a compatible [hashCode] method.
-///
-/// This class is deprecated. In future releases, this package will use
-/// a [HashMap] with a custom equality operation rather than a custom class.
-@Deprecated('1.0.0')
-class YamlMap extends DelegatingMap {
-  YamlMap()
-      : super(new HashMap(equals: deepEquals, hashCode: hashCodeFor));
-
-  YamlMap.from(Map map)
-      : super(new HashMap(equals: deepEquals, hashCode: hashCodeFor)) {
-    addAll(map);
-  }
-
-  int get hashCode => hashCodeFor(this);
-
-  bool operator ==(other) {
-    if (other is! YamlMap) return false;
-    return deepEquals(this, other);
-  }
-}
diff --git a/pkg/yaml/lib/src/yaml_node.dart b/pkg/yaml/lib/src/yaml_node.dart
new file mode 100644
index 0000000..d0e0578
--- /dev/null
+++ b/pkg/yaml/lib/src/yaml_node.dart
@@ -0,0 +1,92 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library yaml.map;
+
+import 'dart:collection' as collection;
+
+import 'package:collection/collection.dart';
+import 'package:source_maps/source_maps.dart';
+
+/// An interface for parsed nodes from a YAML source tree.
+///
+/// [YamlMap]s and [YamlList]s implement this interface in addition to the
+/// normal [Map] and [List] interfaces, so any maps and lists will be
+/// [YamlNode]s regardless of how they're accessed.
+///
+/// Scalars values like strings and numbers, on the other hand, don't have this
+/// interface by default. Instead, they can be accessed as [YamlScalar]s via
+/// [YamlMap.nodes] or [YamlList.nodes].
+abstract class YamlNode {
+  /// The source span for this node.
+  ///
+  /// [Span.getLocationMessage] can be used to produce a human-friendly message
+  /// about this node.
+  Span get span;
+
+  /// The inner value of this node.
+  ///
+  /// For [YamlScalar]s, this will return the wrapped value. For [YamlMap] and
+  /// [YamlList], it will return [this], since they already implement [Map] and
+  /// [List], respectively.
+  get value;
+}
+
+/// A read-only [Map] parsed from YAML.
+class YamlMap extends YamlNode with collection.MapMixin, UnmodifiableMapMixin  {
+  final Span span;
+
+  final Map<dynamic, YamlNode> nodes;
+
+  Map get value => this;
+
+  Iterable get keys => nodes.keys.map((node) => node.value);
+
+  /// Users of the library should not construct [YamlMap]s manually.
+  YamlMap(Map<dynamic, YamlNode> nodes, this.span)
+      : nodes = new UnmodifiableMapView<dynamic, YamlNode>(nodes);
+
+  operator [](key) {
+    var node = nodes[key];
+    return node == null ? null : node.value;
+  }
+}
+
+// TODO(nweiz): Use UnmodifiableListMixin when issue 18970 is fixed.
+/// A read-only [List] parsed from YAML.
+class YamlList extends YamlNode with collection.ListMixin {
+  final Span span;
+
+  final List<YamlNode> nodes;
+
+  List get value => this;
+
+  int get length => nodes.length;
+
+  set length(int index) {
+    throw new UnsupportedError("Cannot modify an unmodifiable List");
+  }
+
+  /// Users of the library should not construct [YamlList]s manually.
+  YamlList(List<YamlNode> nodes, this.span)
+      : nodes = new UnmodifiableListView<YamlNode>(nodes);
+
+  operator [](int index) => nodes[index].value;
+
+  operator []=(int index, value) {
+    throw new UnsupportedError("Cannot modify an unmodifiable List");
+  }
+}
+
+/// A wrapped scalar value parsed from YAML.
+class YamlScalar extends YamlNode {
+  final Span span;
+
+  final value;
+
+  /// Users of the library should not construct [YamlScalar]s manually.
+  YamlScalar(this.value, this.span);
+
+  String toString() => value.toString();
+}
diff --git a/pkg/yaml/lib/yaml.dart b/pkg/yaml/lib/yaml.dart
index dc895e6..f59719d 100644
--- a/pkg/yaml/lib/yaml.dart
+++ b/pkg/yaml/lib/yaml.dart
@@ -8,9 +8,10 @@
 import 'src/constructor.dart';
 import 'src/parser.dart';
 import 'src/yaml_exception.dart';
+import 'src/yaml_node.dart';
 
 export 'src/yaml_exception.dart';
-export 'src/yaml_map.dart';
+export 'src/yaml_node.dart';
 
 /// Loads a single document from a YAML string.
 ///
@@ -25,12 +26,23 @@
 ///
 /// In future versions, maps will instead be [HashMap]s with a custom equality
 /// operation.
-loadYaml(String yaml) {
-  var stream = loadYamlStream(yaml);
+///
+/// If [sourceName] is passed, it's used as the name of the file or URL from
+/// which the YAML originated for error reporting.
+loadYaml(String yaml, {String sourceName}) =>
+    loadYamlNode(yaml, sourceName: sourceName).value;
+
+/// Loads a single document from a YAML string as a [YamlNode].
+///
+/// This is just like [loadYaml], except that where [loadYaml] would return a
+/// normal Dart value this returns a [YamlNode] instead. This allows the caller
+/// to be confident that the return value will always be a [YamlNode].
+YamlNode loadYamlNode(String yaml, {String sourceName}) {
+  var stream = loadYamlStream(yaml, sourceName: sourceName);
   if (stream.length != 1) {
     throw new YamlException("Expected 1 document, were ${stream.length}.");
   }
-  return stream[0];
+  return stream.nodes[0];
 }
 
 /// Loads a stream of documents from a YAML string.
@@ -43,8 +55,19 @@
 ///
 /// In future versions, maps will instead be [HashMap]s with a custom equality
 /// operation.
-List loadYamlStream(String yaml) {
-  return new Parser(yaml).l_yamlStream()
+///
+/// If [sourceName] is passed, it's used as the name of the file or URL from
+/// which the YAML originated for error reporting.
+YamlList loadYamlStream(String yaml, {String sourceName}) {
+  var pair;
+  try {
+    pair = new Parser(yaml, sourceName).l_yamlStream();
+  } on FormatException catch (error) {
+    throw new YamlException(error.toString());
+  }
+
+  var nodes = pair.first
       .map((doc) => new Constructor(new Composer(doc).compose()).construct())
       .toList();
+  return new YamlList(nodes, pair.last);
 }
diff --git a/pkg/yaml/pubspec.yaml b/pkg/yaml/pubspec.yaml
index 7186de0..50fc3db 100644
--- a/pkg/yaml/pubspec.yaml
+++ b/pkg/yaml/pubspec.yaml
@@ -1,11 +1,12 @@
 name: yaml
-version: 0.9.0+2
+version: 1.0.0+1
 author: "Dart Team <misc@dartlang.org>"
 homepage: http://www.dartlang.org
 description: A parser for YAML.
 dependencies:
   collection: ">=0.9.2 <0.10.0"
+  string_scanner: ">=0.0.2 <0.1.0"
 dev_dependencies:
-  unittest: ">=0.9.0 <0.10.0"
+  unittest: ">=0.9.0 <0.12.0"
 environment:
   sdk: ">=0.8.10+6 <2.0.0"
diff --git a/pkg/yaml/test/utils.dart b/pkg/yaml/test/utils.dart
index 0bac9f9..9c96ec1 100644
--- a/pkg/yaml/test/utils.dart
+++ b/pkg/yaml/test/utils.dart
@@ -5,7 +5,7 @@
 library yaml.test.utils;
 
 import 'package:unittest/unittest.dart';
-import 'package:yaml/src/deep_equals.dart' as de;
+import 'package:yaml/src/equality.dart' as equality;
 import 'package:yaml/yaml.dart';
 
 /// A matcher that validates that a closure or Future throws a [YamlException].
@@ -14,25 +14,28 @@
 /// Returns a matcher that asserts that the value equals [expected].
 ///
 /// This handles recursive loops and considers `NaN` to equal itself.
-Matcher deepEquals(expected) =>
-    predicate((actual) => de.deepEquals(actual, expected), "equals $expected");
+Matcher deepEquals(expected) => predicate((actual) =>
+    equality.deepEquals(actual, expected), "equals $expected");
 
 /// Constructs a new yaml.YamlMap, optionally from a normal Map.
-Map yamlMap([Map from]) =>
-    from == null ? new YamlMap() : new YamlMap.from(from);
+Map deepEqualsMap([Map from]) {
+  var map = equality.deepEqualsMap();
+  if (from != null) map.addAll(from);
+  return map;
+}
 
 /// Asserts that a string containing a single YAML document produces a given
 /// value when loaded.
 void expectYamlLoads(expected, String source) {
   var actual = loadYaml(cleanUpLiteral(source));
-  expect(expected, deepEquals(actual));
+  expect(actual, deepEquals(expected));
 }
 
 /// Asserts that a string containing a stream of YAML documents produces a given
 /// list of values when loaded.
 void expectYamlStreamLoads(List expected, String source) {
   var actual = loadYamlStream(cleanUpLiteral(source));
-  expect(expected, deepEquals(actual));
+  expect(actual, deepEquals(expected));
 }
 
 /// Asserts that a string containing a single YAML document throws a
diff --git a/pkg/yaml/test/yaml_test.dart b/pkg/yaml/test/yaml_test.dart
index fcfc12e..4fbb108 100644
--- a/pkg/yaml/test/yaml_test.dart
+++ b/pkg/yaml/test/yaml_test.dart
@@ -14,37 +14,6 @@
   var infinity = double.parse("Infinity");
   var nan = double.parse("NaN");
 
-  group('YamlMap', () {
-    group('accepts as a key', () {
-      _expectKeyWorks(keyFn()) {
-        var map = yamlMap();
-        map[keyFn()] = 5;
-        expect(map.containsKey(keyFn()), isTrue);
-        expect(map[keyFn()], 5);
-      }
-
-      test('null', () => _expectKeyWorks(() => null));
-      test('true', () => _expectKeyWorks(() => true));
-      test('false', () => _expectKeyWorks(() => false));
-      test('a list', () => _expectKeyWorks(() => [1, 2, 3]));
-      test('a map', () => _expectKeyWorks(() => {'foo': 'bar'}));
-      test('a YAML map', () => _expectKeyWorks(() => yamlMap({'foo': 'bar'})));
-    });
-
-    test('works as a hash key', () {
-      var normalMap = new Map();
-      normalMap[yamlMap({'foo': 'bar'})] = 'baz';
-      expect(normalMap.containsKey(yamlMap({'foo': 'bar'})), isTrue);
-      expect(normalMap[yamlMap({'foo': 'bar'})], 'baz');
-    });
-
-    test('treats YamlMap keys the same as normal maps', () {
-      var map = yamlMap();
-      map[{'a': 'b'}] = 5;
-      expect(map[yamlMap({'a': 'b'})], 5);
-    });
-  });
-
   group('has a friendly error message for', () {
     var tabError = predicate((e) =>
         e.toString().contains('tab characters are not allowed as indentation'));
@@ -221,7 +190,7 @@
   //   });
 
     test('[Example 2.11]', () {
-      var doc = yamlMap();
+      var doc = deepEqualsMap();
       doc[["Detroit Tigers", "Chicago cubs"]] = ["2001-07-23"];
       doc[["New York Yankees", "Atlanta Braves"]] =
         ["2001-07-02", "2001-08-12", "2001-08-14"];
@@ -382,7 +351,7 @@
     });
 
     test('[Example 2.21]', () {
-      var doc = yamlMap({
+      var doc = deepEqualsMap({
         "booleans": [true, false],
         "string": "012345"
       });
@@ -900,7 +869,7 @@
     });
 
     test('[Example 6.12]', () {
-      var doc = yamlMap();
+      var doc = deepEqualsMap();
       doc[{'first': 'Sammy', 'last': 'Sosa'}] = {
         'hr': 65,
         'avg': 0.278
@@ -1092,7 +1061,7 @@
     // });
 
     test('[Example 7.3]', () {
-      var doc = yamlMap({"foo": null});
+      var doc = deepEqualsMap({"foo": null});
       doc[null] = "bar";
       expectYamlLoads(doc,
         """
@@ -1239,7 +1208,7 @@
     });
 
     test('[Example 7.16]', () {
-      var doc = yamlMap({
+      var doc = deepEqualsMap({
         "explicit": "entry",
         "implicit": "entry"
       });
@@ -1254,7 +1223,7 @@
     });
 
     test('[Example 7.17]', () {
-      var doc = yamlMap({
+      var doc = deepEqualsMap({
         "unquoted": "separate",
         "http://foo.com": null,
         "omitted value": null
@@ -1302,10 +1271,10 @@
     });
 
     test('[Example 7.21]', () {
-      var el1 = yamlMap();
+      var el1 = deepEqualsMap();
       el1[null] = "empty key entry";
 
-      var el2 = yamlMap();
+      var el2 = deepEqualsMap();
       el2[{"JSON": "like"}] = "adjacent";
 
       expectYamlLoads([[{"YAML": "separate"}], [el1], [el2]],
@@ -1577,7 +1546,7 @@
     });
 
     test('[Example 8.18]', () {
-      var doc = yamlMap({
+      var doc = deepEqualsMap({
         'plain key': 'in-line value',
         "quoted key": ["entry"]
       });
@@ -1591,7 +1560,7 @@
     });
 
     test('[Example 8.19]', () {
-      var el = yamlMap();
+      var el = deepEqualsMap();
       el[{'earth': 'blue'}] = {'moon': 'white'};
       expectYamlLoads([{'sun': 'yellow'}, el],
         """
@@ -1763,7 +1732,7 @@
 
   group('10.2: JSON Schema', () {
     // test('[Example 10.4]', () {
-    //   var doc = yamlMap({"key with null value": null});
+    //   var doc = deepEqualsMap({"key with null value": null});
     //   doc[null] = "value for null key";
     //   expectYamlStreamLoads(doc,
     //     """
diff --git a/runtime/bin/vmservice/client/deploy.sh b/runtime/bin/vmservice/client/deploy.sh
index c1e093e..1990bd6 100755
--- a/runtime/bin/vmservice/client/deploy.sh
+++ b/runtime/bin/vmservice/client/deploy.sh
@@ -14,6 +14,7 @@
 fi
 
 EXCLUDE="--exclude bootstrap_css"
+EXCLUDE="$EXCLUDE --exclude *.map"
 EXCLUDE="$EXCLUDE --exclude *.scriptUrls"
 EXCLUDE="$EXCLUDE --exclude *.precompiled.js"
 EXCLUDE="$EXCLUDE --exclude main.*"
diff --git a/runtime/bin/vmservice/client/deployed/web/index.html_bootstrap.dart.js b/runtime/bin/vmservice/client/deployed/web/index.html_bootstrap.dart.js
index 2892608..7957a93 100644
--- a/runtime/bin/vmservice/client/deployed/web/index.html_bootstrap.dart.js
+++ b/runtime/bin/vmservice/client/deployed/web/index.html_bootstrap.dart.js
@@ -193,7 +193,7 @@
 n:function(a,b){return a===b},
 giO:function(a){return H.eQ(a)},
 bu:function(a){return H.a5(a)},
-T:[function(a,b){throw H.b(P.lr(a,b.gWa(),b.gnd(),b.gVm(),null))},"$1","gxK",2,0,null,63],
+T:[function(a,b){throw H.b(P.lr(a,b.gWa(),b.gnd(),b.gVm(),null))},"$1","gxK",2,0,null,65],
 gbx:function(a){return new H.cu(H.dJ(a),null)},
 "%":"DOMImplementation|Navigator|SVGAnimatedEnumeration|SVGAnimatedLength|SVGAnimatedLengthList|SVGAnimatedNumber|SVGAnimatedNumberList|SVGAnimatedString"},
 yEe:{
@@ -208,7 +208,7 @@
 bu:function(a){return"null"},
 giO:function(a){return 0},
 gbx:function(a){return C.GX},
-T:[function(a,b){return J.Gv.prototype.T.call(this,a,b)},"$1","gxK",2,0,null,63]},
+T:[function(a,b){return J.Gv.prototype.T.call(this,a,b)},"$1","gxK",2,0,null,65]},
 wm:{
 "^":"Gv;",
 giO:function(a){return 0},
@@ -646,11 +646,11 @@
 vM:function(a){return a==null||typeof a==="string"||typeof a==="number"||typeof a==="boolean"},
 ZR:function(a){return a==null||typeof a==="string"||typeof a==="number"||typeof a==="boolean"},
 PK:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:function(){this.b.$1(this.a.a)},
 $isEH:true},
 JO:{
-"^":"Tp:64;a,c",
+"^":"Tp:66;a,c",
 $0:function(){this.c.$2(this.a.a,null)},
 $isEH:true},
 f0:{
@@ -753,7 +753,7 @@
 if(this===init.globalState.Nr)throw v}}finally{this.mf=!1
 init.globalState.N0=z
 if(z!=null)$=z.gEn()
-if(this.M2!=null)for(;u=this.M2,!u.gl0(u);)this.M2.AR().$0()}return y},"$1","gZm",2,0,65,66],
+if(this.M2!=null)for(;u=this.M2,!u.gl0(u);)this.M2.AR().$0()}return y},"$1","gZm",2,0,67,68],
 Ds:function(a){var z=J.U6(a)
 switch(z.t(a,0)){case"pause":this.V0(z.t(a,1),z.t(a,2))
 break
@@ -833,7 +833,7 @@
 JH:{
 "^":"a;"},
 mN:{
-"^":"Tp:64;a,b,c,d,e,f",
+"^":"Tp:66;a,b,c,d,e,f",
 $0:[function(){H.Di(this.a,this.b,this.c,this.d,this.e,this.f)},"$0",null,0,0,null,"call"],
 $isEH:true},
 vK:{
@@ -876,7 +876,7 @@
 $isRZ:true,
 $iswC:true},
 Ua:{
-"^":"Tp:64;a,b,c",
+"^":"Tp:66;a,b,c",
 $0:[function(){var z,y
 z=this.b.JE
 if(!z.gP0()){if(this.c){y=this.a
@@ -892,8 +892,8 @@
 n:function(a,b){if(b==null)return!1
 return!!J.x(b).$isdd&&J.xC(this.ZU,b.ZU)&&J.xC(this.tv,b.tv)&&J.xC(this.bv,b.bv)},
 giO:function(a){var z,y,x
-z=J.lf(this.ZU,16)
-y=J.lf(this.tv,8)
+z=J.xs(this.ZU,16)
+y=J.xs(this.tv,8)
 x=this.bv
 if(typeof x!=="number")return H.s(x)
 return(z^y^x)>>>0},
@@ -1003,7 +1003,7 @@
 DE:function(a){return H.vh(P.SY(null))},
 yf:function(a){return H.vh(P.SY(null))}},
 OW:{
-"^":"Tp:67;a,b",
+"^":"Tp:69;a,b",
 $2:function(a,b){var z=this.b
 J.kW(this.a.a,z.Q9(a),z.Q9(b))},
 $isEH:true},
@@ -1675,7 +1675,7 @@
 $isyN:true},
 hY:{
 "^":"Tp:10;a",
-$1:[function(a){return this.a.TZ(a)},"$1",null,2,0,null,68,"call"],
+$1:[function(a){return this.a.TZ(a)},"$1",null,2,0,null,70,"call"],
 $isEH:true},
 XR:{
 "^":"mW;Y3",
@@ -1755,14 +1755,14 @@
 z[y]=x},
 $isEH:true},
 lk:{
-"^":"Tp:69;a,b,c",
+"^":"Tp:71;a,b,c",
 $2:function(a,b){var z=this.a
 z.b=z.b+"$"+H.d(a)
 this.c.push(a)
 this.b.push(b);++z.a},
 $isEH:true},
 u8:{
-"^":"Tp:69;a,b",
+"^":"Tp:71;a,b",
 $2:function(a,b){var z=this.b
 if(z.x4(a))z.u(0,a,b)
 else this.a.a=!0},
@@ -1837,23 +1837,23 @@
 this.ui=z
 return z}},
 dr:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:function(){return this.a.$0()},
 $isEH:true},
 TL:{
-"^":"Tp:64;b,c",
+"^":"Tp:66;b,c",
 $0:function(){return this.b.$1(this.c)},
 $isEH:true},
 uZ:{
-"^":"Tp:64;d,e,f",
+"^":"Tp:66;d,e,f",
 $0:function(){return this.d.$2(this.e,this.f)},
 $isEH:true},
 OQ:{
-"^":"Tp:64;UI,bK,Gq,Rm",
+"^":"Tp:66;UI,bK,Gq,Rm",
 $0:function(){return this.UI.$3(this.bK,this.Gq,this.Rm)},
 $isEH:true},
 Qx:{
-"^":"Tp:64;w3,HZ,mG,xC,cj",
+"^":"Tp:66;w3,HZ,mG,xC,cj",
 $0:function(){return this.w3.$4(this.HZ,this.mG,this.xC,this.cj)},
 $isEH:true},
 Tp:{
@@ -1980,7 +1980,7 @@
 $1:function(a){return this.a(a)},
 $isEH:true},
 VX:{
-"^":"Tp:70;b",
+"^":"Tp:72;b",
 $2:function(a,b){return this.b(a,b)},
 $isEH:true},
 vZ:{
@@ -2094,7 +2094,7 @@
 F6:[function(a,b,c,d){var z=a.fi
 if(z===!0)return
 if(a.dB!=null){a.fi=this.ct(a,C.S4,z,!0)
-this.LY(a,null).wM(new X.jE(a))}},"$3","gNa",6,0,71,43,44,72],
+this.LY(a,null).wM(new X.jE(a))}},"$3","gNa",6,0,73,43,44,74],
 static:{zy:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -2114,7 +2114,7 @@
 "^":"ir+Pi;",
 $isd3:true},
 jE:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:[function(){var z=this.a
 z.fi=J.Q5(z,C.S4,z.fi,!1)},"$0",null,0,0,null,"call"],
 $isEH:true}}],["app","package:observatory/app.dart",,G,{
@@ -2179,9 +2179,9 @@
 z=z.Li
 H.VM(new P.Ik(z),[H.Kp(z,0)]).yI(this.gXa())},
 kj:[function(a){this.AJ=F.Wi(this,C.F3,this.AJ,a)
-window.location.hash=""},"$1","gbf",2,0,73,21],
+window.location.hash=""},"$1","gbf",2,0,75,21],
 t1:[function(a){this.AJ=F.Wi(this,C.F3,this.AJ,a)
-window.location.hash=""},"$1","gXa",2,0,74,75],
+window.location.hash=""},"$1","gXa",2,0,76,77],
 US:function(){this.Da()},
 hq:function(){this.Da()}},
 Kf:{
@@ -2217,7 +2217,7 @@
 static:{"^":"K3D"}},
 Qe:{
 "^":"Tp:10;a",
-$1:[function(a){this.a.df()},"$1",null,2,0,null,76,"call"],
+$1:[function(a){this.a.df()},"$1",null,2,0,null,78,"call"],
 $isEH:true},
 wX:{
 "^":"Tp:10;a,b",
@@ -2226,7 +2226,7 @@
 y=z.ec
 y.AJ=F.Wi(y,C.F3,y.AJ,a)
 z=z.ec
-z.fz=F.Wi(z,C.Zg,z.fz,this.b)},"$1",null,2,0,null,77,"call"],
+z.fz=F.Wi(z,C.Zg,z.fz,this.b)},"$1",null,2,0,null,79,"call"],
 $isEH:true},
 Y2:{
 "^":"Pi;eT>,yt<,ks>,oH<",
@@ -2261,7 +2261,7 @@
 w=J.U6(z)
 v=w.u8(z,a)+1
 w.UZ(z,v,v+y)}},
-zb:{
+Ktd:{
 "^":"a;ph>,xy<",
 static:{mb:[function(a){return a!=null?J.AG(a):"<null>"},"$1","HP",2,0,14]}},
 Ni:{
@@ -2287,19 +2287,19 @@
 y=J.UQ(J.U8o(z[a]),b)
 z=this.oH
 if(b>>>0!==b||b>=z.length)return H.e(z,b)
-return z[b].gxy().$1(y)},"$2","gwy",4,0,78,79,80],
+return z[b].gxy().$1(y)},"$2","gwy",4,0,80,81,82],
 Qs:[function(a){var z
 if(!J.xC(a,this.pT)){z=this.oH
 if(a>>>0!==a||a>=z.length)return H.e(z,a)
 return J.ew(J.Q4(z[a]),"\u2003")}z=this.oH
 if(a>>>0!==a||a>=z.length)return H.e(z,a)
 z=J.Q4(z[a])
-return J.ew(z,this.jV?"\u25bc":"\u25b2")},"$1","gCO",2,0,12,80],
+return J.ew(z,this.jV?"\u25bc":"\u25b2")},"$1","gCO",2,0,12,82],
 TK:[function(a,b){var z=this.WT
 if(a>>>0!==a||a>=z.length)return H.e(z,a)
-return J.UQ(J.U8o(z[a]),b)},"$2","gyY",4,0,81,79,80]},
+return J.UQ(J.U8o(z[a]),b)},"$2","gyY",4,0,83,81,82]},
 BD:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){var z,y,x,w
 z=this.a
 y=z.WT
@@ -3224,691 +3224,691 @@
 $1:function(a){return a.gaU()},
 $isEH:true},
 e205:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.RX(a,b)},
 $isEH:true},
 e206:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.a8(a,b)},
 $isEH:true},
 e207:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.oO(a,b)},
 $isEH:true},
 e208:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.l7(a,b)},
 $isEH:true},
 e209:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.kB(a,b)},
 $isEH:true},
 e210:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Ae(a,b)},
 $isEH:true},
 e211:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.IX(a,b)},
 $isEH:true},
 e212:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.WI(a,b)},
 $isEH:true},
 e213:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.o0(a,b)},
 $isEH:true},
 e214:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.fH(a,b)},
 $isEH:true},
 e215:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Sf(a,b)},
 $isEH:true},
 e216:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.qA(a,b)},
 $isEH:true},
 e217:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.LM(a,b)},
 $isEH:true},
 e218:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.qq(a,b)},
 $isEH:true},
 e219:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Pk(a,b)},
 $isEH:true},
 e220:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Yz(a,b)},
 $isEH:true},
 e221:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.sw2(b)},
 $isEH:true},
 e222:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Qr(a,b)},
 $isEH:true},
 e223:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.xW(a,b)},
 $isEH:true},
 e224:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.BC(a,b)},
 $isEH:true},
 e225:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.VJ(a,b)},
 $isEH:true},
 e226:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.NO(a,b)},
 $isEH:true},
 e227:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.WB(a,b)},
 $isEH:true},
 e228:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.JZ(a,b)},
 $isEH:true},
 e229:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.fR(a,b)},
 $isEH:true},
 e230:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.shY(b)},
 $isEH:true},
 e231:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.LP(a,b)},
 $isEH:true},
 e232:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.GF(a,b)},
 $isEH:true},
 e233:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Nf(a,b)},
 $isEH:true},
 e234:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Pl(a,b)},
 $isEH:true},
 e235:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.C3(a,b)},
 $isEH:true},
 e236:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.xH(a,b)},
 $isEH:true},
 e237:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Nh(a,b)},
 $isEH:true},
 e238:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.sHP(b)},
 $isEH:true},
 e239:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.AI(a,b)},
 $isEH:true},
 e240:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.nA(a,b)},
 $isEH:true},
 e241:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.fb(a,b)},
 $isEH:true},
 e242:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.tv(a,b)},
 $isEH:true},
 e243:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.siq(b)},
 $isEH:true},
 e244:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Qy(a,b)},
 $isEH:true},
 e245:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.sKt(b)},
 $isEH:true},
 e246:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Oo(a,b)},
 $isEH:true},
 e247:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.mU(a,b)},
 $isEH:true},
 e248:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Kz(a,b)},
 $isEH:true},
 e249:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.uM(a,b)},
 $isEH:true},
 e250:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Er(a,b)},
 $isEH:true},
 e251:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.uX(a,b)},
 $isEH:true},
 e252:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.hS(a,b)},
 $isEH:true},
 e253:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.sSK(b)},
 $isEH:true},
 e254:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.shX(b)},
 $isEH:true},
 e255:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.cl(a,b)},
 $isEH:true},
 e256:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Jb(a,b)},
 $isEH:true},
 e257:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.k7(a,b)},
 $isEH:true},
 e258:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.MX(a,b)},
 $isEH:true},
 e259:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.A4(a,b)},
 $isEH:true},
 e260:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.wD(a,b)},
 $isEH:true},
 e261:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.wJ(a,b)},
 $isEH:true},
 e262:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.oJ(a,b)},
 $isEH:true},
 e263:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.DF(a,b)},
 $isEH:true},
 e264:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Mi(a,b)},
 $isEH:true},
 e265:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.sL1(b)},
 $isEH:true},
 e266:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.XF(a,b)},
 $isEH:true},
 e267:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.SF(a,b)},
 $isEH:true},
 e268:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Qv(a,b)},
 $isEH:true},
 e269:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Xg(a,b)},
 $isEH:true},
 e270:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.aw(a,b)},
 $isEH:true},
 e271:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.CJ(a,b)},
 $isEH:true},
 e272:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.P2(a,b)},
 $isEH:true},
 e273:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.fv(a,b)},
 $isEH:true},
 e274:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.PP(a,b)},
 $isEH:true},
 e275:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Sj(a,b)},
 $isEH:true},
 e276:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.AJ(a,b)},
 $isEH:true},
 e277:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.w7(a,b)},
 $isEH:true},
 e278:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.ME(a,b)},
 $isEH:true},
 e279:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.kX(a,b)},
 $isEH:true},
 e280:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.S5(a,b)},
 $isEH:true},
 e281:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.q0(a,b)},
 $isEH:true},
 e282:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.EJ(a,b)},
 $isEH:true},
 e283:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.iH(a,b)},
 $isEH:true},
 e284:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.B9(a,b)},
 $isEH:true},
 e285:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.PN(a,b)},
 $isEH:true},
 e286:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.sVc(b)},
 $isEH:true},
 e287:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.By(a,b)},
 $isEH:true},
 e288:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.jd(a,b)},
 $isEH:true},
 e289:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Rx(a,b)},
 $isEH:true},
 e290:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.ZI(a,b)},
 $isEH:true},
 e291:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.wg(a,b)},
 $isEH:true},
 e292:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.fa(a,b)},
 $isEH:true},
 e293:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Cu(a,b)},
 $isEH:true},
 e294:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.sV8(b)},
 $isEH:true},
 e295:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Tx(a,b)},
 $isEH:true},
 e296:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.sDo(b)},
 $isEH:true},
 e297:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.H3(a,b)},
 $isEH:true},
 e298:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.t3(a,b)},
 $isEH:true},
 e299:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.GT(a,b)},
 $isEH:true},
 e300:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.sVF(b)},
 $isEH:true},
 e301:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.yO(a,b)},
 $isEH:true},
 e302:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.ZU(a,b)},
 $isEH:true},
 e303:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.tQ(a,b)},
 $isEH:true},
 e304:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.tH(a,b)},
 $isEH:true},
 e305:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("curly-block",C.Lg)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e306:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("observatory-element",C.l4)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e307:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("service-ref",C.il)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e308:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("instance-ref",C.Wz)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e309:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("action-link",C.K4)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e310:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("nav-bar",C.Zj)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e311:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("nav-menu",C.ms)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e312:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("nav-menu-item",C.FA)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e313:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("nav-refresh",C.JW)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e314:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("top-nav-menu",C.Mf)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e315:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("isolate-nav-menu",C.km)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e316:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("library-nav-menu",C.vw)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e317:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("class-nav-menu",C.Ey)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e318:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("breakpoint-list",C.yS)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e319:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("class-ref",C.OG)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e320:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("eval-box",C.wk)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e321:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("eval-link",C.jA)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e322:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("field-ref",C.Jo)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e323:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("function-ref",C.lE)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e324:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("library-ref",C.lp)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e325:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("script-ref",C.Sb)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e326:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("class-view",C.xE)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e327:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("code-ref",C.oT)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e328:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("code-view",C.jR)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e329:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("collapsible-content",C.bh)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e330:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("error-view",C.KO)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e331:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("field-view",C.Az)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e332:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("stack-frame",C.NR)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e333:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("flag-list",C.BL)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e334:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("flag-item",C.Vx)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e335:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("script-inset",C.ON)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e336:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("function-view",C.te)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e337:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("heap-map",C.iD)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e338:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-view",C.tU)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e339:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-ref",C.Jf)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e340:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-http-server-list-view",C.qF)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e341:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-http-server-ref",C.nX)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e342:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-http-server-view",C.Wh)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e343:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-socket-ref",C.FG)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e344:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-socket-list-view",C.EZ)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e345:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-socket-view",C.pJ)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e346:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-web-socket-ref",C.Yy)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e347:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-web-socket-list-view",C.DD)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e348:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-web-socket-view",C.Xv)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e349:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-random-access-file-list-view",C.tc)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e350:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-random-access-file-ref",C.rR)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e351:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-random-access-file-view",C.oG)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e352:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-process-list-view",C.Ep)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e353:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-process-ref",C.dD)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e354:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-process-view",C.hP)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e355:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("isolate-ref",C.UJ)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e356:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("isolate-summary",C.CT)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e357:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("isolate-run-state",C.j4)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e358:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("isolate-location",C.Io)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e359:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("isolate-shared-summary",C.TU)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e360:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("isolate-counter-chart",C.z7)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e361:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("isolate-view",C.mq)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e362:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("instance-view",C.k5)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e363:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("json-view",C.Tq)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e364:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("library-view",C.PT)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e365:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("heap-profile",C.Ju)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e366:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("sliding-checkbox",C.Y3)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e367:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("isolate-profile",C.ce)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e368:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("script-view",C.Th)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e369:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("stack-trace",C.vu)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e370:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("vm-view",C.jK)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e371:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("service-view",C.X8)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e372:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("response-viewer",C.Vh)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e373:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("observatory-application",C.Dl)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e374:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("service-exception-view",C.pK)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e375:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("service-error-view",C.wH)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e376:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("vm-ref",C.cK)},"$0",null,0,0,null,"call"],
 $isEH:true}},1],["breakpoint_list_element","package:observatory/src/elements/breakpoint_list.dart",,B,{
 "^":"",
@@ -3916,7 +3916,7 @@
 "^":"Vf;BW,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 grs:function(a){return a.BW},
 srs:function(a,b){a.BW=this.ct(a,C.UX,a.BW,b)},
-RF:[function(a,b){J.LE(a.BW).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.BW).wM(b)},"$1","gvC",2,0,17,84],
 static:{KU:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -3953,9 +3953,9 @@
 "^":"Vfx;yB,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gRu:function(a){return a.yB},
 sRu:function(a,b){a.yB=this.ct(a,C.XA,a.yB,b)},
-vV:[function(a,b){return J.aT(a.yB).cv(J.ew(J.F8(a.yB),"/eval?expr="+P.jW(C.yD,b,C.xM,!1)))},"$1","gZm",2,0,83,84],
-S1:[function(a,b){return J.aT(a.yB).cv(J.ew(J.F8(a.yB),"/retained"))},"$1","ghN",2,0,83,85],
-RF:[function(a,b){J.LE(a.yB).wM(b)},"$1","gvC",2,0,17,82],
+vV:[function(a,b){return J.aT(a.yB).cv(J.ew(J.F8(a.yB),"/eval?expr="+P.jW(C.yD,b,C.xM,!1)))},"$1","gZm",2,0,85,86],
+S1:[function(a,b){return J.aT(a.yB).cv(J.ew(J.F8(a.yB),"/retained"))},"$1","ghN",2,0,85,87],
+RF:[function(a,b){J.LE(a.yB).wM(b)},"$1","gvC",2,0,17,84],
 static:{zg:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -4000,7 +4000,7 @@
 z=a.Xx
 if(z==null)return
 J.SK(z).ml(new F.aa())},
-RF:[function(a,b){J.LE(a.Xx).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.Xx).wM(b)},"$1","gvC",2,0,17,84],
 m2:function(a,b){var z,y,x
 z=J.Vs(b).MW.getAttribute("data-jump-target")
 if(z==="")return
@@ -4010,10 +4010,10 @@
 return x},
 YI:[function(a,b,c,d){var z=this.m2(a,d)
 if(z==null)return
-J.pP(z).h(0,"highlight")},"$3","gKJ",6,0,86,1,87,88],
+J.pP(z).h(0,"highlight")},"$3","gKJ",6,0,88,1,89,90],
 ZC:[function(a,b,c,d){var z=this.m2(a,d)
 if(z==null)return
-J.pP(z).Rz(0,"highlight")},"$3","gAF",6,0,86,1,87,88],
+J.pP(z).Rz(0,"highlight")},"$3","gAF",6,0,88,1,89,90],
 static:{f9:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -4030,8 +4030,8 @@
 "^":"uL+Pi;",
 $isd3:true},
 aa:{
-"^":"Tp:89;",
-$1:[function(a){a.OF()},"$1",null,2,0,null,72,"call"],
+"^":"Tp:91;",
+$1:[function(a){a.OF()},"$1",null,2,0,null,74,"call"],
 $isEH:true}}],["collapsible_content_element","package:observatory/src/elements/collapsible_content.dart",,R,{
 "^":"",
 i6:{
@@ -4086,7 +4086,7 @@
 if(z===!0)return
 if(a.nx!=null){a.uo=this.ct(a,C.S4,z,!0)
 this.AV(a,a.GV!==!0,this.gN2(a))}else{z=a.GV
-a.GV=this.ct(a,C.mr,z,z!==!0)}},"$3","gDI",6,0,71,43,44,72],
+a.GV=this.ct(a,C.mr,z,z!==!0)}},"$3","gDI",6,0,73,43,44,74],
 static:{U9:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -4611,7 +4611,7 @@
 z=P.YM(null,null,null,null,null)
 return new P.uo(c,d,z)},"$5","Is",10,0,41],
 C6:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:[function(){H.cv()
 this.a.$0()},"$0",null,0,0,null,"call"],
 $isEH:true},
@@ -4621,7 +4621,7 @@
 Ik:{
 "^":"O9;Y8"},
 LR:{
-"^":"oh;Ae@,iE@,SJ@,Y8,pN,o7,Bd,Lj,Gv,lz,nb",
+"^":"Bx;Ae@,iE@,SJ@,Y8,pN,o7,Bd,Lj,Gv,lz,nb",
 gY8:function(){return this.Y8},
 uR:function(a){var z=this.Ae
 if(typeof z!=="number")return z.i()
@@ -4663,9 +4663,9 @@
 q7:function(){if((this.Gv&4)!==0)return new P.lj("Cannot add new events after calling close")
 return new P.lj("Cannot add new events while doing an addStream")},
 h:[function(a,b){if(this.Gv>=4)throw H.b(this.q7())
-this.Iv(b)},"$1","ght",2,0,function(){return H.IG(function(a){return{func:"lU",void:true,args:[a]}},this.$receiver,"WV")},90],
+this.Iv(b)},"$1","ght",2,0,function(){return H.IG(function(a){return{func:"lU",void:true,args:[a]}},this.$receiver,"WV")},92],
 js:[function(a,b){if(this.Gv>=4)throw H.b(this.q7())
-this.pb(a,b)},function(a){return this.js(a,null)},"JT","$2","$1","gGj",2,2,91,20,21,22],
+this.pb(a,b)},function(a){return this.js(a,null)},"JT","$2","$1","gGj",2,2,93,20,21,22],
 S6:function(a){var z,y
 z=this.Gv
 if((z&4)!==0)return this.yx
@@ -4745,25 +4745,29 @@
 "^":"a;",
 $isb8:true},
 w4:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:[function(){var z,y,x,w
 try{this.b.rX(this.a.$0())}catch(x){w=H.Ru(x)
 z=w
 y=new H.XO(x,null)
 this.b.K5(z,y)}},"$0",null,0,0,null,"call"],
 $isEH:true},
+oh:{
+"^":"a;",
+$isoh:true},
 Pf0:{
-"^":"a;"},
+"^":"a;",
+$isoh:true},
 Zf:{
 "^":"Pf0;MM",
 j3:[function(a,b){var z=this.MM
 if(z.Gv!==0)throw H.b(P.w("Future already completed"))
-z.OH(b)},function(a){return this.j3(a,null)},"tZ","$1","$0","gv6",0,2,92,20,18],
-w0:[function(a,b){var z
+z.OH(b)},function(a){return this.j3(a,null)},"tZ","$1","$0","gv6",0,2,94,20,18],
+w0:function(a,b){var z
 if(a==null)throw H.b(P.u("Error must not be null"))
 z=this.MM
 if(z.Gv!==0)throw H.b(P.w("Future already completed"))
-z.CG(a,b)},function(a){return this.w0(a,null)},"rC","$2","$1","gXN",2,2,91,20,21,22]},
+z.CG(a,b)}},
 vs:{
 "^":"a;Gv,Lj<,jk,BQ@,OY,As,qV,o4",
 gcg:function(){return this.Gv>=4},
@@ -4833,8 +4837,8 @@
 CG:function(a,b){if(this.Gv!==0)H.vh(P.w("Future already completed"))
 this.Gv=1
 this.Lj.wr(new P.In(this,a,b))},
-J9:function(a,b){this.OH(a)},
 X8:function(a,b,c){this.CG(a,b)},
+J9:function(a,b){this.OH(a)},
 $isvs:true,
 $isb8:true,
 static:{"^":"ewM,JE,C3n,Xh,NKU",Dt:function(a){return H.VM(new P.vs(0,$.X3,null,null,null,null,null,null),[a])},PG:function(a,b){var z=H.VM(new P.vs(0,$.X3,null,null,null,null,null,null),[b])
@@ -4889,7 +4893,7 @@
 y=b
 b=q}}}},
 da:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:[function(){P.HZ(this.a,this.b)},"$0",null,0,0,null,"call"],
 $isEH:true},
 U7:{
@@ -4897,23 +4901,23 @@
 $1:[function(a){this.a.R8(a)},"$1",null,2,0,null,18,"call"],
 $isEH:true},
 vr:{
-"^":"Tp:93;b",
+"^":"Tp:95;b",
 $2:[function(a,b){this.b.K5(a,b)},function(a){return this.$2(a,null)},"$1","$2",null,null,2,2,null,20,21,22,"call"],
 $isEH:true},
 cX:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:[function(){P.A9(this.b,this.a)},"$0",null,0,0,null,"call"],
 $isEH:true},
 eX:{
-"^":"Tp:64;c,d",
+"^":"Tp:66;c,d",
 $0:[function(){this.c.R8(this.d)},"$0",null,0,0,null,"call"],
 $isEH:true},
 In:{
-"^":"Tp:64;a,b,c",
+"^":"Tp:66;a,b,c",
 $0:[function(){this.a.K5(this.b,this.c)},"$0",null,0,0,null,"call"],
 $isEH:true},
 rq:{
-"^":"Tp:94;b,d,e,f",
+"^":"Tp:96;b,d,e,f",
 $0:function(){var z,y,x,w
 try{this.b.c=this.f.FI(this.d.gO1(),this.e)
 return!0}catch(x){w=H.Ru(x)
@@ -4980,10 +4984,10 @@
 $isEH:true},
 jZ:{
 "^":"Tp:10;c,HZ",
-$1:[function(a){P.HZ(this.c.e,this.HZ)},"$1",null,2,0,null,95,"call"],
+$1:[function(a){P.HZ(this.c.e,this.HZ)},"$1",null,2,0,null,97,"call"],
 $isEH:true},
 FZ:{
-"^":"Tp:93;a,mG",
+"^":"Tp:95;a,mG",
 $2:[function(a,b){var z,y
 z=this.a
 if(!J.x(z.a).$isvs){y=P.Dt(null)
@@ -4995,8 +4999,8 @@
 Ki:function(a){return this.FR.$0()}},
 cb:{
 "^":"a;",
-ez:[function(a,b){return H.VM(new P.c9(b,this),[H.ip(this,"cb",0),null])},"$1","gIr",2,0,function(){return H.IG(function(a){return{func:"bp",ret:P.cb,args:[{func:"Lf",args:[a]}]}},this.$receiver,"cb")},96],
-Ft:[function(a,b){return H.VM(new P.Bg(b,this),[H.ip(this,"cb",0),null])},"$1","git",2,0,function(){return H.IG(function(a){return{func:"xv",ret:P.cb,args:[{func:"Xy",ret:P.QV,args:[a]}]}},this.$receiver,"cb")},96],
+ez:[function(a,b){return H.VM(new P.c9(b,this),[H.ip(this,"cb",0),null])},"$1","gIr",2,0,function(){return H.IG(function(a){return{func:"bp",ret:P.cb,args:[{func:"Lf",args:[a]}]}},this.$receiver,"cb")},98],
+Ft:[function(a,b){return H.VM(new P.Bg(b,this),[H.ip(this,"cb",0),null])},"$1","git",2,0,function(){return H.IG(function(a){return{func:"xv",ret:P.cb,args:[{func:"Xy",ret:P.QV,args:[a]}]}},this.$receiver,"cb")},98],
 tg:function(a,b){var z,y
 z={}
 y=P.Dt(P.a2)
@@ -5027,6 +5031,12 @@
 z.a=null
 z.a=this.KR(new P.qg(z,y),!0,new P.yB(y),y.gaq())
 return y},
+geK:function(a){var z,y
+z={}
+y=P.Dt(H.ip(this,"cb",0))
+z.a=null
+z.a=this.KR(new P.lU(z,this,y),!0,new P.xp(y),y.gaq())
+return y},
 grZ:function(a){var z,y
 z={}
 y=P.Dt(H.ip(this,"cb",0))
@@ -5040,28 +5050,28 @@
 $1:[function(a){var z,y
 z=this.a
 y=this.d
-P.FE(new P.BE(this.c,a),new P.Oh(z,y),P.TB(z.a,y))},"$1",null,2,0,null,97,"call"],
+P.FE(new P.BE(this.c,a),new P.Oh(z,y),P.TB(z.a,y))},"$1",null,2,0,null,99,"call"],
 $isEH:true,
 $signature:function(){return H.IG(function(a){return{func:"Lf",args:[a]}},this.b,"cb")}},
 BE:{
-"^":"Tp:64;e,f",
+"^":"Tp:66;e,f",
 $0:function(){return J.xC(this.f,this.e)},
 $isEH:true},
 Oh:{
-"^":"Tp:98;a,UI",
+"^":"Tp:100;a,UI",
 $1:function(a){if(a===!0)P.Bb(this.a.a,this.UI,!0)},
 $isEH:true},
 kb:{
-"^":"Tp:64;bK",
+"^":"Tp:66;bK",
 $0:[function(){this.bK.rX(!1)},"$0",null,0,0,null,"call"],
 $isEH:true},
 lz:{
 "^":"Tp;a,b,c,d",
-$1:[function(a){P.FE(new P.at(this.c,a),new P.mj(),P.TB(this.a.a,this.d))},"$1",null,2,0,null,97,"call"],
+$1:[function(a){P.FE(new P.at(this.c,a),new P.mj(),P.TB(this.a.a,this.d))},"$1",null,2,0,null,99,"call"],
 $isEH:true,
 $signature:function(){return H.IG(function(a){return{func:"Lf",args:[a]}},this.b,"cb")}},
 at:{
-"^":"Tp:64;e,f",
+"^":"Tp:66;e,f",
 $0:function(){return this.e.$1(this.f)},
 $isEH:true},
 mj:{
@@ -5069,7 +5079,7 @@
 $1:function(a){},
 $isEH:true},
 ib:{
-"^":"Tp:64;UI",
+"^":"Tp:66;UI",
 $0:[function(){this.UI.rX(null)},"$0",null,0,0,null,"call"],
 $isEH:true},
 Ia:{
@@ -5077,19 +5087,19 @@
 $1:[function(a){var z,y
 z=this.a
 y=this.d
-P.FE(new P.WN(this.c,a),new P.XPB(z,y),P.TB(z.a,y))},"$1",null,2,0,null,97,"call"],
+P.FE(new P.WN(this.c,a),new P.XPB(z,y),P.TB(z.a,y))},"$1",null,2,0,null,99,"call"],
 $isEH:true,
 $signature:function(){return H.IG(function(a){return{func:"Lf",args:[a]}},this.b,"cb")}},
 WN:{
-"^":"Tp:64;e,f",
+"^":"Tp:66;e,f",
 $0:function(){return this.e.$1(this.f)},
 $isEH:true},
 XPB:{
-"^":"Tp:98;a,UI",
+"^":"Tp:100;a,UI",
 $1:function(a){if(a===!0)P.Bb(this.a.a,this.UI,!0)},
 $isEH:true},
 BSd:{
-"^":"Tp:64;bK",
+"^":"Tp:66;bK",
 $0:[function(){this.bK.rX(!1)},"$0",null,0,0,null,"call"],
 $isEH:true},
 uO:{
@@ -5097,7 +5107,7 @@
 $1:[function(a){++this.a.a},"$1",null,2,0,null,11,"call"],
 $isEH:true},
 hh:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:[function(){this.b.rX(this.a.a)},"$0",null,0,0,null,"call"],
 $isEH:true},
 qg:{
@@ -5105,9 +5115,18 @@
 $1:[function(a){P.Bb(this.a.a,this.b,!1)},"$1",null,2,0,null,11,"call"],
 $isEH:true},
 yB:{
-"^":"Tp:64;c",
+"^":"Tp:66;c",
 $0:[function(){this.c.rX(!0)},"$0",null,0,0,null,"call"],
 $isEH:true},
+lU:{
+"^":"Tp;a,b,c",
+$1:[function(a){P.Bb(this.a.a,this.c,a)},"$1",null,2,0,null,18,"call"],
+$isEH:true,
+$signature:function(){return H.IG(function(a){return{func:"Lf",args:[a]}},this.b,"cb")}},
+xp:{
+"^":"Tp:66;d",
+$0:[function(){this.d.Lp(new P.lj("No elements"))},"$0",null,0,0,null,"call"],
+$isEH:true},
 UH:{
 "^":"Tp;a,b",
 $1:[function(a){var z=this.a
@@ -5116,7 +5135,7 @@
 $isEH:true,
 $signature:function(){return H.IG(function(a){return{func:"Lf",args:[a]}},this.b,"cb")}},
 Z5:{
-"^":"Tp:64;a,c",
+"^":"Tp:66;a,c",
 $0:[function(){var z=this.a
 if(z.b){this.c.rX(z.a)
 return}this.c.Lp(new P.lj("No elements"))},"$0",null,0,0,null,"call"],
@@ -5148,7 +5167,7 @@
 if(!J.x(b).$isO9)return!1
 return b.Y8===this.Y8},
 $isO9:true},
-oh:{
+Bx:{
 "^":"KA;Y8<",
 tA:function(){return this.gY8().j0(this)},
 uO:[function(){this.gY8()},"$0","gp4",0,0,15],
@@ -5168,7 +5187,7 @@
 this.Gv=(z+128|4)>>>0
 if(b!=null)b.wM(this.gDQ(this))
 if(z<128&&this.nb!=null){y=this.nb
-if(y.Gv===1)y.Gv=3}if((z&4)===0&&(this.Gv&32)===0)this.J7(this.gp4())},function(a){return this.Fv(a,null)},"yy","$1","$0","gX0",0,2,99,20,100],
+if(y.Gv===1)y.Gv=3}if((z&4)===0&&(this.Gv&32)===0)this.J7(this.gp4())},function(a){return this.Fv(a,null)},"yy","$1","$0","gX0",0,2,101,20,102],
 zl:[function(a){var z=this.Gv
 if((z&8)!==0)return
 if(z>=128){z-=128
@@ -5315,7 +5334,7 @@
 return}P.rb(new P.Vd(this,a))
 this.Gv=1}},
 Vd:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:[function(){var z,y
 z=this.a
 y=z.Gv
@@ -5340,15 +5359,15 @@
 this.N6=null
 this.zR=null}},
 dR:{
-"^":"Tp:64;a,b,c",
+"^":"Tp:66;a,b,c",
 $0:function(){return this.a.K5(this.b,this.c)},
 $isEH:true},
 uR:{
-"^":"Tp:101;a,b",
+"^":"Tp:103;a,b",
 $2:function(a,b){return P.NX(this.a,this.b,a,b)},
 $isEH:true},
 Q0:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:function(){return this.a.rX(this.b)},
 $isEH:true},
 og:{
@@ -5384,8 +5403,8 @@
 tA:function(){var z=this.WS
 if(z!=null){this.WS=null
 z.ed()}return},
-vx:[function(a){this.UY.ut(a,this)},"$1","gOa",2,0,function(){return H.IG(function(a,b){return{func:"wa",void:true,args:[a]}},this.$receiver,"fB")},90],
-xL:[function(a,b){this.oJ(a,b)},"$2","gRE",4,0,102,21,22],
+vx:[function(a){this.UY.ut(a,this)},"$1","gOa",2,0,function(){return H.IG(function(a,b){return{func:"wa",void:true,args:[a]}},this.$receiver,"fB")},92],
+xL:[function(a,b){this.oJ(a,b)},"$2","gRE",4,0,104,21,22],
 fE:[function(){this.YB()},"$0","gH1",0,0,15],
 Ri:function(a,b,c,d){var z,y
 z=this.gOa()
@@ -5444,7 +5463,7 @@
 qp:function(a){return this.il.$1$specification(a)}},
 qK:{
 "^":"a;"},
-xp:{
+dl:{
 "^":"a;"},
 Id:{
 "^":"a;nU",
@@ -5517,11 +5536,11 @@
 if(b)return new P.Cg(this,z)
 else return new P.Hs(this,z)}},
 TF:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:[function(){return this.a.bH(this.b)},"$0",null,0,0,null,"call"],
 $isEH:true},
 Xz:{
-"^":"Tp:64;c,d",
+"^":"Tp:66;c,d",
 $0:[function(){return this.c.Gr(this.d)},"$0",null,0,0,null,"call"],
 $isEH:true},
 Cg:{
@@ -5553,11 +5572,11 @@
 uN:function(a,b){return new P.Id(this).dJ(this,a,b)},
 Ch:function(a,b){new P.Id(this).RB(0,this,b)}},
 FO:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:[function(){P.IA(new P.eM(this.a,this.b))},"$0",null,0,0,null,"call"],
 $isEH:true},
 eM:{
-"^":"Tp:64;c,d",
+"^":"Tp:66;c,d",
 $0:[function(){var z,y
 z=this.c
 P.FL("Uncaught Error: "+H.d(z))
@@ -5567,8 +5586,8 @@
 throw H.b(z)},"$0",null,0,0,null,"call"],
 $isEH:true},
 Uez:{
-"^":"Tp:67;a",
-$2:[function(a,b){this.a.u(0,a,b)},"$2",null,4,0,null,68,18,"call"],
+"^":"Tp:69;a",
+$2:[function(a,b){this.a.u(0,a,b)},"$2",null,4,0,null,70,18,"call"],
 $isEH:true},
 AH:{
 "^":"a;",
@@ -5795,7 +5814,7 @@
 return z}}},
 oi:{
 "^":"Tp:10;a",
-$1:[function(a){return this.a.t(0,a)},"$1",null,2,0,null,103,"call"],
+$1:[function(a){return this.a.t(0,a)},"$1",null,2,0,null,105,"call"],
 $isEH:true},
 DJ:{
 "^":"Tp;a",
@@ -5982,7 +6001,7 @@
 return z}}},
 a1:{
 "^":"Tp:10;a",
-$1:[function(a){return this.a.t(0,a)},"$1",null,2,0,null,103,"call"],
+$1:[function(a){return this.a.t(0,a)},"$1",null,2,0,null,105,"call"],
 $isEH:true},
 pk:{
 "^":"Tp;a",
@@ -6447,7 +6466,7 @@
 $isQV:true,
 $asQV:null},
 W0:{
-"^":"Tp:67;a,b",
+"^":"Tp:69;a,b",
 $2:function(a,b){var z=this.a
 if(!z.a)this.b.KF(", ")
 z.a=!1
@@ -6807,7 +6826,7 @@
 throw H.b(P.cD(String(y)))}return P.Uw(z,b)},
 NC:[function(a){return a.Lt()},"$1","bx",2,0,46,47],
 hW:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return b},
 $isEH:true},
 f1:{
@@ -6949,7 +6968,7 @@
 pg:function(a){var z=this.ol
 if(0>=z.length)return H.e(z,0)
 z.pop()},
-static:{"^":"P3,hyY,IE,Jyf,NoV,fg,Wk,pe,E7,MU,vk,NXu,PBv,QVv",uI:function(a,b,c){return new P.Sh(b,a,[])},Vg:function(a,b,c){var z
+static:{"^":"P3,hyY,IE,Jyf,NoV,HVe,Wk,pe,E7,MU,vk,NXu,PBv,QVv",uI:function(a,b,c){return new P.Sh(b,a,[])},Vg:function(a,b,c){var z
 b=P.bx()
 z=P.p9("")
 P.uI(z,b,c).C7(a)
@@ -6970,7 +6989,7 @@
 return C.Nm.aM(y,0,x.L8)},
 $aszF:function(){return[P.qU,[P.WO,P.KN]]}},
 Yu:{
-"^":"a;So,L8,IT",
+"^":"a;aQ,L8,IT",
 GT:function(a,b){var z,y,x,w,v
 z=this.IT
 y=this.L8
@@ -7088,11 +7107,11 @@
 y.vM+=u
 z.$2(v,y)}}return y.vM},
 Y25:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){this.a.u(0,a.gfN(),b)},
 $isEH:true},
 CL:{
-"^":"Tp:104;a",
+"^":"Tp:106;a",
 $2:function(a,b){var z=this.a
 if(z.b>0)z.a.KF(", ")
 z.a.KF(a.gfN())
@@ -7174,12 +7193,12 @@
 return"00"+a},h0:function(a){if(a>=10)return""+a
 return"0"+a}}},
 MF:{
-"^":"Tp:105;",
+"^":"Tp:107;",
 $1:function(a){if(a==null)return 0
 return H.BU(a,null,null)},
 $isEH:true},
 Rq:{
-"^":"Tp:106;",
+"^":"Tp:108;",
 $1:function(a){if(a==null)return 0
 return H.RR(a,null)},
 $isEH:true},
@@ -7421,28 +7440,25 @@
 "^":"a;",
 $isuq:true},
 rI:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){var z=J.Wx(a)
 b.KF(H.Lw(C.xB.j("0123456789ABCDEF",z.m(a,4))))
 b.KF(H.Lw(C.xB.j("0123456789ABCDEF",z.i(a,15))))},
 $isEH:true}}],["dart.dom.html","dart:html",,W,{
 "^":"",
 r3:function(a,b){return document.createElement(a)},
-It:function(a,b,c){return W.lt(a,null,null,b,null,null,null,c).ml(new W.KxY())},
-lt:function(a,b,c,d,e,f,g,h){var z,y,x
-z=W.fJ
-y=H.VM(new P.Zf(P.Dt(z)),[z])
-x=new XMLHttpRequest()
-C.W3.kP(x,"GET",a,!0)
-z=H.VM(new W.RO(x,C.LF.Ph,!1),[null])
-H.VM(new W.fd(0,z.bi,z.Ph,W.aF(new W.bU(y,x)),z.Sg),[H.Kp(z,0)]).Zz()
-z=H.VM(new W.RO(x,C.MD.Ph,!1),[null])
-H.VM(new W.fd(0,z.bi,z.Ph,W.aF(y.gXN()),z.Sg),[H.Kp(z,0)]).Zz()
-x.send()
-return y.MM},
 ED:function(a){var z,y
 z=document.createElement("input",null)
 if(a!=null)try{J.iM(z,a)}catch(y){H.Ru(y)}return z},
+pS:function(a,b){var z,y
+z=typeof a!=="string"
+if((!z||a==null)&&!0)return new WebSocket(a)
+y=H.RB(b,"$isWO",[P.qU],"$asWO")
+if(!y);y=!z||a==null
+if(y)return new WebSocket(a,b)
+z=!z||a==null
+if(z)return new WebSocket(a,b)
+throw H.b(P.u("Incorrect number or type of arguments"))},
 VC:function(a,b){a=536870911&a+b
 a=536870911&a+((524287&a)<<10>>>0)
 return a^a>>>6},
@@ -7461,12 +7477,11 @@
 Hx:[function(a){return J.UC(a)},"$1","Z6",2,0,10,51],
 Qp:[function(a,b,c,d){return J.df(a,b,c,d)},"$4","A6",8,0,52,51,53,54,55],
 aF:function(a){if(J.xC($.X3,C.NU))return a
-if(a==null)return
 return $.X3.Nf(a,!0)},
 Bo:{
 "^":"h4;",
-"%":"HTMLAppletElement|HTMLBRElement|HTMLContentElement|HTMLDListElement|HTMLDataListElement|HTMLDirectoryElement|HTMLDivElement|HTMLFontElement|HTMLFrameElement|HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLMarqueeElement|HTMLMenuElement|HTMLModElement|HTMLParagraphElement|HTMLPreElement|HTMLQuoteElement|HTMLShadowElement|HTMLSpanElement|HTMLTableCaptionElement|HTMLTableColElement|HTMLTitleElement|HTMLUListElement|HTMLUnknownElement;HTMLElement;jpR|Ot|ir|LPc|hV|uL|Vf|G6|pv|xI|eW|Vfx|aC|VY|Dsd|Be|tuj|i6|Xfs|JI|Vct|ZP|D13|nJ|SaM|Eg|i7|WZq|Gk|pva|Nr|cda|MJ|T53|DK|waa|BS|V3|Vb|V5|Ly|pR|V8|hx|V10|L4|Mb|V11|mO|DE|V12|U1|qh|V13|oF|V14|Q6|uE|V15|Zn|V16|n5|V17|Ma|wN|V18|ds|V19|ou|ZzR|av|V20|uz|V21|kK|oa|V22|St|V23|IW|V24|Qh|V25|Oz|V26|YA|V27|qk|V28|vj|LU|V29|CX|V30|md|V31|Bm|V32|Ya|V33|Ww|V34|G1|V35|fl|V36|UK|V37|wM|V38|F1|V39|qZ|V40|ov|oEY|kn|V41|fI|V42|zM|V43|Rk|V44|Ti|KAf|CY|V45|nm|V46|uw|I5|V47|el"},
-zw:{
+"%":"HTMLAppletElement|HTMLBRElement|HTMLContentElement|HTMLDListElement|HTMLDataListElement|HTMLDirectoryElement|HTMLDivElement|HTMLFontElement|HTMLFrameElement|HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLMarqueeElement|HTMLMenuElement|HTMLModElement|HTMLParagraphElement|HTMLPreElement|HTMLQuoteElement|HTMLShadowElement|HTMLSpanElement|HTMLTableCaptionElement|HTMLTableColElement|HTMLTitleElement|HTMLUListElement|HTMLUnknownElement;HTMLElement;jpR|Ot|ir|LPc|hV|uL|Vf|G6|pv|xI|eW|Vfx|aC|VY|Dsd|Be|tuj|i6|Xfs|JI|Vct|ZP|D13|nJ|SaM|Eg|i7|WZq|Gk|pva|Nr|cda|MJ|T53|DK|waa|BS|V3|Vb|V5|Ly|pR|V9|hx|V10|L4|Mb|V11|mO|DE|V12|U1|qh|V13|oF|V14|Q6|uE|V15|Zn|V16|n5|V17|Ma|wN|V18|ds|V19|ou|ZzR|av|V20|uz|V21|kK|oa|V22|St|V23|IW|V24|Qh|V25|Oz|V26|YA|V27|qk|V28|vj|LU|V29|CX|V30|md|V31|Bm|V32|Ya|V33|Ww|V34|G1|V35|fl|V36|UK|V37|wM|V38|F1|V39|qZ|V40|ov|oEY|kn|V41|fI|V42|zM|V43|Rk|V44|Ti|KAf|CY|V45|nm|V46|uw|I5|V47|el"},
+Yyn:{
 "^":"Gv;",
 $isWO:true,
 $asWO:function(){return[W.QI]},
@@ -7519,6 +7534,7 @@
 "%":"Comment;CharacterData"},
 K3:{
 "^":"ea;tT:code=",
+$isK3:true,
 "%":"CloseEvent"},
 y4:{
 "^":"w6O;Rn:data=",
@@ -7662,12 +7678,11 @@
 $isXj:true,
 "%":"HTMLCollection|HTMLFormControlsCollection|HTMLOptionsCollection"},
 fJ:{
-"^":"rk;xN:responseText=,pf:status=",
+"^":"rk;pf:status=",
 gbA:function(a){return W.Z9(a.response)},
 R3:function(a,b,c,d,e,f){return a.open(b,c,d,f,e)},
 kP:function(a,b,c,d){return a.open(b,c,d)},
 wR:function(a,b){return a.send(b)},
-$isfJ:true,
 "%":"XMLHttpRequest"},
 rk:{
 "^":"PZ;",
@@ -7837,7 +7852,6 @@
 "%":"HTMLProgressElement"},
 kQ:{
 "^":"ea;ox:loaded=",
-$iskQ:true,
 "%":"XMLHttpRequestProgressEvent;ProgressEvent"},
 bXi:{
 "^":"kQ;O3:url=",
@@ -7921,6 +7935,13 @@
 SW:{
 "^":"eL;fg:height},R:width}",
 "%":"HTMLVideoElement"},
+lf:{
+"^":"PZ;yv:protocol=,O3:url=",
+LG:function(a,b,c){return a.close(b,c)},
+S6:function(a){return a.close()},
+wR:function(a,b){return a.send(b)},
+$islf:true,
+"%":"WebSocket"},
 K5:{
 "^":"PZ;oc:name%,pf:status%",
 geT:function(a){return W.Pv(a.parent)},
@@ -8125,26 +8146,6 @@
 $isyN:true,
 $isQV:true,
 $asQV:function(){return[W.KV]}},
-KxY:{
-"^":"Tp:10;",
-$1:[function(a){return J.Du(a)},"$1",null,2,0,null,107,"call"],
-$isEH:true},
-bU2:{
-"^":"Tp:67;a",
-$2:function(a,b){this.a.setRequestHeader(a,b)},
-$isEH:true},
-bU:{
-"^":"Tp:10;b,c",
-$1:[function(a){var z,y,x
-z=this.c
-y=z.status
-if(typeof y!=="number")return y.F()
-y=y>=200&&y<300||y===0||y===304
-x=this.b
-if(y){y=x.MM
-if(y.Gv!==0)H.vh(P.w("Future already completed"))
-y.OH(z)}else x.rC(a)},"$1",null,2,0,null,1,"call"],
-$isEH:true},
 wi:{
 "^":"rm;NL",
 grZ:function(a){var z=this.NL.lastChild
@@ -8269,7 +8270,7 @@
 $isZ0:true,
 $asZ0:function(){return[P.qU,P.qU]}},
 Zc:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){this.a.u(0,a,b)},
 $isEH:true},
 E9:{
@@ -8376,7 +8377,7 @@
 return},
 Fv:[function(a,b){if(this.bi==null)return;++this.VP
 this.Jc()
-if(b!=null)b.wM(this.gDQ(this))},function(a){return this.Fv(a,null)},"yy","$1","$0","gX0",0,2,99,20,100],
+if(b!=null)b.wM(this.gDQ(this))},function(a){return this.Fv(a,null)},"yy","$1","$0","gX0",0,2,101,20,102],
 gUF:function(){return this.VP>0},
 zl:[function(a){if(this.bi==null||this.VP<=0)return;--this.VP
 this.Zz()},"$0","gDQ",0,0,15],
@@ -8399,7 +8400,7 @@
 this.aV.S6(0)},"$0","gJK",0,0,15],
 KS:function(a){this.aV=P.bK(this.gJK(this),null,!0,a)}},
 rC:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:[function(){return this.a.Rz(0,this.b)},"$0",null,0,0,null,"call"],
 $isEH:true},
 Gm:{
@@ -8714,7 +8715,7 @@
 $isr7:true,
 static:{mt:function(a){return new P.r7(P.xZ(a,!0))}}},
 Tz:{
-"^":"F6;eh",
+"^":"WkF;eh",
 t:function(a,b){var z
 if(typeof b==="number"&&b===C.CD.yu(b)){if(typeof b==="number"&&Math.floor(b)===b)z=b<0||b>=this.gB(this)
 else z=!1
@@ -8748,7 +8749,7 @@
 Jd:function(a){return this.XP(a,null)},
 static:{oY:function(a,b,c){if(a<0||a>c)throw H.b(P.TE(a,0,c))
 if(b<a||b>c)throw H.b(P.TE(b,a,c))}}},
-F6:{
+WkF:{
 "^":"E4+lD;",
 $isWO:true,
 $asWO:null,
@@ -9274,7 +9275,7 @@
 z=this.ct(a,C.eh,a.Ek,z)
 a.Ek=z
 if(J.xC(z,"1-line")){z=J.JA(a.a3,"\n"," ")
-a.a3=this.ct(a,C.mi,a.a3,z)}},"$3","gxb",6,0,86,1,87,88],
+a.a3=this.ct(a,C.mi,a.a3,z)}},"$3","gxb",6,0,88,1,89,90],
 Z1:[function(a,b,c,d){var z,y,x
 J.fD(b)
 z=a.a3
@@ -9283,9 +9284,9 @@
 x=R.tB(y)
 J.kW(x,"expr",z)
 J.Vk(a.y4,0,x)
-this.LY(a,z).ml(new L.YW(x))}},"$3","gZm",6,0,86,1,87,88],
+this.LY(a,z).ml(new L.YW(x))}},"$3","gZm",6,0,88,1,89,90],
 YC:[function(a,b){var z=J.iz(J.l2(b),"expr")
-a.a3=this.ct(a,C.mi,a.a3,z)},"$1","gHo",2,0,108,1],
+a.a3=this.ct(a,C.mi,a.a3,z)},"$1","gHo",2,0,109,1],
 static:{Rp:function(a){var z,y,x,w,v
 z=R.tB([])
 y=$.XZ()
@@ -9306,7 +9307,7 @@
 $isd3:true},
 YW:{
 "^":"Tp:10;a",
-$1:[function(a){J.kW(this.a,"value",a)},"$1",null,2,0,null,109,"call"],
+$1:[function(a){J.kW(this.a,"value",a)},"$1",null,2,0,null,110,"call"],
 $isEH:true}}],["eval_link_element","package:observatory/src/elements/eval_link.dart",,R,{
 "^":"",
 Eg:{
@@ -9327,7 +9328,7 @@
 if(z===!0)return
 if(a.bY!=null){a.fe=this.ct(a,C.S4,z,!0)
 a.oy=this.ct(a,C.UY,a.oy,null)
-this.LY(a,a.jv).ml(new R.uv(a)).wM(new R.Ou(a))}},"$3","gbN",6,0,71,43,44,72],
+this.LY(a,a.jv).ml(new R.uv(a)).wM(new R.Ou(a))}},"$3","gbN",6,0,73,43,44,74],
 static:{fL:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -9349,12 +9350,12 @@
 "^":"ir+Pi;",
 $isd3:true},
 uv:{
-"^":"Tp:110;a",
+"^":"Tp:111;a",
 $1:[function(a){var z=this.a
-z.oy=J.Q5(z,C.UY,z.oy,a)},"$1",null,2,0,null,77,"call"],
+z.oy=J.Q5(z,C.UY,z.oy,a)},"$1",null,2,0,null,79,"call"],
 $isEH:true},
 Ou:{
-"^":"Tp:64;b",
+"^":"Tp:66;b",
 $0:[function(){var z=this.b
 z.fe=J.Q5(z,C.S4,z.fe,!1)},"$0",null,0,0,null,"call"],
 $isEH:true}}],["field_ref_element","package:observatory/src/elements/field_ref.dart",,D,{
@@ -9379,7 +9380,7 @@
 "^":"WZq;KV,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gt0:function(a){return a.KV},
 st0:function(a,b){a.KV=this.ct(a,C.WQ,a.KV,b)},
-RF:[function(a,b){J.LE(a.KV).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.KV).wM(b)},"$1","gvC",2,0,17,84],
 static:{Sy:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -9400,7 +9401,7 @@
 "^":"pva;DC,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gpM:function(a){return a.DC},
 spM:function(a,b){a.DC=this.ct(a,C.Mc,a.DC,b)},
-RF:[function(a,b){J.LE(a.DC).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.DC).wM(b)},"$1","gvC",2,0,17,84],
 static:{na:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -9531,7 +9532,7 @@
 break
 default:a.ZZ=this.ct(a,C.Lc,y,"UNKNOWN")
 break}},"$1","gnp",2,0,17,54],
-RF:[function(a,b){J.LE(a.P6).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.P6).wM(b)},"$1","gvC",2,0,17,84],
 static:{N0:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -9550,7 +9551,7 @@
 "^":"",
 Hz:{
 "^":"a;zE,mS",
-PY:[function(){return new O.Hz(this.zE,this.mS+4)},"$0","gaw",0,0,111],
+PY:[function(){return new O.Hz(this.zE,this.mS+4)},"$0","gaw",0,0,112],
 gvH:function(a){return C.CD.cU(this.mS,4)},
 static:{"^":"Q0z",x6:function(a,b){var z,y,x
 z=b.gy(b)
@@ -9639,9 +9640,9 @@
 w=z.mS
 v=a.UL.t(0,a.Ge.t(0,this.LV(a,C.yp.Mu(J.Qd(z.zE),w,w+4))))
 z=J.xC(v,"")?"-":H.d(v)+" "+x
-a.PA=this.ct(a,C.PM,a.PA,z)},"$1","gmo",2,0,108,76],
+a.PA=this.ct(a,C.PM,a.PA,z)},"$1","gmo",2,0,109,78],
 X7:[function(a,b){var z=J.cR(this.WE(a,J.HF(b)).Yu,16)
-window.location.hash="/"+H.d(J.Ds(J.aT(a.oj)))+"/address/"+z},"$1","gJb",2,0,108,76],
+window.location.hash="/"+H.d(J.Ds(J.aT(a.oj)))+"/address/"+z},"$1","gJb",2,0,109,78],
 My:function(a){var z,y,x,w
 z=a.oj
 if(z==null||a.hi==null)return
@@ -9709,7 +9710,7 @@
 P.Iw(new O.R5(a,b),null)},
 RF:[function(a,b){var z=a.oj
 if(z==null)return
-J.aT(z).cv("heapmap").ml(new O.aG(a)).OA(new O.aO()).wM(b)},"$1","gvC",2,0,17,82],
+J.aT(z).cv("heapmap").ml(new O.aG(a)).OA(new O.aO()).wM(b)},"$1","gvC",2,0,17,84],
 nY:[function(a,b){P.Iw(new O.oc(a),null)},"$1","gR2",2,0,17,54],
 static:{"^":"nK,fM,SoT",pn:function(a){var z,y,x,w,v,u,t
 z=P.Fl(null,null)
@@ -9733,20 +9734,20 @@
 "^":"uL+Pi;",
 $isd3:true},
 R5:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:function(){J.fi(this.a,this.b+1)},
 $isEH:true},
 aG:{
-"^":"Tp:113;a",
+"^":"Tp:114;a",
 $1:[function(a){var z=this.a
-z.oj=J.Q5(z,C.QH,z.oj,a)},"$1",null,2,0,null,112,"call"],
+z.oj=J.Q5(z,C.QH,z.oj,a)},"$1",null,2,0,null,113,"call"],
 $isEH:true},
 aO:{
-"^":"Tp:67;",
-$2:[function(a,b){N.QM("").To(H.d(a)+" "+H.d(b))},"$2",null,4,0,null,1,114,"call"],
+"^":"Tp:69;",
+$2:[function(a,b){N.QM("").To(H.d(a)+" "+H.d(b))},"$2",null,4,0,null,1,115,"call"],
 $isEH:true},
 oc:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:function(){J.vP(this.a)},
 $isEH:true}}],["heap_profile_element","package:observatory/src/elements/heap_profile.dart",,K,{
 "^":"",
@@ -9840,7 +9841,7 @@
 if(!!J.x(d).$isv6){z=a.Rp.gxp()
 y=d.cellIndex
 if(z==null?y!=null:z!==y){a.Rp.sxp(y)
-J.II(a.Rp)}}},"$3","gQq",6,0,115,1,87,88],
+J.II(a.Rp)}}},"$3","gQq",6,0,116,1,89,90],
 K1:function(a,b){var z,y,x
 z=J.U6(b)
 y=z.t(b,"new")
@@ -9864,13 +9865,13 @@
 return J.ew(J.UQ(z.t(b,"old"),2),J.UQ(z.t(b,"old"),4))}throw H.b(P.a9())},
 RF:[function(a,b){var z=a.Ol
 if(z==null)return
-J.aT(z).cv("/allocationprofile").ml(new K.nx(a)).OA(new K.jm()).wM(b)},"$1","gvC",2,0,17,82],
+J.aT(z).cv("/allocationprofile").ml(new K.nx(a)).OA(new K.jm()).wM(b)},"$1","gvC",2,0,17,84],
 zT:[function(a,b){var z=a.Ol
 if(z==null)return
-J.aT(z).cv("/allocationprofile?gc=full").ml(new K.AN(a)).OA(new K.Ao()).wM(b)},"$1","gyW",2,0,17,82],
+J.aT(z).cv("/allocationprofile?gc=full").ml(new K.AN(a)).OA(new K.Ao()).wM(b)},"$1","gyW",2,0,17,84],
 eJ:[function(a,b){var z=a.Ol
 if(z==null)return
-J.aT(z).cv("/allocationprofile?reset=true").ml(new K.ke(a)).OA(new K.xj()).wM(b)},"$1","gNb",2,0,17,82],
+J.aT(z).cv("/allocationprofile?reset=true").ml(new K.ke(a)).OA(new K.xj()).wM(b)},"$1","gNb",2,0,17,84],
 n1:[function(a,b){var z,y,x,w
 try{this.MQ(a)}catch(x){w=H.Ru(x)
 z=w
@@ -9884,17 +9885,17 @@
 y=b===!0?"new":"old"
 x=J.UQ(J.UQ(z,"heaps"),y)
 z=J.U6(x)
-return C.CD.Sy(J.L9(J.vX(z.t(x,"time"),1000),z.t(x,"collections")),2)+" ms"},"$1","gOd",2,0,116,117],
+return C.CD.Sy(J.L9(J.vX(z.t(x,"time"),1000),z.t(x,"collections")),2)+" ms"},"$1","gOd",2,0,117,118],
 uW:[function(a,b){var z,y
 z=a.Ol
 if(z==null)return""
 y=b===!0?"new":"old"
-return H.d(J.UQ(J.UQ(J.UQ(z,"heaps"),y),"collections"))},"$1","gJN",2,0,116,117],
+return H.d(J.UQ(J.UQ(J.UQ(z,"heaps"),y),"collections"))},"$1","gJN",2,0,117,118],
 Q0:[function(a,b){var z,y
 z=a.Ol
 if(z==null)return""
 y=b===!0?"new":"old"
-return J.r0(J.UQ(J.UQ(J.UQ(z,"heaps"),y),"time"),2)+" secs"},"$1","goN",2,0,116,117],
+return J.r0(J.UQ(J.UQ(J.UQ(z,"heaps"),y),"time"),2)+" secs"},"$1","goN",2,0,117,118],
 Zy:function(a){var z=P.zV(J.UQ($.BY,"DataTable"),null)
 a.GQ=new G.Kf(z)
 z.V7("addColumn",["string","Type"])
@@ -9904,10 +9905,10 @@
 z.V7("addColumn",["string","Type"])
 a.JS.Yb.V7("addColumn",["number","Size"])
 z=H.VM([],[G.Ni])
-z=this.ct(a,C.kG,a.Rp,new G.Vz([new G.zb("Class",G.HP()),new G.zb("Accumulator Size (New)",G.Fx()),new G.zb("Accumulator (New)",G.kh()),new G.zb("Current Size (New)",G.Fx()),new G.zb("Current (New)",G.kh()),new G.zb("Accumulator Size (Old)",G.Fx()),new G.zb("Accumulator (Old)",G.kh()),new G.zb("Current Size (Old)",G.Fx()),new G.zb("Current (Old)",G.kh())],z,[],0,!0,null,null))
+z=this.ct(a,C.kG,a.Rp,new G.Vz([new G.Ktd("Class",G.HP()),new G.Ktd("Accumulator Size (New)",G.Fx()),new G.Ktd("Accumulator (New)",G.kh()),new G.Ktd("Current Size (New)",G.Fx()),new G.Ktd("Current (New)",G.kh()),new G.Ktd("Accumulator Size (Old)",G.Fx()),new G.Ktd("Accumulator (Old)",G.kh()),new G.Ktd("Current Size (Old)",G.Fx()),new G.Ktd("Current (Old)",G.kh())],z,[],0,!0,null,null))
 a.Rp=z
 z.sxp(1)},
-static:{"^":"IJv,bQj,kf,wh,r1K,d6,pC,DY2",Ut:function(a){var z,y,x,w
+static:{"^":"IJv,bQj,kf,wh,r1K,qEV,pC,DY2",Ut:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
 x=P.qU
@@ -9924,31 +9925,31 @@
 "^":"uL+Pi;",
 $isd3:true},
 nx:{
-"^":"Tp:113;a",
+"^":"Tp:114;a",
 $1:[function(a){var z=this.a
-z.Ol=J.Q5(z,C.vb,z.Ol,a)},"$1",null,2,0,null,112,"call"],
+z.Ol=J.Q5(z,C.vb,z.Ol,a)},"$1",null,2,0,null,113,"call"],
 $isEH:true},
 jm:{
-"^":"Tp:67;",
-$2:[function(a,b){N.QM("").To(H.d(a)+" "+H.d(b))},"$2",null,4,0,null,1,114,"call"],
+"^":"Tp:69;",
+$2:[function(a,b){N.QM("").To(H.d(a)+" "+H.d(b))},"$2",null,4,0,null,1,115,"call"],
 $isEH:true},
 AN:{
-"^":"Tp:113;a",
+"^":"Tp:114;a",
 $1:[function(a){var z=this.a
-z.Ol=J.Q5(z,C.vb,z.Ol,a)},"$1",null,2,0,null,112,"call"],
+z.Ol=J.Q5(z,C.vb,z.Ol,a)},"$1",null,2,0,null,113,"call"],
 $isEH:true},
 Ao:{
-"^":"Tp:67;",
-$2:[function(a,b){N.QM("").To(H.d(a)+" "+H.d(b))},"$2",null,4,0,null,1,114,"call"],
+"^":"Tp:69;",
+$2:[function(a,b){N.QM("").To(H.d(a)+" "+H.d(b))},"$2",null,4,0,null,1,115,"call"],
 $isEH:true},
 ke:{
-"^":"Tp:113;a",
+"^":"Tp:114;a",
 $1:[function(a){var z=this.a
-z.Ol=J.Q5(z,C.vb,z.Ol,a)},"$1",null,2,0,null,112,"call"],
+z.Ol=J.Q5(z,C.vb,z.Ol,a)},"$1",null,2,0,null,113,"call"],
 $isEH:true},
 xj:{
-"^":"Tp:67;",
-$2:[function(a,b){N.QM("").To(H.d(a)+" "+H.d(b))},"$2",null,4,0,null,1,114,"call"],
+"^":"Tp:69;",
+$2:[function(a,b){N.QM("").To(H.d(a)+" "+H.d(b))},"$2",null,4,0,null,1,115,"call"],
 $isEH:true}}],["html_common","dart:html_common",,P,{
 "^":"",
 bL:function(a){var z,y
@@ -9981,19 +9982,19 @@
 return y},
 $isEH:true},
 rG:{
-"^":"Tp:118;d",
+"^":"Tp:119;d",
 $1:function(a){var z=this.d
 if(a>=z.length)return H.e(z,a)
 return z[a]},
 $isEH:true},
 fh:{
-"^":"Tp:119;e",
+"^":"Tp:120;e",
 $2:function(a,b){var z=this.e
 if(a>=z.length)return H.e(z,a)
 z[a]=b},
 $isEH:true},
 uS:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:function(){},
 $isEH:true},
 Kk:{
@@ -10031,7 +10032,7 @@
 w[u]=z}return w}throw H.b(P.SY("structured clone of other type"))},
 $isEH:true},
 q1:{
-"^":"Tp:67;a,Gq",
+"^":"Tp:69;a,Gq",
 $2:function(a,b){this.a.a[a]=this.Gq.$1(b)},
 $isEH:true},
 CA:{
@@ -10045,13 +10046,13 @@
 return y},
 $isEH:true},
 D6:{
-"^":"Tp:118;c",
+"^":"Tp:119;c",
 $1:function(a){var z=this.c
 if(a>=z.length)return H.e(z,a)
 return z[a]},
 $isEH:true},
 KC:{
-"^":"Tp:119;d",
+"^":"Tp:120;d",
 $2:function(a,b){var z=this.d
 if(a>=z.length)return H.e(z,a)
 z[a]=b},
@@ -10098,11 +10099,11 @@
 aN:function(a,b){this.lF().aN(0,b)},
 zV:function(a,b){return this.lF().zV(0,b)},
 ez:[function(a,b){var z=this.lF()
-return H.VM(new H.xy(z,b),[H.Kp(z,0),null])},"$1","gIr",2,0,120,28],
+return H.VM(new H.xy(z,b),[H.Kp(z,0),null])},"$1","gIr",2,0,121,28],
 ev:function(a,b){var z=this.lF()
 return H.VM(new H.U5(z,b),[H.Kp(z,0)])},
 Ft:[function(a,b){var z=this.lF()
-return H.VM(new H.zs(z,b),[H.Kp(z,0),null])},"$1","git",2,0,121,28],
+return H.VM(new H.zs(z,b),[H.Kp(z,0),null])},"$1","git",2,0,122,28],
 Vr:function(a,b){return this.lF().Vr(0,b)},
 gl0:function(a){return this.lF().X5===0},
 gor:function(a){return this.lF().X5!==0},
@@ -10194,14 +10195,14 @@
 else if(J.xC(J.F8(a.tY),"objects/not-initialized"))return"This object will be initialized once it is accessed by the program."
 else if(J.xC(J.F8(a.tY),"objects/being-initialized"))return"This object is currently being initialized."
 return Q.xI.prototype.gJp.call(this,a)},
-Qx:[function(a){return this.gNe(a)},"$0","gyX",0,0,64],
+Qx:[function(a){return this.gNe(a)},"$0","gyX",0,0,66],
 vQ:[function(a,b,c){var z,y
 z=a.tY
 if(b===!0)J.LE(z).ml(new B.qB(a)).wM(c)
 else{y=J.w1(z)
 y.u(z,"fields",null)
 y.u(z,"elements",null)
-c.$0()}},"$2","gNe",4,0,122,123,82],
+c.$0()}},"$2","gNe",4,0,123,124,84],
 static:{lu:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10223,19 +10224,19 @@
 a.szz(z.t(a,"valueAsString"))}z=this.a
 y=J.RE(z)
 z.tY=y.ct(z,C.xP,z.tY,a)
-y.ct(z,C.xP,0,1)},"$1",null,2,0,null,109,"call"],
+y.ct(z,C.xP,0,1)},"$1",null,2,0,null,110,"call"],
 $isEH:true}}],["instance_view_element","package:observatory/src/elements/instance_view.dart",,Z,{
 "^":"",
 hx:{
-"^":"V8;Xh,f2,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
+"^":"V9;Xh,f2,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 ghf:function(a){return a.Xh},
 shf:function(a,b){a.Xh=this.ct(a,C.fn,a.Xh,b)},
 gIi:function(a){return a.f2},
 sIi:function(a,b){a.f2=this.ct(a,C.XM,a.f2,b)},
-vV:[function(a,b){return J.aT(a.Xh).cv(J.ew(J.F8(a.Xh),"/eval?expr="+P.jW(C.yD,b,C.xM,!1)))},"$1","gZm",2,0,83,84],
-S1:[function(a,b){return J.aT(a.Xh).cv(J.ew(J.F8(a.Xh),"/retained"))},"$1","ghN",2,0,124,85],
-ee:[function(a,b){return J.aT(a.Xh).cv(J.ew(J.F8(a.Xh),"/retaining_path?limit="+H.d(b))).ml(new Z.cL(a))},"$1","gCI",2,0,124,30],
-RF:[function(a,b){J.LE(a.Xh).wM(b)},"$1","gvC",2,0,17,82],
+vV:[function(a,b){return J.aT(a.Xh).cv(J.ew(J.F8(a.Xh),"/eval?expr="+P.jW(C.yD,b,C.xM,!1)))},"$1","gZm",2,0,85,86],
+S1:[function(a,b){return J.aT(a.Xh).cv(J.ew(J.F8(a.Xh),"/retained"))},"$1","ghN",2,0,125,87],
+ee:[function(a,b){return J.aT(a.Xh).cv(J.ew(J.F8(a.Xh),"/retaining_path?limit="+H.d(b))).ml(new Z.cL(a))},"$1","gCI",2,0,125,30],
+RF:[function(a,b){J.LE(a.Xh).wM(b)},"$1","gvC",2,0,17,84],
 static:{BN:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10248,20 +10249,20 @@
 C.ry.ZL(a)
 C.ry.XI(a)
 return a}}},
-V8:{
+V9:{
 "^":"uL+Pi;",
 $isd3:true},
 cL:{
-"^":"Tp:110;a",
+"^":"Tp:111;a",
 $1:[function(a){var z=this.a
-z.f2=J.Q5(z,C.XM,z.f2,a)},"$1",null,2,0,null,77,"call"],
+z.f2=J.Q5(z,C.XM,z.f2,a)},"$1",null,2,0,null,79,"call"],
 $isEH:true}}],["io_view_element","package:observatory/src/elements/io_view.dart",,E,{
 "^":"",
 L4:{
 "^":"V10;PM,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gkm:function(a){return a.PM},
 skm:function(a,b){a.PM=this.ct(a,C.qs,a.PM,b)},
-RF:[function(a,b){J.LE(a.PM).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.PM).wM(b)},"$1","gvC",2,0,17,84],
 static:{p4:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10296,7 +10297,7 @@
 "^":"V11;Cr,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gjx:function(a){return a.Cr},
 sjx:function(a,b){a.Cr=this.ct(a,C.vp,a.Cr,b)},
-RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,84],
 static:{Ch:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10331,7 +10332,7 @@
 "^":"V12;yR,mZ,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gql:function(a){return a.yR},
 sql:function(a,b){a.yR=this.ct(a,C.oj,a.yR,b)},
-RF:[function(a,b){J.LE(a.yR).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.yR).wM(b)},"$1","gvC",2,0,17,84],
 TY:[function(a){J.LE(a.yR).wM(new E.eG(a))},"$0","gW6",0,0,15],
 q0:function(a){Z.uL.prototype.q0.call(this,a)
 a.mZ=P.ww(P.ii(0,0,0,0,0,1),this.gW6(a))},
@@ -10356,7 +10357,7 @@
 "^":"uL+Pi;",
 $isd3:true},
 eG:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:[function(){var z=this.a
 if(z.mZ!=null)z.mZ=P.ww(P.ii(0,0,0,0,0,1),J.AL(z))},"$0",null,0,0,null,"call"],
 $isEH:true},
@@ -10379,7 +10380,7 @@
 "^":"V13;Cr,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gjx:function(a){return a.Cr},
 sjx:function(a,b){a.Cr=this.ct(a,C.vp,a.Cr,b)},
-RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,84],
 static:{J3z:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10399,7 +10400,7 @@
 "^":"V14;uv,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gj4:function(a){return a.uv},
 sj4:function(a,b){a.uv=this.ct(a,C.Ve,a.uv,b)},
-RF:[function(a,b){J.LE(a.uv).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.uv).wM(b)},"$1","gvC",2,0,17,84],
 static:{chF:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10434,7 +10435,7 @@
 "^":"V15;Cr,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gjx:function(a){return a.Cr},
 sjx:function(a,b){a.Cr=this.ct(a,C.vp,a.Cr,b)},
-RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,84],
 static:{xK:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10454,7 +10455,7 @@
 "^":"V16;h1,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gHy:function(a){return a.h1},
 sHy:function(a,b){a.h1=this.ct(a,C.YE,a.h1,b)},
-RF:[function(a,b){J.LE(a.h1).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.h1).wM(b)},"$1","gvC",2,0,17,84],
 static:{xx:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10474,7 +10475,7 @@
 "^":"V17;Cr,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gjx:function(a){return a.Cr},
 sjx:function(a,b){a.Cr=this.ct(a,C.vp,a.Cr,b)},
-RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,84],
 static:{Ii:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10509,7 +10510,7 @@
 "^":"V18;wT,mZ,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gMZ:function(a){return a.wT},
 sMZ:function(a,b){a.wT=this.ct(a,C.jU,a.wT,b)},
-RF:[function(a,b){J.LE(a.wT).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.wT).wM(b)},"$1","gvC",2,0,17,84],
 Yk:[function(a){J.LE(a.wT).wM(new E.Gf(a))},"$0","guT",0,0,15],
 q0:function(a){Z.uL.prototype.q0.call(this,a)
 a.mZ=P.ww(P.ii(0,0,0,0,0,1),this.guT(a))},
@@ -10534,7 +10535,7 @@
 "^":"uL+Pi;",
 $isd3:true},
 Gf:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:[function(){var z=this.a
 if(z.mZ!=null)z.mZ=P.ww(P.ii(0,0,0,0,0,1),J.lB(z))},"$0",null,0,0,null,"call"],
 $isEH:true},
@@ -10542,7 +10543,7 @@
 "^":"V19;Cr,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gjx:function(a){return a.Cr},
 sjx:function(a,b){a.Cr=this.ct(a,C.vp,a.Cr,b)},
-RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,84],
 static:{dv:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10584,7 +10585,7 @@
 gNN:function(a){return a.RX},
 Fn:function(a){return this.gNN(a).$0()},
 sNN:function(a,b){a.RX=this.ct(a,C.Wj,a.RX,b)},
-RF:[function(a,b){J.LE(a.RX).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.RX).wM(b)},"$1","gvC",2,0,17,84],
 Yk:[function(a){J.LE(a.RX).wM(new E.Cc(a))},"$0","guT",0,0,15],
 q0:function(a){Z.uL.prototype.q0.call(this,a)
 a.mZ=P.ww(P.ii(0,0,0,0,0,1),this.guT(a))},
@@ -10609,7 +10610,7 @@
 "^":"uL+Pi;",
 $isd3:true},
 Cc:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:[function(){var z=this.a
 if(z.mZ!=null)z.mZ=P.ww(P.ii(0,0,0,0,0,1),J.lB(z))},"$0",null,0,0,null,"call"],
 $isEH:true}}],["isolate_profile_element","package:observatory/src/elements/isolate_profile.dart",,X,{
@@ -10700,7 +10701,7 @@
 this.Dq(a)},
 m5:[function(a,b){this.RF(a,null)},"$1","gb6",2,0,17,54],
 RF:[function(a,b){var z="profile?tags="+H.d(a.VH)
-J.aT(a.ix).cv(z).ml(new X.Xy(a)).wM(b)},"$1","gvC",2,0,17,82],
+J.aT(a.ix).cv(z).ml(new X.Xy(a)).wM(b)},"$1","gvC",2,0,17,84],
 Dq:function(a){if(a.ix==null)return
 this.a8(a)},
 a8:function(a){var z,y,x,w,v,u,t
@@ -10717,8 +10718,8 @@
 x=new H.XO(t,null)
 N.QM("").xH("_buildStackTree",y,x)}if(J.xC(J.q8(a.Hm.WT),1))a.Hm.qU(0)
 this.ct(a,C.ep,null,a.Hm)},
-ka:[function(a,b){return"padding-left: "+b.gyt()*16+"px;"},"$1","gHn",2,0,125,79],
-LZ:[function(a,b){return C.QC[C.jn.Y(b.gyt()-1,9)]},"$1","gbw",2,0,125,79],
+ka:[function(a,b){return"padding-left: "+b.gyt()*16+"px;"},"$1","gHn",2,0,126,81],
+LZ:[function(a,b){return C.QC[C.jn.Y(b.gyt()-1,9)]},"$1","gbw",2,0,126,81],
 YF:[function(a,b,c,d){var z,y,x,w,v,u
 w=J.RE(b)
 if(!J.xC(J.F8(w.gN(b)),"expand")&&!J.xC(w.gN(b),d))return
@@ -10729,7 +10730,7 @@
 w.qU(v-1)}catch(u){w=H.Ru(u)
 y=w
 x=new H.XO(u,null)
-N.QM("").xH("toggleExpanded",y,x)}},"$3","gY9",6,0,115,1,87,88],
+N.QM("").xH("toggleExpanded",y,x)}},"$3","gY9",6,0,116,1,89,90],
 static:{"^":"B6",os:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10755,9 +10756,9 @@
 "^":"uL+Pi;",
 $isd3:true},
 Xy:{
-"^":"Tp:113;a",
+"^":"Tp:114;a",
 $1:[function(a){var z=this.a
-z.ix=J.Q5(z,C.vb,z.ix,a)},"$1",null,2,0,null,126,"call"],
+z.ix=J.Q5(z,C.vb,z.ix,a)},"$1",null,2,0,null,127,"call"],
 $isEH:true}}],["isolate_ref_element","package:observatory/src/elements/isolate_ref.dart",,N,{
 "^":"",
 oa:{
@@ -10780,7 +10781,7 @@
 "^":"V22;ow,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 god:function(a){return a.ow},
 sod:function(a,b){a.ow=this.ct(a,C.rB,a.ow,b)},
-static:{N5:function(a){var z,y,x,w
+static:{JR:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
 x=P.qU
@@ -10799,8 +10800,8 @@
 "^":"V23;ow,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 god:function(a){return a.ow},
 sod:function(a,b){a.ow=this.ct(a,C.rB,a.ow,b)},
-Fv:[function(a,b){return a.ow.cv("debug/pause").ml(new D.GG(a))},"$1","gX0",2,0,127,11],
-jh:[function(a,b){return a.ow.cv("debug/resume").ml(new D.r8(a))},"$1","gDQ",2,0,127,11],
+Fv:[function(a,b){return a.ow.cv("debug/pause").ml(new D.GG(a))},"$1","gX0",2,0,128,11],
+jh:[function(a,b){return a.ow.cv("debug/resume").ml(new D.r8(a))},"$1","gDQ",2,0,128,11],
 static:{dm:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10818,11 +10819,11 @@
 $isd3:true},
 GG:{
 "^":"Tp:10;a",
-$1:[function(a){return J.LE(this.a.ow)},"$1",null,2,0,null,109,"call"],
+$1:[function(a){return J.LE(this.a.ow)},"$1",null,2,0,null,110,"call"],
 $isEH:true},
 r8:{
 "^":"Tp:10;a",
-$1:[function(a){return J.LE(this.a.ow)},"$1",null,2,0,null,109,"call"],
+$1:[function(a){return J.LE(this.a.ow)},"$1",null,2,0,null,110,"call"],
 $isEH:true},
 Qh:{
 "^":"V24;ow,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
@@ -10951,7 +10952,7 @@
 god:function(a){return a.ck},
 sod:function(a,b){a.ck=this.ct(a,C.rB,a.ck,b)},
 vV:[function(a,b){var z=a.ck
-return z.cv(J.ew(J.F8(z.gVc()),"/eval?expr="+P.jW(C.yD,b,C.xM,!1)))},"$1","gZm",2,0,83,84],
+return z.cv(J.ew(J.F8(z.gVc()),"/eval?expr="+P.jW(C.yD,b,C.xM,!1)))},"$1","gZm",2,0,85,86],
 Vp:[function(a){a.ck.m7().ml(new L.LX(a))},"$0","gJD",0,0,15],
 q0:function(a){Z.uL.prototype.q0.call(this,a)
 a.ts=P.ww(P.ii(0,0,0,0,0,1),this.gJD(a))},
@@ -10959,10 +10960,10 @@
 Z.uL.prototype.Nz.call(this,a)
 z=a.ts
 if(z!=null)z.ed()},
-RF:[function(a,b){J.LE(a.ck).wM(b)},"$1","gvC",2,0,17,82],
-Fv:[function(a,b){return a.ck.cv("debug/pause").ml(new L.CV(a))},"$1","gX0",2,0,127,11],
-jh:[function(a,b){return a.ck.cv("resume").ml(new L.Vq(a))},"$1","gDQ",2,0,127,11],
-static:{KM:function(a){var z,y,x,w,v
+RF:[function(a,b){J.LE(a.ck).wM(b)},"$1","gvC",2,0,17,84],
+Fv:[function(a,b){return a.ck.cv("debug/pause").ml(new L.CV(a))},"$1","gX0",2,0,128,11],
+jh:[function(a,b){return a.ck.cv("resume").ml(new L.Vq(a))},"$1","gDQ",2,0,128,11],
+static:{Za:function(a){var z,y,x,w,v
 z=P.zV(J.UQ($.BY,"DataTable"),null)
 y=$.XZ()
 x=P.YM(null,null,null,P.qU,W.I0)
@@ -10992,15 +10993,15 @@
 y.YT=v
 w.u(0,"isStacked",!0)
 y.YT.bG.u(0,"connectSteps",!1)
-y.YT.bG.u(0,"vAxis",P.EF(["minValue",0,"maxValue",100],null,null))}y.YT.W2(y.X6)}z.ts=P.ww(P.ii(0,0,0,0,0,1),J.dq(z))},"$1",null,2,0,null,128,"call"],
+y.YT.bG.u(0,"vAxis",P.EF(["minValue",0,"maxValue",100],null,null))}y.YT.W2(y.X6)}z.ts=P.ww(P.ii(0,0,0,0,0,1),J.dq(z))},"$1",null,2,0,null,129,"call"],
 $isEH:true},
 CV:{
 "^":"Tp:10;a",
-$1:[function(a){return J.LE(this.a.ck)},"$1",null,2,0,null,109,"call"],
+$1:[function(a){return J.LE(this.a.ck)},"$1",null,2,0,null,110,"call"],
 $isEH:true},
 Vq:{
 "^":"Tp:10;a",
-$1:[function(a){return J.LE(this.a.ck)},"$1",null,2,0,null,109,"call"],
+$1:[function(a){return J.LE(this.a.ck)},"$1",null,2,0,null,110,"call"],
 $isEH:true}}],["json_view_element","package:observatory/src/elements/json_view.dart",,Z,{
 "^":"",
 xh:{
@@ -11106,8 +11107,8 @@
 "^":"V29;iI,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gHt:function(a){return a.iI},
 sHt:function(a,b){a.iI=this.ct(a,C.EV,a.iI,b)},
-vV:[function(a,b){return J.aT(a.iI).cv(J.ew(J.F8(a.iI),"/eval?expr="+P.jW(C.yD,b,C.xM,!1)))},"$1","gZm",2,0,83,84],
-RF:[function(a,b){J.LE(a.iI).wM(b)},"$1","gvC",2,0,17,82],
+vV:[function(a,b){return J.aT(a.iI).cv(J.ew(J.F8(a.iI),"/eval?expr="+P.jW(C.yD,b,C.xM,!1)))},"$1","gZm",2,0,85,86],
+RF:[function(a,b){J.LE(a.iI).wM(b)},"$1","gvC",2,0,17,84],
 static:{as:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -11171,7 +11172,7 @@
 $isRw:true,
 static:{"^":"Uj",QM:function(a){return $.Iu().to(a,new N.dG(a))}}},
 dG:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:function(){var z,y,x,w,v
 z=this.a
 if(C.xB.nC(z,"."))H.vh(P.u("name shouldn't start with a '.'"))
@@ -11222,13 +11223,13 @@
 z.V7("load",["visualization","1",P.jT(P.EF(["packages",["corechart","table"],"callback",P.mt(y.gv6(y))],null,null))])
 $.Ib().MM.ml(G.vN()).ml(new F.e378())},
 e377:{
-"^":"Tp:130;",
+"^":"Tp:131;",
 $1:[function(a){var z
 if(J.xC(a.gOR(),C.nT)){z=J.RE(a)
 if(J.co(z.gG1(a),"Error evaluating expression"))z=J.x5(z.gG1(a),"Can't assign to null: ")===!0||J.x5(z.gG1(a),"Expression is not assignable: ")===!0
 else z=!1}else z=!1
 if(z)return
-P.FL(a.gOR().oc+": "+a.gFl().bu(0)+": "+H.d(J.z2(a)))},"$1",null,2,0,null,129,"call"],
+P.FL(a.gOR().oc+": "+a.gFl().bu(0)+": "+H.d(J.z2(a)))},"$1",null,2,0,null,130,"call"],
 $isEH:true},
 e378:{
 "^":"Tp:10;",
@@ -11288,7 +11289,7 @@
 sPj:function(a,b){a.KU=this.ct(a,C.kV,a.KU,b)},
 gdU:function(a){return a.V4},
 sdU:function(a,b){a.V4=this.ct(a,C.cg,a.V4,b)},
-static:{JR:function(a){var z,y,x,w
+static:{vn:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
 x=P.qU
@@ -11318,7 +11319,7 @@
 Ty:[function(a,b,c,d){var z=a.SB
 if(z===!0)return
 a.SB=this.ct(a,C.aP,z,!0)
-if(a.rU!=null)this.LY(a,this.gWd(a))},"$3","gzY",6,0,86,1,87,88],
+if(a.rU!=null)this.LY(a,this.gWd(a))},"$3","gzY",6,0,88,1,89,90],
 rT:[function(a){a.SB=this.ct(a,C.aP,a.SB,!1)},"$0","gWd",0,0,15],
 static:{ZC:function(a){var z,y,x,w
 z=$.XZ()
@@ -11368,7 +11369,7 @@
 if(z!=null)return z.gHP()
 else return""},
 su6:function(a,b){},
-static:{zf:function(a){var z,y,x,w
+static:{Du:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
 x=P.qU
@@ -11437,18 +11438,15 @@
 siJ:function(a,b){a.yT=this.ct(a,C.j2,a.yT,b)},
 q0:function(a){var z
 Z.uL.prototype.q0.call(this,a)
-if(a.qC===!0){z=new U.bl(P.L5(null,null,null,null,null),0,"unknown","unknown",0,!1,!1,P.bK(null,null,!1,null),P.bK(null,null,!1,null),P.L5(null,null,null,P.qU,D.af),P.L5(null,null,null,P.qU,D.bv),null,null,null,null,null,!1,null,null,null,null,null)
+if(a.qC===!0){z=new U.bl(P.L5(null,null,null,P.qU,P.oh),0,"unknown","unknown",0,!1,!1,P.bK(null,null,!1,null),P.bK(null,null,!1,null),P.L5(null,null,null,P.qU,D.af),P.L5(null,null,null,P.qU,D.bv),null,null,null,null,null,!1,null,null,null,null,null)
 z.md()
 z.PI()
 z=new G.mL(new G.hq(null,"",null,null),z,null,null,null,null,null)
 z.hq()
-a.yT=this.ct(a,C.j2,a.yT,z)}else{z=new U.XK(null,"unknown","unknown",0,!1,!1,P.bK(null,null,!1,null),P.bK(null,null,!1,null),P.L5(null,null,null,P.qU,D.af),P.L5(null,null,null,P.qU,D.bv),null,null,null,null,null,!1,null,null,null,null,null)
-z.md()
-z.SC()
-z=new G.mL(new G.hq(null,"",null,null),z,null,null,null,null,null)
+a.yT=this.ct(a,C.j2,a.yT,z)}else{z=new G.mL(new G.hq(null,"",null,null),U.bU(),null,null,null,null,null)
 z.US()
 a.yT=this.ct(a,C.j2,a.yT,z)}},
-static:{Lu:function(a){var z,y,x,w
+static:{JT8:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
 x=P.qU
@@ -11471,20 +11469,20 @@
 Nz:function(a){A.dM.prototype.Nz.call(this,a)},
 I9:function(a){A.dM.prototype.I9.call(this,a)},
 wN:function(a,b,c,d){A.dM.prototype.wN.call(this,a,b,c,d)},
-a7:[function(a,b){return G.mG(b)},"$1","gSs",2,0,131,132],
+a7:[function(a,b){return G.mG(b)},"$1","gSs",2,0,132,133],
 Ze:[function(a,b){return G.Ef(b)},"$1","gbJ",2,0,12,13],
-uG:[function(a,b){return J.xC(b,"Null")},"$1","gHh",2,0,133,134],
-i5:[function(a,b){return J.xC(b,"Error")},"$1","gt3",2,0,133,134],
+uG:[function(a,b){return J.xC(b,"Null")},"$1","gHh",2,0,134,135],
+i5:[function(a,b){return J.xC(b,"Error")},"$1","gt3",2,0,134,135],
 OP:[function(a,b){var z=J.x(b)
-return z.n(b,"Smi")||z.n(b,"Mint")||z.n(b,"Bigint")},"$1","gSO",2,0,133,134],
-Qr:[function(a,b){return J.xC(b,"Bool")},"$1","gr9",2,0,133,134],
-ff:[function(a,b){return J.xC(b,"String")},"$1","gu7",2,0,133,134],
-fZ:[function(a,b){return J.xC(b,"Instance")},"$1","gNs",2,0,133,134],
-JG:[function(a,b){return J.xC(b,"Double")},"$1","gzx",2,0,133,134],
+return z.n(b,"Smi")||z.n(b,"Mint")||z.n(b,"Bigint")},"$1","gSO",2,0,134,135],
+Qr:[function(a,b){return J.xC(b,"Bool")},"$1","gr9",2,0,134,135],
+ff:[function(a,b){return J.xC(b,"String")},"$1","gu7",2,0,134,135],
+fZ:[function(a,b){return J.xC(b,"Instance")},"$1","gNs",2,0,134,135],
+JG:[function(a,b){return J.xC(b,"Double")},"$1","gzx",2,0,134,135],
 Cp:[function(a,b){var z=J.x(b)
-return z.n(b,"GrowableObjectArray")||z.n(b,"Array")},"$1","gK4",2,0,133,134],
-tR:[function(a,b){return J.xC(b,"Type")},"$1","gqN",2,0,133,134],
-Cn:[function(a,b){return!C.Nm.tg(["Null","Smi","Mint","Bigint","Bool","String","Double","Instance","GrowableObjectArray","Array","Type","Error"],b)},"$1","geS",2,0,133,134],
+return z.n(b,"GrowableObjectArray")||z.n(b,"Array")},"$1","gK4",2,0,134,135],
+tR:[function(a,b){return J.xC(b,"Type")},"$1","gqN",2,0,134,135],
+Cn:[function(a,b){return!C.Nm.tg(["Null","Smi","Mint","Bigint","Bool","String","Double","Instance","GrowableObjectArray","Array","Type","Error"],b)},"$1","geS",2,0,134,135],
 static:{EE:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -11519,7 +11517,7 @@
 x=H.VM(new P.Yp(z),[T.yj])
 if(y.Gv>=4)H.vh(y.q7())
 y.Iv(x)
-return!0}return!1},"$0","gDx",0,0,94],
+return!0}return!1},"$0","gDx",0,0,96],
 gnz:function(a){var z,y
 z=a.AP
 if(z!=null){y=z.iE
@@ -11567,14 +11565,14 @@
 z=new O.Nq(z)
 return new P.yQ(null,null,null,null,new O.u3(z),new O.bF(z),null,null,null,null,null,null)},
 Nq:{
-"^":"Tp:135;a",
+"^":"Tp:136;a",
 $2:function(a,b){var z=this.a
 if(z.a)return
 z.a=!0
 a.RK(b,new O.c1(z))},
 $isEH:true},
 c1:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:[function(){this.a.a=!1
 O.wR()},"$0",null,0,0,null,"call"],
 $isEH:true},
@@ -11584,19 +11582,19 @@
 return new O.yJ(this.b,b,c,d)},"$4",null,8,0,null,24,25,26,28,"call"],
 $isEH:true},
 yJ:{
-"^":"Tp:64;c,d,e,f",
+"^":"Tp:66;c,d,e,f",
 $0:[function(){this.c.$2(this.d,this.e)
 return this.f.$0()},"$0",null,0,0,null,"call"],
 $isEH:true},
 bF:{
-"^":"Tp:136;UI",
+"^":"Tp:137;UI",
 $4:[function(a,b,c,d){if(d==null)return d
 return new O.f6(this.UI,b,c,d)},"$4",null,8,0,null,24,25,26,28,"call"],
 $isEH:true},
 f6:{
 "^":"Tp:10;bK,Gq,Rm,w3",
 $1:[function(a){this.bK.$2(this.Gq,this.Rm)
-return this.w3.$1(a)},"$1",null,2,0,null,137,"call"],
+return this.w3.$1(a)},"$1",null,2,0,null,62,"call"],
 $isEH:true}}],["observe.src.list_diff","package:observe/src/list_diff.dart",,G,{
 "^":"",
 B5:function(a,b,c,d,e,f){var z,y,x,w,v,u,t,s,r,q,p,o,n,m
@@ -11799,6 +11797,13 @@
 gvH:function(a){return this.jr},
 gRt:function(){return this.Uj},
 gNg:function(){return this.dM},
+LT:function(a){var z
+if(typeof a==="number"&&Math.floor(a)===a){z=this.jr
+if(typeof z!=="number")return H.s(z)
+z=a<z}else z=!0
+if(z)return!1
+if(!J.xC(this.dM,this.Uj.G4.length))return!0
+return J.u6(a,J.ew(this.jr,this.dM))},
 bu:function(a){var z,y
 z="#<ListChangeRecord index: "+H.d(this.jr)+", removed: "
 y=this.Uj
@@ -11823,7 +11828,7 @@
 "^":"a;",
 $isd3:true},
 X6:{
-"^":"Tp:67;a,b",
+"^":"Tp:69;a,b",
 $2:function(a,b){var z,y,x,w,v
 z=this.b
 y=$.cp().jD(z,a)
@@ -12005,7 +12010,7 @@
 if(x&&y.length!==0){x=H.VM(new P.Yp(y),[G.DA])
 if(z.Gv>=4)H.vh(z.q7())
 z.Iv(x)
-return!0}return!1},"$0","gL6",0,0,94],
+return!0}return!1},"$0","gL6",0,0,96],
 $iswn:true,
 static:{ch:function(a,b){var z=H.VM([],[b])
 return H.VM(new Q.wn(null,null,z,null,null),[b])},Y5:function(a,b,c){var z,y,x,w,v,u,t,s,r,q,p,o,n,m,l
@@ -12042,7 +12047,7 @@
 "^":"rm+Pi;",
 $isd3:true},
 cj:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:function(){this.a.iT=null},
 $isEH:true}}],["observe.src.observable_map","package:observe/src/observable_map.dart",,V,{
 "^":"",
@@ -12100,11 +12105,11 @@
 return z}}},
 zT:{
 "^":"Tp;a",
-$2:[function(a,b){this.a.u(0,a,b)},"$2",null,4,0,null,68,18,"call"],
+$2:[function(a,b){this.a.u(0,a,b)},"$2",null,4,0,null,70,18,"call"],
 $isEH:true,
 $signature:function(){return H.IG(function(a,b){return{func:"Bi",args:[a,b]}},this.a,"qC")}},
 Lo:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){var z=this.a
 z.nq(z,H.VM(new V.ya(a,b,null,!1,!0),[null,null]))},
 $isEH:true}}],["observe.src.observer_transform","package:observe/src/observer_transform.dart",,Y,{
@@ -12285,7 +12290,7 @@
 gPu:function(){return!1},
 static:{"^":"qr"}},
 MdQ:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:function(){return new H.VR("^(?:(?:[$_a-zA-Z]+[$_a-zA-Z0-9]*|(?:[0-9]|[1-9]+[0-9]+)))(?:\\.(?:[$_a-zA-Z]+[$_a-zA-Z0-9]*|(?:[0-9]|[1-9]+[0-9]+)))*$",H.ol("^(?:(?:[$_a-zA-Z]+[$_a-zA-Z0-9]*|(?:[0-9]|[1-9]+[0-9]+)))(?:\\.(?:[$_a-zA-Z]+[$_a-zA-Z0-9]*|(?:[0-9]|[1-9]+[0-9]+)))*$",!1,!0,!1),null,null)},
 $isEH:true},
 NV:{
@@ -12363,7 +12368,7 @@
 this.kH()
 this.Wf=null
 this.GX=null},
-xV:[function(a){if(this.GX!=null)this.SG()},"$1","gjM",2,0,17,11],
+xVs:[function(a){if(this.GX!=null)this.SG()},"$1","gjM",2,0,17,11],
 SG:function(){var z=0
 while(!0){if(!(z<1000&&this.lI()))break;++z}return z>0},
 Aw:function(a,b,c){var z,y,x,w
@@ -12423,7 +12428,7 @@
 x.FV(0,z)
 return x}return a},"$1","Ft",2,0,10,18],
 Fk:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){this.a.u(0,R.tB(a),R.tB(b))},
 $isEH:true}}],["polymer","package:polymer/polymer.dart",,A,{
 "^":"",
@@ -12621,11 +12626,11 @@
 return z},
 $isXP:true},
 eY:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){if(C.kr.x4(a)!==!0&&!J.co(a,"on-"))this.a.kK.u(0,a,b)},
 $isEH:true},
 BO:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){var z,y,x
 z=J.rY(a)
 if(z.nC(a,"on-")){y=J.U6(b).u8(b,"{{")
@@ -12641,7 +12646,7 @@
 $1:function(a){return J.RF(a,this.a)},
 $isEH:true},
 ix:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:function(){return[]},
 $isEH:true},
 Tj:{
@@ -12649,13 +12654,13 @@
 $2:function(a,b){this.a.u(0,H.d(a).toLowerCase(),b)},
 $isEH:true},
 DOe:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:function(){var z=P.L5(null,null,null,P.qU,P.qU)
 C.SP.aN(0,new A.xb(z))
 return z},
 $isEH:true},
 xb:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){this.a.u(0,b,a)},
 $isEH:true},
 A2:{
@@ -12861,7 +12866,7 @@
 u=J.UQ($.pT(),v)
 t=w.t(0,u!=null?u:v)
 if(t!=null){if(x)y.J4("["+H.d(this.gqn(a))+"] found host handler name ["+t+"]")
-this.ea(a,a,t,[b,!!z.$iseC?z.gey(b):null,a])}if(x)y.J4("<<< ["+H.d(this.gqn(a))+"]: hostEventListener("+H.d(z.gt5(b))+")")},"$1","gD4",2,0,144,76],
+this.ea(a,a,t,[b,!!z.$iseC?z.gey(b):null,a])}if(x)y.J4("<<< ["+H.d(this.gqn(a))+"]: hostEventListener("+H.d(z.gt5(b))+")")},"$1","gD4",2,0,144,78],
 ea:function(a,b,c,d){var z,y,x,w
 z=$.Uk()
 y=z.Im(C.t4)
@@ -12879,13 +12884,13 @@
 $isPZ:true,
 $isKV:true},
 dZ:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){var z=J.Vs(this.a)
 if(z.x4(a)!==!0)z.u(0,a,new A.Xi(b).$0())
 z.t(0,a)},
 $isEH:true},
 Xi:{
-"^":"Tp:64;b",
+"^":"Tp:66;b",
 $0:function(){return this.b},
 $isEH:true},
 TV:{
@@ -12898,7 +12903,7 @@
 $1:function(a){return J.DB(!!J.x(a).$isvy?a:M.Ky(a))},
 $isEH:true},
 qz:{
-"^":"Tp:67;a,b,c,d,e,f,UI",
+"^":"Tp:69;a,b,c,d,e,f,UI",
 $2:[function(a,b){var z,y,x,w,v,u,t,s,r,q,p,o
 z=this.d
 if(typeof a!=="number")return H.s(a)
@@ -12994,7 +12999,7 @@
 if(C.xB.nC(w,"@")){v=this.U1
 w=L.hk(C.xB.yn(w,1)).Tl(v)}else v=y
 u=J.x(a)
-x.ea(y,v,w,[a,!!u.$iseC?u.gey(a):null,z])},"$1","gwi",2,0,10,76],
+x.ea(y,v,w,[a,!!u.$iseC?u.gey(a):null,z])},"$1","gwi",2,0,10,78],
 gP:function(a){return},
 TR:function(a,b){var z=J.PB(this.v3).t(0,this.pB)
 z=H.VM(new W.fd(0,z.bi,z.Ph,W.aF(this.gwi()),z.Sg),[H.Kp(z,0)])
@@ -13017,11 +13022,11 @@
 tZ:[function(a){if(this.ih!=null){this.TP(0)
 this.Ws()}},"$0","gv6",0,0,15]},
 mS:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.X1($.M6,$.UG)},"$0",null,0,0,null,"call"],
 $isEH:true},
 hp:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){var z=$.ln().MM
 if(z.Gv!==0)H.vh(P.w("Future already completed"))
 z.OH(null)
@@ -13034,7 +13039,7 @@
 return this.b.qP([b,c],a)},"$3",null,6,0,null,152,53,153,"call"],
 $isEH:true},
 v4:{
-"^":"Tp:64;c,d,e,f",
+"^":"Tp:66;c,d,e,f",
 $0:[function(){var z,y,x,w,v,u
 z=this.d
 y=this.e
@@ -13068,26 +13073,26 @@
 return y}catch(x){H.Ru(x)
 return a}},
 Md:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return a},
 $isEH:true},
 lP:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return a},
 $isEH:true},
 Uf:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){var z,y
 try{z=P.zu(a)
 return z}catch(y){H.Ru(y)
 return b}},
 $isEH:true},
 Ra:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return!J.xC(a,"false")},
 $isEH:true},
 wJY:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return H.BU(a,null,new Z.fT(b))},
 $isEH:true},
 fT:{
@@ -13095,7 +13100,7 @@
 $1:function(a){return this.a},
 $isEH:true},
 zOQ:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return H.RR(a,new Z.Lf(b))},
 $isEH:true},
 Lf:{
@@ -13106,11 +13111,12 @@
 dA:[function(a){var z=J.x(a)
 if(!!z.$isZ0)z=J.vo(a.gvc(),new T.o8f(a)).zV(0," ")
 else z=!!z.$isQV?z.zV(a," "):a
-return z},"$1","dI",2,0,46],
+return z},"$1","dI",2,0,46,61],
 qN:[function(a){var z=J.x(a)
 if(!!z.$isZ0)z=J.kl(a.gvc(),new T.GL(a)).zV(0,";")
 else z=!!z.$isQV?z.zV(a,";"):a
-return z},"$1","xe",2,0,46],
+return z},"$1","xe",2,0,46,61],
+Fm:[function(a){return a},"$1","u2",2,0,10,62],
 o8f:{
 "^":"Tp:10;a",
 $1:function(a){return J.xC(this.a.t(0,a),!0)},
@@ -13143,7 +13149,8 @@
 y=z&&J.xC(this.b,"class")?T.dI():null
 if(z&&J.xC(this.b,"style"))y=T.xe()
 if(c===!0)return T.rD(this.c,a,y)
-return new T.tI(a,y,this.c,null,null,null)},"$3",null,6,0,null,147,148,149,"call"],
+z=y==null?T.u2():y
+return new T.tI(a,z,this.c,null,null,null)},"$3",null,6,0,null,147,148,149,"call"],
 $isEH:true},
 uK:{
 "^":"Tp:10;a",
@@ -13151,20 +13158,20 @@
 $isEH:true},
 tI:{
 "^":"Ap;yr,wx,n4,Fg,ML,HR",
+R5:function(a){return this.wx.$1(a)},
 WV:function(a){return this.Fg.$1(a)},
-Ls:[function(a){var z,y
+q1:[function(a,b){var z,y
 z=this.HR
-y=T.r6(a,this.yr,this.wx)
+y=this.R5(a)
 this.HR=y
-if(this.Fg!=null&&!J.xC(z,y))this.WV(this.HR)},"$1","gkR",2,0,10,156],
+if(b!==!0&&this.Fg!=null&&!J.xC(z,y))this.WV(this.HR)},function(a){return this.q1(a,!1)},"UV","$2$skipChanges","$1","gQp",2,3,156,157,61,158],
 gP:function(a){if(this.Fg!=null)return this.HR
 return T.rD(this.n4,this.yr,this.wx)},
 sP:function(a,b){var z,y,x,w,v
-try{w=this.yr
-z=K.jX(this.n4,b,w)
-this.HR=T.r6(z,w,this.wx)}catch(v){w=H.Ru(v)
-y=w
-x=new H.XO(v,null)
+try{z=K.jX(this.n4,b,this.yr)
+this.q1(z,!0)}catch(w){v=H.Ru(w)
+y=v
+x=new H.XO(w,null)
 H.VM(new P.Zf(P.Dt(null)),[null]).w0("Error evaluating expression '"+H.d(this.n4)+"': "+H.d(y),x)}},
 TR:function(a,b){var z,y,x,w,v,u,t
 if(this.Fg!=null)throw H.b(P.w("already open"))
@@ -13175,13 +13182,13 @@
 u.Eo(null,null)
 z=J.okV(w,new K.Oy(v,u))
 this.n4=z
-u=z.glr().yI(this.gkR())
+u=z.glr().yI(this.gQp())
 u.fm(0,new T.Tg(z))
 this.ML=u
 try{w=z
 J.okV(w,new K.Ed(v))
 w.gXr()
-this.HR=T.r6(z.gXr(),v,this.wx)}catch(t){w=H.Ru(t)
+this.q1(z.gXr(),!0)}catch(t){w=H.Ru(t)
 y=w
 x=new H.XO(t,null)
 H.VM(new P.Zf(P.Dt(null)),[null]).w0("Error evaluating expression '"+H.d(z)+"': "+H.d(y),x)}return this.HR},
@@ -13190,21 +13197,15 @@
 this.ML=null
 this.n4=H.Go(this.n4,"$isdE").KL
 this.Fg=null},
-static:{rD:function(a,b,c){var z,y,x,w
-try{x=T.r6(K.Cw(a,b),b,c)
-return x}catch(w){x=H.Ru(w)
-z=x
-y=new H.XO(w,null)
-H.VM(new P.Zf(P.Dt(null)),[null]).w0("Error evaluating expression '"+H.d(a)+"': "+H.d(z),y)}return},r6:function(a,b,c){if(!!J.x(a).$isfk)return J.np(J.kl(a.bm,new T.bI(a,b)),!1)
-else return c==null?a:c.$1(a)}}},
-bI:{
-"^":"Tp:10;a,b",
-$1:[function(a){var z=this.a.xG
-if(J.xC(z,"this"))H.vh(K.xn("'this' cannot be used as a variable name."))
-return new K.ig(this.b,z,a)},"$1",null,2,0,null,145,"call"],
-$isEH:true},
+static:{rD:function(a,b,c){var z,y,x,w,v
+try{z=K.Cw(a,b)
+w=c==null?z:c.$1(z)
+return w}catch(v){w=H.Ru(v)
+y=w
+x=new H.XO(v,null)
+H.VM(new P.Zf(P.Dt(null)),[null]).w0("Error evaluating expression '"+H.d(a)+"': "+H.d(y),x)}return}}},
 Tg:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:[function(a,b){H.VM(new P.Zf(P.Dt(null)),[null]).w0("Error evaluating expression '"+H.d(this.a)+"': "+H.d(a),b)},"$2",null,4,0,null,1,138,"call"],
 $isEH:true}}],["polymer_expressions.async","package:polymer_expressions/async.dart",,B,{
 "^":"",
@@ -13234,7 +13235,7 @@
 z.a=a
 y=new K.c4(z)
 x=H.VM([],[U.hw])
-for(;w=z.a,v=J.x(w),!!v.$isMp;){if(!J.xC(v.gxS(w),"|"))break
+for(;w=z.a,v=J.x(w),!!v.$iszb;){if(!J.xC(v.gxS(w),"|"))break
 x.push(v.gT8(w))
 z.a=v.gBb(w)}w=z.a
 v=J.x(w)
@@ -13270,55 +13271,55 @@
 if(y.x4("this"))H.vh(K.xn("'this' cannot be used as a variable name."))
 y=x}return y},
 lPa:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.ew(a,b)},
 $isEH:true},
 Ufa:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.Hn(a,b)},
 $isEH:true},
 Raa:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.vX(a,b)},
 $isEH:true},
 w0:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.L9(a,b)},
 $isEH:true},
 w5:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.xC(a,b)},
 $isEH:true},
 w10:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return!J.xC(a,b)},
 $isEH:true},
 w11:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.z8(a,b)},
 $isEH:true},
 w12:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.J5(a,b)},
 $isEH:true},
 w13:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.u6(a,b)},
 $isEH:true},
 w14:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.Bl(a,b)},
 $isEH:true},
 w15:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return a===!0||b===!0},
 $isEH:true},
 w16:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return a===!0&&b===!0},
 $isEH:true},
 w17:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){var z=H.Og(P.a)
 z=H.KT(z,[z]).BD(b)
 if(z)return b.$1(a)
@@ -13337,7 +13338,7 @@
 $1:function(a){return a!==!0},
 $isEH:true},
 c4:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:function(){return H.vh(K.xn("Expression is not assignable: "+H.d(this.a.a)))},
 $isEH:true},
 GK:{
@@ -13355,7 +13356,8 @@
 if(y==null||z==null)throw H.b(K.xn("variable '"+H.d(b)+"' not found"))
 y=$.cp().jD(y,z)
 return!!J.x(y).$iscb?B.z4(y,null):y},
-AC:function(a){return!J.xC(a,"this")}},
+AC:function(a){return!J.xC(a,"this")},
+bu:function(a){return"[model: "+H.d(this.ku)+"]"}},
 ig:{
 "^":"GK;eT>,Z0,P>",
 gku:function(){return this.eT.gku()},
@@ -13363,7 +13365,8 @@
 if(J.xC(this.Z0,b)){z=this.P
 return!!J.x(z).$iscb?B.z4(z,null):z}return this.eT.t(0,b)},
 AC:function(a){if(J.xC(this.Z0,a))return!1
-return this.eT.AC(a)}},
+return this.eT.AC(a)},
+bu:function(a){return this.eT.bu(0)+" > [local: "+H.d(this.Z0)+"]"}},
 Ph:{
 "^":"GK;eT>,Z3<",
 gku:function(){return this.eT.ku},
@@ -13371,7 +13374,9 @@
 if(z.x4(b)){z=z.t(0,b)
 return!!J.x(z).$iscb?B.z4(z,null):z}return this.eT.t(0,b)},
 AC:function(a){if(this.Z3.x4(a))return!1
-return!J.xC(a,"this")}},
+return!J.xC(a,"this")},
+bu:function(a){var z=this.Z3
+return"[model: "+H.d(this.eT.ku)+"] > [global: "+P.Ix(H.VM(new P.i5(z),[H.Kp(z,0)]),"(",")")+"]"}},
 dE:{
 "^":"a;bO?,Lv<",
 glr:function(){var z=this.k6
@@ -13402,7 +13407,7 @@
 Oy:{
 "^":"Jg;qu,lk",
 W9:function(a){return new K.uD(a,null,null,null,P.bK(null,null,!1,null))},
-LT:function(a){return a.wz.RR(0,this)},
+Hs:function(a){return a.wz.RR(0,this)},
 fV:function(a){var z,y
 z=J.okV(a.ghP(),this)
 y=new K.vl(z,a,null,null,null,P.bK(null,null,!1,null))
@@ -13459,7 +13464,7 @@
 RD:function(a){var z,y,x,w
 z=J.okV(a.gdc(),this)
 y=J.okV(a.gSl(),this)
-x=J.okV(a.gru(),this)
+x=J.okV(a.gCW(),this)
 w=new K.an(z,y,x,a,null,null,null,P.bK(null,null,!1,null))
 z.sbO(w)
 y.sbO(w)
@@ -13526,7 +13531,7 @@
 $isQb:true,
 $ishw:true},
 Ku:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.kW(a,J.Kt(b).gLv(),b.gv4().gLv())
 return a},
 $isEH:true},
@@ -13592,17 +13597,17 @@
 else{if(J.xC(z.gxS(z),"|")&&!!J.x(x.gLv()).$iswn)this.tj=H.Go(x.gLv(),"$iswn").gRT().yI(new K.P8(this,a))
 this.Lv=y.$2(x.gLv(),this.T8.gLv())}}},
 RR:function(a,b){return b.ex(this)},
-$asdE:function(){return[U.Mp]},
-$isMp:true,
+$asdE:function(){return[U.zb]},
+$iszb:true,
 $ishw:true},
 P8:{
 "^":"Tp:10;a,b",
 $1:[function(a){return this.a.l8(this.b)},"$1",null,2,0,null,11,"call"],
 $isEH:true},
 an:{
-"^":"dE;dc<,Sl<,ru<,KL,bO,tj,Lv,k6",
+"^":"dE;dc<,Sl<,CW<,KL,bO,tj,Lv,k6",
 Qh:function(a){var z=this.dc.gLv()
-this.Lv=(z==null?!1:z)===!0?this.Sl.gLv():this.ru.gLv()},
+this.Lv=(z==null?!1:z)===!0?this.Sl.gLv():this.CW.gLv()},
 RR:function(a,b){return b.RD(this)},
 $asdE:function(){return[U.HB]},
 $isHB:true,
@@ -13619,12 +13624,12 @@
 x=$.b7().I1.t(0,y)
 this.Lv=$.cp().jD(z,x)
 y=J.x(z)
-if(!!y.$isd3)this.tj=y.gqh(z).yI(new K.e9n(this,a,x))},
+if(!!y.$isd3)this.tj=y.gqh(z).yI(new K.fk(this,a,x))},
 RR:function(a,b){return b.fV(this)},
 $asdE:function(){return[U.x9]},
 $isx9:true,
 $ishw:true},
-e9n:{
+fk:{
 "^":"Tp:10;a,b,c",
 $1:[function(a){if(J.xq(a,new K.WKb(this.c))===!0)this.a.l8(this.b)},"$1",null,2,0,null,146,"call"],
 $isEH:true},
@@ -13640,18 +13645,27 @@
 return}y=this.Jn.gLv()
 x=J.U6(z)
 this.Lv=x.t(z,y)
-if(!!x.$isd3)this.tj=x.gqh(z).yI(new K.tE(this,a,y))},
+if(!!x.$iswn)this.tj=z.gRT().yI(new K.tE(this,a,y))
+else if(!!x.$isd3)this.tj=x.gqh(z).yI(new K.cn(this,a,y))},
 RR:function(a,b){return b.CU(this)},
 $asdE:function(){return[U.zX]},
 $iszX:true,
 $ishw:true},
 tE:{
 "^":"Tp:10;a,b,c",
-$1:[function(a){if(J.xq(a,new K.ey(this.c))===!0)this.a.l8(this.b)},"$1",null,2,0,null,146,"call"],
+$1:[function(a){if(J.xq(a,new K.zw(this.c))===!0)this.a.l8(this.b)},"$1",null,2,0,null,146,"call"],
+$isEH:true},
+zw:{
+"^":"Tp:10;d",
+$1:function(a){return a.LT(this.d)},
+$isEH:true},
+cn:{
+"^":"Tp:10;e,f,UI",
+$1:[function(a){if(J.xq(a,new K.ey(this.UI))===!0)this.e.l8(this.f)},"$1",null,2,0,null,146,"call"],
 $isEH:true},
 ey:{
-"^":"Tp:10;d",
-$1:function(a){return!!J.x(a).$isya&&J.xC(a.G3,this.d)},
+"^":"Tp:10;bK",
+$1:function(a){return!!J.x(a).$isya&&J.xC(a.G3,this.bK)},
 $isEH:true},
 xJ:{
 "^":"dE;hP<,re<,KL,bO,tj,Lv,k6",
@@ -13679,7 +13693,7 @@
 $1:[function(a){return a.gLv()},"$1",null,2,0,null,43,"call"],
 $isEH:true},
 vQ:{
-"^":"Tp:157;a,b,c",
+"^":"Tp:159;a,b,c",
 $1:[function(a){if(J.xq(a,new K.ho(this.c))===!0)this.a.l8(this.b)},"$1",null,2,0,null,146,"call"],
 $isEH:true},
 ho:{
@@ -13694,9 +13708,8 @@
 x=J.x(y)
 if(!x.$isQV&&y!=null)throw H.b(K.xn("right side of 'in' is not an iterator"))
 if(!!x.$iswn)this.tj=y.gRT().yI(new K.OF(this,a))
-x=J.Vm(z)
-w=y!=null?y:C.xD
-this.Lv=new K.fk(x,w)},
+w=J.Vm(z)
+this.Lv=y==null?C.xD:J.np(x.ez(y,new K.fg(a,w)),!1)},
 RR:function(a,b){return b.ky(this)},
 $asdE:function(){return[U.ma]},
 $isma:true,
@@ -13705,9 +13718,12 @@
 "^":"Tp:10;a,b",
 $1:[function(a){return this.a.l8(this.b)},"$1",null,2,0,null,11,"call"],
 $isEH:true},
-fk:{
-"^":"a;xG,bm",
-$isfk:true},
+fg:{
+"^":"Tp:10;c,d",
+$1:[function(a){var z=this.d
+if(J.xC(z,"this"))H.vh(K.xn("'this' cannot be used as a variable name."))
+return new K.ig(this.c,z,a)},"$1",null,2,0,null,145,"call"],
+$isEH:true},
 nD:{
 "^":"a;G1>",
 bu:function(a){return"EvalException: "+this.G1},
@@ -13721,7 +13737,7 @@
 if(z>=b.length)return H.e(b,z)
 if(!J.xC(y,b[z]))return!1}return!0},
 b1:function(a){a.toString
-return U.Le(H.n3(a,0,new U.xs()))},
+return U.Le(H.n3(a,0,new U.VU()))},
 Zd:function(a,b){var z=J.ew(a,b)
 if(typeof z!=="number")return H.s(z)
 a=536870911&z
@@ -13733,7 +13749,7 @@
 return 536870911&a+((16383&a)<<15>>>0)},
 tu:{
 "^":"a;",
-Bf:[function(a,b,c){return new U.zX(b,c)},"$2","gvH",4,0,158,1,43]},
+Bf:[function(a,b,c){return new U.zX(b,c)},"$2","gvH",4,0,160,1,43]},
 hw:{
 "^":"a;",
 $ishw:true},
@@ -13785,7 +13801,7 @@
 $isae:true},
 XC:{
 "^":"hw;wz",
-RR:function(a,b){return b.LT(this)},
+RR:function(a,b){return b.Hs(this)},
 bu:function(a){return"("+H.d(this.wz)+")"},
 n:function(a,b){if(b==null)return!1
 return!!J.x(b).$isXC&&J.xC(b.wz,this.wz)},
@@ -13814,30 +13830,30 @@
 y=J.v1(this.wz)
 return U.Le(U.Zd(U.Zd(0,z),y))},
 $iscJ:true},
-Mp:{
+zb:{
 "^":"hw;xS>,Bb>,T8>",
 RR:function(a,b){return b.ex(this)},
 bu:function(a){return"("+H.d(this.Bb)+" "+H.d(this.xS)+" "+H.d(this.T8)+")"},
 n:function(a,b){var z
 if(b==null)return!1
 z=J.x(b)
-return!!z.$isMp&&J.xC(z.gxS(b),this.xS)&&J.xC(z.gBb(b),this.Bb)&&J.xC(z.gT8(b),this.T8)},
+return!!z.$iszb&&J.xC(z.gxS(b),this.xS)&&J.xC(z.gBb(b),this.Bb)&&J.xC(z.gT8(b),this.T8)},
 giO:function(a){var z,y,x
 z=J.v1(this.xS)
 y=J.v1(this.Bb)
 x=J.v1(this.T8)
 return U.Le(U.Zd(U.Zd(U.Zd(0,z),y),x))},
-$isMp:true},
+$iszb:true},
 HB:{
-"^":"hw;dc<,Sl<,ru<",
+"^":"hw;dc<,Sl<,CW<",
 RR:function(a,b){return b.RD(this)},
-bu:function(a){return"("+H.d(this.dc)+" ? "+H.d(this.Sl)+" : "+H.d(this.ru)+")"},
+bu:function(a){return"("+H.d(this.dc)+" ? "+H.d(this.Sl)+" : "+H.d(this.CW)+")"},
 n:function(a,b){if(b==null)return!1
-return!!J.x(b).$isHB&&J.xC(b.gdc(),this.dc)&&J.xC(b.gSl(),this.Sl)&&J.xC(b.gru(),this.ru)},
+return!!J.x(b).$isHB&&J.xC(b.gdc(),this.dc)&&J.xC(b.gSl(),this.Sl)&&J.xC(b.gCW(),this.CW)},
 giO:function(a){var z,y,x
 z=J.v1(this.dc)
 y=J.v1(this.Sl)
-x=J.v1(this.ru)
+x=J.v1(this.CW)
 return U.Le(U.Zd(U.Zd(U.Zd(0,z),y),x))},
 $isHB:true},
 ma:{
@@ -13892,8 +13908,8 @@
 x=U.b1(this.re)
 return U.Le(U.Zd(U.Zd(U.Zd(0,z),y),x))},
 $isNb:true},
-xs:{
-"^":"Tp:67;",
+VU:{
+"^":"Tp:69;",
 $2:function(a,b){return U.Zd(a,J.v1(b))},
 $isEH:true}}],["polymer_expressions.parser","package:polymer_expressions/parser.dart",,T,{
 "^":"",
@@ -13958,7 +13974,7 @@
 if(!x)break
 y=this.tF(y,this.vi.lo.gP9())}x=J.Vm(z)
 this.rp.toString
-return new U.Mp(x,a,y)},
+return new U.zb(x,a,y)},
 Yq:function(){var z,y,x,w
 if(J.xC(J.Iz(this.vi.lo),8)){z=J.Vm(this.vi.lo)
 y=J.x(z)
@@ -14073,7 +14089,7 @@
 return y},
 Xk:function(){return this.u3("")}}}],["polymer_expressions.src.globals","package:polymer_expressions/src/globals.dart",,K,{
 "^":"",
-Dc:[function(a){return H.VM(new K.Bt(a),[null])},"$1","G5",2,0,61,62],
+Dc:[function(a){return H.VM(new K.Bt(a),[null])},"$1","G5",2,0,63,64],
 O1:{
 "^":"a;vH>,P>",
 n:function(a,b){if(b==null)return!1
@@ -14208,12 +14224,12 @@
 "^":"",
 Jg:{
 "^":"a;",
-DV:[function(a){return J.okV(a,this)},"$1","gnG",2,0,159,138]},
+DV:[function(a){return J.okV(a,this)},"$1","gnG",2,0,161,138]},
 cfS:{
 "^":"Jg;",
 xn:function(a){},
 W9:function(a){this.xn(a)},
-LT:function(a){a.wz.RR(0,this)
+Hs:function(a){a.wz.RR(0,this)
 this.xn(a)},
 fV:function(a){J.okV(a.ghP(),this)
 this.xn(a)},
@@ -14242,7 +14258,7 @@
 this.xn(a)},
 RD:function(a){J.okV(a.gdc(),this)
 J.okV(a.gSl(),this)
-J.okV(a.gru(),this)
+J.okV(a.gCW(),this)
 this.xn(a)},
 ky:function(a){J.okV(a.gBb(a),this)
 J.okV(a.gT8(a),this)
@@ -14285,13 +14301,13 @@
 fX:[function(a,b){this.Kn(a)},"$1","gIF",2,0,17,54],
 xx:[function(a,b){this.ct(a,C.SA,0,1)
 this.ct(a,C.wq,0,1)},"$1","gTA",2,0,10,54],
-fT:[function(a,b){var z,y
+Jf:[function(a,b){var z,y
 z=a.Ny
 if(z==null||a.FZ!==!0)return"min-width:32px;"
 y=z.gu9().Zp.t(0,b.gRd())
 if(y==null)return"min-width:32px;"
 if(J.xC(y,0))return"min-width:32px;background-color:red"
-return"min-width:32px;background-color:green"},"$1","gL0",2,0,160,161],
+return"min-width:32px;background-color:green"},"$1","gL0",2,0,162,163],
 Kn:function(a){var z,y,x,w,v
 if(J.iS(a.Ny)!==!0){J.SK(a.Ny).ml(new T.Wd(a))
 return}this.ct(a,C.SA,0,1)
@@ -14379,8 +14395,8 @@
 if(z==null)return
 J.SK(z)},
 ii:[function(a,b){J.qA((a.shadowRoot||a.webkitShadowRoot).querySelector("#scriptInset"),a.HJ)},"$1","gVU",2,0,10,54],
-RF:[function(a,b){J.LE(a.Uz).wM(b)},"$1","gvC",2,0,17,82],
-j9:[function(a,b){J.y9(J.aT(a.Uz)).wM(b)},"$1","gWp",2,0,17,82],
+RF:[function(a,b){J.LE(a.Uz).wM(b)},"$1","gvC",2,0,17,84],
+j9:[function(a,b){J.y9(J.aT(a.Uz)).wM(b)},"$1","gWp",2,0,17,84],
 static:{TXt:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -14528,7 +14544,7 @@
 if(J.xC(this.r0,""))return P.PG(this,null)
 if(this.Sa&&this.gfS())return P.PG(this,null)
 z=this.VR
-if(z==null){z=this.gwv(this).HL(this.gPj(this)).ml(new D.Pa(this)).wM(new D.jI(this))
+if(z==null){z=this.gwv(this).HL(this.gPj(this)).ml(new D.Pa(this)).wM(new D.Jt(this))
 this.VR=z}return z},
 eC:function(a){var z,y,x,w
 z=J.U6(a)
@@ -14542,7 +14558,7 @@
 this.bF(0,a,y)},
 $isaf:true},
 Pa:{
-"^":"Tp:163;a",
+"^":"Tp:165;a",
 $1:[function(a){var z,y
 z=J.UQ(a,"type")
 y=J.rY(z)
@@ -14550,10 +14566,10 @@
 y=this.a
 if(!J.xC(z,y.mQ))return D.hi(y.Jz,a)
 y.eC(a)
-return y},"$1",null,2,0,null,162,"call"],
+return y},"$1",null,2,0,null,164,"call"],
 $isEH:true},
-jI:{
-"^":"Tp:64;b",
+Jt:{
+"^":"Tp:66;b",
 $0:[function(){this.b.VR=null},"$0",null,0,0,null,"call"],
 $isEH:true},
 fz:{
@@ -14607,7 +14623,7 @@
 return this.Tn(x).ml(new D.lb(this,w))}v=this.Qy.t(0,z.a)
 if(v!=null)return J.LE(v)
 return this.HL(z.a).ml(new D.aEE(z,this))},
-nJ:[function(a,b){return b},"$2","ge1",4,0,67],
+nJ:[function(a,b){return b},"$2","ge1",4,0,69],
 ng:function(a){var z,y,x
 z=null
 try{y=new P.Cf(this.ge1())
@@ -14658,7 +14674,7 @@
 MZ:{
 "^":"Tp:10;a,b",
 $1:[function(a){if(!J.x(a).$iswv)return
-return this.a.z7.t(0,this.b)},"$1",null,2,0,null,109,"call"],
+return this.a.z7.t(0,this.b)},"$1",null,2,0,null,110,"call"],
 $isEH:true},
 lb:{
 "^":"Tp:10;b,c",
@@ -14669,15 +14685,15 @@
 else return a.cv(z)},"$1",null,2,0,null,4,"call"],
 $isEH:true},
 aEE:{
-"^":"Tp:163;a,d",
+"^":"Tp:165;a,d",
 $1:[function(a){var z,y
 z=this.d
 y=D.hi(z,a)
 if(y.gUm())z.Qy.to(this.a.a,new D.zK(y))
-return y},"$1",null,2,0,null,162,"call"],
+return y},"$1",null,2,0,null,164,"call"],
 $isEH:true},
 zK:{
-"^":"Tp:64;e",
+"^":"Tp:66;e",
 $0:function(){return this.e},
 $isEH:true},
 zA:{
@@ -14689,7 +14705,7 @@
 P.FL("Hit V8 bug.")
 w=P.EF(["type","ServiceException","id","","kind","DecodeException","response","This is likely a result of a known V8 bug. Although the the bug has been fixed the fix may not be in your Chrome version. For more information see dartbug.com/18385. Observatory is still functioning and you should try your action again.","message","Could not decode JSON: "+H.d(y)],null,null)
 w=R.tB(w)
-return P.Vu(D.hi(this.a,w),null,null)}return this.a.N7(z)},"$1",null,2,0,null,112,"call"],
+return P.Vu(D.hi(this.a,w),null,null)}return this.a.N7(z)},"$1",null,2,0,null,113,"call"],
 $isEH:true},
 tm:{
 "^":"Tp:10;b",
@@ -14707,14 +14723,14 @@
 $1:[function(a){var z=this.c.Li
 if(z.Gv>=4)H.vh(z.q7())
 z.Iv(a)
-return P.Vu(a,null,null)},"$1",null,2,0,null,75,"call"],
+return P.Vu(a,null,null)},"$1",null,2,0,null,77,"call"],
 $isEH:true},
 hc:{
 "^":"Tp:10;",
 $1:[function(a){return!!J.x(a).$isEP},"$1",null,2,0,null,1,"call"],
 $isEH:true},
 Hq:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.LE(b)},
 $isEH:true},
 ER:{
@@ -14794,7 +14810,7 @@
 gn0:function(){return this.zG},
 gwg:function(){return this.XV},
 Mq:function(a){return H.d(this.r0)+"/"+H.d(a)},
-xQ:[function(a){return"#/"+(H.d(this.r0)+"/"+H.d(a))},"$1","gw6",2,0,164,165],
+xQ:[function(a){return"#/"+(H.d(this.r0)+"/"+H.d(a))},"$1","gw6",2,0,166,167],
 N3:function(a){var z,y,x,w
 z=H.VM([],[D.kx])
 y=J.U6(a)
@@ -14811,8 +14827,8 @@
 x=z.t(a,"samples")
 for(z=J.mY(y);z.G();){w=z.gl()
 J.UQ(w,"code").eL(w,b,x)}},
-lh:[function(a){return this.cv("coverage").ml(this.gJJ())},"$0","gWp",0,0,166],
-cNN:[function(a){J.kH(J.UQ(a,"coverage"),new D.Yb(this))},"$1","gJJ",2,0,167,168],
+lh:[function(a){return this.cv("coverage").ml(this.gJJ())},"$0","gWp",0,0,168],
+cNN:[function(a){J.kH(J.UQ(a,"coverage"),new D.Yb(this))},"$1","gJJ",2,0,169,170],
 Qn:function(a){var z,y,x
 if(a==null)return
 z=J.UQ(a,"id")
@@ -14973,37 +14989,37 @@
 Yb:{
 "^":"Tp:10;a",
 $1:[function(a){var z=J.U6(a)
-z.t(a,"script").vW(z.t(a,"hits"))},"$1",null,2,0,null,169,"call"],
+z.t(a,"script").SC(z.t(a,"hits"))},"$1",null,2,0,null,171,"call"],
 $isEH:true},
 KQ:{
-"^":"Tp:163;a,b",
+"^":"Tp:165;a,b",
 $1:[function(a){var z,y
 z=this.a
 y=D.hi(z,a)
 if(y.gUm())z.Qy.to(this.b,new D.Ng(y))
-return y},"$1",null,2,0,null,162,"call"],
+return y},"$1",null,2,0,null,164,"call"],
 $isEH:true},
 Ng:{
-"^":"Tp:64;c",
+"^":"Tp:66;c",
 $0:function(){return this.c},
 $isEH:true},
 Qq:{
 "^":"Tp:10;a",
 $1:[function(a){var z=J.U6(a)
-this.a.u(0,z.t(a,"name"),z.t(a,"time"))},"$1",null,2,0,null,170,"call"],
+this.a.u(0,z.t(a,"name"),z.t(a,"time"))},"$1",null,2,0,null,172,"call"],
 $isEH:true},
 hU:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.oE(J.O6(a),J.O6(b))},
 $isEH:true},
 AP:{
-"^":"Tp:163;a",
+"^":"Tp:165;a",
 $1:[function(a){var z,y
 z=Date.now()
 new P.iP(z,!1).EK()
 y=this.a.GH
 y.xZ(z/1000,a)
-return y},"$1",null,2,0,null,126,"call"],
+return y},"$1",null,2,0,null,127,"call"],
 $isEH:true},
 vO:{
 "^":"af;Ce,Jz,r0,mQ,Sa,px,t7,VR,AP,fn",
@@ -15037,7 +15053,7 @@
 gB:function(a){var z=this.Ce.Zp
 return z.gB(z)},
 HC:[function(a){var z=this.Ce
-return z.HC(z)},"$0","gDx",0,0,94],
+return z.HC(z)},"$0","gDx",0,0,96],
 nq:function(a,b){var z=this.Ce
 return z.nq(z,b)},
 ct:function(a,b,c,d){return F.Wi(this.Ce,b,c,d)},
@@ -15244,7 +15260,7 @@
 this.nq(this,r)}this.lx=u}this.y6.u(0,t,w)
 this.FB.u(0,t,s)
 v+=2}}},
-vW:function(a){var z,y,x,w
+SC:function(a){var z,y,x,w
 z=J.U6(a)
 y=this.u9
 x=0
@@ -15280,7 +15296,7 @@
 z=this.Ix
 y=J.x(z)
 if(y.n(z,-1))return"N/A"
-return y.bu(z)},"$0","gkA",0,0,171],
+return y.bu(z)},"$0","gkA",0,0,173],
 bR:function(a){var z,y
 this.ar=F.Wi(this,C.PX,this.ar,null)
 z=this.VF
@@ -15300,18 +15316,18 @@
 z=this.Yu
 y=J.x(z)
 if(y.n(z,0))return""
-return"0x"+y.WZ(z,16)},"$0","gZd",0,0,171],
+return"0x"+y.WZ(z,16)},"$0","gZd",0,0,173],
 io:[function(a){var z
 if(a==null)return""
 z=a.gOo().Zp.t(0,this.Yu)
 if(z==null)return""
 if(J.xC(z.gfF(),z.gDu()))return""
-return D.Tn(z.gfF(),a.glt())+" ("+H.d(z.gfF())+")"},"$1","gcQ",2,0,172,66],
+return D.Tn(z.gfF(),a.glt())+" ("+H.d(z.gfF())+")"},"$1","gcQ",2,0,174,68],
 HU:[function(a){var z
 if(a==null)return""
 z=a.gOo().Zp.t(0,this.Yu)
 if(z==null)return""
-return D.Tn(z.gDu(),a.glt())+" ("+H.d(z.gDu())+")"},"$1","gGK",2,0,172,66],
+return D.Tn(z.gDu(),a.glt())+" ("+H.d(z.gDu())+")"},"$1","gGK",2,0,174,68],
 eQ:function(){var z,y,x,w
 y=J.uH(this.L4," ")
 x=y.length
@@ -15371,7 +15387,7 @@
 gfS:function(){return!0},
 tx:[function(a){var z,y
 this.ar=F.Wi(this,C.PX,this.ar,a)
-for(z=this.va,z=z.gA(z);z.G();)for(y=z.lo.guH(),y=y.gA(y);y.G();)y.lo.bR(a)},"$1","guL",2,0,173,174],
+for(z=this.va,z=z.gA(z);z.G();)for(y=z.lo.guH(),y=y.gA(y);y.G();)y.lo.bR(a)},"$1","guL",2,0,175,176],
 OF:function(){if(this.ar!=null)return
 if(!J.xC(this.I0,C.l8))return
 var z=this.MO
@@ -15482,10 +15498,10 @@
 z=this.a
 y=J.UQ(z.MO,"script")
 if(y==null)return
-J.SK(y).ml(z.guL())},"$1",null,2,0,null,175,"call"],
+J.SK(y).ml(z.guL())},"$1",null,2,0,null,177,"call"],
 $isEH:true},
 fx:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.Hn(b.gAv(),a.gAv())},
 $isEH:true},
 l8R:{
@@ -15551,7 +15567,7 @@
 "^":"af+Pi;",
 $isd3:true},
 Qf:{
-"^":"Tp:67;a,b",
+"^":"Tp:69;a,b",
 $2:function(a,b){var z,y
 z=J.x(b)
 y=!!z.$isqC
@@ -15600,34 +15616,79 @@
 "^":"uL+Pi;",
 $isd3:true}}],["service_html","package:observatory/service_html.dart",,U,{
 "^":"",
-XK:{
-"^":"wv;Jf,Ox,GY,RW,Ts,Va,Li,G2,Qy,z7,AP,fn,Jz,r0,mQ,Sa,px,t7,VR,AP,fn",
-z6:function(a,b){var z
-N.QM("").To("Fetching "+H.d(b)+" from "+H.d(this.Jf))
-z=this.Jf
-if(typeof z!=="string")return z.g()
-return W.It(J.ew(z,b),null,null).OA(new U.dT())},
-SC:function(){this.Jf="http://"+H.d(window.location.host)+"/"}},
-dT:{
-"^":"Tp:10;",
-$1:[function(a){var z
-N.QM("").YX("HttpRequest.getString failed.")
-z=J.RE(a)
-z.gN(a)
-return C.xr.KP(P.EF(["type","ServiceException","id","","response",J.Du(z.gN(a)),"kind","NetworkException","message","Could not connect to service. Check that you started the VM with the following flags:\n --enable-vm-service --pause-isolates-on-exit"],null,null))},"$1",null,2,0,null,21,"call"],
+KM:{
+"^":"wv;S3,yb,xV,DA,Ox,GY,RW,Ts,Va,Li,G2,Qy,z7,AP,fn,Jz,r0,mQ,Sa,px,t7,VR,AP,fn",
+H4:[function(a){var z,y,x,w,v
+z=C.xr.kV(J.Qd(a))
+y=J.U6(z)
+x=y.t(z,"seq")
+w=y.t(z,"response")
+v=this.S3.Rz(0,x)
+if(v==null)N.QM("").YX("Received unexpected message: "+H.d(z))
+else J.KD(v,w)},"$1","gqF",2,0,178,78],
+z6:function(a,b){var z=this.DA
+if(z==null)return P.PG(C.xr.KP(P.EF(["type","ServiceException","id","","response","","kind","NetworkException","message","Could not connect to service. Check that you started the VM with the following flags:\n --enable-vm-service --pause-isolates-on-exit"],null,null)),null)
+return z.ml(new U.N5(this,b))},
+ru:function(){var z,y,x
+this.xV="ws://"+H.d(window.location.host)+"/ws"
+z=W.lf
+y=H.VM(new P.Zf(P.Dt(z)),[z])
+this.DA=y.MM
+x=W.pS(this.xV,null)
+z=H.VM(new W.RO(x,C.Mp.Ph,!1),[null])
+z.geK(z).ml(new U.Lu(this,y,x))
+z=H.VM(new W.RO(x,C.MD.Ph,!1),[null])
+z.geK(z).ml(new U.VO(this))},
+static:{bU:function(){var z=new U.KM(P.L5(null,null,null,P.KN,P.oh),0,null,null,"unknown","unknown",0,!1,!1,P.bK(null,null,!1,null),P.bK(null,null,!1,null),P.L5(null,null,null,P.qU,D.af),P.L5(null,null,null,P.qU,D.bv),null,null,null,null,null,!1,null,null,null,null,null)
+z.md()
+z.ru()
+return z}}},
+Lu:{
+"^":"Tp:10;a,b,c",
+$1:[function(a){var z,y,x
+z=this.c
+y=H.VM(new W.RO(z,C.ph.Ph,!1),[null])
+x=this.a
+H.VM(new W.fd(0,y.bi,y.Ph,W.aF(x.gqF()),y.Sg),[H.Kp(y,0)]).Zz()
+y=H.VM(new W.RO(z,C.d6.Ph,!1),[null])
+y.geK(y).ml(new U.jI(x))
+y=this.b.MM
+if(y.Gv!==0)H.vh(P.w("Future already completed"))
+y.OH(z)},"$1",null,2,0,null,11,"call"],
+$isEH:true},
+jI:{
+"^":"Tp:10;d",
+$1:[function(a){this.d.DA=null},"$1",null,2,0,null,11,"call"],
+$isEH:true},
+VO:{
+"^":"Tp:10;e",
+$1:[function(a){this.e.DA=null},"$1",null,2,0,null,11,"call"],
+$isEH:true},
+N5:{
+"^":"Tp:10;a,b",
+$1:[function(a){var z,y,x,w,v
+z=this.a
+y=z.yb++
+x=this.b
+if(!J.RY(x,"/profile/tag"))N.QM("").To("Fetching "+H.d(x)+" from "+H.d(z.xV))
+w=P.qU
+v=H.VM(new P.Zf(P.Dt(w)),[w])
+z.S3.u(0,y,v)
+J.m9(a,C.xr.KP(P.EF(["seq",y,"request",x],null,null)))
+return v.MM},"$1",null,2,0,null,179,"call"],
 $isEH:true},
 bl:{
-"^":"wv;ba,yb,Ox,GY,RW,Ts,Va,Li,G2,Qy,z7,AP,fn,Jz,r0,mQ,Sa,px,t7,VR,AP,fn",
+"^":"wv;S3,yb,Ox,GY,RW,Ts,Va,Li,G2,Qy,z7,AP,fn,Jz,r0,mQ,Sa,px,t7,VR,AP,fn",
 q3:[function(a){var z,y,x,w,v
 z=J.RE(a)
 y=J.UQ(z.gRn(a),"id")
 x=J.UQ(z.gRn(a),"name")
 w=J.UQ(z.gRn(a),"data")
 if(!J.xC(x,"observatoryData"))return
-z=this.ba
+z=this.S3
 v=z.t(0,y)
 z.Rz(0,y)
-J.KD(v,w)},"$1","gVx",2,0,17,176],
+J.KD(v,w)},"$1","gVx",2,0,17,180],
 z6:function(a,b){var z,y,x
 z=""+this.yb
 y=P.Fl(null,null)
@@ -15635,7 +15696,7 @@
 y.u(0,"method","observatoryQuery")
 y.u(0,"query","/"+H.d(b));++this.yb
 x=H.VM(new P.Zf(P.Dt(null)),[null])
-this.ba.u(0,z,x)
+this.S3.u(0,z,x)
 J.vI(W.Pv(window.parent),C.xr.KP(y),"*")
 return x.MM},
 PI:function(){var z=H.VM(new W.RO(window,C.ph.Ph,!1),[null])
@@ -15808,7 +15869,7 @@
 gRY:function(a){return a.bP},
 sRY:function(a,b){a.bP=this.ct(a,C.zU,a.bP,b)},
 RC:[function(a,b,c,d){var z=J.K0((a.shadowRoot||a.webkitShadowRoot).querySelector("#slide-switch"))
-a.kF=this.ct(a,C.bk,a.kF,z)},"$3","gQU",6,0,86,1,177,88],
+a.kF=this.ct(a,C.bk,a.kF,z)},"$3","gQU",6,0,88,1,181,90],
 static:{Al:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -15986,7 +16047,7 @@
 z.Ut(a)
 return z}}},
 Fi:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){this.a.I1.u(0,b,a)},
 $isEH:true},
 tk:{
@@ -16018,8 +16079,8 @@
 "^":"V46;ju,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gtN:function(a){return a.ju},
 stN:function(a,b){a.ju=this.ct(a,C.kw,a.ju,b)},
-RF:[function(a,b){J.LE(a.ju).wM(b)},"$1","gvC",2,0,17,82],
-static:{HI:function(a){var z,y,x,w
+RF:[function(a,b){J.LE(a.ju).wM(b)},"$1","gvC",2,0,17,84],
+static:{lt:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
 x=P.qU
@@ -16215,7 +16276,7 @@
 J.Fc(t.gvt(),y)}},"$1","ge2",2,0,17,55]},
 WF:{
 "^":"Tp:10;a,b,c",
-$1:[function(a){return M.AD(this.b.grF(),this.a.a,this.c,a)},"$1",null,2,0,null,137,"call"],
+$1:[function(a){return M.AD(this.b.grF(),this.a.a,this.c,a)},"$1",null,2,0,null,62,"call"],
 $isEH:true},
 b2:{
 "^":"Ap;rF<,E3,vt<,jS",
@@ -16264,7 +16325,7 @@
 return x.ev(x,new M.qx(a))}},bC:function(a){if(typeof a==="string")return H.BU(a,null,new M.LG())
 return typeof a==="number"&&Math.floor(a)===a?a:0}}},
 YJG:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:function(){var z,y,x,w,v
 z=document.createElement("div",null).appendChild(W.ED(null))
 y=J.RE(z)
@@ -16515,7 +16576,7 @@
 $1:function(a){return this.c.pm(a,this.a,this.b)},
 $isEH:true},
 NW:{
-"^":"Tp:67;a,b,c,d",
+"^":"Tp:69;a,b,c,d",
 $2:function(a,b){var z,y,x,w
 for(;z=J.U6(a),J.xC(z.t(a,0),"_");)a=z.yn(a,1)
 if(this.d)z=z.n(a,"bind")||z.n(a,"if")||z.n(a,"repeat")
@@ -16657,7 +16718,7 @@
 j=v
 if(j==null)H.vh(P.u("Error must not be null"))
 if(k.Gv!==0)H.vh(P.w("Future already completed"))
-k.CG(j,u)}g=null}this.uy(i,x,g,w)}}for(t=p.gUQ(p),t=H.VM(new H.MH(null,J.mY(t.l6),t.T6),[H.Kp(t,0),H.Kp(t,1)]);t.G();)this.Ep(t.lo.gpp())},"$1","gk8",2,0,178,179],
+k.CG(j,u)}g=null}this.uy(i,x,g,w)}}for(t=p.gUQ(p),t=H.VM(new H.MH(null,J.mY(t.l6),t.T6),[H.Kp(t,0),H.Kp(t,1)]);t.G();)this.Ep(t.lo.gpp())},"$1","gk8",2,0,182,183],
 Ep:function(a){var z
 for(z=J.mY(a);z.G();)J.x0(z.gl())},
 Ke:function(){var z=this.VC
@@ -16744,7 +16805,7 @@
 x=z.length
 w=C.jn.cU(x,4)*4
 if(w>=x)return H.e(z,w)
-return y+H.d(z[w])},"$1","gzf",2,0,180,18],
+return y+H.d(z[w])},"$1","gzf",2,0,184,18],
 cH:[function(a){var z,y,x,w,v,u,t,s
 z=this.jU
 if(0>=z.length)return H.e(z,0)
@@ -16755,7 +16816,7 @@
 t=v*4
 if(t>=z.length)return H.e(z,t)
 s=z[t]
-y.vM+=typeof s==="string"?s:H.d(s)}return y.vM},"$1","gB5",2,0,181,182],
+y.vM+=typeof s==="string"?s:H.d(s)}return y.vM},"$1","gB5",2,0,185,186],
 l3:function(a,b){this.V6=this.jU.length===5?this.gzf():this.gB5()},
 static:{"^":"rz5,jO,t3a,epG,oM,Ftg",iw:function(a,b){var z,y,x,w,v,u,t,s,r,q,p,o,n,m
 if(a==null||a.length===0)return
@@ -16796,8 +16857,8 @@
 a.on=z
 a.BA=y
 a.LL=w
-C.u2.ZL(a)
-C.u2.XI(a)
+C.V8.ZL(a)
+C.V8.XI(a)
 return a}}}}],["vm_view_element","package:observatory/src/elements/vm_view.dart",,U,{
 "^":"",
 el:{
@@ -16806,7 +16867,7 @@
 swv:function(a,b){a.uB=this.ct(a,C.RJ,a.uB,b)},
 gkc:function(a){return a.lc},
 skc:function(a,b){a.lc=this.ct(a,C.yh,a.lc,b)},
-RF:[function(a,b){J.LE(a.uB).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.uB).wM(b)},"$1","gvC",2,0,17,84],
 static:{oH:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -16873,15 +16934,14 @@
 U.ma.$isa=true
 U.HB.$ishw=true
 U.HB.$isa=true
-U.Mp.$ishw=true
-U.Mp.$isa=true
+U.zb.$ishw=true
+U.zb.$isa=true
 U.x9.$ishw=true
 U.x9.$isa=true
 U.no.$ishw=true
 U.no.$isa=true
 U.cJ.$ishw=true
 U.cJ.$isa=true
-U.elO.$iselO=true
 U.elO.$ishw=true
 U.elO.$isa=true
 U.c0.$ishw=true
@@ -16923,10 +16983,17 @@
 A.dM.$ish4=true
 A.dM.$isKV=true
 A.dM.$isa=true
+P.oh.$isa=true
 D.af.$isaf=true
 D.af.$isa=true
 D.bv.$isaf=true
 D.bv.$isa=true
+W.lf.$isa=true
+W.AW.$isAW=true
+W.AW.$isea=true
+W.AW.$isa=true
+W.K3.$isea=true
+W.K3.$isa=true
 D.ta.$isa=true
 D.ER.$isa=true
 D.DP.$isa=true
@@ -16945,16 +17012,11 @@
 D.vO.$isa=true
 D.c2.$isc2=true
 D.c2.$isa=true
-W.fJ.$isa=true
-W.kQ.$isea=true
-W.kQ.$isa=true
 D.kx.$iskx=true
 D.kx.$isaf=true
 D.kx.$isa=true
 D.t9.$isa=true
 D.HJ.$isa=true
-W.AW.$isea=true
-W.AW.$isa=true
 N.HV.$isHV=true
 N.HV.$isa=true
 H.yo.$isa=true
@@ -16968,8 +17030,8 @@
 G.Ni.$isa=true
 P.qK.$isqK=true
 P.qK.$isa=true
-P.xp.$isxp=true
-P.xp.$isa=true
+P.dl.$isdl=true
+P.dl.$isa=true
 P.mE.$ismE=true
 P.mE.$isa=true
 P.KA.$isKA=true
@@ -17084,7 +17146,6 @@
 J.Do=function(a){return J.RE(a).gM0(a)}
 J.Dq=function(a,b){return J.w1(a).Rz(a,b)}
 J.Ds=function(a){return J.RE(a).gPj(a)}
-J.Du=function(a){return J.RE(a).gxN(a)}
 J.E3=function(a){return J.RE(a).gRu(a)}
 J.EC=function(a){return J.RE(a).giC(a)}
 J.EJ=function(a,b){return J.RE(a).sCf(a,b)}
@@ -17337,7 +17398,6 @@
 J.l7=function(a,b){return J.RE(a).sv8(a,b)}
 J.lB=function(a){return J.RE(a).guT(a)}
 J.lT=function(a){return J.RE(a).gOd(a)}
-J.lf=function(a,b){return J.Wx(a).O(a,b)}
 J.ls=function(a){return J.RE(a).gt3(a)}
 J.m4=function(a){return J.RE(a).gig(a)}
 J.m9=function(a,b){return J.RE(a).wR(a,b)}
@@ -17427,6 +17487,7 @@
 J.xW=function(a,b){return J.RE(a).sZm(a,b)}
 J.xa=function(a){return J.RE(a).geS(a)}
 J.xq=function(a,b){return J.w1(a).Vr(a,b)}
+J.xs=function(a,b){return J.Wx(a).O(a,b)}
 J.y2=function(a,b){return J.RE(a).mx(a,b)}
 J.y9=function(a){return J.RE(a).lh(a)}
 J.yA=function(a){return J.RE(a).gvu(a)}
@@ -17526,7 +17587,7 @@
 C.wB=X.uw.prototype
 C.lx=A.G1.prototype
 C.vB=J.kdQ.prototype
-C.u2=X.I5.prototype
+C.V8=X.I5.prototype
 C.bV=U.el.prototype
 C.KZ=new H.hJ()
 C.x4=new U.WH()
@@ -17559,8 +17620,8 @@
 C.ZQ=new A.ES(C.rB,C.BM,!1,C.Ks,!1,C.XVh)
 C.Ms=new H.GD("iconClass")
 C.Db=H.IL('qU')
-C.mI=new K.ndx()
-C.y0=I.ko([C.NS,C.mI])
+C.J19=new K.ndx()
+C.y0=I.ko([C.NS,C.J19])
 C.Gl=new A.ES(C.Ms,C.BM,!1,C.Db,!1,C.y0)
 C.VK=new H.GD("devtools")
 C.BQ=H.IL('a2')
@@ -17632,8 +17693,8 @@
 C.mr=new H.GD("expanded")
 C.DC=new A.ES(C.mr,C.BM,!1,C.BQ,!1,C.y0)
 C.j2=new H.GD("app")
-C.oP=H.IL('mL')
-C.zJ=new A.ES(C.j2,C.BM,!1,C.oP,!1,C.XVh)
+C.jY=H.IL('mL')
+C.zJ=new A.ES(C.j2,C.BM,!1,C.jY,!1,C.XVh)
 C.xP=new H.GD("ref")
 C.hI=new A.ES(C.xP,C.BM,!1,C.SmN,!1,C.XVh)
 C.jU=new H.GD("file")
@@ -17664,8 +17725,8 @@
 C.UY=new H.GD("result")
 C.rT=new A.ES(C.UY,C.BM,!1,C.SmN,!1,C.XVh)
 C.PX=new H.GD("script")
-C.KB=H.IL('vx')
-C.Cj=new A.ES(C.PX,C.BM,!1,C.KB,!1,C.XVh)
+C.c3=H.IL('vx')
+C.Cj=new A.ES(C.PX,C.BM,!1,C.c3,!1,C.XVh)
 C.S4=new H.GD("busy")
 C.FB=new A.ES(C.S4,C.BM,!1,C.BQ,!1,C.y0)
 C.AO=new H.GD("qualifiedName")
@@ -17748,7 +17809,7 @@
 C.Tt=new A.ES(C.Lc,C.BM,!1,C.Db,!1,C.XVh)
 C.YE=new H.GD("webSocket")
 C.Xt=new A.ES(C.YE,C.BM,!1,C.MR1,!1,C.XVh)
-C.ng=I.ko([C.mI])
+C.ng=I.ko([C.J19])
 C.Qs=new A.ES(C.i4,C.BM,!0,C.nq,!1,C.ng)
 C.lH=new H.GD("checkedText")
 C.A5=new A.ES(C.lH,C.BM,!1,C.Db,!1,C.XVh)
@@ -17764,13 +17825,14 @@
 C.ny=new P.a6(0)
 C.U3=H.VM(new W.FkO("change"),[W.ea])
 C.nI=H.VM(new W.FkO("click"),[W.Oq])
-C.MD=H.VM(new W.FkO("error"),[W.kQ])
+C.d6=H.VM(new W.FkO("close"),[W.K3])
+C.MD=H.VM(new W.FkO("error"),[W.ea])
 C.yZ=H.VM(new W.FkO("hashchange"),[W.ea])
 C.i3=H.VM(new W.FkO("input"),[W.ea])
-C.LF=H.VM(new W.FkO("load"),[W.kQ])
 C.ph=H.VM(new W.FkO("message"),[W.AW])
 C.uh=H.VM(new W.FkO("mousedown"),[W.Oq])
 C.Kq=H.VM(new W.FkO("mousemove"),[W.Oq])
+C.Mp=H.VM(new W.FkO("open"),[W.ea])
 C.mp=function(hooks) {
   if (typeof dartExperimentalFixupGetTag != "function") return hooks;
   hooks.getTag = dartExperimentalFixupGetTag(hooks.getTag);
@@ -18220,7 +18282,7 @@
 $.UG=!0
 $.RQ="objects/"
 $.vU=null
-$.Au=[C.tq,W.Bo,{},C.k5,Z.hx,{created:Z.BN},C.hP,E.uz,{created:E.fr},C.Mf,A.G1,{created:A.J8},C.q0S,H.Dg,{"":H.jZN},C.Dl,V.F1,{created:V.Lu},C.Jf,E.Mb,{created:E.pD},C.UJ,N.oa,{created:N.IB},C.Y3,Q.CY,{created:Q.Al},C.j4,D.IW,{created:D.dm},C.Vx,X.MJ,{created:X.Bs},C.Vh,Q.qZ,{created:Q.RH},C.rR,E.wN,{created:E.wZ7},C.yS,B.G6,{created:B.KU},C.z7,D.YA,{created:D.BP},C.Sb,A.kn,{created:A.D2},C.EZ,E.oF,{created:E.J3z},C.vw,A.UK,{created:A.JT},C.Jo,D.i7,{created:D.qb},C.BL,X.Nr,{created:X.na},C.ON,T.ov,{created:T.Zz},C.jR,F.Be,{created:F.f9},C.PT,M.CX,{created:M.as},C.iD,O.Vb,{created:O.pn},C.ce,X.kK,{created:X.os},C.dD,E.av,{created:E.R7},C.FA,A.Ya,{created:A.JR},C.hG,A.ir,{created:A.G7},C.Th,U.fI,{created:U.TXt},C.tU,E.L4,{created:E.p4},C.cK,X.I5,{created:X.cF},C.jA,R.Eg,{created:R.fL},C.K4,X.hV,{created:X.zy},C.xE,Z.aC,{created:Z.zg},C.vu,X.uw,{created:X.HI},C.pJ,E.Q6,{created:E.chF},C.Yy,E.uE,{created:E.eg},C.Yxm,H.Pg,{"":H.KY},C.il,Q.xI,{created:Q.lK},C.lp,R.LU,{created:R.rA},C.oG,E.ds,{created:E.pI},C.TU,D.Oz,{created:D.RP},C.OG,Q.eW,{created:Q.rt},C.km,A.fl,{created:A.zf},C.Tq,Z.vj,{created:Z.M7},C.JW,A.Ww,{created:A.ZC},C.CT,D.St,{created:D.N5},C.wH,R.zM,{created:R.cE},C.l4,Z.uL,{created:Z.EE},C.Wh,E.U1,{created:E.hm},C.Zj,A.md,{created:A.DCi},C.FG,E.qh,{created:E.Sc},C.NR,K.nm,{created:K.qa},C.DD,E.Zn,{created:E.xK},C.qF,E.mO,{created:E.Ch},C.Ey,A.wM,{created:A.GO},C.nX,E.DE,{created:E.oB},C.bh,R.i6,{created:R.IT},C.jRi,H.we,{"":H.ic},C.Xv,E.n5,{created:E.xx},C.KO,F.ZP,{created:F.Yw},C.Wz,B.pR,{created:B.lu},C.Ep,E.ou,{created:E.dv},C.tc,E.Ma,{created:E.Ii},C.Io,D.Qh,{created:D.Qj},C.wk,L.nJ,{created:L.Rp},C.te,N.BS,{created:N.N0},C.ms,A.Bm,{created:A.yU},C.pK,D.Rk,{created:D.dP},C.lE,U.DK,{created:U.E5},C.ri,W.yy,{},C.Az,A.Gk,{created:A.Sy},C.X8,U.Ti,{created:U.lv},C.Lg,R.JI,{created:R.U9},C.Ju,K.Ly,{created:K.Ut},C.mq,L.qk,{created:L.KM},C.XW,W.uEY,{},C.oT,O.VY,{created:O.On},C.jK,U.el,{created:U.oH}]
+$.Au=[C.tq,W.Bo,{},C.k5,Z.hx,{created:Z.BN},C.hP,E.uz,{created:E.fr},C.Mf,A.G1,{created:A.J8},C.q0S,H.Dg,{"":H.jZN},C.Dl,V.F1,{created:V.JT8},C.Jf,E.Mb,{created:E.pD},C.UJ,N.oa,{created:N.IB},C.Y3,Q.CY,{created:Q.Al},C.j4,D.IW,{created:D.dm},C.Vx,X.MJ,{created:X.Bs},C.Vh,Q.qZ,{created:Q.RH},C.rR,E.wN,{created:E.wZ7},C.yS,B.G6,{created:B.KU},C.z7,D.YA,{created:D.BP},C.Sb,A.kn,{created:A.D2},C.EZ,E.oF,{created:E.J3z},C.vw,A.UK,{created:A.JT},C.Jo,D.i7,{created:D.qb},C.BL,X.Nr,{created:X.na},C.ON,T.ov,{created:T.Zz},C.jR,F.Be,{created:F.f9},C.PT,M.CX,{created:M.as},C.iD,O.Vb,{created:O.pn},C.ce,X.kK,{created:X.os},C.dD,E.av,{created:E.R7},C.FA,A.Ya,{created:A.vn},C.hG,A.ir,{created:A.G7},C.Th,U.fI,{created:U.TXt},C.tU,E.L4,{created:E.p4},C.cK,X.I5,{created:X.cF},C.jA,R.Eg,{created:R.fL},C.K4,X.hV,{created:X.zy},C.xE,Z.aC,{created:Z.zg},C.vu,X.uw,{created:X.lt},C.pJ,E.Q6,{created:E.chF},C.Yy,E.uE,{created:E.eg},C.Yxm,H.Pg,{"":H.KY},C.il,Q.xI,{created:Q.lK},C.lp,R.LU,{created:R.rA},C.oG,E.ds,{created:E.pI},C.TU,D.Oz,{created:D.RP},C.OG,Q.eW,{created:Q.rt},C.km,A.fl,{created:A.Du},C.Tq,Z.vj,{created:Z.M7},C.JW,A.Ww,{created:A.ZC},C.CT,D.St,{created:D.JR},C.wH,R.zM,{created:R.cE},C.l4,Z.uL,{created:Z.EE},C.Wh,E.U1,{created:E.hm},C.Zj,A.md,{created:A.DCi},C.FG,E.qh,{created:E.Sc},C.NR,K.nm,{created:K.qa},C.DD,E.Zn,{created:E.xK},C.qF,E.mO,{created:E.Ch},C.Ey,A.wM,{created:A.GO},C.nX,E.DE,{created:E.oB},C.bh,R.i6,{created:R.IT},C.jRi,H.we,{"":H.ic},C.Xv,E.n5,{created:E.xx},C.KO,F.ZP,{created:F.Yw},C.Wz,B.pR,{created:B.lu},C.Ep,E.ou,{created:E.dv},C.tc,E.Ma,{created:E.Ii},C.Io,D.Qh,{created:D.Qj},C.wk,L.nJ,{created:L.Rp},C.te,N.BS,{created:N.N0},C.ms,A.Bm,{created:A.yU},C.pK,D.Rk,{created:D.dP},C.lE,U.DK,{created:U.E5},C.ri,W.yy,{},C.Az,A.Gk,{created:A.Sy},C.X8,U.Ti,{created:U.lv},C.Lg,R.JI,{created:R.U9},C.Ju,K.Ly,{created:K.Ut},C.mq,L.qk,{created:L.Za},C.XW,W.uEY,{},C.oT,O.VY,{created:O.On},C.jK,U.el,{created:U.oH}]
 I.$lazy($,"globalThis","DX","jk",function(){return function(){return this}()})
 I.$lazy($,"globalWindow","UW","My",function(){return $.jk().window})
 I.$lazy($,"globalWorker","uj","nB",function(){return $.jk().Worker})
@@ -18288,8 +18350,8 @@
 I.$lazy($,"_templateCreator","H8","rf",function(){return H.VM(new P.kM(null),[null])})
 I.$lazy($,"_expando","fF","cm",function(){return H.VM(new P.kM("template_binding"),[null])})
 
-init.functionAliases={Sa:183}
-init.metadata=["sender","e",{func:"pL",args:[P.qU]},"closure","isolate","numberOfArguments","arg1","arg2","arg3","arg4",{func:"aB",args:[null]},"_",{func:"Pt",ret:P.qU,args:[P.KN]},"bytes",{func:"RJ",ret:P.qU,args:[null]},{func:"kl",void:true},{func:"n9",void:true,args:[{func:"kl",void:true}]},{func:"G5",void:true,args:[null]},"value",{func:"Mx",void:true,args:[null],opt:[P.mE]},,"error","stackTrace",{func:"cX",void:true,args:[P.xp,P.qK,P.xp,null,P.mE]},"self","parent","zone",{func:"QN",args:[P.xp,P.qK,P.xp,{func:"NT"}]},"f",{func:"wD",args:[P.xp,P.qK,P.xp,{func:"aB",args:[null]},null]},"arg",{func:"ta",args:[P.xp,P.qK,P.xp,{func:"bh",args:[null,null]},null,null]},{func:"HQ",ret:{func:"NT"},args:[P.xp,P.qK,P.xp,{func:"NT"}]},{func:"ie",ret:{func:"aB",args:[null]},args:[P.xp,P.qK,P.xp,{func:"aB",args:[null]}]},{func:"IU",ret:{func:"bh",args:[null,null]},args:[P.xp,P.qK,P.xp,{func:"bh",args:[null,null]}]},{func:"iV",void:true,args:[P.xp,P.qK,P.xp,{func:"NT"}]},{func:"Uk",ret:P.Xa,args:[P.xp,P.qK,P.xp,P.a6,{func:"kl",void:true}]},"duration","callback",{func:"Zb",void:true,args:[P.xp,P.qK,P.xp,P.qU]},{func:"kx",void:true,args:[P.qU]},{func:"Jj",ret:P.xp,args:[P.xp,P.qK,P.xp,P.aY,P.Z0]},{func:"Gl",ret:P.a2,args:[null,null]},"a","b",{func:"bX",ret:P.KN,args:[null]},{func:"uJ",ret:P.a,args:[null]},"object",{func:"xh",ret:P.KN,args:[P.Rz,P.Rz]},{func:"E0",ret:P.a2,args:[P.a,P.a]},{func:"ZY",ret:P.KN,args:[P.a]},"receiver",{func:"wI",args:[null,null,null,null]},"name","oldValue","newValue","captureThis","arguments","o",{func:"Z5",ret:P.a2,args:[P.IN]},"symbol",{func:"qq",ret:[P.QV,K.O1],args:[P.QV]},"iterable","invocation",{func:"NT"},{func:"ob",args:[P.EH]},"code",{func:"bh",args:[null,null]},"key",{func:"Za",args:[P.qU,null]},{func:"TS",args:[null,P.qU]},{func:"Yv",void:true,args:[null,null,null]},"c",{func:"F3",void:true,args:[D.N7]},{func:"GJ",void:true,args:[D.EP]},"exception","event","obj",{func:"qE",ret:P.qU,args:[P.KN,P.KN]},"row","column",{func:"c3",args:[P.KN,P.KN]},"done",{func:"Wr",ret:[P.b8,D.af],args:[P.qU]},"text","dummy",{func:"Np",void:true,args:[W.ea,null,W.KV]},"detail","target",{func:"lQ",args:[D.kx]},"data",{func:"uu",void:true,args:[P.a],opt:[P.mE]},{func:"cq",void:true,opt:[null]},{func:"BG",args:[null],opt:[null]},{func:"Uf",ret:P.a2},"ignored","convert","element",{func:"SF",args:[P.a2]},{func:"a9",void:true,opt:[P.b8]},"resumeSignal",{func:"ha",args:[null,P.mE]},{func:"N5",void:true,args:[null,P.mE]},"each",{func:"lv",args:[P.IN,null]},{func:"jK",ret:P.KN,args:[P.qU]},{func:"cS",ret:P.CP,args:[P.qU]},"xhr",{func:"QO",void:true,args:[W.Oq]},"result",{func:"jH",args:[D.af]},{func:"XG",ret:O.Hz},"response",{func:"Q5",args:[D.vO]},"st",{func:"Sz",void:true,args:[W.ea,null,W.h4]},{func:"xo",ret:P.qU,args:[P.a2]},"newSpace",{func:"rI",args:[P.KN]},{func:"iR",args:[P.KN,null]},{func:"xD",ret:P.QV,args:[{func:"pL",args:[P.qU]}]},{func:"Qd",ret:P.QV,args:[{func:"qt",ret:P.QV,args:[P.qU]}]},{func:"pw",void:true,args:[P.a2,null]},"expand",{func:"KDY",ret:[P.b8,D.af],args:[null]},{func:"Df",ret:P.qU,args:[G.Y2]},"m",{func:"fnh",ret:P.b8,args:[null]},"tagProfile","rec",{func:"IM",args:[N.HV]},{func:"le",ret:P.qU,args:[P.CP]},"time",{func:"h6",ret:P.a2,args:[P.qU]},"type",{func:"Aa",args:[P.qK,P.xp]},{func:"h2",args:[P.xp,P.qK,P.xp,{func:"aB",args:[null]}]},"x","s",{func:"DF",void:true,args:[P.a]},"records",{func:"kk",args:[L.Tv,null]},{func:"qx",void:true,args:[P.qU,P.qU]},{func:"aA",void:true,args:[P.WO,P.Z0,P.WO]},{func:"WW",void:true,args:[W.ea]},"i","changes","model","node","oneTime",{func:"oYt",args:[null,null,null]},{func:"K7",void:true,args:[[P.WO,T.yj]]},"jsElem","extendee",{func:"QP",args:[null,P.qU,P.qU]},"k","v",{func:"ZD",args:[[P.WO,T.yj]]},{func:"Cx",ret:U.zX,args:[U.hw,U.hw]},{func:"Qc",args:[U.hw]},{func:"Yg",ret:P.qU,args:[D.c2]},"line","map",{func:"JC",args:[V.qC]},{func:"If",ret:P.qU,args:[P.qU]},"id",{func:"rl",ret:P.b8},{func:"a0",void:true,args:[D.vO]},"coverage","scriptCoverage","timer",{func:"Br",ret:P.qU},{func:"xA",ret:P.qU,args:[D.kx]},{func:"qQ",void:true,args:[D.vx]},"script","func","msg","details",{func:"PzC",void:true,args:[[P.WO,G.DA]]},"splices",{func:"Vv",ret:P.qU,args:[P.a]},{func:"e3",ret:P.qU,args:[[P.WO,P.a]]},"values",{func:"vl",ret:P.b8,args:[P.qU]},];$=null
+init.functionAliases={Sa:187}
+init.metadata=["sender","e",{func:"pL",args:[P.qU]},"closure","isolate","numberOfArguments","arg1","arg2","arg3","arg4",{func:"aB",args:[null]},"_",{func:"Pt",ret:P.qU,args:[P.KN]},"bytes",{func:"RJ",ret:P.qU,args:[null]},{func:"kl",void:true},{func:"n9",void:true,args:[{func:"kl",void:true}]},{func:"G5",void:true,args:[null]},"value",{func:"Mx",void:true,args:[null],opt:[P.mE]},,"error","stackTrace",{func:"cX",void:true,args:[P.dl,P.qK,P.dl,null,P.mE]},"self","parent","zone",{func:"QN",args:[P.dl,P.qK,P.dl,{func:"NT"}]},"f",{func:"wD",args:[P.dl,P.qK,P.dl,{func:"aB",args:[null]},null]},"arg",{func:"ta",args:[P.dl,P.qK,P.dl,{func:"bh",args:[null,null]},null,null]},{func:"HQ",ret:{func:"NT"},args:[P.dl,P.qK,P.dl,{func:"NT"}]},{func:"ie",ret:{func:"aB",args:[null]},args:[P.dl,P.qK,P.dl,{func:"aB",args:[null]}]},{func:"IU",ret:{func:"bh",args:[null,null]},args:[P.dl,P.qK,P.dl,{func:"bh",args:[null,null]}]},{func:"iV",void:true,args:[P.dl,P.qK,P.dl,{func:"NT"}]},{func:"Uk",ret:P.Xa,args:[P.dl,P.qK,P.dl,P.a6,{func:"kl",void:true}]},"duration","callback",{func:"Zb",void:true,args:[P.dl,P.qK,P.dl,P.qU]},{func:"kx",void:true,args:[P.qU]},{func:"Jj",ret:P.dl,args:[P.dl,P.qK,P.dl,P.aY,P.Z0]},{func:"Gl",ret:P.a2,args:[null,null]},"a","b",{func:"bX",ret:P.KN,args:[null]},{func:"uJ",ret:P.a,args:[null]},"object",{func:"xh",ret:P.KN,args:[P.Rz,P.Rz]},{func:"E0",ret:P.a2,args:[P.a,P.a]},{func:"ZY",ret:P.KN,args:[P.a]},"receiver",{func:"wI",args:[null,null,null,null]},"name","oldValue","newValue","captureThis","arguments","o",{func:"Z5",ret:P.a2,args:[P.IN]},"symbol","v","x",{func:"qq",ret:[P.QV,K.O1],args:[P.QV]},"iterable","invocation",{func:"NT"},{func:"ob",args:[P.EH]},"code",{func:"bh",args:[null,null]},"key",{func:"Za",args:[P.qU,null]},{func:"TS",args:[null,P.qU]},{func:"Yv",void:true,args:[null,null,null]},"c",{func:"F3",void:true,args:[D.N7]},{func:"GJ",void:true,args:[D.EP]},"exception","event","obj",{func:"qE",ret:P.qU,args:[P.KN,P.KN]},"row","column",{func:"c3",args:[P.KN,P.KN]},"done",{func:"Wr",ret:[P.b8,D.af],args:[P.qU]},"text","dummy",{func:"Np",void:true,args:[W.ea,null,W.KV]},"detail","target",{func:"lQ",args:[D.kx]},"data",{func:"uu",void:true,args:[P.a],opt:[P.mE]},{func:"cq",void:true,opt:[null]},{func:"BG",args:[null],opt:[null]},{func:"Uf",ret:P.a2},"ignored","convert","element",{func:"SF",args:[P.a2]},{func:"a9",void:true,opt:[P.b8]},"resumeSignal",{func:"ha",args:[null,P.mE]},{func:"N5",void:true,args:[null,P.mE]},"each",{func:"lv",args:[P.IN,null]},{func:"jK",ret:P.KN,args:[P.qU]},{func:"cS",ret:P.CP,args:[P.qU]},{func:"QO",void:true,args:[W.Oq]},"result",{func:"jH",args:[D.af]},{func:"XG",ret:O.Hz},"response",{func:"Q5",args:[D.vO]},"st",{func:"Sz",void:true,args:[W.ea,null,W.h4]},{func:"xo",ret:P.qU,args:[P.a2]},"newSpace",{func:"rI",args:[P.KN]},{func:"iR",args:[P.KN,null]},{func:"xD",ret:P.QV,args:[{func:"pL",args:[P.qU]}]},{func:"Qd",ret:P.QV,args:[{func:"qt",ret:P.QV,args:[P.qU]}]},{func:"S0",void:true,args:[P.a2,null]},"expand",{func:"KDY",ret:[P.b8,D.af],args:[null]},{func:"Df",ret:P.qU,args:[G.Y2]},"m",{func:"fnh",ret:P.b8,args:[null]},"tagProfile","rec",{func:"IM",args:[N.HV]},{func:"le",ret:P.qU,args:[P.CP]},"time",{func:"h6",ret:P.a2,args:[P.qU]},"type",{func:"Aa",args:[P.qK,P.dl]},{func:"h2",args:[P.dl,P.qK,P.dl,{func:"aB",args:[null]}]},"s",{func:"DF",void:true,args:[P.a]},"records",{func:"kk",args:[L.Tv,null]},{func:"qx",void:true,args:[P.qU,P.qU]},{func:"aA",void:true,args:[P.WO,P.Z0,P.WO]},{func:"WW",void:true,args:[W.ea]},"i","changes","model","node","oneTime",{func:"oYt",args:[null,null,null]},{func:"K7",void:true,args:[[P.WO,T.yj]]},"jsElem","extendee",{func:"QP",args:[null,P.qU,P.qU]},"k",{func:"Hb",args:[null],named:{skipChanges:P.a2}},!1,"skipChanges",{func:"ZD",args:[[P.WO,T.yj]]},{func:"Cx",ret:U.zX,args:[U.hw,U.hw]},{func:"Qc",args:[U.hw]},{func:"Yg",ret:P.qU,args:[D.c2]},"line","map",{func:"JC",args:[V.qC]},{func:"If",ret:P.qU,args:[P.qU]},"id",{func:"rl",ret:P.b8},{func:"a0",void:true,args:[D.vO]},"coverage","scriptCoverage","timer",{func:"Br",ret:P.qU},{func:"xA",ret:P.qU,args:[D.kx]},{func:"qQ",void:true,args:[D.vx]},"script","func",{func:"lb",void:true,args:[W.AW]},"socket","msg","details",{func:"PzC",void:true,args:[[P.WO,G.DA]]},"splices",{func:"Vv",ret:P.qU,args:[P.a]},{func:"e3",ret:P.qU,args:[[P.WO,P.a]]},"values",{func:"vl",ret:P.b8,args:[P.qU]},];$=null
 I = I.$finishIsolateConstructor(I)
 $=new I()
 function convertToFastObject(a){function MyClass(){}MyClass.prototype=a
diff --git a/runtime/bin/vmservice/client/deployed/web/index_devtools.html_bootstrap.dart.js b/runtime/bin/vmservice/client/deployed/web/index_devtools.html_bootstrap.dart.js
index 0e32be3..9a82ab7 100644
--- a/runtime/bin/vmservice/client/deployed/web/index_devtools.html_bootstrap.dart.js
+++ b/runtime/bin/vmservice/client/deployed/web/index_devtools.html_bootstrap.dart.js
@@ -193,7 +193,7 @@
 n:function(a,b){return a===b},
 giO:function(a){return H.eQ(a)},
 bu:function(a){return H.a5(a)},
-T:[function(a,b){throw H.b(P.lr(a,b.gWa(),b.gnd(),b.gVm(),null))},"$1","gxK",2,0,null,63],
+T:[function(a,b){throw H.b(P.lr(a,b.gWa(),b.gnd(),b.gVm(),null))},"$1","gxK",2,0,null,65],
 gbx:function(a){return new H.cu(H.dJ(a),null)},
 "%":"DOMImplementation|Navigator|SVGAnimatedEnumeration|SVGAnimatedLength|SVGAnimatedLengthList|SVGAnimatedNumber|SVGAnimatedNumberList|SVGAnimatedString"},
 yEe:{
@@ -208,7 +208,7 @@
 bu:function(a){return"null"},
 giO:function(a){return 0},
 gbx:function(a){return C.GX},
-T:[function(a,b){return J.Gv.prototype.T.call(this,a,b)},"$1","gxK",2,0,null,63]},
+T:[function(a,b){return J.Gv.prototype.T.call(this,a,b)},"$1","gxK",2,0,null,65]},
 wm:{
 "^":"Gv;",
 giO:function(a){return 0},
@@ -646,11 +646,11 @@
 vM:function(a){return a==null||typeof a==="string"||typeof a==="number"||typeof a==="boolean"},
 ZR:function(a){return a==null||typeof a==="string"||typeof a==="number"||typeof a==="boolean"},
 PK:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:function(){this.b.$1(this.a.a)},
 $isEH:true},
 JO:{
-"^":"Tp:64;a,c",
+"^":"Tp:66;a,c",
 $0:function(){this.c.$2(this.a.a,null)},
 $isEH:true},
 f0:{
@@ -753,7 +753,7 @@
 if(this===init.globalState.Nr)throw v}}finally{this.mf=!1
 init.globalState.N0=z
 if(z!=null)$=z.gEn()
-if(this.M2!=null)for(;u=this.M2,!u.gl0(u);)this.M2.AR().$0()}return y},"$1","gZm",2,0,65,66],
+if(this.M2!=null)for(;u=this.M2,!u.gl0(u);)this.M2.AR().$0()}return y},"$1","gZm",2,0,67,68],
 Ds:function(a){var z=J.U6(a)
 switch(z.t(a,0)){case"pause":this.V0(z.t(a,1),z.t(a,2))
 break
@@ -833,7 +833,7 @@
 JH:{
 "^":"a;"},
 mN:{
-"^":"Tp:64;a,b,c,d,e,f",
+"^":"Tp:66;a,b,c,d,e,f",
 $0:[function(){H.Di(this.a,this.b,this.c,this.d,this.e,this.f)},"$0",null,0,0,null,"call"],
 $isEH:true},
 vK:{
@@ -876,7 +876,7 @@
 $isRZ:true,
 $iswC:true},
 Ua:{
-"^":"Tp:64;a,b,c",
+"^":"Tp:66;a,b,c",
 $0:[function(){var z,y
 z=this.b.JE
 if(!z.gP0()){if(this.c){y=this.a
@@ -892,8 +892,8 @@
 n:function(a,b){if(b==null)return!1
 return!!J.x(b).$isdd&&J.xC(this.ZU,b.ZU)&&J.xC(this.tv,b.tv)&&J.xC(this.bv,b.bv)},
 giO:function(a){var z,y,x
-z=J.lf(this.ZU,16)
-y=J.lf(this.tv,8)
+z=J.xs(this.ZU,16)
+y=J.xs(this.tv,8)
 x=this.bv
 if(typeof x!=="number")return H.s(x)
 return(z^y^x)>>>0},
@@ -1003,7 +1003,7 @@
 DE:function(a){return H.vh(P.SY(null))},
 yf:function(a){return H.vh(P.SY(null))}},
 OW:{
-"^":"Tp:67;a,b",
+"^":"Tp:69;a,b",
 $2:function(a,b){var z=this.b
 J.kW(this.a.a,z.Q9(a),z.Q9(b))},
 $isEH:true},
@@ -1675,7 +1675,7 @@
 $isyN:true},
 hY:{
 "^":"Tp:10;a",
-$1:[function(a){return this.a.TZ(a)},"$1",null,2,0,null,68,"call"],
+$1:[function(a){return this.a.TZ(a)},"$1",null,2,0,null,70,"call"],
 $isEH:true},
 XR:{
 "^":"mW;Y3",
@@ -1755,14 +1755,14 @@
 z[y]=x},
 $isEH:true},
 lk:{
-"^":"Tp:69;a,b,c",
+"^":"Tp:71;a,b,c",
 $2:function(a,b){var z=this.a
 z.b=z.b+"$"+H.d(a)
 this.c.push(a)
 this.b.push(b);++z.a},
 $isEH:true},
 u8:{
-"^":"Tp:69;a,b",
+"^":"Tp:71;a,b",
 $2:function(a,b){var z=this.b
 if(z.x4(a))z.u(0,a,b)
 else this.a.a=!0},
@@ -1837,23 +1837,23 @@
 this.ui=z
 return z}},
 dr:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:function(){return this.a.$0()},
 $isEH:true},
 TL:{
-"^":"Tp:64;b,c",
+"^":"Tp:66;b,c",
 $0:function(){return this.b.$1(this.c)},
 $isEH:true},
 uZ:{
-"^":"Tp:64;d,e,f",
+"^":"Tp:66;d,e,f",
 $0:function(){return this.d.$2(this.e,this.f)},
 $isEH:true},
 OQ:{
-"^":"Tp:64;UI,bK,Gq,Rm",
+"^":"Tp:66;UI,bK,Gq,Rm",
 $0:function(){return this.UI.$3(this.bK,this.Gq,this.Rm)},
 $isEH:true},
 Qx:{
-"^":"Tp:64;w3,HZ,mG,xC,cj",
+"^":"Tp:66;w3,HZ,mG,xC,cj",
 $0:function(){return this.w3.$4(this.HZ,this.mG,this.xC,this.cj)},
 $isEH:true},
 Tp:{
@@ -1980,7 +1980,7 @@
 $1:function(a){return this.a(a)},
 $isEH:true},
 VX:{
-"^":"Tp:70;b",
+"^":"Tp:72;b",
 $2:function(a,b){return this.b(a,b)},
 $isEH:true},
 vZ:{
@@ -2094,7 +2094,7 @@
 F6:[function(a,b,c,d){var z=a.fi
 if(z===!0)return
 if(a.dB!=null){a.fi=this.ct(a,C.S4,z,!0)
-this.LY(a,null).wM(new X.jE(a))}},"$3","gNa",6,0,71,43,44,72],
+this.LY(a,null).wM(new X.jE(a))}},"$3","gNa",6,0,73,43,44,74],
 static:{zy:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -2114,7 +2114,7 @@
 "^":"ir+Pi;",
 $isd3:true},
 jE:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:[function(){var z=this.a
 z.fi=J.Q5(z,C.S4,z.fi,!1)},"$0",null,0,0,null,"call"],
 $isEH:true}}],["app","package:observatory/app.dart",,G,{
@@ -2179,9 +2179,9 @@
 z=z.Li
 H.VM(new P.Ik(z),[H.Kp(z,0)]).yI(this.gXa())},
 kj:[function(a){this.AJ=F.Wi(this,C.F3,this.AJ,a)
-window.location.hash=""},"$1","gbf",2,0,73,21],
+window.location.hash=""},"$1","gbf",2,0,75,21],
 t1:[function(a){this.AJ=F.Wi(this,C.F3,this.AJ,a)
-window.location.hash=""},"$1","gXa",2,0,74,75],
+window.location.hash=""},"$1","gXa",2,0,76,77],
 US:function(){this.Da()},
 hq:function(){this.Da()}},
 Kf:{
@@ -2217,7 +2217,7 @@
 static:{"^":"K3D"}},
 Qe:{
 "^":"Tp:10;a",
-$1:[function(a){this.a.df()},"$1",null,2,0,null,76,"call"],
+$1:[function(a){this.a.df()},"$1",null,2,0,null,78,"call"],
 $isEH:true},
 wX:{
 "^":"Tp:10;a,b",
@@ -2226,7 +2226,7 @@
 y=z.ec
 y.AJ=F.Wi(y,C.F3,y.AJ,a)
 z=z.ec
-z.fz=F.Wi(z,C.Zg,z.fz,this.b)},"$1",null,2,0,null,77,"call"],
+z.fz=F.Wi(z,C.Zg,z.fz,this.b)},"$1",null,2,0,null,79,"call"],
 $isEH:true},
 Y2:{
 "^":"Pi;eT>,yt<,ks>,oH<",
@@ -2261,7 +2261,7 @@
 w=J.U6(z)
 v=w.u8(z,a)+1
 w.UZ(z,v,v+y)}},
-zb:{
+Ktd:{
 "^":"a;ph>,xy<",
 static:{mb:[function(a){return a!=null?J.AG(a):"<null>"},"$1","HP",2,0,14]}},
 Ni:{
@@ -2287,19 +2287,19 @@
 y=J.UQ(J.U8o(z[a]),b)
 z=this.oH
 if(b>>>0!==b||b>=z.length)return H.e(z,b)
-return z[b].gxy().$1(y)},"$2","gwy",4,0,78,79,80],
+return z[b].gxy().$1(y)},"$2","gwy",4,0,80,81,82],
 Qs:[function(a){var z
 if(!J.xC(a,this.pT)){z=this.oH
 if(a>>>0!==a||a>=z.length)return H.e(z,a)
 return J.ew(J.Q4(z[a]),"\u2003")}z=this.oH
 if(a>>>0!==a||a>=z.length)return H.e(z,a)
 z=J.Q4(z[a])
-return J.ew(z,this.jV?"\u25bc":"\u25b2")},"$1","gCO",2,0,12,80],
+return J.ew(z,this.jV?"\u25bc":"\u25b2")},"$1","gCO",2,0,12,82],
 TK:[function(a,b){var z=this.WT
 if(a>>>0!==a||a>=z.length)return H.e(z,a)
-return J.UQ(J.U8o(z[a]),b)},"$2","gyY",4,0,81,79,80]},
+return J.UQ(J.U8o(z[a]),b)},"$2","gyY",4,0,83,81,82]},
 BD:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){var z,y,x,w
 z=this.a
 y=z.WT
@@ -3224,691 +3224,691 @@
 $1:function(a){return a.gaU()},
 $isEH:true},
 e205:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.RX(a,b)},
 $isEH:true},
 e206:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.a8(a,b)},
 $isEH:true},
 e207:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.oO(a,b)},
 $isEH:true},
 e208:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.l7(a,b)},
 $isEH:true},
 e209:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.kB(a,b)},
 $isEH:true},
 e210:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Ae(a,b)},
 $isEH:true},
 e211:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.IX(a,b)},
 $isEH:true},
 e212:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.WI(a,b)},
 $isEH:true},
 e213:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.o0(a,b)},
 $isEH:true},
 e214:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.fH(a,b)},
 $isEH:true},
 e215:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Sf(a,b)},
 $isEH:true},
 e216:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.qA(a,b)},
 $isEH:true},
 e217:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.LM(a,b)},
 $isEH:true},
 e218:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.qq(a,b)},
 $isEH:true},
 e219:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Pk(a,b)},
 $isEH:true},
 e220:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Yz(a,b)},
 $isEH:true},
 e221:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.sw2(b)},
 $isEH:true},
 e222:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Qr(a,b)},
 $isEH:true},
 e223:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.xW(a,b)},
 $isEH:true},
 e224:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.BC(a,b)},
 $isEH:true},
 e225:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.VJ(a,b)},
 $isEH:true},
 e226:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.NO(a,b)},
 $isEH:true},
 e227:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.WB(a,b)},
 $isEH:true},
 e228:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.JZ(a,b)},
 $isEH:true},
 e229:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.fR(a,b)},
 $isEH:true},
 e230:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.shY(b)},
 $isEH:true},
 e231:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.LP(a,b)},
 $isEH:true},
 e232:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.GF(a,b)},
 $isEH:true},
 e233:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Nf(a,b)},
 $isEH:true},
 e234:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Pl(a,b)},
 $isEH:true},
 e235:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.C3(a,b)},
 $isEH:true},
 e236:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.xH(a,b)},
 $isEH:true},
 e237:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Nh(a,b)},
 $isEH:true},
 e238:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.sHP(b)},
 $isEH:true},
 e239:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.AI(a,b)},
 $isEH:true},
 e240:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.nA(a,b)},
 $isEH:true},
 e241:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.fb(a,b)},
 $isEH:true},
 e242:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.tv(a,b)},
 $isEH:true},
 e243:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.siq(b)},
 $isEH:true},
 e244:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Qy(a,b)},
 $isEH:true},
 e245:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.sKt(b)},
 $isEH:true},
 e246:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Oo(a,b)},
 $isEH:true},
 e247:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.mU(a,b)},
 $isEH:true},
 e248:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Kz(a,b)},
 $isEH:true},
 e249:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.uM(a,b)},
 $isEH:true},
 e250:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Er(a,b)},
 $isEH:true},
 e251:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.uX(a,b)},
 $isEH:true},
 e252:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.hS(a,b)},
 $isEH:true},
 e253:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.sSK(b)},
 $isEH:true},
 e254:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.shX(b)},
 $isEH:true},
 e255:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.cl(a,b)},
 $isEH:true},
 e256:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Jb(a,b)},
 $isEH:true},
 e257:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.k7(a,b)},
 $isEH:true},
 e258:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.MX(a,b)},
 $isEH:true},
 e259:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.A4(a,b)},
 $isEH:true},
 e260:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.wD(a,b)},
 $isEH:true},
 e261:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.wJ(a,b)},
 $isEH:true},
 e262:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.oJ(a,b)},
 $isEH:true},
 e263:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.DF(a,b)},
 $isEH:true},
 e264:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Mi(a,b)},
 $isEH:true},
 e265:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.sL1(b)},
 $isEH:true},
 e266:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.XF(a,b)},
 $isEH:true},
 e267:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.SF(a,b)},
 $isEH:true},
 e268:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Qv(a,b)},
 $isEH:true},
 e269:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Xg(a,b)},
 $isEH:true},
 e270:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.aw(a,b)},
 $isEH:true},
 e271:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.CJ(a,b)},
 $isEH:true},
 e272:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.P2(a,b)},
 $isEH:true},
 e273:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.fv(a,b)},
 $isEH:true},
 e274:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.PP(a,b)},
 $isEH:true},
 e275:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Sj(a,b)},
 $isEH:true},
 e276:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.AJ(a,b)},
 $isEH:true},
 e277:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.w7(a,b)},
 $isEH:true},
 e278:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.ME(a,b)},
 $isEH:true},
 e279:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.kX(a,b)},
 $isEH:true},
 e280:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.S5(a,b)},
 $isEH:true},
 e281:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.q0(a,b)},
 $isEH:true},
 e282:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.EJ(a,b)},
 $isEH:true},
 e283:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.iH(a,b)},
 $isEH:true},
 e284:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.B9(a,b)},
 $isEH:true},
 e285:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.PN(a,b)},
 $isEH:true},
 e286:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.sVc(b)},
 $isEH:true},
 e287:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.By(a,b)},
 $isEH:true},
 e288:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.jd(a,b)},
 $isEH:true},
 e289:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Rx(a,b)},
 $isEH:true},
 e290:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.ZI(a,b)},
 $isEH:true},
 e291:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.wg(a,b)},
 $isEH:true},
 e292:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.fa(a,b)},
 $isEH:true},
 e293:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Cu(a,b)},
 $isEH:true},
 e294:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.sV8(b)},
 $isEH:true},
 e295:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.Tx(a,b)},
 $isEH:true},
 e296:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.sDo(b)},
 $isEH:true},
 e297:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.H3(a,b)},
 $isEH:true},
 e298:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.t3(a,b)},
 $isEH:true},
 e299:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.GT(a,b)},
 $isEH:true},
 e300:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){a.sVF(b)},
 $isEH:true},
 e301:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.yO(a,b)},
 $isEH:true},
 e302:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.ZU(a,b)},
 $isEH:true},
 e303:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.tQ(a,b)},
 $isEH:true},
 e304:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.tH(a,b)},
 $isEH:true},
 e305:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("curly-block",C.Lg)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e306:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("observatory-element",C.l4)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e307:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("service-ref",C.il)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e308:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("instance-ref",C.Wz)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e309:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("action-link",C.K4)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e310:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("nav-bar",C.Zj)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e311:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("nav-menu",C.ms)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e312:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("nav-menu-item",C.FA)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e313:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("nav-refresh",C.JW)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e314:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("top-nav-menu",C.Mf)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e315:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("isolate-nav-menu",C.km)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e316:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("library-nav-menu",C.vw)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e317:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("class-nav-menu",C.Ey)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e318:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("breakpoint-list",C.yS)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e319:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("class-ref",C.OG)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e320:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("eval-box",C.wk)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e321:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("eval-link",C.jA)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e322:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("field-ref",C.Jo)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e323:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("function-ref",C.lE)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e324:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("library-ref",C.lp)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e325:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("script-ref",C.Sb)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e326:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("class-view",C.xE)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e327:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("code-ref",C.oT)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e328:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("code-view",C.jR)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e329:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("collapsible-content",C.bh)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e330:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("error-view",C.KO)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e331:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("field-view",C.Az)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e332:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("stack-frame",C.NR)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e333:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("flag-list",C.BL)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e334:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("flag-item",C.Vx)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e335:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("script-inset",C.ON)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e336:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("function-view",C.te)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e337:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("heap-map",C.iD)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e338:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-view",C.tU)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e339:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-ref",C.Jf)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e340:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-http-server-list-view",C.qF)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e341:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-http-server-ref",C.nX)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e342:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-http-server-view",C.Wh)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e343:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-socket-ref",C.FG)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e344:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-socket-list-view",C.EZ)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e345:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-socket-view",C.pJ)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e346:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-web-socket-ref",C.Yy)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e347:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-web-socket-list-view",C.DD)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e348:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-web-socket-view",C.Xv)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e349:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-random-access-file-list-view",C.tc)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e350:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-random-access-file-ref",C.rR)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e351:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-random-access-file-view",C.oG)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e352:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-process-list-view",C.Ep)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e353:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-process-ref",C.dD)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e354:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("io-process-view",C.hP)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e355:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("isolate-ref",C.UJ)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e356:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("isolate-summary",C.CT)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e357:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("isolate-run-state",C.j4)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e358:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("isolate-location",C.Io)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e359:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("isolate-shared-summary",C.TU)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e360:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("isolate-counter-chart",C.z7)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e361:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("isolate-view",C.mq)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e362:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("instance-view",C.k5)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e363:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("json-view",C.Tq)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e364:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("library-view",C.PT)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e365:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("heap-profile",C.Ju)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e366:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("sliding-checkbox",C.Y3)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e367:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("isolate-profile",C.ce)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e368:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("script-view",C.Th)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e369:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("stack-trace",C.vu)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e370:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("vm-view",C.jK)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e371:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("service-view",C.X8)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e372:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("response-viewer",C.Vh)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e373:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("observatory-application",C.Dl)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e374:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("service-exception-view",C.pK)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e375:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("service-error-view",C.wH)},"$0",null,0,0,null,"call"],
 $isEH:true},
 e376:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.Ad("vm-ref",C.cK)},"$0",null,0,0,null,"call"],
 $isEH:true}},1],["breakpoint_list_element","package:observatory/src/elements/breakpoint_list.dart",,B,{
 "^":"",
@@ -3916,7 +3916,7 @@
 "^":"Vf;BW,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 grs:function(a){return a.BW},
 srs:function(a,b){a.BW=this.ct(a,C.UX,a.BW,b)},
-RF:[function(a,b){J.LE(a.BW).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.BW).wM(b)},"$1","gvC",2,0,17,84],
 static:{KU:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -3953,9 +3953,9 @@
 "^":"Vfx;yB,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gRu:function(a){return a.yB},
 sRu:function(a,b){a.yB=this.ct(a,C.XA,a.yB,b)},
-vV:[function(a,b){return J.aT(a.yB).cv(J.ew(J.F8(a.yB),"/eval?expr="+P.jW(C.yD,b,C.xM,!1)))},"$1","gZm",2,0,83,84],
-S1:[function(a,b){return J.aT(a.yB).cv(J.ew(J.F8(a.yB),"/retained"))},"$1","ghN",2,0,83,85],
-RF:[function(a,b){J.LE(a.yB).wM(b)},"$1","gvC",2,0,17,82],
+vV:[function(a,b){return J.aT(a.yB).cv(J.ew(J.F8(a.yB),"/eval?expr="+P.jW(C.yD,b,C.xM,!1)))},"$1","gZm",2,0,85,86],
+S1:[function(a,b){return J.aT(a.yB).cv(J.ew(J.F8(a.yB),"/retained"))},"$1","ghN",2,0,85,87],
+RF:[function(a,b){J.LE(a.yB).wM(b)},"$1","gvC",2,0,17,84],
 static:{zg:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -4000,7 +4000,7 @@
 z=a.Xx
 if(z==null)return
 J.SK(z).ml(new F.aa())},
-RF:[function(a,b){J.LE(a.Xx).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.Xx).wM(b)},"$1","gvC",2,0,17,84],
 m2:function(a,b){var z,y,x
 z=J.Vs(b).MW.getAttribute("data-jump-target")
 if(z==="")return
@@ -4010,10 +4010,10 @@
 return x},
 YI:[function(a,b,c,d){var z=this.m2(a,d)
 if(z==null)return
-J.pP(z).h(0,"highlight")},"$3","gKJ",6,0,86,1,87,88],
+J.pP(z).h(0,"highlight")},"$3","gKJ",6,0,88,1,89,90],
 ZC:[function(a,b,c,d){var z=this.m2(a,d)
 if(z==null)return
-J.pP(z).Rz(0,"highlight")},"$3","gAF",6,0,86,1,87,88],
+J.pP(z).Rz(0,"highlight")},"$3","gAF",6,0,88,1,89,90],
 static:{f9:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -4030,8 +4030,8 @@
 "^":"uL+Pi;",
 $isd3:true},
 aa:{
-"^":"Tp:89;",
-$1:[function(a){a.OF()},"$1",null,2,0,null,72,"call"],
+"^":"Tp:91;",
+$1:[function(a){a.OF()},"$1",null,2,0,null,74,"call"],
 $isEH:true}}],["collapsible_content_element","package:observatory/src/elements/collapsible_content.dart",,R,{
 "^":"",
 i6:{
@@ -4086,7 +4086,7 @@
 if(z===!0)return
 if(a.nx!=null){a.uo=this.ct(a,C.S4,z,!0)
 this.AV(a,a.GV!==!0,this.gN2(a))}else{z=a.GV
-a.GV=this.ct(a,C.mr,z,z!==!0)}},"$3","gDI",6,0,71,43,44,72],
+a.GV=this.ct(a,C.mr,z,z!==!0)}},"$3","gDI",6,0,73,43,44,74],
 static:{U9:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -4611,7 +4611,7 @@
 z=P.YM(null,null,null,null,null)
 return new P.uo(c,d,z)},"$5","Is",10,0,41],
 C6:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:[function(){H.cv()
 this.a.$0()},"$0",null,0,0,null,"call"],
 $isEH:true},
@@ -4621,7 +4621,7 @@
 Ik:{
 "^":"O9;Y8"},
 LR:{
-"^":"oh;Ae@,iE@,SJ@,Y8,pN,o7,Bd,Lj,Gv,lz,nb",
+"^":"Bx;Ae@,iE@,SJ@,Y8,pN,o7,Bd,Lj,Gv,lz,nb",
 gY8:function(){return this.Y8},
 uR:function(a){var z=this.Ae
 if(typeof z!=="number")return z.i()
@@ -4663,9 +4663,9 @@
 q7:function(){if((this.Gv&4)!==0)return new P.lj("Cannot add new events after calling close")
 return new P.lj("Cannot add new events while doing an addStream")},
 h:[function(a,b){if(this.Gv>=4)throw H.b(this.q7())
-this.Iv(b)},"$1","ght",2,0,function(){return H.IG(function(a){return{func:"lU",void:true,args:[a]}},this.$receiver,"WV")},90],
+this.Iv(b)},"$1","ght",2,0,function(){return H.IG(function(a){return{func:"lU",void:true,args:[a]}},this.$receiver,"WV")},92],
 js:[function(a,b){if(this.Gv>=4)throw H.b(this.q7())
-this.pb(a,b)},function(a){return this.js(a,null)},"JT","$2","$1","gGj",2,2,91,20,21,22],
+this.pb(a,b)},function(a){return this.js(a,null)},"JT","$2","$1","gGj",2,2,93,20,21,22],
 S6:function(a){var z,y
 z=this.Gv
 if((z&4)!==0)return this.yx
@@ -4745,25 +4745,29 @@
 "^":"a;",
 $isb8:true},
 w4:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:[function(){var z,y,x,w
 try{this.b.rX(this.a.$0())}catch(x){w=H.Ru(x)
 z=w
 y=new H.XO(x,null)
 this.b.K5(z,y)}},"$0",null,0,0,null,"call"],
 $isEH:true},
+oh:{
+"^":"a;",
+$isoh:true},
 Pf0:{
-"^":"a;"},
+"^":"a;",
+$isoh:true},
 Zf:{
 "^":"Pf0;MM",
 j3:[function(a,b){var z=this.MM
 if(z.Gv!==0)throw H.b(P.w("Future already completed"))
-z.OH(b)},function(a){return this.j3(a,null)},"tZ","$1","$0","gv6",0,2,92,20,18],
-w0:[function(a,b){var z
+z.OH(b)},function(a){return this.j3(a,null)},"tZ","$1","$0","gv6",0,2,94,20,18],
+w0:function(a,b){var z
 if(a==null)throw H.b(P.u("Error must not be null"))
 z=this.MM
 if(z.Gv!==0)throw H.b(P.w("Future already completed"))
-z.CG(a,b)},function(a){return this.w0(a,null)},"rC","$2","$1","gXN",2,2,91,20,21,22]},
+z.CG(a,b)}},
 vs:{
 "^":"a;Gv,Lj<,jk,BQ@,OY,As,qV,o4",
 gcg:function(){return this.Gv>=4},
@@ -4833,8 +4837,8 @@
 CG:function(a,b){if(this.Gv!==0)H.vh(P.w("Future already completed"))
 this.Gv=1
 this.Lj.wr(new P.In(this,a,b))},
-J9:function(a,b){this.OH(a)},
 X8:function(a,b,c){this.CG(a,b)},
+J9:function(a,b){this.OH(a)},
 $isvs:true,
 $isb8:true,
 static:{"^":"ewM,JE,C3n,Xh,NKU",Dt:function(a){return H.VM(new P.vs(0,$.X3,null,null,null,null,null,null),[a])},PG:function(a,b){var z=H.VM(new P.vs(0,$.X3,null,null,null,null,null,null),[b])
@@ -4889,7 +4893,7 @@
 y=b
 b=q}}}},
 da:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:[function(){P.HZ(this.a,this.b)},"$0",null,0,0,null,"call"],
 $isEH:true},
 U7:{
@@ -4897,23 +4901,23 @@
 $1:[function(a){this.a.R8(a)},"$1",null,2,0,null,18,"call"],
 $isEH:true},
 vr:{
-"^":"Tp:93;b",
+"^":"Tp:95;b",
 $2:[function(a,b){this.b.K5(a,b)},function(a){return this.$2(a,null)},"$1","$2",null,null,2,2,null,20,21,22,"call"],
 $isEH:true},
 cX:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:[function(){P.A9(this.b,this.a)},"$0",null,0,0,null,"call"],
 $isEH:true},
 eX:{
-"^":"Tp:64;c,d",
+"^":"Tp:66;c,d",
 $0:[function(){this.c.R8(this.d)},"$0",null,0,0,null,"call"],
 $isEH:true},
 In:{
-"^":"Tp:64;a,b,c",
+"^":"Tp:66;a,b,c",
 $0:[function(){this.a.K5(this.b,this.c)},"$0",null,0,0,null,"call"],
 $isEH:true},
 rq:{
-"^":"Tp:94;b,d,e,f",
+"^":"Tp:96;b,d,e,f",
 $0:function(){var z,y,x,w
 try{this.b.c=this.f.FI(this.d.gO1(),this.e)
 return!0}catch(x){w=H.Ru(x)
@@ -4980,10 +4984,10 @@
 $isEH:true},
 jZ:{
 "^":"Tp:10;c,HZ",
-$1:[function(a){P.HZ(this.c.e,this.HZ)},"$1",null,2,0,null,95,"call"],
+$1:[function(a){P.HZ(this.c.e,this.HZ)},"$1",null,2,0,null,97,"call"],
 $isEH:true},
 FZ:{
-"^":"Tp:93;a,mG",
+"^":"Tp:95;a,mG",
 $2:[function(a,b){var z,y
 z=this.a
 if(!J.x(z.a).$isvs){y=P.Dt(null)
@@ -4995,8 +4999,8 @@
 Ki:function(a){return this.FR.$0()}},
 cb:{
 "^":"a;",
-ez:[function(a,b){return H.VM(new P.c9(b,this),[H.ip(this,"cb",0),null])},"$1","gIr",2,0,function(){return H.IG(function(a){return{func:"bp",ret:P.cb,args:[{func:"Lf",args:[a]}]}},this.$receiver,"cb")},96],
-Ft:[function(a,b){return H.VM(new P.Bg(b,this),[H.ip(this,"cb",0),null])},"$1","git",2,0,function(){return H.IG(function(a){return{func:"xv",ret:P.cb,args:[{func:"Xy",ret:P.QV,args:[a]}]}},this.$receiver,"cb")},96],
+ez:[function(a,b){return H.VM(new P.c9(b,this),[H.ip(this,"cb",0),null])},"$1","gIr",2,0,function(){return H.IG(function(a){return{func:"bp",ret:P.cb,args:[{func:"Lf",args:[a]}]}},this.$receiver,"cb")},98],
+Ft:[function(a,b){return H.VM(new P.Bg(b,this),[H.ip(this,"cb",0),null])},"$1","git",2,0,function(){return H.IG(function(a){return{func:"xv",ret:P.cb,args:[{func:"Xy",ret:P.QV,args:[a]}]}},this.$receiver,"cb")},98],
 tg:function(a,b){var z,y
 z={}
 y=P.Dt(P.a2)
@@ -5027,6 +5031,12 @@
 z.a=null
 z.a=this.KR(new P.qg(z,y),!0,new P.yB(y),y.gaq())
 return y},
+geK:function(a){var z,y
+z={}
+y=P.Dt(H.ip(this,"cb",0))
+z.a=null
+z.a=this.KR(new P.lU(z,this,y),!0,new P.xp(y),y.gaq())
+return y},
 grZ:function(a){var z,y
 z={}
 y=P.Dt(H.ip(this,"cb",0))
@@ -5040,28 +5050,28 @@
 $1:[function(a){var z,y
 z=this.a
 y=this.d
-P.FE(new P.BE(this.c,a),new P.Oh(z,y),P.TB(z.a,y))},"$1",null,2,0,null,97,"call"],
+P.FE(new P.BE(this.c,a),new P.Oh(z,y),P.TB(z.a,y))},"$1",null,2,0,null,99,"call"],
 $isEH:true,
 $signature:function(){return H.IG(function(a){return{func:"Lf",args:[a]}},this.b,"cb")}},
 BE:{
-"^":"Tp:64;e,f",
+"^":"Tp:66;e,f",
 $0:function(){return J.xC(this.f,this.e)},
 $isEH:true},
 Oh:{
-"^":"Tp:98;a,UI",
+"^":"Tp:100;a,UI",
 $1:function(a){if(a===!0)P.Bb(this.a.a,this.UI,!0)},
 $isEH:true},
 kb:{
-"^":"Tp:64;bK",
+"^":"Tp:66;bK",
 $0:[function(){this.bK.rX(!1)},"$0",null,0,0,null,"call"],
 $isEH:true},
 lz:{
 "^":"Tp;a,b,c,d",
-$1:[function(a){P.FE(new P.at(this.c,a),new P.mj(),P.TB(this.a.a,this.d))},"$1",null,2,0,null,97,"call"],
+$1:[function(a){P.FE(new P.at(this.c,a),new P.mj(),P.TB(this.a.a,this.d))},"$1",null,2,0,null,99,"call"],
 $isEH:true,
 $signature:function(){return H.IG(function(a){return{func:"Lf",args:[a]}},this.b,"cb")}},
 at:{
-"^":"Tp:64;e,f",
+"^":"Tp:66;e,f",
 $0:function(){return this.e.$1(this.f)},
 $isEH:true},
 mj:{
@@ -5069,7 +5079,7 @@
 $1:function(a){},
 $isEH:true},
 ib:{
-"^":"Tp:64;UI",
+"^":"Tp:66;UI",
 $0:[function(){this.UI.rX(null)},"$0",null,0,0,null,"call"],
 $isEH:true},
 Ia:{
@@ -5077,19 +5087,19 @@
 $1:[function(a){var z,y
 z=this.a
 y=this.d
-P.FE(new P.WN(this.c,a),new P.XPB(z,y),P.TB(z.a,y))},"$1",null,2,0,null,97,"call"],
+P.FE(new P.WN(this.c,a),new P.XPB(z,y),P.TB(z.a,y))},"$1",null,2,0,null,99,"call"],
 $isEH:true,
 $signature:function(){return H.IG(function(a){return{func:"Lf",args:[a]}},this.b,"cb")}},
 WN:{
-"^":"Tp:64;e,f",
+"^":"Tp:66;e,f",
 $0:function(){return this.e.$1(this.f)},
 $isEH:true},
 XPB:{
-"^":"Tp:98;a,UI",
+"^":"Tp:100;a,UI",
 $1:function(a){if(a===!0)P.Bb(this.a.a,this.UI,!0)},
 $isEH:true},
 BSd:{
-"^":"Tp:64;bK",
+"^":"Tp:66;bK",
 $0:[function(){this.bK.rX(!1)},"$0",null,0,0,null,"call"],
 $isEH:true},
 uO:{
@@ -5097,7 +5107,7 @@
 $1:[function(a){++this.a.a},"$1",null,2,0,null,11,"call"],
 $isEH:true},
 hh:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:[function(){this.b.rX(this.a.a)},"$0",null,0,0,null,"call"],
 $isEH:true},
 qg:{
@@ -5105,9 +5115,18 @@
 $1:[function(a){P.Bb(this.a.a,this.b,!1)},"$1",null,2,0,null,11,"call"],
 $isEH:true},
 yB:{
-"^":"Tp:64;c",
+"^":"Tp:66;c",
 $0:[function(){this.c.rX(!0)},"$0",null,0,0,null,"call"],
 $isEH:true},
+lU:{
+"^":"Tp;a,b,c",
+$1:[function(a){P.Bb(this.a.a,this.c,a)},"$1",null,2,0,null,18,"call"],
+$isEH:true,
+$signature:function(){return H.IG(function(a){return{func:"Lf",args:[a]}},this.b,"cb")}},
+xp:{
+"^":"Tp:66;d",
+$0:[function(){this.d.Lp(new P.lj("No elements"))},"$0",null,0,0,null,"call"],
+$isEH:true},
 UH:{
 "^":"Tp;a,b",
 $1:[function(a){var z=this.a
@@ -5116,7 +5135,7 @@
 $isEH:true,
 $signature:function(){return H.IG(function(a){return{func:"Lf",args:[a]}},this.b,"cb")}},
 Z5:{
-"^":"Tp:64;a,c",
+"^":"Tp:66;a,c",
 $0:[function(){var z=this.a
 if(z.b){this.c.rX(z.a)
 return}this.c.Lp(new P.lj("No elements"))},"$0",null,0,0,null,"call"],
@@ -5148,7 +5167,7 @@
 if(!J.x(b).$isO9)return!1
 return b.Y8===this.Y8},
 $isO9:true},
-oh:{
+Bx:{
 "^":"KA;Y8<",
 tA:function(){return this.gY8().j0(this)},
 uO:[function(){this.gY8()},"$0","gp4",0,0,15],
@@ -5168,7 +5187,7 @@
 this.Gv=(z+128|4)>>>0
 if(b!=null)b.wM(this.gDQ(this))
 if(z<128&&this.nb!=null){y=this.nb
-if(y.Gv===1)y.Gv=3}if((z&4)===0&&(this.Gv&32)===0)this.J7(this.gp4())},function(a){return this.Fv(a,null)},"yy","$1","$0","gX0",0,2,99,20,100],
+if(y.Gv===1)y.Gv=3}if((z&4)===0&&(this.Gv&32)===0)this.J7(this.gp4())},function(a){return this.Fv(a,null)},"yy","$1","$0","gX0",0,2,101,20,102],
 zl:[function(a){var z=this.Gv
 if((z&8)!==0)return
 if(z>=128){z-=128
@@ -5315,7 +5334,7 @@
 return}P.rb(new P.Vd(this,a))
 this.Gv=1}},
 Vd:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:[function(){var z,y
 z=this.a
 y=z.Gv
@@ -5340,15 +5359,15 @@
 this.N6=null
 this.zR=null}},
 dR:{
-"^":"Tp:64;a,b,c",
+"^":"Tp:66;a,b,c",
 $0:function(){return this.a.K5(this.b,this.c)},
 $isEH:true},
 uR:{
-"^":"Tp:101;a,b",
+"^":"Tp:103;a,b",
 $2:function(a,b){return P.NX(this.a,this.b,a,b)},
 $isEH:true},
 Q0:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:function(){return this.a.rX(this.b)},
 $isEH:true},
 og:{
@@ -5384,8 +5403,8 @@
 tA:function(){var z=this.WS
 if(z!=null){this.WS=null
 z.ed()}return},
-vx:[function(a){this.UY.ut(a,this)},"$1","gOa",2,0,function(){return H.IG(function(a,b){return{func:"wa",void:true,args:[a]}},this.$receiver,"fB")},90],
-xL:[function(a,b){this.oJ(a,b)},"$2","gRE",4,0,102,21,22],
+vx:[function(a){this.UY.ut(a,this)},"$1","gOa",2,0,function(){return H.IG(function(a,b){return{func:"wa",void:true,args:[a]}},this.$receiver,"fB")},92],
+xL:[function(a,b){this.oJ(a,b)},"$2","gRE",4,0,104,21,22],
 fE:[function(){this.YB()},"$0","gH1",0,0,15],
 Ri:function(a,b,c,d){var z,y
 z=this.gOa()
@@ -5444,7 +5463,7 @@
 qp:function(a){return this.il.$1$specification(a)}},
 qK:{
 "^":"a;"},
-xp:{
+dl:{
 "^":"a;"},
 Id:{
 "^":"a;nU",
@@ -5517,11 +5536,11 @@
 if(b)return new P.Cg(this,z)
 else return new P.Hs(this,z)}},
 TF:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:[function(){return this.a.bH(this.b)},"$0",null,0,0,null,"call"],
 $isEH:true},
 Xz:{
-"^":"Tp:64;c,d",
+"^":"Tp:66;c,d",
 $0:[function(){return this.c.Gr(this.d)},"$0",null,0,0,null,"call"],
 $isEH:true},
 Cg:{
@@ -5553,11 +5572,11 @@
 uN:function(a,b){return new P.Id(this).dJ(this,a,b)},
 Ch:function(a,b){new P.Id(this).RB(0,this,b)}},
 FO:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:[function(){P.IA(new P.eM(this.a,this.b))},"$0",null,0,0,null,"call"],
 $isEH:true},
 eM:{
-"^":"Tp:64;c,d",
+"^":"Tp:66;c,d",
 $0:[function(){var z,y
 z=this.c
 P.FL("Uncaught Error: "+H.d(z))
@@ -5567,8 +5586,8 @@
 throw H.b(z)},"$0",null,0,0,null,"call"],
 $isEH:true},
 Uez:{
-"^":"Tp:67;a",
-$2:[function(a,b){this.a.u(0,a,b)},"$2",null,4,0,null,68,18,"call"],
+"^":"Tp:69;a",
+$2:[function(a,b){this.a.u(0,a,b)},"$2",null,4,0,null,70,18,"call"],
 $isEH:true},
 AH:{
 "^":"a;",
@@ -5795,7 +5814,7 @@
 return z}}},
 oi:{
 "^":"Tp:10;a",
-$1:[function(a){return this.a.t(0,a)},"$1",null,2,0,null,103,"call"],
+$1:[function(a){return this.a.t(0,a)},"$1",null,2,0,null,105,"call"],
 $isEH:true},
 DJ:{
 "^":"Tp;a",
@@ -5982,7 +6001,7 @@
 return z}}},
 a1:{
 "^":"Tp:10;a",
-$1:[function(a){return this.a.t(0,a)},"$1",null,2,0,null,103,"call"],
+$1:[function(a){return this.a.t(0,a)},"$1",null,2,0,null,105,"call"],
 $isEH:true},
 pk:{
 "^":"Tp;a",
@@ -6447,7 +6466,7 @@
 $isQV:true,
 $asQV:null},
 W0:{
-"^":"Tp:67;a,b",
+"^":"Tp:69;a,b",
 $2:function(a,b){var z=this.a
 if(!z.a)this.b.KF(", ")
 z.a=!1
@@ -6807,7 +6826,7 @@
 throw H.b(P.cD(String(y)))}return P.Uw(z,b)},
 NC:[function(a){return a.Lt()},"$1","bx",2,0,46,47],
 hW:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return b},
 $isEH:true},
 f1:{
@@ -6949,7 +6968,7 @@
 pg:function(a){var z=this.ol
 if(0>=z.length)return H.e(z,0)
 z.pop()},
-static:{"^":"P3,hyY,IE,Jyf,NoV,fg,Wk,pe,E7,MU,vk,NXu,PBv,QVv",uI:function(a,b,c){return new P.Sh(b,a,[])},Vg:function(a,b,c){var z
+static:{"^":"P3,hyY,IE,Jyf,NoV,HVe,Wk,pe,E7,MU,vk,NXu,PBv,QVv",uI:function(a,b,c){return new P.Sh(b,a,[])},Vg:function(a,b,c){var z
 b=P.bx()
 z=P.p9("")
 P.uI(z,b,c).C7(a)
@@ -6970,7 +6989,7 @@
 return C.Nm.aM(y,0,x.L8)},
 $aszF:function(){return[P.qU,[P.WO,P.KN]]}},
 Yu:{
-"^":"a;So,L8,IT",
+"^":"a;aQ,L8,IT",
 GT:function(a,b){var z,y,x,w,v
 z=this.IT
 y=this.L8
@@ -7088,11 +7107,11 @@
 y.vM+=u
 z.$2(v,y)}}return y.vM},
 Y25:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){this.a.u(0,a.gfN(),b)},
 $isEH:true},
 CL:{
-"^":"Tp:104;a",
+"^":"Tp:106;a",
 $2:function(a,b){var z=this.a
 if(z.b>0)z.a.KF(", ")
 z.a.KF(a.gfN())
@@ -7174,12 +7193,12 @@
 return"00"+a},h0:function(a){if(a>=10)return""+a
 return"0"+a}}},
 MF:{
-"^":"Tp:105;",
+"^":"Tp:107;",
 $1:function(a){if(a==null)return 0
 return H.BU(a,null,null)},
 $isEH:true},
 Rq:{
-"^":"Tp:106;",
+"^":"Tp:108;",
 $1:function(a){if(a==null)return 0
 return H.RR(a,null)},
 $isEH:true},
@@ -7421,28 +7440,25 @@
 "^":"a;",
 $isuq:true},
 rI:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){var z=J.Wx(a)
 b.KF(H.Lw(C.xB.j("0123456789ABCDEF",z.m(a,4))))
 b.KF(H.Lw(C.xB.j("0123456789ABCDEF",z.i(a,15))))},
 $isEH:true}}],["dart.dom.html","dart:html",,W,{
 "^":"",
 r3:function(a,b){return document.createElement(a)},
-It:function(a,b,c){return W.lt(a,null,null,b,null,null,null,c).ml(new W.KxY())},
-lt:function(a,b,c,d,e,f,g,h){var z,y,x
-z=W.fJ
-y=H.VM(new P.Zf(P.Dt(z)),[z])
-x=new XMLHttpRequest()
-C.W3.kP(x,"GET",a,!0)
-z=H.VM(new W.RO(x,C.LF.Ph,!1),[null])
-H.VM(new W.fd(0,z.bi,z.Ph,W.aF(new W.bU(y,x)),z.Sg),[H.Kp(z,0)]).Zz()
-z=H.VM(new W.RO(x,C.MD.Ph,!1),[null])
-H.VM(new W.fd(0,z.bi,z.Ph,W.aF(y.gXN()),z.Sg),[H.Kp(z,0)]).Zz()
-x.send()
-return y.MM},
 ED:function(a){var z,y
 z=document.createElement("input",null)
 if(a!=null)try{J.iM(z,a)}catch(y){H.Ru(y)}return z},
+pS:function(a,b){var z,y
+z=typeof a!=="string"
+if((!z||a==null)&&!0)return new WebSocket(a)
+y=H.RB(b,"$isWO",[P.qU],"$asWO")
+if(!y);y=!z||a==null
+if(y)return new WebSocket(a,b)
+z=!z||a==null
+if(z)return new WebSocket(a,b)
+throw H.b(P.u("Incorrect number or type of arguments"))},
 VC:function(a,b){a=536870911&a+b
 a=536870911&a+((524287&a)<<10>>>0)
 return a^a>>>6},
@@ -7461,12 +7477,11 @@
 Hx:[function(a){return J.UC(a)},"$1","Z6",2,0,10,51],
 Qp:[function(a,b,c,d){return J.df(a,b,c,d)},"$4","A6",8,0,52,51,53,54,55],
 aF:function(a){if(J.xC($.X3,C.NU))return a
-if(a==null)return
 return $.X3.Nf(a,!0)},
 Bo:{
 "^":"h4;",
-"%":"HTMLAppletElement|HTMLBRElement|HTMLContentElement|HTMLDListElement|HTMLDataListElement|HTMLDirectoryElement|HTMLDivElement|HTMLFontElement|HTMLFrameElement|HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLMarqueeElement|HTMLMenuElement|HTMLModElement|HTMLParagraphElement|HTMLPreElement|HTMLQuoteElement|HTMLShadowElement|HTMLSpanElement|HTMLTableCaptionElement|HTMLTableColElement|HTMLTitleElement|HTMLUListElement|HTMLUnknownElement;HTMLElement;jpR|Ot|ir|LPc|hV|uL|Vf|G6|pv|xI|eW|Vfx|aC|VY|Dsd|Be|tuj|i6|Xfs|JI|Vct|ZP|D13|nJ|SaM|Eg|i7|WZq|Gk|pva|Nr|cda|MJ|T53|DK|waa|BS|V3|Vb|V5|Ly|pR|V8|hx|V10|L4|Mb|V11|mO|DE|V12|U1|qh|V13|oF|V14|Q6|uE|V15|Zn|V16|n5|V17|Ma|wN|V18|ds|V19|ou|ZzR|av|V20|uz|V21|kK|oa|V22|St|V23|IW|V24|Qh|V25|Oz|V26|YA|V27|qk|V28|vj|LU|V29|CX|V30|md|V31|Bm|V32|Ya|V33|Ww|V34|G1|V35|fl|V36|UK|V37|wM|V38|F1|V39|qZ|V40|ov|oEY|kn|V41|fI|V42|zM|V43|Rk|V44|Ti|KAf|CY|V45|nm|V46|uw|I5|V47|el"},
-zw:{
+"%":"HTMLAppletElement|HTMLBRElement|HTMLContentElement|HTMLDListElement|HTMLDataListElement|HTMLDirectoryElement|HTMLDivElement|HTMLFontElement|HTMLFrameElement|HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLMarqueeElement|HTMLMenuElement|HTMLModElement|HTMLParagraphElement|HTMLPreElement|HTMLQuoteElement|HTMLShadowElement|HTMLSpanElement|HTMLTableCaptionElement|HTMLTableColElement|HTMLTitleElement|HTMLUListElement|HTMLUnknownElement;HTMLElement;jpR|Ot|ir|LPc|hV|uL|Vf|G6|pv|xI|eW|Vfx|aC|VY|Dsd|Be|tuj|i6|Xfs|JI|Vct|ZP|D13|nJ|SaM|Eg|i7|WZq|Gk|pva|Nr|cda|MJ|T53|DK|waa|BS|V3|Vb|V5|Ly|pR|V9|hx|V10|L4|Mb|V11|mO|DE|V12|U1|qh|V13|oF|V14|Q6|uE|V15|Zn|V16|n5|V17|Ma|wN|V18|ds|V19|ou|ZzR|av|V20|uz|V21|kK|oa|V22|St|V23|IW|V24|Qh|V25|Oz|V26|YA|V27|qk|V28|vj|LU|V29|CX|V30|md|V31|Bm|V32|Ya|V33|Ww|V34|G1|V35|fl|V36|UK|V37|wM|V38|F1|V39|qZ|V40|ov|oEY|kn|V41|fI|V42|zM|V43|Rk|V44|Ti|KAf|CY|V45|nm|V46|uw|I5|V47|el"},
+Yyn:{
 "^":"Gv;",
 $isWO:true,
 $asWO:function(){return[W.QI]},
@@ -7519,6 +7534,7 @@
 "%":"Comment;CharacterData"},
 K3:{
 "^":"ea;tT:code=",
+$isK3:true,
 "%":"CloseEvent"},
 y4:{
 "^":"w6O;Rn:data=",
@@ -7662,12 +7678,11 @@
 $isXj:true,
 "%":"HTMLCollection|HTMLFormControlsCollection|HTMLOptionsCollection"},
 fJ:{
-"^":"rk;xN:responseText=,pf:status=",
+"^":"rk;pf:status=",
 gbA:function(a){return W.Z9(a.response)},
 R3:function(a,b,c,d,e,f){return a.open(b,c,d,f,e)},
 kP:function(a,b,c,d){return a.open(b,c,d)},
 wR:function(a,b){return a.send(b)},
-$isfJ:true,
 "%":"XMLHttpRequest"},
 rk:{
 "^":"PZ;",
@@ -7837,7 +7852,6 @@
 "%":"HTMLProgressElement"},
 kQ:{
 "^":"ea;ox:loaded=",
-$iskQ:true,
 "%":"XMLHttpRequestProgressEvent;ProgressEvent"},
 bXi:{
 "^":"kQ;O3:url=",
@@ -7921,6 +7935,13 @@
 SW:{
 "^":"eL;fg:height},R:width}",
 "%":"HTMLVideoElement"},
+lf:{
+"^":"PZ;yv:protocol=,O3:url=",
+LG:function(a,b,c){return a.close(b,c)},
+S6:function(a){return a.close()},
+wR:function(a,b){return a.send(b)},
+$islf:true,
+"%":"WebSocket"},
 K5:{
 "^":"PZ;oc:name%,pf:status%",
 geT:function(a){return W.Pv(a.parent)},
@@ -8125,26 +8146,6 @@
 $isyN:true,
 $isQV:true,
 $asQV:function(){return[W.KV]}},
-KxY:{
-"^":"Tp:10;",
-$1:[function(a){return J.Du(a)},"$1",null,2,0,null,107,"call"],
-$isEH:true},
-bU2:{
-"^":"Tp:67;a",
-$2:function(a,b){this.a.setRequestHeader(a,b)},
-$isEH:true},
-bU:{
-"^":"Tp:10;b,c",
-$1:[function(a){var z,y,x
-z=this.c
-y=z.status
-if(typeof y!=="number")return y.F()
-y=y>=200&&y<300||y===0||y===304
-x=this.b
-if(y){y=x.MM
-if(y.Gv!==0)H.vh(P.w("Future already completed"))
-y.OH(z)}else x.rC(a)},"$1",null,2,0,null,1,"call"],
-$isEH:true},
 wi:{
 "^":"rm;NL",
 grZ:function(a){var z=this.NL.lastChild
@@ -8269,7 +8270,7 @@
 $isZ0:true,
 $asZ0:function(){return[P.qU,P.qU]}},
 Zc:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){this.a.u(0,a,b)},
 $isEH:true},
 E9:{
@@ -8376,7 +8377,7 @@
 return},
 Fv:[function(a,b){if(this.bi==null)return;++this.VP
 this.Jc()
-if(b!=null)b.wM(this.gDQ(this))},function(a){return this.Fv(a,null)},"yy","$1","$0","gX0",0,2,99,20,100],
+if(b!=null)b.wM(this.gDQ(this))},function(a){return this.Fv(a,null)},"yy","$1","$0","gX0",0,2,101,20,102],
 gUF:function(){return this.VP>0},
 zl:[function(a){if(this.bi==null||this.VP<=0)return;--this.VP
 this.Zz()},"$0","gDQ",0,0,15],
@@ -8399,7 +8400,7 @@
 this.aV.S6(0)},"$0","gJK",0,0,15],
 KS:function(a){this.aV=P.bK(this.gJK(this),null,!0,a)}},
 rC:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:[function(){return this.a.Rz(0,this.b)},"$0",null,0,0,null,"call"],
 $isEH:true},
 Gm:{
@@ -8714,7 +8715,7 @@
 $isr7:true,
 static:{mt:function(a){return new P.r7(P.xZ(a,!0))}}},
 Tz:{
-"^":"F6;eh",
+"^":"WkF;eh",
 t:function(a,b){var z
 if(typeof b==="number"&&b===C.CD.yu(b)){if(typeof b==="number"&&Math.floor(b)===b)z=b<0||b>=this.gB(this)
 else z=!1
@@ -8748,7 +8749,7 @@
 Jd:function(a){return this.XP(a,null)},
 static:{oY:function(a,b,c){if(a<0||a>c)throw H.b(P.TE(a,0,c))
 if(b<a||b>c)throw H.b(P.TE(b,a,c))}}},
-F6:{
+WkF:{
 "^":"E4+lD;",
 $isWO:true,
 $asWO:null,
@@ -9274,7 +9275,7 @@
 z=this.ct(a,C.eh,a.Ek,z)
 a.Ek=z
 if(J.xC(z,"1-line")){z=J.JA(a.a3,"\n"," ")
-a.a3=this.ct(a,C.mi,a.a3,z)}},"$3","gxb",6,0,86,1,87,88],
+a.a3=this.ct(a,C.mi,a.a3,z)}},"$3","gxb",6,0,88,1,89,90],
 Z1:[function(a,b,c,d){var z,y,x
 J.fD(b)
 z=a.a3
@@ -9283,9 +9284,9 @@
 x=R.tB(y)
 J.kW(x,"expr",z)
 J.Vk(a.y4,0,x)
-this.LY(a,z).ml(new L.YW(x))}},"$3","gZm",6,0,86,1,87,88],
+this.LY(a,z).ml(new L.YW(x))}},"$3","gZm",6,0,88,1,89,90],
 YC:[function(a,b){var z=J.iz(J.l2(b),"expr")
-a.a3=this.ct(a,C.mi,a.a3,z)},"$1","gHo",2,0,108,1],
+a.a3=this.ct(a,C.mi,a.a3,z)},"$1","gHo",2,0,109,1],
 static:{Rp:function(a){var z,y,x,w,v
 z=R.tB([])
 y=$.XZ()
@@ -9306,7 +9307,7 @@
 $isd3:true},
 YW:{
 "^":"Tp:10;a",
-$1:[function(a){J.kW(this.a,"value",a)},"$1",null,2,0,null,109,"call"],
+$1:[function(a){J.kW(this.a,"value",a)},"$1",null,2,0,null,110,"call"],
 $isEH:true}}],["eval_link_element","package:observatory/src/elements/eval_link.dart",,R,{
 "^":"",
 Eg:{
@@ -9327,7 +9328,7 @@
 if(z===!0)return
 if(a.bY!=null){a.fe=this.ct(a,C.S4,z,!0)
 a.oy=this.ct(a,C.UY,a.oy,null)
-this.LY(a,a.jv).ml(new R.uv(a)).wM(new R.Ou(a))}},"$3","gbN",6,0,71,43,44,72],
+this.LY(a,a.jv).ml(new R.uv(a)).wM(new R.Ou(a))}},"$3","gbN",6,0,73,43,44,74],
 static:{fL:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -9349,12 +9350,12 @@
 "^":"ir+Pi;",
 $isd3:true},
 uv:{
-"^":"Tp:110;a",
+"^":"Tp:111;a",
 $1:[function(a){var z=this.a
-z.oy=J.Q5(z,C.UY,z.oy,a)},"$1",null,2,0,null,77,"call"],
+z.oy=J.Q5(z,C.UY,z.oy,a)},"$1",null,2,0,null,79,"call"],
 $isEH:true},
 Ou:{
-"^":"Tp:64;b",
+"^":"Tp:66;b",
 $0:[function(){var z=this.b
 z.fe=J.Q5(z,C.S4,z.fe,!1)},"$0",null,0,0,null,"call"],
 $isEH:true}}],["field_ref_element","package:observatory/src/elements/field_ref.dart",,D,{
@@ -9379,7 +9380,7 @@
 "^":"WZq;KV,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gt0:function(a){return a.KV},
 st0:function(a,b){a.KV=this.ct(a,C.WQ,a.KV,b)},
-RF:[function(a,b){J.LE(a.KV).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.KV).wM(b)},"$1","gvC",2,0,17,84],
 static:{Sy:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -9400,7 +9401,7 @@
 "^":"pva;DC,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gpM:function(a){return a.DC},
 spM:function(a,b){a.DC=this.ct(a,C.Mc,a.DC,b)},
-RF:[function(a,b){J.LE(a.DC).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.DC).wM(b)},"$1","gvC",2,0,17,84],
 static:{na:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -9531,7 +9532,7 @@
 break
 default:a.ZZ=this.ct(a,C.Lc,y,"UNKNOWN")
 break}},"$1","gnp",2,0,17,54],
-RF:[function(a,b){J.LE(a.P6).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.P6).wM(b)},"$1","gvC",2,0,17,84],
 static:{N0:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -9550,7 +9551,7 @@
 "^":"",
 Hz:{
 "^":"a;zE,mS",
-PY:[function(){return new O.Hz(this.zE,this.mS+4)},"$0","gaw",0,0,111],
+PY:[function(){return new O.Hz(this.zE,this.mS+4)},"$0","gaw",0,0,112],
 gvH:function(a){return C.CD.cU(this.mS,4)},
 static:{"^":"Q0z",x6:function(a,b){var z,y,x
 z=b.gy(b)
@@ -9639,9 +9640,9 @@
 w=z.mS
 v=a.UL.t(0,a.Ge.t(0,this.LV(a,C.yp.Mu(J.Qd(z.zE),w,w+4))))
 z=J.xC(v,"")?"-":H.d(v)+" "+x
-a.PA=this.ct(a,C.PM,a.PA,z)},"$1","gmo",2,0,108,76],
+a.PA=this.ct(a,C.PM,a.PA,z)},"$1","gmo",2,0,109,78],
 X7:[function(a,b){var z=J.cR(this.WE(a,J.HF(b)).Yu,16)
-window.location.hash="/"+H.d(J.Ds(J.aT(a.oj)))+"/address/"+z},"$1","gJb",2,0,108,76],
+window.location.hash="/"+H.d(J.Ds(J.aT(a.oj)))+"/address/"+z},"$1","gJb",2,0,109,78],
 My:function(a){var z,y,x,w
 z=a.oj
 if(z==null||a.hi==null)return
@@ -9709,7 +9710,7 @@
 P.Iw(new O.R5(a,b),null)},
 RF:[function(a,b){var z=a.oj
 if(z==null)return
-J.aT(z).cv("heapmap").ml(new O.aG(a)).OA(new O.aO()).wM(b)},"$1","gvC",2,0,17,82],
+J.aT(z).cv("heapmap").ml(new O.aG(a)).OA(new O.aO()).wM(b)},"$1","gvC",2,0,17,84],
 nY:[function(a,b){P.Iw(new O.oc(a),null)},"$1","gR2",2,0,17,54],
 static:{"^":"nK,fM,SoT",pn:function(a){var z,y,x,w,v,u,t
 z=P.Fl(null,null)
@@ -9733,20 +9734,20 @@
 "^":"uL+Pi;",
 $isd3:true},
 R5:{
-"^":"Tp:64;a,b",
+"^":"Tp:66;a,b",
 $0:function(){J.fi(this.a,this.b+1)},
 $isEH:true},
 aG:{
-"^":"Tp:113;a",
+"^":"Tp:114;a",
 $1:[function(a){var z=this.a
-z.oj=J.Q5(z,C.QH,z.oj,a)},"$1",null,2,0,null,112,"call"],
+z.oj=J.Q5(z,C.QH,z.oj,a)},"$1",null,2,0,null,113,"call"],
 $isEH:true},
 aO:{
-"^":"Tp:67;",
-$2:[function(a,b){N.QM("").To(H.d(a)+" "+H.d(b))},"$2",null,4,0,null,1,114,"call"],
+"^":"Tp:69;",
+$2:[function(a,b){N.QM("").To(H.d(a)+" "+H.d(b))},"$2",null,4,0,null,1,115,"call"],
 $isEH:true},
 oc:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:function(){J.vP(this.a)},
 $isEH:true}}],["heap_profile_element","package:observatory/src/elements/heap_profile.dart",,K,{
 "^":"",
@@ -9840,7 +9841,7 @@
 if(!!J.x(d).$isv6){z=a.Rp.gxp()
 y=d.cellIndex
 if(z==null?y!=null:z!==y){a.Rp.sxp(y)
-J.II(a.Rp)}}},"$3","gQq",6,0,115,1,87,88],
+J.II(a.Rp)}}},"$3","gQq",6,0,116,1,89,90],
 K1:function(a,b){var z,y,x
 z=J.U6(b)
 y=z.t(b,"new")
@@ -9864,13 +9865,13 @@
 return J.ew(J.UQ(z.t(b,"old"),2),J.UQ(z.t(b,"old"),4))}throw H.b(P.a9())},
 RF:[function(a,b){var z=a.Ol
 if(z==null)return
-J.aT(z).cv("/allocationprofile").ml(new K.nx(a)).OA(new K.jm()).wM(b)},"$1","gvC",2,0,17,82],
+J.aT(z).cv("/allocationprofile").ml(new K.nx(a)).OA(new K.jm()).wM(b)},"$1","gvC",2,0,17,84],
 zT:[function(a,b){var z=a.Ol
 if(z==null)return
-J.aT(z).cv("/allocationprofile?gc=full").ml(new K.AN(a)).OA(new K.Ao()).wM(b)},"$1","gyW",2,0,17,82],
+J.aT(z).cv("/allocationprofile?gc=full").ml(new K.AN(a)).OA(new K.Ao()).wM(b)},"$1","gyW",2,0,17,84],
 eJ:[function(a,b){var z=a.Ol
 if(z==null)return
-J.aT(z).cv("/allocationprofile?reset=true").ml(new K.ke(a)).OA(new K.xj()).wM(b)},"$1","gNb",2,0,17,82],
+J.aT(z).cv("/allocationprofile?reset=true").ml(new K.ke(a)).OA(new K.xj()).wM(b)},"$1","gNb",2,0,17,84],
 n1:[function(a,b){var z,y,x,w
 try{this.MQ(a)}catch(x){w=H.Ru(x)
 z=w
@@ -9884,17 +9885,17 @@
 y=b===!0?"new":"old"
 x=J.UQ(J.UQ(z,"heaps"),y)
 z=J.U6(x)
-return C.CD.Sy(J.L9(J.vX(z.t(x,"time"),1000),z.t(x,"collections")),2)+" ms"},"$1","gOd",2,0,116,117],
+return C.CD.Sy(J.L9(J.vX(z.t(x,"time"),1000),z.t(x,"collections")),2)+" ms"},"$1","gOd",2,0,117,118],
 uW:[function(a,b){var z,y
 z=a.Ol
 if(z==null)return""
 y=b===!0?"new":"old"
-return H.d(J.UQ(J.UQ(J.UQ(z,"heaps"),y),"collections"))},"$1","gJN",2,0,116,117],
+return H.d(J.UQ(J.UQ(J.UQ(z,"heaps"),y),"collections"))},"$1","gJN",2,0,117,118],
 Q0:[function(a,b){var z,y
 z=a.Ol
 if(z==null)return""
 y=b===!0?"new":"old"
-return J.r0(J.UQ(J.UQ(J.UQ(z,"heaps"),y),"time"),2)+" secs"},"$1","goN",2,0,116,117],
+return J.r0(J.UQ(J.UQ(J.UQ(z,"heaps"),y),"time"),2)+" secs"},"$1","goN",2,0,117,118],
 Zy:function(a){var z=P.zV(J.UQ($.BY,"DataTable"),null)
 a.GQ=new G.Kf(z)
 z.V7("addColumn",["string","Type"])
@@ -9904,10 +9905,10 @@
 z.V7("addColumn",["string","Type"])
 a.JS.Yb.V7("addColumn",["number","Size"])
 z=H.VM([],[G.Ni])
-z=this.ct(a,C.kG,a.Rp,new G.Vz([new G.zb("Class",G.HP()),new G.zb("Accumulator Size (New)",G.Fx()),new G.zb("Accumulator (New)",G.kh()),new G.zb("Current Size (New)",G.Fx()),new G.zb("Current (New)",G.kh()),new G.zb("Accumulator Size (Old)",G.Fx()),new G.zb("Accumulator (Old)",G.kh()),new G.zb("Current Size (Old)",G.Fx()),new G.zb("Current (Old)",G.kh())],z,[],0,!0,null,null))
+z=this.ct(a,C.kG,a.Rp,new G.Vz([new G.Ktd("Class",G.HP()),new G.Ktd("Accumulator Size (New)",G.Fx()),new G.Ktd("Accumulator (New)",G.kh()),new G.Ktd("Current Size (New)",G.Fx()),new G.Ktd("Current (New)",G.kh()),new G.Ktd("Accumulator Size (Old)",G.Fx()),new G.Ktd("Accumulator (Old)",G.kh()),new G.Ktd("Current Size (Old)",G.Fx()),new G.Ktd("Current (Old)",G.kh())],z,[],0,!0,null,null))
 a.Rp=z
 z.sxp(1)},
-static:{"^":"IJv,bQj,kf,wh,r1K,d6,pC,DY2",Ut:function(a){var z,y,x,w
+static:{"^":"IJv,bQj,kf,wh,r1K,qEV,pC,DY2",Ut:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
 x=P.qU
@@ -9924,31 +9925,31 @@
 "^":"uL+Pi;",
 $isd3:true},
 nx:{
-"^":"Tp:113;a",
+"^":"Tp:114;a",
 $1:[function(a){var z=this.a
-z.Ol=J.Q5(z,C.vb,z.Ol,a)},"$1",null,2,0,null,112,"call"],
+z.Ol=J.Q5(z,C.vb,z.Ol,a)},"$1",null,2,0,null,113,"call"],
 $isEH:true},
 jm:{
-"^":"Tp:67;",
-$2:[function(a,b){N.QM("").To(H.d(a)+" "+H.d(b))},"$2",null,4,0,null,1,114,"call"],
+"^":"Tp:69;",
+$2:[function(a,b){N.QM("").To(H.d(a)+" "+H.d(b))},"$2",null,4,0,null,1,115,"call"],
 $isEH:true},
 AN:{
-"^":"Tp:113;a",
+"^":"Tp:114;a",
 $1:[function(a){var z=this.a
-z.Ol=J.Q5(z,C.vb,z.Ol,a)},"$1",null,2,0,null,112,"call"],
+z.Ol=J.Q5(z,C.vb,z.Ol,a)},"$1",null,2,0,null,113,"call"],
 $isEH:true},
 Ao:{
-"^":"Tp:67;",
-$2:[function(a,b){N.QM("").To(H.d(a)+" "+H.d(b))},"$2",null,4,0,null,1,114,"call"],
+"^":"Tp:69;",
+$2:[function(a,b){N.QM("").To(H.d(a)+" "+H.d(b))},"$2",null,4,0,null,1,115,"call"],
 $isEH:true},
 ke:{
-"^":"Tp:113;a",
+"^":"Tp:114;a",
 $1:[function(a){var z=this.a
-z.Ol=J.Q5(z,C.vb,z.Ol,a)},"$1",null,2,0,null,112,"call"],
+z.Ol=J.Q5(z,C.vb,z.Ol,a)},"$1",null,2,0,null,113,"call"],
 $isEH:true},
 xj:{
-"^":"Tp:67;",
-$2:[function(a,b){N.QM("").To(H.d(a)+" "+H.d(b))},"$2",null,4,0,null,1,114,"call"],
+"^":"Tp:69;",
+$2:[function(a,b){N.QM("").To(H.d(a)+" "+H.d(b))},"$2",null,4,0,null,1,115,"call"],
 $isEH:true}}],["html_common","dart:html_common",,P,{
 "^":"",
 bL:function(a){var z,y
@@ -9981,19 +9982,19 @@
 return y},
 $isEH:true},
 rG:{
-"^":"Tp:118;d",
+"^":"Tp:119;d",
 $1:function(a){var z=this.d
 if(a>=z.length)return H.e(z,a)
 return z[a]},
 $isEH:true},
 fh:{
-"^":"Tp:119;e",
+"^":"Tp:120;e",
 $2:function(a,b){var z=this.e
 if(a>=z.length)return H.e(z,a)
 z[a]=b},
 $isEH:true},
 uS:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:function(){},
 $isEH:true},
 Kk:{
@@ -10031,7 +10032,7 @@
 w[u]=z}return w}throw H.b(P.SY("structured clone of other type"))},
 $isEH:true},
 q1:{
-"^":"Tp:67;a,Gq",
+"^":"Tp:69;a,Gq",
 $2:function(a,b){this.a.a[a]=this.Gq.$1(b)},
 $isEH:true},
 CA:{
@@ -10045,13 +10046,13 @@
 return y},
 $isEH:true},
 D6:{
-"^":"Tp:118;c",
+"^":"Tp:119;c",
 $1:function(a){var z=this.c
 if(a>=z.length)return H.e(z,a)
 return z[a]},
 $isEH:true},
 KC:{
-"^":"Tp:119;d",
+"^":"Tp:120;d",
 $2:function(a,b){var z=this.d
 if(a>=z.length)return H.e(z,a)
 z[a]=b},
@@ -10098,11 +10099,11 @@
 aN:function(a,b){this.lF().aN(0,b)},
 zV:function(a,b){return this.lF().zV(0,b)},
 ez:[function(a,b){var z=this.lF()
-return H.VM(new H.xy(z,b),[H.Kp(z,0),null])},"$1","gIr",2,0,120,28],
+return H.VM(new H.xy(z,b),[H.Kp(z,0),null])},"$1","gIr",2,0,121,28],
 ev:function(a,b){var z=this.lF()
 return H.VM(new H.U5(z,b),[H.Kp(z,0)])},
 Ft:[function(a,b){var z=this.lF()
-return H.VM(new H.zs(z,b),[H.Kp(z,0),null])},"$1","git",2,0,121,28],
+return H.VM(new H.zs(z,b),[H.Kp(z,0),null])},"$1","git",2,0,122,28],
 Vr:function(a,b){return this.lF().Vr(0,b)},
 gl0:function(a){return this.lF().X5===0},
 gor:function(a){return this.lF().X5!==0},
@@ -10194,14 +10195,14 @@
 else if(J.xC(J.F8(a.tY),"objects/not-initialized"))return"This object will be initialized once it is accessed by the program."
 else if(J.xC(J.F8(a.tY),"objects/being-initialized"))return"This object is currently being initialized."
 return Q.xI.prototype.gJp.call(this,a)},
-Qx:[function(a){return this.gNe(a)},"$0","gyX",0,0,64],
+Qx:[function(a){return this.gNe(a)},"$0","gyX",0,0,66],
 vQ:[function(a,b,c){var z,y
 z=a.tY
 if(b===!0)J.LE(z).ml(new B.qB(a)).wM(c)
 else{y=J.w1(z)
 y.u(z,"fields",null)
 y.u(z,"elements",null)
-c.$0()}},"$2","gNe",4,0,122,123,82],
+c.$0()}},"$2","gNe",4,0,123,124,84],
 static:{lu:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10223,19 +10224,19 @@
 a.szz(z.t(a,"valueAsString"))}z=this.a
 y=J.RE(z)
 z.tY=y.ct(z,C.xP,z.tY,a)
-y.ct(z,C.xP,0,1)},"$1",null,2,0,null,109,"call"],
+y.ct(z,C.xP,0,1)},"$1",null,2,0,null,110,"call"],
 $isEH:true}}],["instance_view_element","package:observatory/src/elements/instance_view.dart",,Z,{
 "^":"",
 hx:{
-"^":"V8;Xh,f2,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
+"^":"V9;Xh,f2,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 ghf:function(a){return a.Xh},
 shf:function(a,b){a.Xh=this.ct(a,C.fn,a.Xh,b)},
 gIi:function(a){return a.f2},
 sIi:function(a,b){a.f2=this.ct(a,C.XM,a.f2,b)},
-vV:[function(a,b){return J.aT(a.Xh).cv(J.ew(J.F8(a.Xh),"/eval?expr="+P.jW(C.yD,b,C.xM,!1)))},"$1","gZm",2,0,83,84],
-S1:[function(a,b){return J.aT(a.Xh).cv(J.ew(J.F8(a.Xh),"/retained"))},"$1","ghN",2,0,124,85],
-ee:[function(a,b){return J.aT(a.Xh).cv(J.ew(J.F8(a.Xh),"/retaining_path?limit="+H.d(b))).ml(new Z.cL(a))},"$1","gCI",2,0,124,30],
-RF:[function(a,b){J.LE(a.Xh).wM(b)},"$1","gvC",2,0,17,82],
+vV:[function(a,b){return J.aT(a.Xh).cv(J.ew(J.F8(a.Xh),"/eval?expr="+P.jW(C.yD,b,C.xM,!1)))},"$1","gZm",2,0,85,86],
+S1:[function(a,b){return J.aT(a.Xh).cv(J.ew(J.F8(a.Xh),"/retained"))},"$1","ghN",2,0,125,87],
+ee:[function(a,b){return J.aT(a.Xh).cv(J.ew(J.F8(a.Xh),"/retaining_path?limit="+H.d(b))).ml(new Z.cL(a))},"$1","gCI",2,0,125,30],
+RF:[function(a,b){J.LE(a.Xh).wM(b)},"$1","gvC",2,0,17,84],
 static:{BN:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10248,20 +10249,20 @@
 C.ry.ZL(a)
 C.ry.XI(a)
 return a}}},
-V8:{
+V9:{
 "^":"uL+Pi;",
 $isd3:true},
 cL:{
-"^":"Tp:110;a",
+"^":"Tp:111;a",
 $1:[function(a){var z=this.a
-z.f2=J.Q5(z,C.XM,z.f2,a)},"$1",null,2,0,null,77,"call"],
+z.f2=J.Q5(z,C.XM,z.f2,a)},"$1",null,2,0,null,79,"call"],
 $isEH:true}}],["io_view_element","package:observatory/src/elements/io_view.dart",,E,{
 "^":"",
 L4:{
 "^":"V10;PM,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gkm:function(a){return a.PM},
 skm:function(a,b){a.PM=this.ct(a,C.qs,a.PM,b)},
-RF:[function(a,b){J.LE(a.PM).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.PM).wM(b)},"$1","gvC",2,0,17,84],
 static:{p4:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10296,7 +10297,7 @@
 "^":"V11;Cr,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gjx:function(a){return a.Cr},
 sjx:function(a,b){a.Cr=this.ct(a,C.vp,a.Cr,b)},
-RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,84],
 static:{Ch:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10331,7 +10332,7 @@
 "^":"V12;yR,mZ,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gql:function(a){return a.yR},
 sql:function(a,b){a.yR=this.ct(a,C.oj,a.yR,b)},
-RF:[function(a,b){J.LE(a.yR).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.yR).wM(b)},"$1","gvC",2,0,17,84],
 TY:[function(a){J.LE(a.yR).wM(new E.eG(a))},"$0","gW6",0,0,15],
 q0:function(a){Z.uL.prototype.q0.call(this,a)
 a.mZ=P.ww(P.ii(0,0,0,0,0,1),this.gW6(a))},
@@ -10356,7 +10357,7 @@
 "^":"uL+Pi;",
 $isd3:true},
 eG:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:[function(){var z=this.a
 if(z.mZ!=null)z.mZ=P.ww(P.ii(0,0,0,0,0,1),J.AL(z))},"$0",null,0,0,null,"call"],
 $isEH:true},
@@ -10379,7 +10380,7 @@
 "^":"V13;Cr,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gjx:function(a){return a.Cr},
 sjx:function(a,b){a.Cr=this.ct(a,C.vp,a.Cr,b)},
-RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,84],
 static:{J3z:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10399,7 +10400,7 @@
 "^":"V14;uv,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gj4:function(a){return a.uv},
 sj4:function(a,b){a.uv=this.ct(a,C.Ve,a.uv,b)},
-RF:[function(a,b){J.LE(a.uv).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.uv).wM(b)},"$1","gvC",2,0,17,84],
 static:{chF:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10434,7 +10435,7 @@
 "^":"V15;Cr,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gjx:function(a){return a.Cr},
 sjx:function(a,b){a.Cr=this.ct(a,C.vp,a.Cr,b)},
-RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,84],
 static:{xK:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10454,7 +10455,7 @@
 "^":"V16;h1,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gHy:function(a){return a.h1},
 sHy:function(a,b){a.h1=this.ct(a,C.YE,a.h1,b)},
-RF:[function(a,b){J.LE(a.h1).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.h1).wM(b)},"$1","gvC",2,0,17,84],
 static:{xx:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10474,7 +10475,7 @@
 "^":"V17;Cr,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gjx:function(a){return a.Cr},
 sjx:function(a,b){a.Cr=this.ct(a,C.vp,a.Cr,b)},
-RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,84],
 static:{Ii:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10509,7 +10510,7 @@
 "^":"V18;wT,mZ,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gMZ:function(a){return a.wT},
 sMZ:function(a,b){a.wT=this.ct(a,C.jU,a.wT,b)},
-RF:[function(a,b){J.LE(a.wT).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.wT).wM(b)},"$1","gvC",2,0,17,84],
 Yk:[function(a){J.LE(a.wT).wM(new E.Gf(a))},"$0","guT",0,0,15],
 q0:function(a){Z.uL.prototype.q0.call(this,a)
 a.mZ=P.ww(P.ii(0,0,0,0,0,1),this.guT(a))},
@@ -10534,7 +10535,7 @@
 "^":"uL+Pi;",
 $isd3:true},
 Gf:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:[function(){var z=this.a
 if(z.mZ!=null)z.mZ=P.ww(P.ii(0,0,0,0,0,1),J.lB(z))},"$0",null,0,0,null,"call"],
 $isEH:true},
@@ -10542,7 +10543,7 @@
 "^":"V19;Cr,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gjx:function(a){return a.Cr},
 sjx:function(a,b){a.Cr=this.ct(a,C.vp,a.Cr,b)},
-RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.Cr).wM(b)},"$1","gvC",2,0,17,84],
 static:{dv:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10584,7 +10585,7 @@
 gNN:function(a){return a.RX},
 Fn:function(a){return this.gNN(a).$0()},
 sNN:function(a,b){a.RX=this.ct(a,C.Wj,a.RX,b)},
-RF:[function(a,b){J.LE(a.RX).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.RX).wM(b)},"$1","gvC",2,0,17,84],
 Yk:[function(a){J.LE(a.RX).wM(new E.Cc(a))},"$0","guT",0,0,15],
 q0:function(a){Z.uL.prototype.q0.call(this,a)
 a.mZ=P.ww(P.ii(0,0,0,0,0,1),this.guT(a))},
@@ -10609,7 +10610,7 @@
 "^":"uL+Pi;",
 $isd3:true},
 Cc:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:[function(){var z=this.a
 if(z.mZ!=null)z.mZ=P.ww(P.ii(0,0,0,0,0,1),J.lB(z))},"$0",null,0,0,null,"call"],
 $isEH:true}}],["isolate_profile_element","package:observatory/src/elements/isolate_profile.dart",,X,{
@@ -10700,7 +10701,7 @@
 this.Dq(a)},
 m5:[function(a,b){this.RF(a,null)},"$1","gb6",2,0,17,54],
 RF:[function(a,b){var z="profile?tags="+H.d(a.VH)
-J.aT(a.ix).cv(z).ml(new X.Xy(a)).wM(b)},"$1","gvC",2,0,17,82],
+J.aT(a.ix).cv(z).ml(new X.Xy(a)).wM(b)},"$1","gvC",2,0,17,84],
 Dq:function(a){if(a.ix==null)return
 this.a8(a)},
 a8:function(a){var z,y,x,w,v,u,t
@@ -10717,8 +10718,8 @@
 x=new H.XO(t,null)
 N.QM("").xH("_buildStackTree",y,x)}if(J.xC(J.q8(a.Hm.WT),1))a.Hm.qU(0)
 this.ct(a,C.ep,null,a.Hm)},
-ka:[function(a,b){return"padding-left: "+b.gyt()*16+"px;"},"$1","gHn",2,0,125,79],
-LZ:[function(a,b){return C.QC[C.jn.Y(b.gyt()-1,9)]},"$1","gbw",2,0,125,79],
+ka:[function(a,b){return"padding-left: "+b.gyt()*16+"px;"},"$1","gHn",2,0,126,81],
+LZ:[function(a,b){return C.QC[C.jn.Y(b.gyt()-1,9)]},"$1","gbw",2,0,126,81],
 YF:[function(a,b,c,d){var z,y,x,w,v,u
 w=J.RE(b)
 if(!J.xC(J.F8(w.gN(b)),"expand")&&!J.xC(w.gN(b),d))return
@@ -10729,7 +10730,7 @@
 w.qU(v-1)}catch(u){w=H.Ru(u)
 y=w
 x=new H.XO(u,null)
-N.QM("").xH("toggleExpanded",y,x)}},"$3","gY9",6,0,115,1,87,88],
+N.QM("").xH("toggleExpanded",y,x)}},"$3","gY9",6,0,116,1,89,90],
 static:{"^":"B6",os:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10755,9 +10756,9 @@
 "^":"uL+Pi;",
 $isd3:true},
 Xy:{
-"^":"Tp:113;a",
+"^":"Tp:114;a",
 $1:[function(a){var z=this.a
-z.ix=J.Q5(z,C.vb,z.ix,a)},"$1",null,2,0,null,126,"call"],
+z.ix=J.Q5(z,C.vb,z.ix,a)},"$1",null,2,0,null,127,"call"],
 $isEH:true}}],["isolate_ref_element","package:observatory/src/elements/isolate_ref.dart",,N,{
 "^":"",
 oa:{
@@ -10780,7 +10781,7 @@
 "^":"V22;ow,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 god:function(a){return a.ow},
 sod:function(a,b){a.ow=this.ct(a,C.rB,a.ow,b)},
-static:{N5:function(a){var z,y,x,w
+static:{JR:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
 x=P.qU
@@ -10799,8 +10800,8 @@
 "^":"V23;ow,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 god:function(a){return a.ow},
 sod:function(a,b){a.ow=this.ct(a,C.rB,a.ow,b)},
-Fv:[function(a,b){return a.ow.cv("debug/pause").ml(new D.GG(a))},"$1","gX0",2,0,127,11],
-jh:[function(a,b){return a.ow.cv("debug/resume").ml(new D.r8(a))},"$1","gDQ",2,0,127,11],
+Fv:[function(a,b){return a.ow.cv("debug/pause").ml(new D.GG(a))},"$1","gX0",2,0,128,11],
+jh:[function(a,b){return a.ow.cv("debug/resume").ml(new D.r8(a))},"$1","gDQ",2,0,128,11],
 static:{dm:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -10818,11 +10819,11 @@
 $isd3:true},
 GG:{
 "^":"Tp:10;a",
-$1:[function(a){return J.LE(this.a.ow)},"$1",null,2,0,null,109,"call"],
+$1:[function(a){return J.LE(this.a.ow)},"$1",null,2,0,null,110,"call"],
 $isEH:true},
 r8:{
 "^":"Tp:10;a",
-$1:[function(a){return J.LE(this.a.ow)},"$1",null,2,0,null,109,"call"],
+$1:[function(a){return J.LE(this.a.ow)},"$1",null,2,0,null,110,"call"],
 $isEH:true},
 Qh:{
 "^":"V24;ow,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
@@ -10951,7 +10952,7 @@
 god:function(a){return a.ck},
 sod:function(a,b){a.ck=this.ct(a,C.rB,a.ck,b)},
 vV:[function(a,b){var z=a.ck
-return z.cv(J.ew(J.F8(z.gVc()),"/eval?expr="+P.jW(C.yD,b,C.xM,!1)))},"$1","gZm",2,0,83,84],
+return z.cv(J.ew(J.F8(z.gVc()),"/eval?expr="+P.jW(C.yD,b,C.xM,!1)))},"$1","gZm",2,0,85,86],
 Vp:[function(a){a.ck.m7().ml(new L.LX(a))},"$0","gJD",0,0,15],
 q0:function(a){Z.uL.prototype.q0.call(this,a)
 a.ts=P.ww(P.ii(0,0,0,0,0,1),this.gJD(a))},
@@ -10959,10 +10960,10 @@
 Z.uL.prototype.Nz.call(this,a)
 z=a.ts
 if(z!=null)z.ed()},
-RF:[function(a,b){J.LE(a.ck).wM(b)},"$1","gvC",2,0,17,82],
-Fv:[function(a,b){return a.ck.cv("debug/pause").ml(new L.CV(a))},"$1","gX0",2,0,127,11],
-jh:[function(a,b){return a.ck.cv("resume").ml(new L.Vq(a))},"$1","gDQ",2,0,127,11],
-static:{KM:function(a){var z,y,x,w,v
+RF:[function(a,b){J.LE(a.ck).wM(b)},"$1","gvC",2,0,17,84],
+Fv:[function(a,b){return a.ck.cv("debug/pause").ml(new L.CV(a))},"$1","gX0",2,0,128,11],
+jh:[function(a,b){return a.ck.cv("resume").ml(new L.Vq(a))},"$1","gDQ",2,0,128,11],
+static:{Za:function(a){var z,y,x,w,v
 z=P.zV(J.UQ($.BY,"DataTable"),null)
 y=$.XZ()
 x=P.YM(null,null,null,P.qU,W.I0)
@@ -10992,15 +10993,15 @@
 y.YT=v
 w.u(0,"isStacked",!0)
 y.YT.bG.u(0,"connectSteps",!1)
-y.YT.bG.u(0,"vAxis",P.EF(["minValue",0,"maxValue",100],null,null))}y.YT.W2(y.X6)}z.ts=P.ww(P.ii(0,0,0,0,0,1),J.dq(z))},"$1",null,2,0,null,128,"call"],
+y.YT.bG.u(0,"vAxis",P.EF(["minValue",0,"maxValue",100],null,null))}y.YT.W2(y.X6)}z.ts=P.ww(P.ii(0,0,0,0,0,1),J.dq(z))},"$1",null,2,0,null,129,"call"],
 $isEH:true},
 CV:{
 "^":"Tp:10;a",
-$1:[function(a){return J.LE(this.a.ck)},"$1",null,2,0,null,109,"call"],
+$1:[function(a){return J.LE(this.a.ck)},"$1",null,2,0,null,110,"call"],
 $isEH:true},
 Vq:{
 "^":"Tp:10;a",
-$1:[function(a){return J.LE(this.a.ck)},"$1",null,2,0,null,109,"call"],
+$1:[function(a){return J.LE(this.a.ck)},"$1",null,2,0,null,110,"call"],
 $isEH:true}}],["json_view_element","package:observatory/src/elements/json_view.dart",,Z,{
 "^":"",
 xh:{
@@ -11106,8 +11107,8 @@
 "^":"V29;iI,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gHt:function(a){return a.iI},
 sHt:function(a,b){a.iI=this.ct(a,C.EV,a.iI,b)},
-vV:[function(a,b){return J.aT(a.iI).cv(J.ew(J.F8(a.iI),"/eval?expr="+P.jW(C.yD,b,C.xM,!1)))},"$1","gZm",2,0,83,84],
-RF:[function(a,b){J.LE(a.iI).wM(b)},"$1","gvC",2,0,17,82],
+vV:[function(a,b){return J.aT(a.iI).cv(J.ew(J.F8(a.iI),"/eval?expr="+P.jW(C.yD,b,C.xM,!1)))},"$1","gZm",2,0,85,86],
+RF:[function(a,b){J.LE(a.iI).wM(b)},"$1","gvC",2,0,17,84],
 static:{as:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -11171,7 +11172,7 @@
 $isRw:true,
 static:{"^":"Uj",QM:function(a){return $.Iu().to(a,new N.dG(a))}}},
 dG:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:function(){var z,y,x,w,v
 z=this.a
 if(C.xB.nC(z,"."))H.vh(P.u("name shouldn't start with a '.'"))
@@ -11222,13 +11223,13 @@
 z.V7("load",["visualization","1",P.jT(P.EF(["packages",["corechart","table"],"callback",P.mt(y.gv6(y))],null,null))])
 $.Ib().MM.ml(G.vN()).ml(new F.e378())},
 e377:{
-"^":"Tp:130;",
+"^":"Tp:131;",
 $1:[function(a){var z
 if(J.xC(a.gOR(),C.nT)){z=J.RE(a)
 if(J.co(z.gG1(a),"Error evaluating expression"))z=J.x5(z.gG1(a),"Can't assign to null: ")===!0||J.x5(z.gG1(a),"Expression is not assignable: ")===!0
 else z=!1}else z=!1
 if(z)return
-P.FL(a.gOR().oc+": "+a.gFl().bu(0)+": "+H.d(J.z2(a)))},"$1",null,2,0,null,129,"call"],
+P.FL(a.gOR().oc+": "+a.gFl().bu(0)+": "+H.d(J.z2(a)))},"$1",null,2,0,null,130,"call"],
 $isEH:true},
 e378:{
 "^":"Tp:10;",
@@ -11288,7 +11289,7 @@
 sPj:function(a,b){a.KU=this.ct(a,C.kV,a.KU,b)},
 gdU:function(a){return a.V4},
 sdU:function(a,b){a.V4=this.ct(a,C.cg,a.V4,b)},
-static:{JR:function(a){var z,y,x,w
+static:{vn:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
 x=P.qU
@@ -11318,7 +11319,7 @@
 Ty:[function(a,b,c,d){var z=a.SB
 if(z===!0)return
 a.SB=this.ct(a,C.aP,z,!0)
-if(a.rU!=null)this.LY(a,this.gWd(a))},"$3","gzY",6,0,86,1,87,88],
+if(a.rU!=null)this.LY(a,this.gWd(a))},"$3","gzY",6,0,88,1,89,90],
 rT:[function(a){a.SB=this.ct(a,C.aP,a.SB,!1)},"$0","gWd",0,0,15],
 static:{ZC:function(a){var z,y,x,w
 z=$.XZ()
@@ -11368,7 +11369,7 @@
 if(z!=null)return z.gHP()
 else return""},
 su6:function(a,b){},
-static:{zf:function(a){var z,y,x,w
+static:{Du:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
 x=P.qU
@@ -11437,18 +11438,15 @@
 siJ:function(a,b){a.yT=this.ct(a,C.j2,a.yT,b)},
 q0:function(a){var z
 Z.uL.prototype.q0.call(this,a)
-if(a.qC===!0){z=new U.bl(P.L5(null,null,null,null,null),0,"unknown","unknown",0,!1,!1,P.bK(null,null,!1,null),P.bK(null,null,!1,null),P.L5(null,null,null,P.qU,D.af),P.L5(null,null,null,P.qU,D.bv),null,null,null,null,null,!1,null,null,null,null,null)
+if(a.qC===!0){z=new U.bl(P.L5(null,null,null,P.qU,P.oh),0,"unknown","unknown",0,!1,!1,P.bK(null,null,!1,null),P.bK(null,null,!1,null),P.L5(null,null,null,P.qU,D.af),P.L5(null,null,null,P.qU,D.bv),null,null,null,null,null,!1,null,null,null,null,null)
 z.md()
 z.PI()
 z=new G.mL(new G.hq(null,"",null,null),z,null,null,null,null,null)
 z.hq()
-a.yT=this.ct(a,C.j2,a.yT,z)}else{z=new U.XK(null,"unknown","unknown",0,!1,!1,P.bK(null,null,!1,null),P.bK(null,null,!1,null),P.L5(null,null,null,P.qU,D.af),P.L5(null,null,null,P.qU,D.bv),null,null,null,null,null,!1,null,null,null,null,null)
-z.md()
-z.SC()
-z=new G.mL(new G.hq(null,"",null,null),z,null,null,null,null,null)
+a.yT=this.ct(a,C.j2,a.yT,z)}else{z=new G.mL(new G.hq(null,"",null,null),U.bU(),null,null,null,null,null)
 z.US()
 a.yT=this.ct(a,C.j2,a.yT,z)}},
-static:{Lu:function(a){var z,y,x,w
+static:{JT8:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
 x=P.qU
@@ -11471,20 +11469,20 @@
 Nz:function(a){A.dM.prototype.Nz.call(this,a)},
 I9:function(a){A.dM.prototype.I9.call(this,a)},
 wN:function(a,b,c,d){A.dM.prototype.wN.call(this,a,b,c,d)},
-a7:[function(a,b){return G.mG(b)},"$1","gSs",2,0,131,132],
+a7:[function(a,b){return G.mG(b)},"$1","gSs",2,0,132,133],
 Ze:[function(a,b){return G.Ef(b)},"$1","gbJ",2,0,12,13],
-uG:[function(a,b){return J.xC(b,"Null")},"$1","gHh",2,0,133,134],
-i5:[function(a,b){return J.xC(b,"Error")},"$1","gt3",2,0,133,134],
+uG:[function(a,b){return J.xC(b,"Null")},"$1","gHh",2,0,134,135],
+i5:[function(a,b){return J.xC(b,"Error")},"$1","gt3",2,0,134,135],
 OP:[function(a,b){var z=J.x(b)
-return z.n(b,"Smi")||z.n(b,"Mint")||z.n(b,"Bigint")},"$1","gSO",2,0,133,134],
-Qr:[function(a,b){return J.xC(b,"Bool")},"$1","gr9",2,0,133,134],
-ff:[function(a,b){return J.xC(b,"String")},"$1","gu7",2,0,133,134],
-fZ:[function(a,b){return J.xC(b,"Instance")},"$1","gNs",2,0,133,134],
-JG:[function(a,b){return J.xC(b,"Double")},"$1","gzx",2,0,133,134],
+return z.n(b,"Smi")||z.n(b,"Mint")||z.n(b,"Bigint")},"$1","gSO",2,0,134,135],
+Qr:[function(a,b){return J.xC(b,"Bool")},"$1","gr9",2,0,134,135],
+ff:[function(a,b){return J.xC(b,"String")},"$1","gu7",2,0,134,135],
+fZ:[function(a,b){return J.xC(b,"Instance")},"$1","gNs",2,0,134,135],
+JG:[function(a,b){return J.xC(b,"Double")},"$1","gzx",2,0,134,135],
 Cp:[function(a,b){var z=J.x(b)
-return z.n(b,"GrowableObjectArray")||z.n(b,"Array")},"$1","gK4",2,0,133,134],
-tR:[function(a,b){return J.xC(b,"Type")},"$1","gqN",2,0,133,134],
-Cn:[function(a,b){return!C.Nm.tg(["Null","Smi","Mint","Bigint","Bool","String","Double","Instance","GrowableObjectArray","Array","Type","Error"],b)},"$1","geS",2,0,133,134],
+return z.n(b,"GrowableObjectArray")||z.n(b,"Array")},"$1","gK4",2,0,134,135],
+tR:[function(a,b){return J.xC(b,"Type")},"$1","gqN",2,0,134,135],
+Cn:[function(a,b){return!C.Nm.tg(["Null","Smi","Mint","Bigint","Bool","String","Double","Instance","GrowableObjectArray","Array","Type","Error"],b)},"$1","geS",2,0,134,135],
 static:{EE:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -11519,7 +11517,7 @@
 x=H.VM(new P.Yp(z),[T.yj])
 if(y.Gv>=4)H.vh(y.q7())
 y.Iv(x)
-return!0}return!1},"$0","gDx",0,0,94],
+return!0}return!1},"$0","gDx",0,0,96],
 gnz:function(a){var z,y
 z=a.AP
 if(z!=null){y=z.iE
@@ -11567,14 +11565,14 @@
 z=new O.Nq(z)
 return new P.yQ(null,null,null,null,new O.u3(z),new O.bF(z),null,null,null,null,null,null)},
 Nq:{
-"^":"Tp:135;a",
+"^":"Tp:136;a",
 $2:function(a,b){var z=this.a
 if(z.a)return
 z.a=!0
 a.RK(b,new O.c1(z))},
 $isEH:true},
 c1:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:[function(){this.a.a=!1
 O.wR()},"$0",null,0,0,null,"call"],
 $isEH:true},
@@ -11584,19 +11582,19 @@
 return new O.yJ(this.b,b,c,d)},"$4",null,8,0,null,24,25,26,28,"call"],
 $isEH:true},
 yJ:{
-"^":"Tp:64;c,d,e,f",
+"^":"Tp:66;c,d,e,f",
 $0:[function(){this.c.$2(this.d,this.e)
 return this.f.$0()},"$0",null,0,0,null,"call"],
 $isEH:true},
 bF:{
-"^":"Tp:136;UI",
+"^":"Tp:137;UI",
 $4:[function(a,b,c,d){if(d==null)return d
 return new O.f6(this.UI,b,c,d)},"$4",null,8,0,null,24,25,26,28,"call"],
 $isEH:true},
 f6:{
 "^":"Tp:10;bK,Gq,Rm,w3",
 $1:[function(a){this.bK.$2(this.Gq,this.Rm)
-return this.w3.$1(a)},"$1",null,2,0,null,137,"call"],
+return this.w3.$1(a)},"$1",null,2,0,null,62,"call"],
 $isEH:true}}],["observe.src.list_diff","package:observe/src/list_diff.dart",,G,{
 "^":"",
 B5:function(a,b,c,d,e,f){var z,y,x,w,v,u,t,s,r,q,p,o,n,m
@@ -11799,6 +11797,13 @@
 gvH:function(a){return this.jr},
 gRt:function(){return this.Uj},
 gNg:function(){return this.dM},
+LT:function(a){var z
+if(typeof a==="number"&&Math.floor(a)===a){z=this.jr
+if(typeof z!=="number")return H.s(z)
+z=a<z}else z=!0
+if(z)return!1
+if(!J.xC(this.dM,this.Uj.G4.length))return!0
+return J.u6(a,J.ew(this.jr,this.dM))},
 bu:function(a){var z,y
 z="#<ListChangeRecord index: "+H.d(this.jr)+", removed: "
 y=this.Uj
@@ -11823,7 +11828,7 @@
 "^":"a;",
 $isd3:true},
 X6:{
-"^":"Tp:67;a,b",
+"^":"Tp:69;a,b",
 $2:function(a,b){var z,y,x,w,v
 z=this.b
 y=$.cp().jD(z,a)
@@ -12005,7 +12010,7 @@
 if(x&&y.length!==0){x=H.VM(new P.Yp(y),[G.DA])
 if(z.Gv>=4)H.vh(z.q7())
 z.Iv(x)
-return!0}return!1},"$0","gL6",0,0,94],
+return!0}return!1},"$0","gL6",0,0,96],
 $iswn:true,
 static:{ch:function(a,b){var z=H.VM([],[b])
 return H.VM(new Q.wn(null,null,z,null,null),[b])},Y5:function(a,b,c){var z,y,x,w,v,u,t,s,r,q,p,o,n,m,l
@@ -12042,7 +12047,7 @@
 "^":"rm+Pi;",
 $isd3:true},
 cj:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:function(){this.a.iT=null},
 $isEH:true}}],["observe.src.observable_map","package:observe/src/observable_map.dart",,V,{
 "^":"",
@@ -12100,11 +12105,11 @@
 return z}}},
 zT:{
 "^":"Tp;a",
-$2:[function(a,b){this.a.u(0,a,b)},"$2",null,4,0,null,68,18,"call"],
+$2:[function(a,b){this.a.u(0,a,b)},"$2",null,4,0,null,70,18,"call"],
 $isEH:true,
 $signature:function(){return H.IG(function(a,b){return{func:"Bi",args:[a,b]}},this.a,"qC")}},
 Lo:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){var z=this.a
 z.nq(z,H.VM(new V.ya(a,b,null,!1,!0),[null,null]))},
 $isEH:true}}],["observe.src.observer_transform","package:observe/src/observer_transform.dart",,Y,{
@@ -12285,7 +12290,7 @@
 gPu:function(){return!1},
 static:{"^":"qr"}},
 MdQ:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:function(){return new H.VR("^(?:(?:[$_a-zA-Z]+[$_a-zA-Z0-9]*|(?:[0-9]|[1-9]+[0-9]+)))(?:\\.(?:[$_a-zA-Z]+[$_a-zA-Z0-9]*|(?:[0-9]|[1-9]+[0-9]+)))*$",H.ol("^(?:(?:[$_a-zA-Z]+[$_a-zA-Z0-9]*|(?:[0-9]|[1-9]+[0-9]+)))(?:\\.(?:[$_a-zA-Z]+[$_a-zA-Z0-9]*|(?:[0-9]|[1-9]+[0-9]+)))*$",!1,!0,!1),null,null)},
 $isEH:true},
 NV:{
@@ -12363,7 +12368,7 @@
 this.kH()
 this.Wf=null
 this.GX=null},
-xV:[function(a){if(this.GX!=null)this.SG()},"$1","gjM",2,0,17,11],
+xVs:[function(a){if(this.GX!=null)this.SG()},"$1","gjM",2,0,17,11],
 SG:function(){var z=0
 while(!0){if(!(z<1000&&this.lI()))break;++z}return z>0},
 Aw:function(a,b,c){var z,y,x,w
@@ -12423,7 +12428,7 @@
 x.FV(0,z)
 return x}return a},"$1","Ft",2,0,10,18],
 Fk:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){this.a.u(0,R.tB(a),R.tB(b))},
 $isEH:true}}],["polymer","package:polymer/polymer.dart",,A,{
 "^":"",
@@ -12621,11 +12626,11 @@
 return z},
 $isXP:true},
 eY:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){if(C.kr.x4(a)!==!0&&!J.co(a,"on-"))this.a.kK.u(0,a,b)},
 $isEH:true},
 BO:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){var z,y,x
 z=J.rY(a)
 if(z.nC(a,"on-")){y=J.U6(b).u8(b,"{{")
@@ -12641,7 +12646,7 @@
 $1:function(a){return J.RF(a,this.a)},
 $isEH:true},
 ix:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:function(){return[]},
 $isEH:true},
 Tj:{
@@ -12649,13 +12654,13 @@
 $2:function(a,b){this.a.u(0,H.d(a).toLowerCase(),b)},
 $isEH:true},
 DOe:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:function(){var z=P.L5(null,null,null,P.qU,P.qU)
 C.SP.aN(0,new A.xb(z))
 return z},
 $isEH:true},
 xb:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){this.a.u(0,b,a)},
 $isEH:true},
 A2:{
@@ -12861,7 +12866,7 @@
 u=J.UQ($.pT(),v)
 t=w.t(0,u!=null?u:v)
 if(t!=null){if(x)y.J4("["+H.d(this.gqn(a))+"] found host handler name ["+t+"]")
-this.ea(a,a,t,[b,!!z.$iseC?z.gey(b):null,a])}if(x)y.J4("<<< ["+H.d(this.gqn(a))+"]: hostEventListener("+H.d(z.gt5(b))+")")},"$1","gD4",2,0,144,76],
+this.ea(a,a,t,[b,!!z.$iseC?z.gey(b):null,a])}if(x)y.J4("<<< ["+H.d(this.gqn(a))+"]: hostEventListener("+H.d(z.gt5(b))+")")},"$1","gD4",2,0,144,78],
 ea:function(a,b,c,d){var z,y,x,w
 z=$.Uk()
 y=z.Im(C.t4)
@@ -12879,13 +12884,13 @@
 $isPZ:true,
 $isKV:true},
 dZ:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){var z=J.Vs(this.a)
 if(z.x4(a)!==!0)z.u(0,a,new A.Xi(b).$0())
 z.t(0,a)},
 $isEH:true},
 Xi:{
-"^":"Tp:64;b",
+"^":"Tp:66;b",
 $0:function(){return this.b},
 $isEH:true},
 TV:{
@@ -12898,7 +12903,7 @@
 $1:function(a){return J.DB(!!J.x(a).$isvy?a:M.Ky(a))},
 $isEH:true},
 qz:{
-"^":"Tp:67;a,b,c,d,e,f,UI",
+"^":"Tp:69;a,b,c,d,e,f,UI",
 $2:[function(a,b){var z,y,x,w,v,u,t,s,r,q,p,o
 z=this.d
 if(typeof a!=="number")return H.s(a)
@@ -12994,7 +12999,7 @@
 if(C.xB.nC(w,"@")){v=this.U1
 w=L.hk(C.xB.yn(w,1)).Tl(v)}else v=y
 u=J.x(a)
-x.ea(y,v,w,[a,!!u.$iseC?u.gey(a):null,z])},"$1","gwi",2,0,10,76],
+x.ea(y,v,w,[a,!!u.$iseC?u.gey(a):null,z])},"$1","gwi",2,0,10,78],
 gP:function(a){return},
 TR:function(a,b){var z=J.PB(this.v3).t(0,this.pB)
 z=H.VM(new W.fd(0,z.bi,z.Ph,W.aF(this.gwi()),z.Sg),[H.Kp(z,0)])
@@ -13017,11 +13022,11 @@
 tZ:[function(a){if(this.ih!=null){this.TP(0)
 this.Ws()}},"$0","gv6",0,0,15]},
 mS:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){return A.X1($.M6,$.UG)},"$0",null,0,0,null,"call"],
 $isEH:true},
 hp:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:[function(){var z=$.ln().MM
 if(z.Gv!==0)H.vh(P.w("Future already completed"))
 z.OH(null)
@@ -13034,7 +13039,7 @@
 return this.b.qP([b,c],a)},"$3",null,6,0,null,152,53,153,"call"],
 $isEH:true},
 v4:{
-"^":"Tp:64;c,d,e,f",
+"^":"Tp:66;c,d,e,f",
 $0:[function(){var z,y,x,w,v,u
 z=this.d
 y=this.e
@@ -13068,26 +13073,26 @@
 return y}catch(x){H.Ru(x)
 return a}},
 Md:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return a},
 $isEH:true},
 lP:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return a},
 $isEH:true},
 Uf:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){var z,y
 try{z=P.zu(a)
 return z}catch(y){H.Ru(y)
 return b}},
 $isEH:true},
 Ra:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return!J.xC(a,"false")},
 $isEH:true},
 wJY:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return H.BU(a,null,new Z.fT(b))},
 $isEH:true},
 fT:{
@@ -13095,7 +13100,7 @@
 $1:function(a){return this.a},
 $isEH:true},
 zOQ:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return H.RR(a,new Z.Lf(b))},
 $isEH:true},
 Lf:{
@@ -13106,11 +13111,12 @@
 dA:[function(a){var z=J.x(a)
 if(!!z.$isZ0)z=J.vo(a.gvc(),new T.o8f(a)).zV(0," ")
 else z=!!z.$isQV?z.zV(a," "):a
-return z},"$1","dI",2,0,46],
+return z},"$1","dI",2,0,46,61],
 qN:[function(a){var z=J.x(a)
 if(!!z.$isZ0)z=J.kl(a.gvc(),new T.GL(a)).zV(0,";")
 else z=!!z.$isQV?z.zV(a,";"):a
-return z},"$1","xe",2,0,46],
+return z},"$1","xe",2,0,46,61],
+Fm:[function(a){return a},"$1","u2",2,0,10,62],
 o8f:{
 "^":"Tp:10;a",
 $1:function(a){return J.xC(this.a.t(0,a),!0)},
@@ -13143,7 +13149,8 @@
 y=z&&J.xC(this.b,"class")?T.dI():null
 if(z&&J.xC(this.b,"style"))y=T.xe()
 if(c===!0)return T.rD(this.c,a,y)
-return new T.tI(a,y,this.c,null,null,null)},"$3",null,6,0,null,147,148,149,"call"],
+z=y==null?T.u2():y
+return new T.tI(a,z,this.c,null,null,null)},"$3",null,6,0,null,147,148,149,"call"],
 $isEH:true},
 uK:{
 "^":"Tp:10;a",
@@ -13151,20 +13158,20 @@
 $isEH:true},
 tI:{
 "^":"Ap;yr,wx,n4,Fg,ML,HR",
+R5:function(a){return this.wx.$1(a)},
 WV:function(a){return this.Fg.$1(a)},
-Ls:[function(a){var z,y
+q1:[function(a,b){var z,y
 z=this.HR
-y=T.r6(a,this.yr,this.wx)
+y=this.R5(a)
 this.HR=y
-if(this.Fg!=null&&!J.xC(z,y))this.WV(this.HR)},"$1","gkR",2,0,10,156],
+if(b!==!0&&this.Fg!=null&&!J.xC(z,y))this.WV(this.HR)},function(a){return this.q1(a,!1)},"UV","$2$skipChanges","$1","gQp",2,3,156,157,61,158],
 gP:function(a){if(this.Fg!=null)return this.HR
 return T.rD(this.n4,this.yr,this.wx)},
 sP:function(a,b){var z,y,x,w,v
-try{w=this.yr
-z=K.jX(this.n4,b,w)
-this.HR=T.r6(z,w,this.wx)}catch(v){w=H.Ru(v)
-y=w
-x=new H.XO(v,null)
+try{z=K.jX(this.n4,b,this.yr)
+this.q1(z,!0)}catch(w){v=H.Ru(w)
+y=v
+x=new H.XO(w,null)
 H.VM(new P.Zf(P.Dt(null)),[null]).w0("Error evaluating expression '"+H.d(this.n4)+"': "+H.d(y),x)}},
 TR:function(a,b){var z,y,x,w,v,u,t
 if(this.Fg!=null)throw H.b(P.w("already open"))
@@ -13175,13 +13182,13 @@
 u.Eo(null,null)
 z=J.okV(w,new K.Oy(v,u))
 this.n4=z
-u=z.glr().yI(this.gkR())
+u=z.glr().yI(this.gQp())
 u.fm(0,new T.Tg(z))
 this.ML=u
 try{w=z
 J.okV(w,new K.Ed(v))
 w.gXr()
-this.HR=T.r6(z.gXr(),v,this.wx)}catch(t){w=H.Ru(t)
+this.q1(z.gXr(),!0)}catch(t){w=H.Ru(t)
 y=w
 x=new H.XO(t,null)
 H.VM(new P.Zf(P.Dt(null)),[null]).w0("Error evaluating expression '"+H.d(z)+"': "+H.d(y),x)}return this.HR},
@@ -13190,21 +13197,15 @@
 this.ML=null
 this.n4=H.Go(this.n4,"$isdE").KL
 this.Fg=null},
-static:{rD:function(a,b,c){var z,y,x,w
-try{x=T.r6(K.Cw(a,b),b,c)
-return x}catch(w){x=H.Ru(w)
-z=x
-y=new H.XO(w,null)
-H.VM(new P.Zf(P.Dt(null)),[null]).w0("Error evaluating expression '"+H.d(a)+"': "+H.d(z),y)}return},r6:function(a,b,c){if(!!J.x(a).$isfk)return J.np(J.kl(a.bm,new T.bI(a,b)),!1)
-else return c==null?a:c.$1(a)}}},
-bI:{
-"^":"Tp:10;a,b",
-$1:[function(a){var z=this.a.xG
-if(J.xC(z,"this"))H.vh(K.xn("'this' cannot be used as a variable name."))
-return new K.ig(this.b,z,a)},"$1",null,2,0,null,145,"call"],
-$isEH:true},
+static:{rD:function(a,b,c){var z,y,x,w,v
+try{z=K.Cw(a,b)
+w=c==null?z:c.$1(z)
+return w}catch(v){w=H.Ru(v)
+y=w
+x=new H.XO(v,null)
+H.VM(new P.Zf(P.Dt(null)),[null]).w0("Error evaluating expression '"+H.d(a)+"': "+H.d(y),x)}return}}},
 Tg:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:[function(a,b){H.VM(new P.Zf(P.Dt(null)),[null]).w0("Error evaluating expression '"+H.d(this.a)+"': "+H.d(a),b)},"$2",null,4,0,null,1,138,"call"],
 $isEH:true}}],["polymer_expressions.async","package:polymer_expressions/async.dart",,B,{
 "^":"",
@@ -13234,7 +13235,7 @@
 z.a=a
 y=new K.c4(z)
 x=H.VM([],[U.hw])
-for(;w=z.a,v=J.x(w),!!v.$isMp;){if(!J.xC(v.gxS(w),"|"))break
+for(;w=z.a,v=J.x(w),!!v.$iszb;){if(!J.xC(v.gxS(w),"|"))break
 x.push(v.gT8(w))
 z.a=v.gBb(w)}w=z.a
 v=J.x(w)
@@ -13270,55 +13271,55 @@
 if(y.x4("this"))H.vh(K.xn("'this' cannot be used as a variable name."))
 y=x}return y},
 lPa:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.ew(a,b)},
 $isEH:true},
 Ufa:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.Hn(a,b)},
 $isEH:true},
 Raa:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.vX(a,b)},
 $isEH:true},
 w0:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.L9(a,b)},
 $isEH:true},
 w5:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.xC(a,b)},
 $isEH:true},
 w10:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return!J.xC(a,b)},
 $isEH:true},
 w11:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.z8(a,b)},
 $isEH:true},
 w12:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.J5(a,b)},
 $isEH:true},
 w13:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.u6(a,b)},
 $isEH:true},
 w14:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.Bl(a,b)},
 $isEH:true},
 w15:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return a===!0||b===!0},
 $isEH:true},
 w16:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return a===!0&&b===!0},
 $isEH:true},
 w17:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){var z=H.Og(P.a)
 z=H.KT(z,[z]).BD(b)
 if(z)return b.$1(a)
@@ -13337,7 +13338,7 @@
 $1:function(a){return a!==!0},
 $isEH:true},
 c4:{
-"^":"Tp:64;a",
+"^":"Tp:66;a",
 $0:function(){return H.vh(K.xn("Expression is not assignable: "+H.d(this.a.a)))},
 $isEH:true},
 GK:{
@@ -13355,7 +13356,8 @@
 if(y==null||z==null)throw H.b(K.xn("variable '"+H.d(b)+"' not found"))
 y=$.cp().jD(y,z)
 return!!J.x(y).$iscb?B.z4(y,null):y},
-AC:function(a){return!J.xC(a,"this")}},
+AC:function(a){return!J.xC(a,"this")},
+bu:function(a){return"[model: "+H.d(this.ku)+"]"}},
 ig:{
 "^":"GK;eT>,Z0,P>",
 gku:function(){return this.eT.gku()},
@@ -13363,7 +13365,8 @@
 if(J.xC(this.Z0,b)){z=this.P
 return!!J.x(z).$iscb?B.z4(z,null):z}return this.eT.t(0,b)},
 AC:function(a){if(J.xC(this.Z0,a))return!1
-return this.eT.AC(a)}},
+return this.eT.AC(a)},
+bu:function(a){return this.eT.bu(0)+" > [local: "+H.d(this.Z0)+"]"}},
 Ph:{
 "^":"GK;eT>,Z3<",
 gku:function(){return this.eT.ku},
@@ -13371,7 +13374,9 @@
 if(z.x4(b)){z=z.t(0,b)
 return!!J.x(z).$iscb?B.z4(z,null):z}return this.eT.t(0,b)},
 AC:function(a){if(this.Z3.x4(a))return!1
-return!J.xC(a,"this")}},
+return!J.xC(a,"this")},
+bu:function(a){var z=this.Z3
+return"[model: "+H.d(this.eT.ku)+"] > [global: "+P.Ix(H.VM(new P.i5(z),[H.Kp(z,0)]),"(",")")+"]"}},
 dE:{
 "^":"a;bO?,Lv<",
 glr:function(){var z=this.k6
@@ -13402,7 +13407,7 @@
 Oy:{
 "^":"Jg;qu,lk",
 W9:function(a){return new K.uD(a,null,null,null,P.bK(null,null,!1,null))},
-LT:function(a){return a.wz.RR(0,this)},
+Hs:function(a){return a.wz.RR(0,this)},
 fV:function(a){var z,y
 z=J.okV(a.ghP(),this)
 y=new K.vl(z,a,null,null,null,P.bK(null,null,!1,null))
@@ -13459,7 +13464,7 @@
 RD:function(a){var z,y,x,w
 z=J.okV(a.gdc(),this)
 y=J.okV(a.gSl(),this)
-x=J.okV(a.gru(),this)
+x=J.okV(a.gCW(),this)
 w=new K.an(z,y,x,a,null,null,null,P.bK(null,null,!1,null))
 z.sbO(w)
 y.sbO(w)
@@ -13526,7 +13531,7 @@
 $isQb:true,
 $ishw:true},
 Ku:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.kW(a,J.Kt(b).gLv(),b.gv4().gLv())
 return a},
 $isEH:true},
@@ -13592,17 +13597,17 @@
 else{if(J.xC(z.gxS(z),"|")&&!!J.x(x.gLv()).$iswn)this.tj=H.Go(x.gLv(),"$iswn").gRT().yI(new K.P8(this,a))
 this.Lv=y.$2(x.gLv(),this.T8.gLv())}}},
 RR:function(a,b){return b.ex(this)},
-$asdE:function(){return[U.Mp]},
-$isMp:true,
+$asdE:function(){return[U.zb]},
+$iszb:true,
 $ishw:true},
 P8:{
 "^":"Tp:10;a,b",
 $1:[function(a){return this.a.l8(this.b)},"$1",null,2,0,null,11,"call"],
 $isEH:true},
 an:{
-"^":"dE;dc<,Sl<,ru<,KL,bO,tj,Lv,k6",
+"^":"dE;dc<,Sl<,CW<,KL,bO,tj,Lv,k6",
 Qh:function(a){var z=this.dc.gLv()
-this.Lv=(z==null?!1:z)===!0?this.Sl.gLv():this.ru.gLv()},
+this.Lv=(z==null?!1:z)===!0?this.Sl.gLv():this.CW.gLv()},
 RR:function(a,b){return b.RD(this)},
 $asdE:function(){return[U.HB]},
 $isHB:true,
@@ -13619,12 +13624,12 @@
 x=$.b7().I1.t(0,y)
 this.Lv=$.cp().jD(z,x)
 y=J.x(z)
-if(!!y.$isd3)this.tj=y.gqh(z).yI(new K.e9n(this,a,x))},
+if(!!y.$isd3)this.tj=y.gqh(z).yI(new K.fk(this,a,x))},
 RR:function(a,b){return b.fV(this)},
 $asdE:function(){return[U.x9]},
 $isx9:true,
 $ishw:true},
-e9n:{
+fk:{
 "^":"Tp:10;a,b,c",
 $1:[function(a){if(J.xq(a,new K.WKb(this.c))===!0)this.a.l8(this.b)},"$1",null,2,0,null,146,"call"],
 $isEH:true},
@@ -13640,18 +13645,27 @@
 return}y=this.Jn.gLv()
 x=J.U6(z)
 this.Lv=x.t(z,y)
-if(!!x.$isd3)this.tj=x.gqh(z).yI(new K.tE(this,a,y))},
+if(!!x.$iswn)this.tj=z.gRT().yI(new K.tE(this,a,y))
+else if(!!x.$isd3)this.tj=x.gqh(z).yI(new K.cn(this,a,y))},
 RR:function(a,b){return b.CU(this)},
 $asdE:function(){return[U.zX]},
 $iszX:true,
 $ishw:true},
 tE:{
 "^":"Tp:10;a,b,c",
-$1:[function(a){if(J.xq(a,new K.ey(this.c))===!0)this.a.l8(this.b)},"$1",null,2,0,null,146,"call"],
+$1:[function(a){if(J.xq(a,new K.zw(this.c))===!0)this.a.l8(this.b)},"$1",null,2,0,null,146,"call"],
+$isEH:true},
+zw:{
+"^":"Tp:10;d",
+$1:function(a){return a.LT(this.d)},
+$isEH:true},
+cn:{
+"^":"Tp:10;e,f,UI",
+$1:[function(a){if(J.xq(a,new K.ey(this.UI))===!0)this.e.l8(this.f)},"$1",null,2,0,null,146,"call"],
 $isEH:true},
 ey:{
-"^":"Tp:10;d",
-$1:function(a){return!!J.x(a).$isya&&J.xC(a.G3,this.d)},
+"^":"Tp:10;bK",
+$1:function(a){return!!J.x(a).$isya&&J.xC(a.G3,this.bK)},
 $isEH:true},
 xJ:{
 "^":"dE;hP<,re<,KL,bO,tj,Lv,k6",
@@ -13679,7 +13693,7 @@
 $1:[function(a){return a.gLv()},"$1",null,2,0,null,43,"call"],
 $isEH:true},
 vQ:{
-"^":"Tp:157;a,b,c",
+"^":"Tp:159;a,b,c",
 $1:[function(a){if(J.xq(a,new K.ho(this.c))===!0)this.a.l8(this.b)},"$1",null,2,0,null,146,"call"],
 $isEH:true},
 ho:{
@@ -13694,9 +13708,8 @@
 x=J.x(y)
 if(!x.$isQV&&y!=null)throw H.b(K.xn("right side of 'in' is not an iterator"))
 if(!!x.$iswn)this.tj=y.gRT().yI(new K.OF(this,a))
-x=J.Vm(z)
-w=y!=null?y:C.xD
-this.Lv=new K.fk(x,w)},
+w=J.Vm(z)
+this.Lv=y==null?C.xD:J.np(x.ez(y,new K.fg(a,w)),!1)},
 RR:function(a,b){return b.ky(this)},
 $asdE:function(){return[U.ma]},
 $isma:true,
@@ -13705,9 +13718,12 @@
 "^":"Tp:10;a,b",
 $1:[function(a){return this.a.l8(this.b)},"$1",null,2,0,null,11,"call"],
 $isEH:true},
-fk:{
-"^":"a;xG,bm",
-$isfk:true},
+fg:{
+"^":"Tp:10;c,d",
+$1:[function(a){var z=this.d
+if(J.xC(z,"this"))H.vh(K.xn("'this' cannot be used as a variable name."))
+return new K.ig(this.c,z,a)},"$1",null,2,0,null,145,"call"],
+$isEH:true},
 nD:{
 "^":"a;G1>",
 bu:function(a){return"EvalException: "+this.G1},
@@ -13721,7 +13737,7 @@
 if(z>=b.length)return H.e(b,z)
 if(!J.xC(y,b[z]))return!1}return!0},
 b1:function(a){a.toString
-return U.Le(H.n3(a,0,new U.xs()))},
+return U.Le(H.n3(a,0,new U.VU()))},
 Zd:function(a,b){var z=J.ew(a,b)
 if(typeof z!=="number")return H.s(z)
 a=536870911&z
@@ -13733,7 +13749,7 @@
 return 536870911&a+((16383&a)<<15>>>0)},
 tu:{
 "^":"a;",
-Bf:[function(a,b,c){return new U.zX(b,c)},"$2","gvH",4,0,158,1,43]},
+Bf:[function(a,b,c){return new U.zX(b,c)},"$2","gvH",4,0,160,1,43]},
 hw:{
 "^":"a;",
 $ishw:true},
@@ -13785,7 +13801,7 @@
 $isae:true},
 XC:{
 "^":"hw;wz",
-RR:function(a,b){return b.LT(this)},
+RR:function(a,b){return b.Hs(this)},
 bu:function(a){return"("+H.d(this.wz)+")"},
 n:function(a,b){if(b==null)return!1
 return!!J.x(b).$isXC&&J.xC(b.wz,this.wz)},
@@ -13814,30 +13830,30 @@
 y=J.v1(this.wz)
 return U.Le(U.Zd(U.Zd(0,z),y))},
 $iscJ:true},
-Mp:{
+zb:{
 "^":"hw;xS>,Bb>,T8>",
 RR:function(a,b){return b.ex(this)},
 bu:function(a){return"("+H.d(this.Bb)+" "+H.d(this.xS)+" "+H.d(this.T8)+")"},
 n:function(a,b){var z
 if(b==null)return!1
 z=J.x(b)
-return!!z.$isMp&&J.xC(z.gxS(b),this.xS)&&J.xC(z.gBb(b),this.Bb)&&J.xC(z.gT8(b),this.T8)},
+return!!z.$iszb&&J.xC(z.gxS(b),this.xS)&&J.xC(z.gBb(b),this.Bb)&&J.xC(z.gT8(b),this.T8)},
 giO:function(a){var z,y,x
 z=J.v1(this.xS)
 y=J.v1(this.Bb)
 x=J.v1(this.T8)
 return U.Le(U.Zd(U.Zd(U.Zd(0,z),y),x))},
-$isMp:true},
+$iszb:true},
 HB:{
-"^":"hw;dc<,Sl<,ru<",
+"^":"hw;dc<,Sl<,CW<",
 RR:function(a,b){return b.RD(this)},
-bu:function(a){return"("+H.d(this.dc)+" ? "+H.d(this.Sl)+" : "+H.d(this.ru)+")"},
+bu:function(a){return"("+H.d(this.dc)+" ? "+H.d(this.Sl)+" : "+H.d(this.CW)+")"},
 n:function(a,b){if(b==null)return!1
-return!!J.x(b).$isHB&&J.xC(b.gdc(),this.dc)&&J.xC(b.gSl(),this.Sl)&&J.xC(b.gru(),this.ru)},
+return!!J.x(b).$isHB&&J.xC(b.gdc(),this.dc)&&J.xC(b.gSl(),this.Sl)&&J.xC(b.gCW(),this.CW)},
 giO:function(a){var z,y,x
 z=J.v1(this.dc)
 y=J.v1(this.Sl)
-x=J.v1(this.ru)
+x=J.v1(this.CW)
 return U.Le(U.Zd(U.Zd(U.Zd(0,z),y),x))},
 $isHB:true},
 ma:{
@@ -13892,8 +13908,8 @@
 x=U.b1(this.re)
 return U.Le(U.Zd(U.Zd(U.Zd(0,z),y),x))},
 $isNb:true},
-xs:{
-"^":"Tp:67;",
+VU:{
+"^":"Tp:69;",
 $2:function(a,b){return U.Zd(a,J.v1(b))},
 $isEH:true}}],["polymer_expressions.parser","package:polymer_expressions/parser.dart",,T,{
 "^":"",
@@ -13958,7 +13974,7 @@
 if(!x)break
 y=this.tF(y,this.vi.lo.gP9())}x=J.Vm(z)
 this.rp.toString
-return new U.Mp(x,a,y)},
+return new U.zb(x,a,y)},
 Yq:function(){var z,y,x,w
 if(J.xC(J.Iz(this.vi.lo),8)){z=J.Vm(this.vi.lo)
 y=J.x(z)
@@ -14073,7 +14089,7 @@
 return y},
 Xk:function(){return this.u3("")}}}],["polymer_expressions.src.globals","package:polymer_expressions/src/globals.dart",,K,{
 "^":"",
-Dc:[function(a){return H.VM(new K.Bt(a),[null])},"$1","G5",2,0,61,62],
+Dc:[function(a){return H.VM(new K.Bt(a),[null])},"$1","G5",2,0,63,64],
 O1:{
 "^":"a;vH>,P>",
 n:function(a,b){if(b==null)return!1
@@ -14208,12 +14224,12 @@
 "^":"",
 Jg:{
 "^":"a;",
-DV:[function(a){return J.okV(a,this)},"$1","gnG",2,0,159,138]},
+DV:[function(a){return J.okV(a,this)},"$1","gnG",2,0,161,138]},
 cfS:{
 "^":"Jg;",
 xn:function(a){},
 W9:function(a){this.xn(a)},
-LT:function(a){a.wz.RR(0,this)
+Hs:function(a){a.wz.RR(0,this)
 this.xn(a)},
 fV:function(a){J.okV(a.ghP(),this)
 this.xn(a)},
@@ -14242,7 +14258,7 @@
 this.xn(a)},
 RD:function(a){J.okV(a.gdc(),this)
 J.okV(a.gSl(),this)
-J.okV(a.gru(),this)
+J.okV(a.gCW(),this)
 this.xn(a)},
 ky:function(a){J.okV(a.gBb(a),this)
 J.okV(a.gT8(a),this)
@@ -14285,13 +14301,13 @@
 fX:[function(a,b){this.Kn(a)},"$1","gIF",2,0,17,54],
 xx:[function(a,b){this.ct(a,C.SA,0,1)
 this.ct(a,C.wq,0,1)},"$1","gTA",2,0,10,54],
-fT:[function(a,b){var z,y
+Jf:[function(a,b){var z,y
 z=a.Ny
 if(z==null||a.FZ!==!0)return"min-width:32px;"
 y=z.gu9().Zp.t(0,b.gRd())
 if(y==null)return"min-width:32px;"
 if(J.xC(y,0))return"min-width:32px;background-color:red"
-return"min-width:32px;background-color:green"},"$1","gL0",2,0,160,161],
+return"min-width:32px;background-color:green"},"$1","gL0",2,0,162,163],
 Kn:function(a){var z,y,x,w,v
 if(J.iS(a.Ny)!==!0){J.SK(a.Ny).ml(new T.Wd(a))
 return}this.ct(a,C.SA,0,1)
@@ -14379,8 +14395,8 @@
 if(z==null)return
 J.SK(z)},
 ii:[function(a,b){J.qA((a.shadowRoot||a.webkitShadowRoot).querySelector("#scriptInset"),a.HJ)},"$1","gVU",2,0,10,54],
-RF:[function(a,b){J.LE(a.Uz).wM(b)},"$1","gvC",2,0,17,82],
-j9:[function(a,b){J.y9(J.aT(a.Uz)).wM(b)},"$1","gWp",2,0,17,82],
+RF:[function(a,b){J.LE(a.Uz).wM(b)},"$1","gvC",2,0,17,84],
+j9:[function(a,b){J.y9(J.aT(a.Uz)).wM(b)},"$1","gWp",2,0,17,84],
 static:{TXt:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -14528,7 +14544,7 @@
 if(J.xC(this.r0,""))return P.PG(this,null)
 if(this.Sa&&this.gfS())return P.PG(this,null)
 z=this.VR
-if(z==null){z=this.gwv(this).HL(this.gPj(this)).ml(new D.Pa(this)).wM(new D.jI(this))
+if(z==null){z=this.gwv(this).HL(this.gPj(this)).ml(new D.Pa(this)).wM(new D.Jt(this))
 this.VR=z}return z},
 eC:function(a){var z,y,x,w
 z=J.U6(a)
@@ -14542,7 +14558,7 @@
 this.bF(0,a,y)},
 $isaf:true},
 Pa:{
-"^":"Tp:163;a",
+"^":"Tp:165;a",
 $1:[function(a){var z,y
 z=J.UQ(a,"type")
 y=J.rY(z)
@@ -14550,10 +14566,10 @@
 y=this.a
 if(!J.xC(z,y.mQ))return D.hi(y.Jz,a)
 y.eC(a)
-return y},"$1",null,2,0,null,162,"call"],
+return y},"$1",null,2,0,null,164,"call"],
 $isEH:true},
-jI:{
-"^":"Tp:64;b",
+Jt:{
+"^":"Tp:66;b",
 $0:[function(){this.b.VR=null},"$0",null,0,0,null,"call"],
 $isEH:true},
 fz:{
@@ -14607,7 +14623,7 @@
 return this.Tn(x).ml(new D.lb(this,w))}v=this.Qy.t(0,z.a)
 if(v!=null)return J.LE(v)
 return this.HL(z.a).ml(new D.aEE(z,this))},
-nJ:[function(a,b){return b},"$2","ge1",4,0,67],
+nJ:[function(a,b){return b},"$2","ge1",4,0,69],
 ng:function(a){var z,y,x
 z=null
 try{y=new P.Cf(this.ge1())
@@ -14658,7 +14674,7 @@
 MZ:{
 "^":"Tp:10;a,b",
 $1:[function(a){if(!J.x(a).$iswv)return
-return this.a.z7.t(0,this.b)},"$1",null,2,0,null,109,"call"],
+return this.a.z7.t(0,this.b)},"$1",null,2,0,null,110,"call"],
 $isEH:true},
 lb:{
 "^":"Tp:10;b,c",
@@ -14669,15 +14685,15 @@
 else return a.cv(z)},"$1",null,2,0,null,4,"call"],
 $isEH:true},
 aEE:{
-"^":"Tp:163;a,d",
+"^":"Tp:165;a,d",
 $1:[function(a){var z,y
 z=this.d
 y=D.hi(z,a)
 if(y.gUm())z.Qy.to(this.a.a,new D.zK(y))
-return y},"$1",null,2,0,null,162,"call"],
+return y},"$1",null,2,0,null,164,"call"],
 $isEH:true},
 zK:{
-"^":"Tp:64;e",
+"^":"Tp:66;e",
 $0:function(){return this.e},
 $isEH:true},
 zA:{
@@ -14689,7 +14705,7 @@
 P.FL("Hit V8 bug.")
 w=P.EF(["type","ServiceException","id","","kind","DecodeException","response","This is likely a result of a known V8 bug. Although the the bug has been fixed the fix may not be in your Chrome version. For more information see dartbug.com/18385. Observatory is still functioning and you should try your action again.","message","Could not decode JSON: "+H.d(y)],null,null)
 w=R.tB(w)
-return P.Vu(D.hi(this.a,w),null,null)}return this.a.N7(z)},"$1",null,2,0,null,112,"call"],
+return P.Vu(D.hi(this.a,w),null,null)}return this.a.N7(z)},"$1",null,2,0,null,113,"call"],
 $isEH:true},
 tm:{
 "^":"Tp:10;b",
@@ -14707,14 +14723,14 @@
 $1:[function(a){var z=this.c.Li
 if(z.Gv>=4)H.vh(z.q7())
 z.Iv(a)
-return P.Vu(a,null,null)},"$1",null,2,0,null,75,"call"],
+return P.Vu(a,null,null)},"$1",null,2,0,null,77,"call"],
 $isEH:true},
 hc:{
 "^":"Tp:10;",
 $1:[function(a){return!!J.x(a).$isEP},"$1",null,2,0,null,1,"call"],
 $isEH:true},
 Hq:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){J.LE(b)},
 $isEH:true},
 ER:{
@@ -14794,7 +14810,7 @@
 gn0:function(){return this.zG},
 gwg:function(){return this.XV},
 Mq:function(a){return H.d(this.r0)+"/"+H.d(a)},
-xQ:[function(a){return"#/"+(H.d(this.r0)+"/"+H.d(a))},"$1","gw6",2,0,164,165],
+xQ:[function(a){return"#/"+(H.d(this.r0)+"/"+H.d(a))},"$1","gw6",2,0,166,167],
 N3:function(a){var z,y,x,w
 z=H.VM([],[D.kx])
 y=J.U6(a)
@@ -14811,8 +14827,8 @@
 x=z.t(a,"samples")
 for(z=J.mY(y);z.G();){w=z.gl()
 J.UQ(w,"code").eL(w,b,x)}},
-lh:[function(a){return this.cv("coverage").ml(this.gJJ())},"$0","gWp",0,0,166],
-cNN:[function(a){J.kH(J.UQ(a,"coverage"),new D.Yb(this))},"$1","gJJ",2,0,167,168],
+lh:[function(a){return this.cv("coverage").ml(this.gJJ())},"$0","gWp",0,0,168],
+cNN:[function(a){J.kH(J.UQ(a,"coverage"),new D.Yb(this))},"$1","gJJ",2,0,169,170],
 Qn:function(a){var z,y,x
 if(a==null)return
 z=J.UQ(a,"id")
@@ -14973,37 +14989,37 @@
 Yb:{
 "^":"Tp:10;a",
 $1:[function(a){var z=J.U6(a)
-z.t(a,"script").vW(z.t(a,"hits"))},"$1",null,2,0,null,169,"call"],
+z.t(a,"script").SC(z.t(a,"hits"))},"$1",null,2,0,null,171,"call"],
 $isEH:true},
 KQ:{
-"^":"Tp:163;a,b",
+"^":"Tp:165;a,b",
 $1:[function(a){var z,y
 z=this.a
 y=D.hi(z,a)
 if(y.gUm())z.Qy.to(this.b,new D.Ng(y))
-return y},"$1",null,2,0,null,162,"call"],
+return y},"$1",null,2,0,null,164,"call"],
 $isEH:true},
 Ng:{
-"^":"Tp:64;c",
+"^":"Tp:66;c",
 $0:function(){return this.c},
 $isEH:true},
 Qq:{
 "^":"Tp:10;a",
 $1:[function(a){var z=J.U6(a)
-this.a.u(0,z.t(a,"name"),z.t(a,"time"))},"$1",null,2,0,null,170,"call"],
+this.a.u(0,z.t(a,"name"),z.t(a,"time"))},"$1",null,2,0,null,172,"call"],
 $isEH:true},
 hU:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.oE(J.O6(a),J.O6(b))},
 $isEH:true},
 AP:{
-"^":"Tp:163;a",
+"^":"Tp:165;a",
 $1:[function(a){var z,y
 z=Date.now()
 new P.iP(z,!1).EK()
 y=this.a.GH
 y.xZ(z/1000,a)
-return y},"$1",null,2,0,null,126,"call"],
+return y},"$1",null,2,0,null,127,"call"],
 $isEH:true},
 vO:{
 "^":"af;Ce,Jz,r0,mQ,Sa,px,t7,VR,AP,fn",
@@ -15037,7 +15053,7 @@
 gB:function(a){var z=this.Ce.Zp
 return z.gB(z)},
 HC:[function(a){var z=this.Ce
-return z.HC(z)},"$0","gDx",0,0,94],
+return z.HC(z)},"$0","gDx",0,0,96],
 nq:function(a,b){var z=this.Ce
 return z.nq(z,b)},
 ct:function(a,b,c,d){return F.Wi(this.Ce,b,c,d)},
@@ -15244,7 +15260,7 @@
 this.nq(this,r)}this.lx=u}this.y6.u(0,t,w)
 this.FB.u(0,t,s)
 v+=2}}},
-vW:function(a){var z,y,x,w
+SC:function(a){var z,y,x,w
 z=J.U6(a)
 y=this.u9
 x=0
@@ -15280,7 +15296,7 @@
 z=this.Ix
 y=J.x(z)
 if(y.n(z,-1))return"N/A"
-return y.bu(z)},"$0","gkA",0,0,171],
+return y.bu(z)},"$0","gkA",0,0,173],
 bR:function(a){var z,y
 this.ar=F.Wi(this,C.PX,this.ar,null)
 z=this.VF
@@ -15300,18 +15316,18 @@
 z=this.Yu
 y=J.x(z)
 if(y.n(z,0))return""
-return"0x"+y.WZ(z,16)},"$0","gZd",0,0,171],
+return"0x"+y.WZ(z,16)},"$0","gZd",0,0,173],
 io:[function(a){var z
 if(a==null)return""
 z=a.gOo().Zp.t(0,this.Yu)
 if(z==null)return""
 if(J.xC(z.gfF(),z.gDu()))return""
-return D.Tn(z.gfF(),a.glt())+" ("+H.d(z.gfF())+")"},"$1","gcQ",2,0,172,66],
+return D.Tn(z.gfF(),a.glt())+" ("+H.d(z.gfF())+")"},"$1","gcQ",2,0,174,68],
 HU:[function(a){var z
 if(a==null)return""
 z=a.gOo().Zp.t(0,this.Yu)
 if(z==null)return""
-return D.Tn(z.gDu(),a.glt())+" ("+H.d(z.gDu())+")"},"$1","gGK",2,0,172,66],
+return D.Tn(z.gDu(),a.glt())+" ("+H.d(z.gDu())+")"},"$1","gGK",2,0,174,68],
 eQ:function(){var z,y,x,w
 y=J.uH(this.L4," ")
 x=y.length
@@ -15371,7 +15387,7 @@
 gfS:function(){return!0},
 tx:[function(a){var z,y
 this.ar=F.Wi(this,C.PX,this.ar,a)
-for(z=this.va,z=z.gA(z);z.G();)for(y=z.lo.guH(),y=y.gA(y);y.G();)y.lo.bR(a)},"$1","guL",2,0,173,174],
+for(z=this.va,z=z.gA(z);z.G();)for(y=z.lo.guH(),y=y.gA(y);y.G();)y.lo.bR(a)},"$1","guL",2,0,175,176],
 OF:function(){if(this.ar!=null)return
 if(!J.xC(this.I0,C.l8))return
 var z=this.MO
@@ -15482,10 +15498,10 @@
 z=this.a
 y=J.UQ(z.MO,"script")
 if(y==null)return
-J.SK(y).ml(z.guL())},"$1",null,2,0,null,175,"call"],
+J.SK(y).ml(z.guL())},"$1",null,2,0,null,177,"call"],
 $isEH:true},
 fx:{
-"^":"Tp:67;",
+"^":"Tp:69;",
 $2:function(a,b){return J.Hn(b.gAv(),a.gAv())},
 $isEH:true},
 l8R:{
@@ -15551,7 +15567,7 @@
 "^":"af+Pi;",
 $isd3:true},
 Qf:{
-"^":"Tp:67;a,b",
+"^":"Tp:69;a,b",
 $2:function(a,b){var z,y
 z=J.x(b)
 y=!!z.$isqC
@@ -15600,34 +15616,79 @@
 "^":"uL+Pi;",
 $isd3:true}}],["service_html","package:observatory/service_html.dart",,U,{
 "^":"",
-XK:{
-"^":"wv;Jf,Ox,GY,RW,Ts,Va,Li,G2,Qy,z7,AP,fn,Jz,r0,mQ,Sa,px,t7,VR,AP,fn",
-z6:function(a,b){var z
-N.QM("").To("Fetching "+H.d(b)+" from "+H.d(this.Jf))
-z=this.Jf
-if(typeof z!=="string")return z.g()
-return W.It(J.ew(z,b),null,null).OA(new U.dT())},
-SC:function(){this.Jf="http://"+H.d(window.location.host)+"/"}},
-dT:{
-"^":"Tp:10;",
-$1:[function(a){var z
-N.QM("").YX("HttpRequest.getString failed.")
-z=J.RE(a)
-z.gN(a)
-return C.xr.KP(P.EF(["type","ServiceException","id","","response",J.Du(z.gN(a)),"kind","NetworkException","message","Could not connect to service. Check that you started the VM with the following flags:\n --enable-vm-service --pause-isolates-on-exit"],null,null))},"$1",null,2,0,null,21,"call"],
+KM:{
+"^":"wv;S3,yb,xV,DA,Ox,GY,RW,Ts,Va,Li,G2,Qy,z7,AP,fn,Jz,r0,mQ,Sa,px,t7,VR,AP,fn",
+H4:[function(a){var z,y,x,w,v
+z=C.xr.kV(J.Qd(a))
+y=J.U6(z)
+x=y.t(z,"seq")
+w=y.t(z,"response")
+v=this.S3.Rz(0,x)
+if(v==null)N.QM("").YX("Received unexpected message: "+H.d(z))
+else J.KD(v,w)},"$1","gqF",2,0,178,78],
+z6:function(a,b){var z=this.DA
+if(z==null)return P.PG(C.xr.KP(P.EF(["type","ServiceException","id","","response","","kind","NetworkException","message","Could not connect to service. Check that you started the VM with the following flags:\n --enable-vm-service --pause-isolates-on-exit"],null,null)),null)
+return z.ml(new U.N5(this,b))},
+ru:function(){var z,y,x
+this.xV="ws://"+H.d(window.location.host)+"/ws"
+z=W.lf
+y=H.VM(new P.Zf(P.Dt(z)),[z])
+this.DA=y.MM
+x=W.pS(this.xV,null)
+z=H.VM(new W.RO(x,C.Mp.Ph,!1),[null])
+z.geK(z).ml(new U.Lu(this,y,x))
+z=H.VM(new W.RO(x,C.MD.Ph,!1),[null])
+z.geK(z).ml(new U.VO(this))},
+static:{bU:function(){var z=new U.KM(P.L5(null,null,null,P.KN,P.oh),0,null,null,"unknown","unknown",0,!1,!1,P.bK(null,null,!1,null),P.bK(null,null,!1,null),P.L5(null,null,null,P.qU,D.af),P.L5(null,null,null,P.qU,D.bv),null,null,null,null,null,!1,null,null,null,null,null)
+z.md()
+z.ru()
+return z}}},
+Lu:{
+"^":"Tp:10;a,b,c",
+$1:[function(a){var z,y,x
+z=this.c
+y=H.VM(new W.RO(z,C.ph.Ph,!1),[null])
+x=this.a
+H.VM(new W.fd(0,y.bi,y.Ph,W.aF(x.gqF()),y.Sg),[H.Kp(y,0)]).Zz()
+y=H.VM(new W.RO(z,C.d6.Ph,!1),[null])
+y.geK(y).ml(new U.jI(x))
+y=this.b.MM
+if(y.Gv!==0)H.vh(P.w("Future already completed"))
+y.OH(z)},"$1",null,2,0,null,11,"call"],
+$isEH:true},
+jI:{
+"^":"Tp:10;d",
+$1:[function(a){this.d.DA=null},"$1",null,2,0,null,11,"call"],
+$isEH:true},
+VO:{
+"^":"Tp:10;e",
+$1:[function(a){this.e.DA=null},"$1",null,2,0,null,11,"call"],
+$isEH:true},
+N5:{
+"^":"Tp:10;a,b",
+$1:[function(a){var z,y,x,w,v
+z=this.a
+y=z.yb++
+x=this.b
+if(!J.RY(x,"/profile/tag"))N.QM("").To("Fetching "+H.d(x)+" from "+H.d(z.xV))
+w=P.qU
+v=H.VM(new P.Zf(P.Dt(w)),[w])
+z.S3.u(0,y,v)
+J.m9(a,C.xr.KP(P.EF(["seq",y,"request",x],null,null)))
+return v.MM},"$1",null,2,0,null,179,"call"],
 $isEH:true},
 bl:{
-"^":"wv;ba,yb,Ox,GY,RW,Ts,Va,Li,G2,Qy,z7,AP,fn,Jz,r0,mQ,Sa,px,t7,VR,AP,fn",
+"^":"wv;S3,yb,Ox,GY,RW,Ts,Va,Li,G2,Qy,z7,AP,fn,Jz,r0,mQ,Sa,px,t7,VR,AP,fn",
 q3:[function(a){var z,y,x,w,v
 z=J.RE(a)
 y=J.UQ(z.gRn(a),"id")
 x=J.UQ(z.gRn(a),"name")
 w=J.UQ(z.gRn(a),"data")
 if(!J.xC(x,"observatoryData"))return
-z=this.ba
+z=this.S3
 v=z.t(0,y)
 z.Rz(0,y)
-J.KD(v,w)},"$1","gVx",2,0,17,176],
+J.KD(v,w)},"$1","gVx",2,0,17,180],
 z6:function(a,b){var z,y,x
 z=""+this.yb
 y=P.Fl(null,null)
@@ -15635,7 +15696,7 @@
 y.u(0,"method","observatoryQuery")
 y.u(0,"query","/"+H.d(b));++this.yb
 x=H.VM(new P.Zf(P.Dt(null)),[null])
-this.ba.u(0,z,x)
+this.S3.u(0,z,x)
 J.vI(W.Pv(window.parent),C.xr.KP(y),"*")
 return x.MM},
 PI:function(){var z=H.VM(new W.RO(window,C.ph.Ph,!1),[null])
@@ -15808,7 +15869,7 @@
 gRY:function(a){return a.bP},
 sRY:function(a,b){a.bP=this.ct(a,C.zU,a.bP,b)},
 RC:[function(a,b,c,d){var z=J.K0((a.shadowRoot||a.webkitShadowRoot).querySelector("#slide-switch"))
-a.kF=this.ct(a,C.bk,a.kF,z)},"$3","gQU",6,0,86,1,177,88],
+a.kF=this.ct(a,C.bk,a.kF,z)},"$3","gQU",6,0,88,1,181,90],
 static:{Al:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -15986,7 +16047,7 @@
 z.Ut(a)
 return z}}},
 Fi:{
-"^":"Tp:67;a",
+"^":"Tp:69;a",
 $2:function(a,b){this.a.I1.u(0,b,a)},
 $isEH:true},
 tk:{
@@ -16018,8 +16079,8 @@
 "^":"V46;ju,AP,fn,AP,fn,a6,nh,q9,YE,JB,on,BA,LL",
 gtN:function(a){return a.ju},
 stN:function(a,b){a.ju=this.ct(a,C.kw,a.ju,b)},
-RF:[function(a,b){J.LE(a.ju).wM(b)},"$1","gvC",2,0,17,82],
-static:{HI:function(a){var z,y,x,w
+RF:[function(a,b){J.LE(a.ju).wM(b)},"$1","gvC",2,0,17,84],
+static:{lt:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
 x=P.qU
@@ -16215,7 +16276,7 @@
 J.Fc(t.gvt(),y)}},"$1","ge2",2,0,17,55]},
 WF:{
 "^":"Tp:10;a,b,c",
-$1:[function(a){return M.AD(this.b.grF(),this.a.a,this.c,a)},"$1",null,2,0,null,137,"call"],
+$1:[function(a){return M.AD(this.b.grF(),this.a.a,this.c,a)},"$1",null,2,0,null,62,"call"],
 $isEH:true},
 b2:{
 "^":"Ap;rF<,E3,vt<,jS",
@@ -16264,7 +16325,7 @@
 return x.ev(x,new M.qx(a))}},bC:function(a){if(typeof a==="string")return H.BU(a,null,new M.LG())
 return typeof a==="number"&&Math.floor(a)===a?a:0}}},
 YJG:{
-"^":"Tp:64;",
+"^":"Tp:66;",
 $0:function(){var z,y,x,w,v
 z=document.createElement("div",null).appendChild(W.ED(null))
 y=J.RE(z)
@@ -16515,7 +16576,7 @@
 $1:function(a){return this.c.pm(a,this.a,this.b)},
 $isEH:true},
 NW:{
-"^":"Tp:67;a,b,c,d",
+"^":"Tp:69;a,b,c,d",
 $2:function(a,b){var z,y,x,w
 for(;z=J.U6(a),J.xC(z.t(a,0),"_");)a=z.yn(a,1)
 if(this.d)z=z.n(a,"bind")||z.n(a,"if")||z.n(a,"repeat")
@@ -16657,7 +16718,7 @@
 j=v
 if(j==null)H.vh(P.u("Error must not be null"))
 if(k.Gv!==0)H.vh(P.w("Future already completed"))
-k.CG(j,u)}g=null}this.uy(i,x,g,w)}}for(t=p.gUQ(p),t=H.VM(new H.MH(null,J.mY(t.l6),t.T6),[H.Kp(t,0),H.Kp(t,1)]);t.G();)this.Ep(t.lo.gpp())},"$1","gk8",2,0,178,179],
+k.CG(j,u)}g=null}this.uy(i,x,g,w)}}for(t=p.gUQ(p),t=H.VM(new H.MH(null,J.mY(t.l6),t.T6),[H.Kp(t,0),H.Kp(t,1)]);t.G();)this.Ep(t.lo.gpp())},"$1","gk8",2,0,182,183],
 Ep:function(a){var z
 for(z=J.mY(a);z.G();)J.x0(z.gl())},
 Ke:function(){var z=this.VC
@@ -16744,7 +16805,7 @@
 x=z.length
 w=C.jn.cU(x,4)*4
 if(w>=x)return H.e(z,w)
-return y+H.d(z[w])},"$1","gzf",2,0,180,18],
+return y+H.d(z[w])},"$1","gzf",2,0,184,18],
 cH:[function(a){var z,y,x,w,v,u,t,s
 z=this.jU
 if(0>=z.length)return H.e(z,0)
@@ -16755,7 +16816,7 @@
 t=v*4
 if(t>=z.length)return H.e(z,t)
 s=z[t]
-y.vM+=typeof s==="string"?s:H.d(s)}return y.vM},"$1","gB5",2,0,181,182],
+y.vM+=typeof s==="string"?s:H.d(s)}return y.vM},"$1","gB5",2,0,185,186],
 l3:function(a,b){this.V6=this.jU.length===5?this.gzf():this.gB5()},
 static:{"^":"rz5,jO,t3a,epG,oM,Ftg",iw:function(a,b){var z,y,x,w,v,u,t,s,r,q,p,o,n,m
 if(a==null||a.length===0)return
@@ -16796,8 +16857,8 @@
 a.on=z
 a.BA=y
 a.LL=w
-C.u2.ZL(a)
-C.u2.XI(a)
+C.V8.ZL(a)
+C.V8.XI(a)
 return a}}}}],["vm_view_element","package:observatory/src/elements/vm_view.dart",,U,{
 "^":"",
 el:{
@@ -16806,7 +16867,7 @@
 swv:function(a,b){a.uB=this.ct(a,C.RJ,a.uB,b)},
 gkc:function(a){return a.lc},
 skc:function(a,b){a.lc=this.ct(a,C.yh,a.lc,b)},
-RF:[function(a,b){J.LE(a.uB).wM(b)},"$1","gvC",2,0,17,82],
+RF:[function(a,b){J.LE(a.uB).wM(b)},"$1","gvC",2,0,17,84],
 static:{oH:function(a){var z,y,x,w
 z=$.XZ()
 y=P.YM(null,null,null,P.qU,W.I0)
@@ -16873,15 +16934,14 @@
 U.ma.$isa=true
 U.HB.$ishw=true
 U.HB.$isa=true
-U.Mp.$ishw=true
-U.Mp.$isa=true
+U.zb.$ishw=true
+U.zb.$isa=true
 U.x9.$ishw=true
 U.x9.$isa=true
 U.no.$ishw=true
 U.no.$isa=true
 U.cJ.$ishw=true
 U.cJ.$isa=true
-U.elO.$iselO=true
 U.elO.$ishw=true
 U.elO.$isa=true
 U.c0.$ishw=true
@@ -16923,10 +16983,17 @@
 A.dM.$ish4=true
 A.dM.$isKV=true
 A.dM.$isa=true
+P.oh.$isa=true
 D.af.$isaf=true
 D.af.$isa=true
 D.bv.$isaf=true
 D.bv.$isa=true
+W.lf.$isa=true
+W.AW.$isAW=true
+W.AW.$isea=true
+W.AW.$isa=true
+W.K3.$isea=true
+W.K3.$isa=true
 D.ta.$isa=true
 D.ER.$isa=true
 D.DP.$isa=true
@@ -16945,16 +17012,11 @@
 D.vO.$isa=true
 D.c2.$isc2=true
 D.c2.$isa=true
-W.fJ.$isa=true
-W.kQ.$isea=true
-W.kQ.$isa=true
 D.kx.$iskx=true
 D.kx.$isaf=true
 D.kx.$isa=true
 D.t9.$isa=true
 D.HJ.$isa=true
-W.AW.$isea=true
-W.AW.$isa=true
 N.HV.$isHV=true
 N.HV.$isa=true
 H.yo.$isa=true
@@ -16968,8 +17030,8 @@
 G.Ni.$isa=true
 P.qK.$isqK=true
 P.qK.$isa=true
-P.xp.$isxp=true
-P.xp.$isa=true
+P.dl.$isdl=true
+P.dl.$isa=true
 P.mE.$ismE=true
 P.mE.$isa=true
 P.KA.$isKA=true
@@ -17084,7 +17146,6 @@
 J.Do=function(a){return J.RE(a).gM0(a)}
 J.Dq=function(a,b){return J.w1(a).Rz(a,b)}
 J.Ds=function(a){return J.RE(a).gPj(a)}
-J.Du=function(a){return J.RE(a).gxN(a)}
 J.E3=function(a){return J.RE(a).gRu(a)}
 J.EC=function(a){return J.RE(a).giC(a)}
 J.EJ=function(a,b){return J.RE(a).sCf(a,b)}
@@ -17337,7 +17398,6 @@
 J.l7=function(a,b){return J.RE(a).sv8(a,b)}
 J.lB=function(a){return J.RE(a).guT(a)}
 J.lT=function(a){return J.RE(a).gOd(a)}
-J.lf=function(a,b){return J.Wx(a).O(a,b)}
 J.ls=function(a){return J.RE(a).gt3(a)}
 J.m4=function(a){return J.RE(a).gig(a)}
 J.m9=function(a,b){return J.RE(a).wR(a,b)}
@@ -17427,6 +17487,7 @@
 J.xW=function(a,b){return J.RE(a).sZm(a,b)}
 J.xa=function(a){return J.RE(a).geS(a)}
 J.xq=function(a,b){return J.w1(a).Vr(a,b)}
+J.xs=function(a,b){return J.Wx(a).O(a,b)}
 J.y2=function(a,b){return J.RE(a).mx(a,b)}
 J.y9=function(a){return J.RE(a).lh(a)}
 J.yA=function(a){return J.RE(a).gvu(a)}
@@ -17526,7 +17587,7 @@
 C.wB=X.uw.prototype
 C.lx=A.G1.prototype
 C.vB=J.kdQ.prototype
-C.u2=X.I5.prototype
+C.V8=X.I5.prototype
 C.bV=U.el.prototype
 C.KZ=new H.hJ()
 C.x4=new U.WH()
@@ -17559,8 +17620,8 @@
 C.ZQ=new A.ES(C.rB,C.BM,!1,C.Ks,!1,C.XVh)
 C.Ms=new H.GD("iconClass")
 C.Db=H.IL('qU')
-C.mI=new K.ndx()
-C.y0=I.ko([C.NS,C.mI])
+C.J19=new K.ndx()
+C.y0=I.ko([C.NS,C.J19])
 C.Gl=new A.ES(C.Ms,C.BM,!1,C.Db,!1,C.y0)
 C.VK=new H.GD("devtools")
 C.BQ=H.IL('a2')
@@ -17632,8 +17693,8 @@
 C.mr=new H.GD("expanded")
 C.DC=new A.ES(C.mr,C.BM,!1,C.BQ,!1,C.y0)
 C.j2=new H.GD("app")
-C.oP=H.IL('mL')
-C.zJ=new A.ES(C.j2,C.BM,!1,C.oP,!1,C.XVh)
+C.jY=H.IL('mL')
+C.zJ=new A.ES(C.j2,C.BM,!1,C.jY,!1,C.XVh)
 C.xP=new H.GD("ref")
 C.hI=new A.ES(C.xP,C.BM,!1,C.SmN,!1,C.XVh)
 C.jU=new H.GD("file")
@@ -17664,8 +17725,8 @@
 C.UY=new H.GD("result")
 C.rT=new A.ES(C.UY,C.BM,!1,C.SmN,!1,C.XVh)
 C.PX=new H.GD("script")
-C.KB=H.IL('vx')
-C.Cj=new A.ES(C.PX,C.BM,!1,C.KB,!1,C.XVh)
+C.c3=H.IL('vx')
+C.Cj=new A.ES(C.PX,C.BM,!1,C.c3,!1,C.XVh)
 C.S4=new H.GD("busy")
 C.FB=new A.ES(C.S4,C.BM,!1,C.BQ,!1,C.y0)
 C.AO=new H.GD("qualifiedName")
@@ -17748,7 +17809,7 @@
 C.Tt=new A.ES(C.Lc,C.BM,!1,C.Db,!1,C.XVh)
 C.YE=new H.GD("webSocket")
 C.Xt=new A.ES(C.YE,C.BM,!1,C.MR1,!1,C.XVh)
-C.ng=I.ko([C.mI])
+C.ng=I.ko([C.J19])
 C.Qs=new A.ES(C.i4,C.BM,!0,C.nq,!1,C.ng)
 C.lH=new H.GD("checkedText")
 C.A5=new A.ES(C.lH,C.BM,!1,C.Db,!1,C.XVh)
@@ -17764,13 +17825,14 @@
 C.ny=new P.a6(0)
 C.U3=H.VM(new W.FkO("change"),[W.ea])
 C.nI=H.VM(new W.FkO("click"),[W.Oq])
-C.MD=H.VM(new W.FkO("error"),[W.kQ])
+C.d6=H.VM(new W.FkO("close"),[W.K3])
+C.MD=H.VM(new W.FkO("error"),[W.ea])
 C.yZ=H.VM(new W.FkO("hashchange"),[W.ea])
 C.i3=H.VM(new W.FkO("input"),[W.ea])
-C.LF=H.VM(new W.FkO("load"),[W.kQ])
 C.ph=H.VM(new W.FkO("message"),[W.AW])
 C.uh=H.VM(new W.FkO("mousedown"),[W.Oq])
 C.Kq=H.VM(new W.FkO("mousemove"),[W.Oq])
+C.Mp=H.VM(new W.FkO("open"),[W.ea])
 C.mp=function(hooks) {
   if (typeof dartExperimentalFixupGetTag != "function") return hooks;
   hooks.getTag = dartExperimentalFixupGetTag(hooks.getTag);
@@ -18220,7 +18282,7 @@
 $.UG=!0
 $.RQ="objects/"
 $.vU=null
-$.Au=[C.tq,W.Bo,{},C.k5,Z.hx,{created:Z.BN},C.hP,E.uz,{created:E.fr},C.Mf,A.G1,{created:A.J8},C.q0S,H.Dg,{"":H.jZN},C.Dl,V.F1,{created:V.Lu},C.Jf,E.Mb,{created:E.pD},C.UJ,N.oa,{created:N.IB},C.Y3,Q.CY,{created:Q.Al},C.j4,D.IW,{created:D.dm},C.Vx,X.MJ,{created:X.Bs},C.Vh,Q.qZ,{created:Q.RH},C.rR,E.wN,{created:E.wZ7},C.yS,B.G6,{created:B.KU},C.z7,D.YA,{created:D.BP},C.Sb,A.kn,{created:A.D2},C.EZ,E.oF,{created:E.J3z},C.vw,A.UK,{created:A.JT},C.Jo,D.i7,{created:D.qb},C.BL,X.Nr,{created:X.na},C.ON,T.ov,{created:T.Zz},C.jR,F.Be,{created:F.f9},C.PT,M.CX,{created:M.as},C.iD,O.Vb,{created:O.pn},C.ce,X.kK,{created:X.os},C.dD,E.av,{created:E.R7},C.FA,A.Ya,{created:A.JR},C.hG,A.ir,{created:A.G7},C.Th,U.fI,{created:U.TXt},C.tU,E.L4,{created:E.p4},C.cK,X.I5,{created:X.cF},C.jA,R.Eg,{created:R.fL},C.K4,X.hV,{created:X.zy},C.xE,Z.aC,{created:Z.zg},C.vu,X.uw,{created:X.HI},C.pJ,E.Q6,{created:E.chF},C.Yy,E.uE,{created:E.eg},C.Yxm,H.Pg,{"":H.KY},C.il,Q.xI,{created:Q.lK},C.lp,R.LU,{created:R.rA},C.oG,E.ds,{created:E.pI},C.TU,D.Oz,{created:D.RP},C.OG,Q.eW,{created:Q.rt},C.km,A.fl,{created:A.zf},C.Tq,Z.vj,{created:Z.M7},C.JW,A.Ww,{created:A.ZC},C.CT,D.St,{created:D.N5},C.wH,R.zM,{created:R.cE},C.l4,Z.uL,{created:Z.EE},C.Wh,E.U1,{created:E.hm},C.Zj,A.md,{created:A.DCi},C.FG,E.qh,{created:E.Sc},C.NR,K.nm,{created:K.qa},C.DD,E.Zn,{created:E.xK},C.qF,E.mO,{created:E.Ch},C.Ey,A.wM,{created:A.GO},C.nX,E.DE,{created:E.oB},C.bh,R.i6,{created:R.IT},C.jRi,H.we,{"":H.ic},C.Xv,E.n5,{created:E.xx},C.KO,F.ZP,{created:F.Yw},C.Wz,B.pR,{created:B.lu},C.Ep,E.ou,{created:E.dv},C.tc,E.Ma,{created:E.Ii},C.Io,D.Qh,{created:D.Qj},C.wk,L.nJ,{created:L.Rp},C.te,N.BS,{created:N.N0},C.ms,A.Bm,{created:A.yU},C.pK,D.Rk,{created:D.dP},C.lE,U.DK,{created:U.E5},C.ri,W.yy,{},C.Az,A.Gk,{created:A.Sy},C.X8,U.Ti,{created:U.lv},C.Lg,R.JI,{created:R.U9},C.Ju,K.Ly,{created:K.Ut},C.mq,L.qk,{created:L.KM},C.XW,W.uEY,{},C.oT,O.VY,{created:O.On},C.jK,U.el,{created:U.oH}]
+$.Au=[C.tq,W.Bo,{},C.k5,Z.hx,{created:Z.BN},C.hP,E.uz,{created:E.fr},C.Mf,A.G1,{created:A.J8},C.q0S,H.Dg,{"":H.jZN},C.Dl,V.F1,{created:V.JT8},C.Jf,E.Mb,{created:E.pD},C.UJ,N.oa,{created:N.IB},C.Y3,Q.CY,{created:Q.Al},C.j4,D.IW,{created:D.dm},C.Vx,X.MJ,{created:X.Bs},C.Vh,Q.qZ,{created:Q.RH},C.rR,E.wN,{created:E.wZ7},C.yS,B.G6,{created:B.KU},C.z7,D.YA,{created:D.BP},C.Sb,A.kn,{created:A.D2},C.EZ,E.oF,{created:E.J3z},C.vw,A.UK,{created:A.JT},C.Jo,D.i7,{created:D.qb},C.BL,X.Nr,{created:X.na},C.ON,T.ov,{created:T.Zz},C.jR,F.Be,{created:F.f9},C.PT,M.CX,{created:M.as},C.iD,O.Vb,{created:O.pn},C.ce,X.kK,{created:X.os},C.dD,E.av,{created:E.R7},C.FA,A.Ya,{created:A.vn},C.hG,A.ir,{created:A.G7},C.Th,U.fI,{created:U.TXt},C.tU,E.L4,{created:E.p4},C.cK,X.I5,{created:X.cF},C.jA,R.Eg,{created:R.fL},C.K4,X.hV,{created:X.zy},C.xE,Z.aC,{created:Z.zg},C.vu,X.uw,{created:X.lt},C.pJ,E.Q6,{created:E.chF},C.Yy,E.uE,{created:E.eg},C.Yxm,H.Pg,{"":H.KY},C.il,Q.xI,{created:Q.lK},C.lp,R.LU,{created:R.rA},C.oG,E.ds,{created:E.pI},C.TU,D.Oz,{created:D.RP},C.OG,Q.eW,{created:Q.rt},C.km,A.fl,{created:A.Du},C.Tq,Z.vj,{created:Z.M7},C.JW,A.Ww,{created:A.ZC},C.CT,D.St,{created:D.JR},C.wH,R.zM,{created:R.cE},C.l4,Z.uL,{created:Z.EE},C.Wh,E.U1,{created:E.hm},C.Zj,A.md,{created:A.DCi},C.FG,E.qh,{created:E.Sc},C.NR,K.nm,{created:K.qa},C.DD,E.Zn,{created:E.xK},C.qF,E.mO,{created:E.Ch},C.Ey,A.wM,{created:A.GO},C.nX,E.DE,{created:E.oB},C.bh,R.i6,{created:R.IT},C.jRi,H.we,{"":H.ic},C.Xv,E.n5,{created:E.xx},C.KO,F.ZP,{created:F.Yw},C.Wz,B.pR,{created:B.lu},C.Ep,E.ou,{created:E.dv},C.tc,E.Ma,{created:E.Ii},C.Io,D.Qh,{created:D.Qj},C.wk,L.nJ,{created:L.Rp},C.te,N.BS,{created:N.N0},C.ms,A.Bm,{created:A.yU},C.pK,D.Rk,{created:D.dP},C.lE,U.DK,{created:U.E5},C.ri,W.yy,{},C.Az,A.Gk,{created:A.Sy},C.X8,U.Ti,{created:U.lv},C.Lg,R.JI,{created:R.U9},C.Ju,K.Ly,{created:K.Ut},C.mq,L.qk,{created:L.Za},C.XW,W.uEY,{},C.oT,O.VY,{created:O.On},C.jK,U.el,{created:U.oH}]
 I.$lazy($,"globalThis","DX","jk",function(){return function(){return this}()})
 I.$lazy($,"globalWindow","UW","My",function(){return $.jk().window})
 I.$lazy($,"globalWorker","uj","nB",function(){return $.jk().Worker})
@@ -18288,8 +18350,8 @@
 I.$lazy($,"_templateCreator","H8","rf",function(){return H.VM(new P.kM(null),[null])})
 I.$lazy($,"_expando","fF","cm",function(){return H.VM(new P.kM("template_binding"),[null])})
 
-init.functionAliases={Sa:183}
-init.metadata=["sender","e",{func:"pL",args:[P.qU]},"closure","isolate","numberOfArguments","arg1","arg2","arg3","arg4",{func:"aB",args:[null]},"_",{func:"Pt",ret:P.qU,args:[P.KN]},"bytes",{func:"RJ",ret:P.qU,args:[null]},{func:"kl",void:true},{func:"n9",void:true,args:[{func:"kl",void:true}]},{func:"G5",void:true,args:[null]},"value",{func:"Mx",void:true,args:[null],opt:[P.mE]},,"error","stackTrace",{func:"cX",void:true,args:[P.xp,P.qK,P.xp,null,P.mE]},"self","parent","zone",{func:"QN",args:[P.xp,P.qK,P.xp,{func:"NT"}]},"f",{func:"wD",args:[P.xp,P.qK,P.xp,{func:"aB",args:[null]},null]},"arg",{func:"ta",args:[P.xp,P.qK,P.xp,{func:"bh",args:[null,null]},null,null]},{func:"HQ",ret:{func:"NT"},args:[P.xp,P.qK,P.xp,{func:"NT"}]},{func:"ie",ret:{func:"aB",args:[null]},args:[P.xp,P.qK,P.xp,{func:"aB",args:[null]}]},{func:"IU",ret:{func:"bh",args:[null,null]},args:[P.xp,P.qK,P.xp,{func:"bh",args:[null,null]}]},{func:"iV",void:true,args:[P.xp,P.qK,P.xp,{func:"NT"}]},{func:"Uk",ret:P.Xa,args:[P.xp,P.qK,P.xp,P.a6,{func:"kl",void:true}]},"duration","callback",{func:"Zb",void:true,args:[P.xp,P.qK,P.xp,P.qU]},{func:"kx",void:true,args:[P.qU]},{func:"Jj",ret:P.xp,args:[P.xp,P.qK,P.xp,P.aY,P.Z0]},{func:"Gl",ret:P.a2,args:[null,null]},"a","b",{func:"bX",ret:P.KN,args:[null]},{func:"uJ",ret:P.a,args:[null]},"object",{func:"xh",ret:P.KN,args:[P.Rz,P.Rz]},{func:"E0",ret:P.a2,args:[P.a,P.a]},{func:"ZY",ret:P.KN,args:[P.a]},"receiver",{func:"wI",args:[null,null,null,null]},"name","oldValue","newValue","captureThis","arguments","o",{func:"Z5",ret:P.a2,args:[P.IN]},"symbol",{func:"qq",ret:[P.QV,K.O1],args:[P.QV]},"iterable","invocation",{func:"NT"},{func:"ob",args:[P.EH]},"code",{func:"bh",args:[null,null]},"key",{func:"Za",args:[P.qU,null]},{func:"TS",args:[null,P.qU]},{func:"Yv",void:true,args:[null,null,null]},"c",{func:"F3",void:true,args:[D.N7]},{func:"GJ",void:true,args:[D.EP]},"exception","event","obj",{func:"qE",ret:P.qU,args:[P.KN,P.KN]},"row","column",{func:"c3",args:[P.KN,P.KN]},"done",{func:"Wr",ret:[P.b8,D.af],args:[P.qU]},"text","dummy",{func:"Np",void:true,args:[W.ea,null,W.KV]},"detail","target",{func:"lQ",args:[D.kx]},"data",{func:"uu",void:true,args:[P.a],opt:[P.mE]},{func:"cq",void:true,opt:[null]},{func:"BG",args:[null],opt:[null]},{func:"Uf",ret:P.a2},"ignored","convert","element",{func:"SF",args:[P.a2]},{func:"a9",void:true,opt:[P.b8]},"resumeSignal",{func:"ha",args:[null,P.mE]},{func:"N5",void:true,args:[null,P.mE]},"each",{func:"lv",args:[P.IN,null]},{func:"jK",ret:P.KN,args:[P.qU]},{func:"cS",ret:P.CP,args:[P.qU]},"xhr",{func:"QO",void:true,args:[W.Oq]},"result",{func:"jH",args:[D.af]},{func:"XG",ret:O.Hz},"response",{func:"Q5",args:[D.vO]},"st",{func:"Sz",void:true,args:[W.ea,null,W.h4]},{func:"xo",ret:P.qU,args:[P.a2]},"newSpace",{func:"rI",args:[P.KN]},{func:"iR",args:[P.KN,null]},{func:"xD",ret:P.QV,args:[{func:"pL",args:[P.qU]}]},{func:"Qd",ret:P.QV,args:[{func:"qt",ret:P.QV,args:[P.qU]}]},{func:"pw",void:true,args:[P.a2,null]},"expand",{func:"KDY",ret:[P.b8,D.af],args:[null]},{func:"Df",ret:P.qU,args:[G.Y2]},"m",{func:"fnh",ret:P.b8,args:[null]},"tagProfile","rec",{func:"IM",args:[N.HV]},{func:"le",ret:P.qU,args:[P.CP]},"time",{func:"h6",ret:P.a2,args:[P.qU]},"type",{func:"Aa",args:[P.qK,P.xp]},{func:"h2",args:[P.xp,P.qK,P.xp,{func:"aB",args:[null]}]},"x","s",{func:"DF",void:true,args:[P.a]},"records",{func:"kk",args:[L.Tv,null]},{func:"qx",void:true,args:[P.qU,P.qU]},{func:"aA",void:true,args:[P.WO,P.Z0,P.WO]},{func:"WW",void:true,args:[W.ea]},"i","changes","model","node","oneTime",{func:"oYt",args:[null,null,null]},{func:"K7",void:true,args:[[P.WO,T.yj]]},"jsElem","extendee",{func:"QP",args:[null,P.qU,P.qU]},"k","v",{func:"ZD",args:[[P.WO,T.yj]]},{func:"Cx",ret:U.zX,args:[U.hw,U.hw]},{func:"Qc",args:[U.hw]},{func:"Yg",ret:P.qU,args:[D.c2]},"line","map",{func:"JC",args:[V.qC]},{func:"If",ret:P.qU,args:[P.qU]},"id",{func:"rl",ret:P.b8},{func:"a0",void:true,args:[D.vO]},"coverage","scriptCoverage","timer",{func:"Br",ret:P.qU},{func:"xA",ret:P.qU,args:[D.kx]},{func:"qQ",void:true,args:[D.vx]},"script","func","msg","details",{func:"PzC",void:true,args:[[P.WO,G.DA]]},"splices",{func:"Vv",ret:P.qU,args:[P.a]},{func:"e3",ret:P.qU,args:[[P.WO,P.a]]},"values",{func:"vl",ret:P.b8,args:[P.qU]},];$=null
+init.functionAliases={Sa:187}
+init.metadata=["sender","e",{func:"pL",args:[P.qU]},"closure","isolate","numberOfArguments","arg1","arg2","arg3","arg4",{func:"aB",args:[null]},"_",{func:"Pt",ret:P.qU,args:[P.KN]},"bytes",{func:"RJ",ret:P.qU,args:[null]},{func:"kl",void:true},{func:"n9",void:true,args:[{func:"kl",void:true}]},{func:"G5",void:true,args:[null]},"value",{func:"Mx",void:true,args:[null],opt:[P.mE]},,"error","stackTrace",{func:"cX",void:true,args:[P.dl,P.qK,P.dl,null,P.mE]},"self","parent","zone",{func:"QN",args:[P.dl,P.qK,P.dl,{func:"NT"}]},"f",{func:"wD",args:[P.dl,P.qK,P.dl,{func:"aB",args:[null]},null]},"arg",{func:"ta",args:[P.dl,P.qK,P.dl,{func:"bh",args:[null,null]},null,null]},{func:"HQ",ret:{func:"NT"},args:[P.dl,P.qK,P.dl,{func:"NT"}]},{func:"ie",ret:{func:"aB",args:[null]},args:[P.dl,P.qK,P.dl,{func:"aB",args:[null]}]},{func:"IU",ret:{func:"bh",args:[null,null]},args:[P.dl,P.qK,P.dl,{func:"bh",args:[null,null]}]},{func:"iV",void:true,args:[P.dl,P.qK,P.dl,{func:"NT"}]},{func:"Uk",ret:P.Xa,args:[P.dl,P.qK,P.dl,P.a6,{func:"kl",void:true}]},"duration","callback",{func:"Zb",void:true,args:[P.dl,P.qK,P.dl,P.qU]},{func:"kx",void:true,args:[P.qU]},{func:"Jj",ret:P.dl,args:[P.dl,P.qK,P.dl,P.aY,P.Z0]},{func:"Gl",ret:P.a2,args:[null,null]},"a","b",{func:"bX",ret:P.KN,args:[null]},{func:"uJ",ret:P.a,args:[null]},"object",{func:"xh",ret:P.KN,args:[P.Rz,P.Rz]},{func:"E0",ret:P.a2,args:[P.a,P.a]},{func:"ZY",ret:P.KN,args:[P.a]},"receiver",{func:"wI",args:[null,null,null,null]},"name","oldValue","newValue","captureThis","arguments","o",{func:"Z5",ret:P.a2,args:[P.IN]},"symbol","v","x",{func:"qq",ret:[P.QV,K.O1],args:[P.QV]},"iterable","invocation",{func:"NT"},{func:"ob",args:[P.EH]},"code",{func:"bh",args:[null,null]},"key",{func:"Za",args:[P.qU,null]},{func:"TS",args:[null,P.qU]},{func:"Yv",void:true,args:[null,null,null]},"c",{func:"F3",void:true,args:[D.N7]},{func:"GJ",void:true,args:[D.EP]},"exception","event","obj",{func:"qE",ret:P.qU,args:[P.KN,P.KN]},"row","column",{func:"c3",args:[P.KN,P.KN]},"done",{func:"Wr",ret:[P.b8,D.af],args:[P.qU]},"text","dummy",{func:"Np",void:true,args:[W.ea,null,W.KV]},"detail","target",{func:"lQ",args:[D.kx]},"data",{func:"uu",void:true,args:[P.a],opt:[P.mE]},{func:"cq",void:true,opt:[null]},{func:"BG",args:[null],opt:[null]},{func:"Uf",ret:P.a2},"ignored","convert","element",{func:"SF",args:[P.a2]},{func:"a9",void:true,opt:[P.b8]},"resumeSignal",{func:"ha",args:[null,P.mE]},{func:"N5",void:true,args:[null,P.mE]},"each",{func:"lv",args:[P.IN,null]},{func:"jK",ret:P.KN,args:[P.qU]},{func:"cS",ret:P.CP,args:[P.qU]},{func:"QO",void:true,args:[W.Oq]},"result",{func:"jH",args:[D.af]},{func:"XG",ret:O.Hz},"response",{func:"Q5",args:[D.vO]},"st",{func:"Sz",void:true,args:[W.ea,null,W.h4]},{func:"xo",ret:P.qU,args:[P.a2]},"newSpace",{func:"rI",args:[P.KN]},{func:"iR",args:[P.KN,null]},{func:"xD",ret:P.QV,args:[{func:"pL",args:[P.qU]}]},{func:"Qd",ret:P.QV,args:[{func:"qt",ret:P.QV,args:[P.qU]}]},{func:"S0",void:true,args:[P.a2,null]},"expand",{func:"KDY",ret:[P.b8,D.af],args:[null]},{func:"Df",ret:P.qU,args:[G.Y2]},"m",{func:"fnh",ret:P.b8,args:[null]},"tagProfile","rec",{func:"IM",args:[N.HV]},{func:"le",ret:P.qU,args:[P.CP]},"time",{func:"h6",ret:P.a2,args:[P.qU]},"type",{func:"Aa",args:[P.qK,P.dl]},{func:"h2",args:[P.dl,P.qK,P.dl,{func:"aB",args:[null]}]},"s",{func:"DF",void:true,args:[P.a]},"records",{func:"kk",args:[L.Tv,null]},{func:"qx",void:true,args:[P.qU,P.qU]},{func:"aA",void:true,args:[P.WO,P.Z0,P.WO]},{func:"WW",void:true,args:[W.ea]},"i","changes","model","node","oneTime",{func:"oYt",args:[null,null,null]},{func:"K7",void:true,args:[[P.WO,T.yj]]},"jsElem","extendee",{func:"QP",args:[null,P.qU,P.qU]},"k",{func:"Hb",args:[null],named:{skipChanges:P.a2}},!1,"skipChanges",{func:"ZD",args:[[P.WO,T.yj]]},{func:"Cx",ret:U.zX,args:[U.hw,U.hw]},{func:"Qc",args:[U.hw]},{func:"Yg",ret:P.qU,args:[D.c2]},"line","map",{func:"JC",args:[V.qC]},{func:"If",ret:P.qU,args:[P.qU]},"id",{func:"rl",ret:P.b8},{func:"a0",void:true,args:[D.vO]},"coverage","scriptCoverage","timer",{func:"Br",ret:P.qU},{func:"xA",ret:P.qU,args:[D.kx]},{func:"qQ",void:true,args:[D.vx]},"script","func",{func:"lb",void:true,args:[W.AW]},"socket","msg","details",{func:"PzC",void:true,args:[[P.WO,G.DA]]},"splices",{func:"Vv",ret:P.qU,args:[P.a]},{func:"e3",ret:P.qU,args:[[P.WO,P.a]]},"values",{func:"vl",ret:P.b8,args:[P.qU]},];$=null
 I = I.$finishIsolateConstructor(I)
 $=new I()
 function convertToFastObject(a){function MyClass(){}MyClass.prototype=a
diff --git a/runtime/bin/vmservice/client/deployed/web/packages/polymer/src/js/polymer/polymer.concat.js.map b/runtime/bin/vmservice/client/deployed/web/packages/polymer/src/js/polymer/polymer.concat.js.map
deleted file mode 100644
index eed265f..0000000
--- a/runtime/bin/vmservice/client/deployed/web/packages/polymer/src/js/polymer/polymer.concat.js.map
+++ /dev/null
@@ -1,60 +0,0 @@
-{
-  "version": 3,
-  "file": "polymer.concat.js",
-  "sources": [
-    "src/polymer.js",
-    "src/boot.js",
-    "src/lib/lang.js",
-    "src/lib/job.js",
-    "src/lib/dom.js",
-    "src/lib/super.js",
-    "src/lib/deserialize.js",
-    "src/api.js",
-    "src/instance/utils.js",
-    "src/instance/events.js",
-    "src/instance/attributes.js",
-    "src/instance/properties.js",
-    "src/instance/mdv.js",
-    "src/instance/base.js",
-    "src/instance/styles.js",
-    "src/declaration/polymer.js",
-    "src/declaration/path.js",
-    "src/declaration/styles.js",
-    "src/declaration/events.js",
-    "src/declaration/properties.js",
-    "src/declaration/attributes.js",
-    "src/declaration/prototype.js",
-    "src/declaration/queue.js",
-    "src/declaration/import.js",
-    "src/declaration/polymer-element.js"
-  ],
-  "names": [],
-  "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;;AC5BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;;AC5FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,Y;AC/CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA",
-  "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 */\nPolymer = {};\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// TODO(sorvell): this ensures Polymer is an object and not a function\n// Platform is currently defining it as a function to allow for async loading\n// of polymer; once we refine the loading process this likely goes away.\nif (typeof window.Polymer === 'function') {\n  Polymer = {};\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  // copy own properties from 'api' to 'prototype, with name hinting for 'super'\n  function extend(prototype, api) {\n    if (prototype && api) {\n      // use only own properties of 'api'\n      Object.getOwnPropertyNames(api).forEach(function(n) {\n        // acquire property descriptor\n        var pd = Object.getOwnPropertyDescriptor(api, n);\n        if (pd) {\n          // clone property via descriptor\n          Object.defineProperty(prototype, n, pd);\n          // cache name-of-method for 'super' engine\n          if (typeof pd.value == 'function') {\n            // hint the 'super' engine\n            pd.value.nom = n;\n          }\n        }\n      });\n    }\n    return prototype;\n  }\n  \n  // exports\n\n  scope.extend = extend;\n\n})(Polymer);\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  // usage\n  \n  // invoke cb.call(this) in 100ms, unless the job is re-registered,\n  // which resets the timer\n  // \n  // this.myJob = this.job(this.myJob, cb, 100)\n  //\n  // returns a job handle which can be used to re-register a job\n\n  var Job = function(inContext) {\n    this.context = inContext;\n    this.boundComplete = this.complete.bind(this)\n  };\n  Job.prototype = {\n    go: function(callback, wait) {\n      this.callback = callback;\n      var h;\n      if (!wait) {\n        h = requestAnimationFrame(this.boundComplete);\n        this.handle = function() {\n          cancelAnimationFrame(h);\n        }\n      } else {\n        h = setTimeout(this.boundComplete, wait);\n        this.handle = function() {\n          clearTimeout(h);\n        }\n      }\n    },\n    stop: function() {\n      if (this.handle) {\n        this.handle();\n        this.handle = null;\n      }\n    },\n    complete: function() {\n      if (this.handle) {\n        this.stop();\n        this.callback.call(this.context);\n      }\n    }\n  };\n  \n  function job(job, callback, wait) {\n    if (job) {\n      job.stop();\n    } else {\n      job = new Job(this);\n    }\n    job.go(callback, wait);\n    return job;\n  }\n  \n  // exports \n\n  scope.job = job;\n  \n})(Polymer);\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  var registry = {};\n\n  HTMLElement.register = function(tag, prototype) {\n    registry[tag] = prototype;\n  }\n\n  // get prototype mapped to node <tag>\n  HTMLElement.getPrototypeForTag = function(tag) {\n    var prototype = !tag ? HTMLElement.prototype : registry[tag];\n    // TODO(sjmiles): creating <tag> is likely to have wasteful side-effects\n    return prototype || Object.getPrototypeOf(document.createElement(tag));\n  };\n\n  // we have to flag propagation stoppage for the event dispatcher\n  var originalStopPropagation = Event.prototype.stopPropagation;\n  Event.prototype.stopPropagation = function() {\n    this.cancelBubble = true;\n    originalStopPropagation.apply(this, arguments);\n  };\n  \n  // TODO(sorvell): remove when we're sure imports does not need\n  // to load stylesheets\n  /*\n  HTMLImports.importer.preloadSelectors += \n      ', polymer-element link[rel=stylesheet]';\n  */\n})(Polymer);\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    // super\n\n    // `arrayOfArgs` is an optional array of args like one might pass\n    // to `Function.apply`\n\n    // TODO(sjmiles):\n    //    $super must be installed on an instance or prototype chain\n    //    as `super`, and invoked via `this`, e.g.\n    //      `this.super();`\n\n    //    will not work if function objects are not unique, for example,\n    //    when using mixins.\n    //    The memoization strategy assumes each function exists on only one \n    //    prototype chain i.e. we use the function object for memoizing)\n    //    perhaps we can bookkeep on the prototype itself instead\n    function $super(arrayOfArgs) {\n      // since we are thunking a method call, performance is important here: \n      // memoize all lookups, once memoized the fast path calls no other \n      // functions\n      //\n      // find the caller (cannot be `strict` because of 'caller')\n      var caller = $super.caller;\n      // memoized 'name of method' \n      var nom = caller.nom;\n      // memoized next implementation prototype\n      var _super = caller._super;\n      if (!_super) {\n        if (!nom) {\n          nom = caller.nom = nameInThis.call(this, caller);\n        }\n        if (!nom) {\n          console.warn('called super() on a method not installed declaratively (has no .nom property)');\n        }\n        // super prototype is either cached or we have to find it\n        // by searching __proto__ (at the 'top')\n        _super = memoizeSuper(caller, nom, getPrototypeOf(this));\n      }\n      if (!_super) {\n        // if _super is falsey, there is no super implementation\n        //console.warn('called $super(' + nom + ') where there is no super implementation');\n      } else {\n        // our super function\n        var fn = _super[nom];\n        // memoize information so 'fn' can call 'super'\n        if (!fn._super) {\n          memoizeSuper(fn, nom, _super);\n        }\n        // invoke the inherited method\n        // if 'fn' is not function valued, this will throw\n        return fn.apply(this, arrayOfArgs || []);\n      }\n    }\n\n    function nextSuper(proto, name, caller) {\n      // look for an inherited prototype that implements name\n      while (proto) {\n        if ((proto[name] !== caller) && proto[name]) {\n          return proto;\n        }\n        proto = getPrototypeOf(proto);\n      }\n    }\n\n    function memoizeSuper(method, name, proto) {\n      // find and cache next prototype containing `name`\n      // we need the prototype so we can do another lookup\n      // from here\n      method._super = nextSuper(proto, name, method);\n      if (method._super) {\n        // _super is a prototype, the actual method is _super[name]\n        // tag super method with it's name for further lookups\n        method._super[name].nom = name;\n      }\n      return method._super;\n    }\n\n    function nameInThis(value) {\n      var p = this.__proto__;\n      while (p && p !== HTMLElement.prototype) {\n        // TODO(sjmiles): getOwnPropertyNames is absurdly expensive\n        var n$ = Object.getOwnPropertyNames(p);\n        for (var i=0, l=n$.length, n; i<l && (n=n$[i]); i++) {\n          var d = Object.getOwnPropertyDescriptor(p, n);\n          if (typeof d.value === 'function' && d.value === value) {\n            return n;\n          }\n        }\n        p = p.__proto__;\n      }\n    }\n\n    // NOTE: In some platforms (IE10) the prototype chain is faked via \n    // __proto__. Therefore, always get prototype via __proto__ instead of\n    // the more standard Object.getPrototypeOf.\n    function getPrototypeOf(prototype) {\n      return prototype.__proto__;\n    }\n\n    // utility function to precompute name tags for functions\n    // in a (unchained) prototype\n    function hintSuper(prototype) {\n      // tag functions with their prototype name to optimize\n      // super call invocations\n      for (var n in prototype) {\n        var pd = Object.getOwnPropertyDescriptor(prototype, n);\n        if (pd && typeof pd.value === 'function') {\n          pd.value.nom = n;\n        }\n      }\n    }\n\n    // exports\n\n    scope.super = $super;\n\n})(Polymer);\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  var typeHandlers = {\n    string: function(value) {\n      return value;\n    },\n    date: function(value) {\n      return new Date(Date.parse(value) || Date.now());\n    },\n    boolean: function(value) {\n      if (value === '') {\n        return true;\n      }\n      return value === 'false' ? false : !!value;\n    },\n    number: function(value) {\n      var n = parseFloat(value);\n      // hex values like \"0xFFFF\" parseFloat as 0\n      if (n === 0) {\n        n = parseInt(value);\n      }\n      return isNaN(n) ? value : n;\n      // this code disabled because encoded values (like \"0xFFFF\")\n      // do not round trip to their original format\n      //return (String(floatVal) === value) ? floatVal : value;\n    },\n    object: function(value, currentValue) {\n      if (currentValue === null) {\n        return value;\n      }\n      try {\n        // If the string is an object, we can parse is with the JSON library.\n        // include convenience replace for single-quotes. If the author omits\n        // quotes altogether, parse will fail.\n        return JSON.parse(value.replace(/'/g, '\"'));\n      } catch(e) {\n        // The object isn't valid JSON, return the raw value\n        return value;\n      }\n    },\n    // avoid deserialization of functions\n    'function': function(value, currentValue) {\n      return currentValue;\n    }\n  };\n\n  function deserializeValue(value, currentValue) {\n    // attempt to infer type from default value\n    var inferredType = typeof currentValue;\n    // invent 'date' type value for Date\n    if (currentValue instanceof Date) {\n      inferredType = 'date';\n    }\n    // delegate deserialization via type string\n    return typeHandlers[inferredType](value, currentValue);\n  }\n\n  // exports\n\n  scope.deserializeValue = deserializeValue;\n\n})(Polymer);\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  // imports\n\n  var extend = scope.extend;\n\n  // module\n\n  var api = {};\n\n  api.declaration = {};\n  api.instance = {};\n\n  api.publish = function(apis, prototype) {\n    for (var n in apis) {\n      extend(prototype, apis[n]);\n    }\n  }\n\n  // exports\n\n  scope.api = api;\n\n})(Polymer);\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  var utils = {\n    /**\n      * Invokes a function asynchronously. The context of the callback\n      * function is bound to 'this' automatically.\n      * @method async\n      * @param {Function|String} method\n      * @param {any|Array} args\n      * @param {number} timeout\n      */\n    async: function(method, args, timeout) {\n      // when polyfilling Object.observe, ensure changes \n      // propagate before executing the async method\n      Platform.flush();\n      // second argument to `apply` must be an array\n      args = (args && args.length) ? args : [args];\n      // function to invoke\n      var fn = function() {\n        (this[method] || method).apply(this, args);\n      }.bind(this);\n      // execute `fn` sooner or later\n      var handle = timeout ? setTimeout(fn, timeout) :\n          requestAnimationFrame(fn);\n      // NOTE: switch on inverting handle to determine which time is used.\n      return timeout ? handle : ~handle;\n    },\n    cancelAsync: function(handle) {\n      if (handle < 0) {\n        cancelAnimationFrame(~handle);\n      } else {\n        clearTimeout(handle);\n      }\n    },\n    /**\n      * Fire an event.\n      * @method fire\n      * @returns {Object} event\n      * @param {string} type An event name.\n      * @param {any} detail\n      * @param {Node} onNode Target node.\n      */\n    fire: function(type, detail, onNode, bubbles, cancelable) {\n      var node = onNode || this;\n      var detail = detail || {};\n      var event = new CustomEvent(type, {\n        bubbles: (bubbles !== undefined ? bubbles : true), \n        cancelable: (cancelable !== undefined ? cancelable : true), \n        detail: detail\n      });\n      node.dispatchEvent(event);\n      return event;\n    },\n    /**\n      * Fire an event asynchronously.\n      * @method asyncFire\n      * @param {string} type An event name.\n      * @param detail\n      * @param {Node} toNode Target node.\n      */\n    asyncFire: function(/*inType, inDetail*/) {\n      this.async(\"fire\", arguments);\n    },\n    /**\n      * Remove class from old, add class to anew, if they exist\n      * @param classFollows\n      * @param anew A node.\n      * @param old A node\n      * @param className\n      */\n    classFollows: function(anew, old, className) {\n      if (old) {\n        old.classList.remove(className);\n      }\n      if (anew) {\n        anew.classList.add(className);\n      }\n    }\n  };\n\n  // no-operation function for handy stubs\n  var nop = function() {};\n\n  // null-object for handy stubs\n  var nob = {};\n\n  // deprecated\n\n  utils.asyncMethod = utils.async;\n\n  // exports\n\n  scope.api.instance.utils = utils;\n  scope.nop = nop;\n  scope.nob = nob;\n\n})(Polymer);\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  // imports\n\n  var log = window.logFlags || {};\n  var EVENT_PREFIX = 'on-';\n\n  // instance events api\n  var events = {\n    // read-only\n    EVENT_PREFIX: EVENT_PREFIX,\n    // event listeners on host\n    addHostListeners: function() {\n      var events = this.eventDelegates;\n      log.events && (Object.keys(events).length > 0) && console.log('[%s] addHostListeners:', this.localName, events);\n      // NOTE: host events look like bindings but really are not;\n      // (1) we don't want the attribute to be set and (2) we want to support\n      // multiple event listeners ('host' and 'instance') and Node.bind\n      // by default supports 1 thing being bound.\n      // We do, however, leverage the event hookup code in PolymerExpressions\n      // so that we have a common code path for handling declarative events.\n      var self = this, bindable, eventName;\n      for (var n in events) {\n        eventName = EVENT_PREFIX + n;\n        bindable = PolymerExpressions.prepareEventBinding(\n          Path.get(events[n]),\n          eventName, \n          {\n            resolveEventHandler: function(model, path, node) {\n              var fn = path.getValueFrom(self);\n              if (fn) {\n                return fn.bind(self);\n              }\n            }\n          }\n        );\n        bindable(this, this, false);\n      }\n    },\n    // call 'method' or function method on 'obj' with 'args', if the method exists\n    dispatchMethod: function(obj, method, args) {\n      if (obj) {\n        log.events && console.group('[%s] dispatch [%s]', obj.localName, method);\n        var fn = typeof method === 'function' ? method : obj[method];\n        if (fn) {\n          fn[args ? 'apply' : 'call'](obj, args);\n        }\n        log.events && console.groupEnd();\n        Platform.flush();\n      }\n    }\n  };\n\n  // exports\n\n  scope.api.instance.events = events;\n\n})(Polymer);\n",
-    "/*\r\n * Copyright 2013 The Polymer Authors. All rights reserved.\r\n * Use of this source code is governed by a BSD-style\r\n * license that can be found in the LICENSE file.\r\n */\r\n(function(scope) {\r\n\r\n  // instance api for attributes\r\n\r\n  var attributes = {\r\n    copyInstanceAttributes: function () {\r\n      var a$ = this._instanceAttributes;\r\n      for (var k in a$) {\r\n        if (!this.hasAttribute(k)) {\r\n          this.setAttribute(k, a$[k]);\r\n        }\r\n      }\r\n    },\r\n    // for each attribute on this, deserialize value to property as needed\r\n    takeAttributes: function() {\r\n      // if we have no publish lookup table, we have no attributes to take\r\n      // TODO(sjmiles): ad hoc\r\n      if (this._publishLC) {\r\n        for (var i=0, a$=this.attributes, l=a$.length, a; (a=a$[i]) && i<l; i++) {\r\n          this.attributeToProperty(a.name, a.value);\r\n        }\r\n      }\r\n    },\r\n    // if attribute 'name' is mapped to a property, deserialize\r\n    // 'value' into that property\r\n    attributeToProperty: function(name, value) {\r\n      // try to match this attribute to a property (attributes are\r\n      // all lower-case, so this is case-insensitive search)\r\n      var name = this.propertyForAttribute(name);\r\n      if (name) {\r\n        // filter out 'mustached' values, these are to be\r\n        // replaced with bound-data and are not yet values\r\n        // themselves\r\n        if (value && value.search(scope.bindPattern) >= 0) {\r\n          return;\r\n        }\r\n        // get original value\r\n        var currentValue = this[name];\r\n        // deserialize Boolean or Number values from attribute\r\n        var value = this.deserializeValue(value, currentValue);\r\n        // only act if the value has changed\r\n        if (value !== currentValue) {\r\n          // install new value (has side-effects)\r\n          this[name] = value;\r\n        }\r\n      }\r\n    },\r\n    // return the published property matching name, or undefined\r\n    propertyForAttribute: function(name) {\r\n      var match = this._publishLC && this._publishLC[name];\r\n      //console.log('propertyForAttribute:', name, 'matches', match);\r\n      return match;\r\n    },\r\n    // convert representation of 'stringValue' based on type of 'currentValue'\r\n    deserializeValue: function(stringValue, currentValue) {\r\n      return scope.deserializeValue(stringValue, currentValue);\r\n    },\r\n    serializeValue: function(value, inferredType) {\r\n      if (inferredType === 'boolean') {\r\n        return value ? '' : undefined;\r\n      } else if (inferredType !== 'object' && inferredType !== 'function'\r\n          && value !== undefined) {\r\n        return value;\r\n      }\r\n    },\r\n    reflectPropertyToAttribute: function(name) {\r\n      var inferredType = typeof this[name];\r\n      // try to intelligently serialize property value\r\n      var serializedValue = this.serializeValue(this[name], inferredType);\r\n      // boolean properties must reflect as boolean attributes\r\n      if (serializedValue !== undefined) {\r\n        this.setAttribute(name, serializedValue);\r\n        // TODO(sorvell): we should remove attr for all properties\r\n        // that have undefined serialization; however, we will need to\r\n        // refine the attr reflection system to achieve this; pica, for example,\r\n        // relies on having inferredType object properties not removed as\r\n        // attrs.\r\n      } else if (inferredType === 'boolean') {\r\n        this.removeAttribute(name);\r\n      }\r\n    }\r\n  };\r\n\r\n  // exports\r\n\r\n  scope.api.instance.attributes = attributes;\r\n\r\n})(Polymer);\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(function(scope) {\n\n  // imports\n\n  var log = window.logFlags || {};\n\n  // magic words\n\n  var OBSERVE_SUFFIX = 'Changed';\n\n  // element api\n\n  var empty = [];\n\n  var properties = {\n    observeProperties: function() {\n      var n$ = this._observeNames, pn$ = this._publishNames;\n      if ((n$ && n$.length) || (pn$ && pn$.length)) {\n        var self = this;\n        var o = this._propertyObserver = new CompoundObserver();\n        // keep track of property observer so we can shut it down\n        this.registerObservers([o]);\n        for (var i=0, l=n$.length, n; (i<l) && (n=n$[i]); i++) {\n          o.addPath(this, n);\n          // observer array properties\n          var pd = Object.getOwnPropertyDescriptor(this.__proto__, n);\n          if (pd && pd.value) {\n            this.observeArrayValue(n, pd.value, null);\n          }\n        }\n        for (var i=0, l=pn$.length, n; (i<l) && (n=pn$[i]); i++) {\n          if (!this.observe || (this.observe[n] === undefined)) {\n            o.addPath(this, n);\n          }\n        }\n        o.open(this.notifyPropertyChanges, this);\n      }\n    },\n    notifyPropertyChanges: function(newValues, oldValues, paths) {\n      var name, method, called = {};\n      for (var i in oldValues) {\n        // note: paths is of form [object, path, object, path]\n        name = paths[2 * i + 1];\n        if (this.publish[name] !== undefined) {\n          this.reflectPropertyToAttribute(name);\n        }\n        method = this.observe[name];\n        if (method) {\n          this.observeArrayValue(name, newValues[i], oldValues[i]);\n          if (!called[method]) {\n            called[method] = true;\n            // observes the value if it is an array\n            this.invokeMethod(method, [oldValues[i], newValues[i], arguments]);\n          }\n        }\n      }\n    },\n    observeArrayValue: function(name, value, old) {\n      // we only care if there are registered side-effects\n      var callbackName = this.observe[name];\n      if (callbackName) {\n        // if we are observing the previous value, stop\n        if (Array.isArray(old)) {\n          log.observe && console.log('[%s] observeArrayValue: unregister observer [%s]', this.localName, name);\n          this.closeNamedObserver(name + '__array');\n        }\n        // if the new value is an array, being observing it\n        if (Array.isArray(value)) {\n          log.observe && console.log('[%s] observeArrayValue: register observer [%s]', this.localName, name, value);\n          var observer = new ArrayObserver(value);\n          observer.open(function(value, old) {\n            this.invokeMethod(callbackName, [old]);\n          }, this);\n          this.registerNamedObserver(name + '__array', observer);\n        }\n      }\n    },\n    bindProperty: function(property, observable) {\n      // apply Polymer two-way reference binding\n      return bindProperties(this, property, observable);\n    },\n    invokeMethod: function(method, args) {\n      var fn = this[method] || method;\n      if (typeof fn === 'function') {\n        fn.apply(this, args);\n      }\n    },\n    registerObservers: function(observers) {\n      this._observers.push(observers);\n    },\n    // observer array items are arrays of observers.\n    closeObservers: function() {\n      for (var i=0, l=this._observers.length; i<l; i++) {\n        this.closeObserverArray(this._observers[i]);\n      }\n      this._observers = [];\n    },\n    closeObserverArray: function(observerArray) {\n      for (var i=0, l=observerArray.length, o; i<l; i++) {\n        o = observerArray[i];\n        if (o && o.close) {\n          o.close();\n        }\n      }\n    },\n    // bookkeeping observers for memory management\n    registerNamedObserver: function(name, observer) {\n      var o$ = this._namedObservers || (this._namedObservers = {});\n      o$[name] = observer;\n    },\n    closeNamedObserver: function(name) {\n      var o$ = this._namedObservers;\n      if (o$ && o$[name]) {\n        o$[name].close();\n        o$[name] = null;\n        return true;\n      }\n    },\n    closeNamedObservers: function() {\n      if (this._namedObservers) {\n        var keys=Object.keys(this._namedObservers);\n        for (var i=0, l=keys.length, k, o; (i < l) && (k=keys[i]); i++) {\n          o = this._namedObservers[k];\n          o.close();\n        }\n        this._namedObservers = {};\n      }\n    }\n  };\n\n  // property binding\n  // bind a property in A to a path in B by converting A[property] to a\n  // getter/setter pair that accesses B[...path...]\n  function bindProperties(inA, inProperty, observable) {\n    log.bind && console.log(LOG_BIND_PROPS, inB.localName || 'object', inPath, inA.localName, inProperty);\n    // capture A's value if B's value is null or undefined,\n    // otherwise use B's value\n    // TODO(sorvell): need to review, can do with ObserverTransform\n    var v = observable.discardChanges();\n    if (v === null || v === undefined) {\n      observable.setValue(inA[inProperty]);\n    }\n    return Observer.defineComputedProperty(inA, inProperty, observable);\n  }\n\n  // logging\n  var LOG_OBSERVE = '[%s] watching [%s]';\n  var LOG_OBSERVED = '[%s#%s] watch: [%s] now [%s] was [%s]';\n  var LOG_CHANGED = '[%s#%s] propertyChanged: [%s] now [%s] was [%s]';\n  var LOG_BIND_PROPS = \"[%s]: bindProperties: [%s] to [%s].[%s]\";\n\n  // exports\n\n  scope.api.instance.properties = properties;\n\n})(Polymer);\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  // imports\n\n  var log = window.logFlags || 0;\n  var events = scope.api.instance.events;\n\n  var syntax = new PolymerExpressions();\n  syntax.resolveEventHandler = function(model, path, node) {\n    var ctlr = findEventController(node);\n    if (ctlr) {\n      var fn = path.getValueFrom(ctlr);\n      if (fn) {\n        return fn.bind(ctlr);\n      }\n    }\n  }\n\n  // An event controller is the host element for the shadowRoot in which \n  // the node exists, or the first ancestor with a 'lightDomController'\n  // property.\n  function findEventController(node) {\n    while (node.parentNode) {\n      if (node.lightDomController) {\n        return node;\n      }\n      node = node.parentNode;\n    }\n    return node.host;\n  };\n\n  // element api supporting mdv\n\n  var mdv = {\n    syntax: syntax,\n    instanceTemplate: function(template) {\n      var dom = template.createInstance(this, this.syntax);\n      this.registerObservers(dom.bindings_);\n      return dom;\n    },\n    bind: function(name, observable, oneTime) {\n      var property = this.propertyForAttribute(name);\n      if (!property) {\n        // TODO(sjmiles): this mixin method must use the special form\n        // of `super` installed by `mixinMethod` in declaration/prototype.js\n        return this.mixinSuper(arguments);\n      } else {\n        // use n-way Polymer binding\n        var observer = this.bindProperty(property, observable);\n        this.reflectPropertyToAttribute(property);\n        // NOTE: reflecting binding information is typically required only for\n        // tooling. It has a performance cost so it's opt-in in Node.bind.\n        if (Platform.enableBindingsReflection) {\n          observer.path = observable.path_;\n          this.bindings_ = this.bindings_ || {};\n          this.bindings_[name] = observer;\n        }\n        return observer;\n      }\n    },\n    // TODO(sorvell): unbind/unbindAll has been removed, as public api, from\n    // TemplateBinding. We still need to close/dispose of observers but perhaps\n    // we should choose a more explicit name.\n    asyncUnbindAll: function() {\n      if (!this._unbound) {\n        log.unbind && console.log('[%s] asyncUnbindAll', this.localName);\n        this._unbindAllJob = this.job(this._unbindAllJob, this.unbindAll, 0);\n      }\n    },\n    unbindAll: function() {\n      if (!this._unbound) {\n        this.closeObservers();\n        this.closeNamedObservers();\n        this._unbound = true;\n      }\n    },\n    cancelUnbindAll: function() {\n      if (this._unbound) {\n        log.unbind && console.warn('[%s] already unbound, cannot cancel unbindAll', this.localName);\n        return;\n      }\n      log.unbind && console.log('[%s] cancelUnbindAll', this.localName);\n      if (this._unbindAllJob) {\n        this._unbindAllJob = this._unbindAllJob.stop();\n      }\n    }\n  };\n\n  function unbindNodeTree(node) {\n    forNodeTree(node, _nodeUnbindAll);\n  }\n\n  function _nodeUnbindAll(node) {\n    node.unbindAll();\n  }\n\n  function forNodeTree(node, callback) {\n    if (node) {\n      callback(node);\n      for (var child = node.firstChild; child; child = child.nextSibling) {\n        forNodeTree(child, callback);\n      }\n    }\n  }\n\n  var mustachePattern = /\\{\\{([^{}]*)}}/;\n\n  // exports\n\n  scope.bindPattern = mustachePattern;\n  scope.api.instance.mdv = mdv;\n\n})(Polymer);\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  var base = {\n    PolymerBase: true,\n    job: function(job, callback, wait) {\n      if (typeof job === 'string') {\n        var n = '___' + job;\n        this[n] = Polymer.job.call(this, this[n], callback, wait);\n      } else {\n        return Polymer.job.call(this, job, callback, wait);\n      }\n    },\n    super: Polymer.super,\n    // user entry point for element has had its createdCallback called\n    created: function() {\n    },\n    // user entry point for element has shadowRoot and is ready for\n    // api interaction\n    ready: function() {\n    },\n    createdCallback: function() {\n      if (this.templateInstance && this.templateInstance.model) {\n        console.warn('Attributes on ' + this.localName + ' were data bound ' +\n            'prior to Polymer upgrading the element. This may result in ' +\n            'incorrect binding types.');\n      }\n      this.created();\n      this.prepareElement();\n    },\n    // system entry point, do not override\n    prepareElement: function() {\n      this._elementPrepared = true;\n      // install shadowRoots storage\n      this.shadowRoots = {};\n      // storage for closeable observers.\n      this._observers = [];\n      // install property observers\n      this.observeProperties();\n      // install boilerplate attributes\n      this.copyInstanceAttributes();\n      // process input attributes\n      this.takeAttributes();\n      // add event listeners\n      this.addHostListeners();\n      // process declarative resources\n      this.parseDeclarations(this.__proto__);\n      // TODO(sorvell): CE polyfill uses unresolved attribute to simulate\n      // :unresolved; remove this attribute to be compatible with native\n      // CE.\n      this.removeAttribute('unresolved');\n      // user entry point\n      this.ready();\n    },\n    attachedCallback: function() {\n      this.cancelUnbindAll();\n      // invoke user action\n      if (this.attached) {\n        this.attached();\n      }\n      // TODO(sorvell): bc\n      if (this.enteredView) {\n        this.enteredView();\n      }\n      // NOTE: domReady can be used to access elements in dom (descendants, \n      // ancestors, siblings) such that the developer is enured to upgrade\n      // ordering. If the element definitions have loaded, domReady\n      // can be used to access upgraded elements.\n      if (!this.hasBeenAttached) {\n        this.hasBeenAttached = true;\n        if (this.domReady) {\n          this.async('domReady');\n        }\n      }\n    },\n    detachedCallback: function() {\n      if (!this.preventDispose) {\n        this.asyncUnbindAll();\n      }\n      // invoke user action\n      if (this.detached) {\n        this.detached();\n      }\n      // TODO(sorvell): bc\n      if (this.leftView) {\n        this.leftView();\n      }\n    },\n    // TODO(sorvell): bc\n    enteredViewCallback: function() {\n      this.attachedCallback();\n    },\n    // TODO(sorvell): bc\n    leftViewCallback: function() {\n      this.detachedCallback();\n    },\n    // TODO(sorvell): bc\n    enteredDocumentCallback: function() {\n      this.attachedCallback();\n    },\n    // TODO(sorvell): bc\n    leftDocumentCallback: function() {\n      this.detachedCallback();\n    },\n    // recursive ancestral <element> initialization, oldest first\n    parseDeclarations: function(p) {\n      if (p && p.element) {\n        this.parseDeclarations(p.__proto__);\n        p.parseDeclaration.call(this, p.element);\n      }\n    },\n    // parse input <element> as needed, override for custom behavior\n    parseDeclaration: function(elementElement) {\n      var template = this.fetchTemplate(elementElement);\n      if (template) {\n        var root = this.shadowFromTemplate(template);\n        this.shadowRoots[elementElement.name] = root;\n      }\n    },\n    // return a shadow-root template (if desired), override for custom behavior\n    fetchTemplate: function(elementElement) {\n      return elementElement.querySelector('template');\n    },\n    // utility function that creates a shadow root from a <template>\n    shadowFromTemplate: function(template) {\n      if (template) {\n        // make a shadow root\n        var root = this.createShadowRoot();\n        // stamp template\n        // which includes parsing and applying MDV bindings before being \n        // inserted (to avoid {{}} in attribute values)\n        // e.g. to prevent <img src=\"images/{{icon}}\"> from generating a 404.\n        var dom = this.instanceTemplate(template);\n        // append to shadow dom\n        root.appendChild(dom);\n        // perform post-construction initialization tasks on shadow root\n        this.shadowRootReady(root, template);\n        // return the created shadow root\n        return root;\n      }\n    },\n    // utility function that stamps a <template> into light-dom\n    lightFromTemplate: function(template, refNode) {\n      if (template) {\n        // TODO(sorvell): mark this element as a lightDOMController so that\n        // event listeners on bound nodes inside it will be called on it.\n        // Note, the expectation here is that events on all descendants \n        // should be handled by this element.\n        this.lightDomController = true;\n        // stamp template\n        // which includes parsing and applying MDV bindings before being \n        // inserted (to avoid {{}} in attribute values)\n        // e.g. to prevent <img src=\"images/{{icon}}\"> from generating a 404.\n        var dom = this.instanceTemplate(template);\n        // append to shadow dom\n        if (refNode) {\n          this.insertBefore(dom, refNode);          \n        } else {\n          this.appendChild(dom);\n        }\n        // perform post-construction initialization tasks on ahem, light root\n        this.shadowRootReady(this);\n        // return the created shadow root\n        return dom;\n      }\n    },\n    shadowRootReady: function(root) {\n      // locate nodes with id and store references to them in this.$ hash\n      this.marshalNodeReferences(root);\n      // set up pointer gestures\n      PointerGestures.register(root);\n    },\n    // locate nodes with id and store references to them in this.$ hash\n    marshalNodeReferences: function(root) {\n      // establish $ instance variable\n      var $ = this.$ = this.$ || {};\n      // populate $ from nodes with ID from the LOCAL tree\n      if (root) {\n        var n$ = root.querySelectorAll(\"[id]\");\n        for (var i=0, l=n$.length, n; (i<l) && (n=n$[i]); i++) {\n          $[n.id] = n;\n        };\n      }\n    },\n    attributeChangedCallback: function(name, oldValue) {\n      // TODO(sjmiles): adhoc filter\n      if (name !== 'class' && name !== 'style') {\n        this.attributeToProperty(name, this.getAttribute(name));\n      }\n      if (this.attributeChanged) {\n        this.attributeChanged.apply(this, arguments);\n      }\n    },\n    onMutation: function(node, listener) {\n      var observer = new MutationObserver(function(mutations) {\n        listener.call(this, observer, mutations);\n        observer.disconnect();\n      }.bind(this));\n      observer.observe(node, {childList: true, subtree: true});\n    }\n  };\n\n  // true if object has own PolymerBase api\n  function isBase(object) {\n    return object.hasOwnProperty('PolymerBase') \n  }\n\n  // name a base constructor for dev tools\n\n  function PolymerBase() {};\n  PolymerBase.prototype = base;\n  base.constructor = PolymerBase;\n  \n  // exports\n\n  scope.Base = PolymerBase;\n  scope.isBase = isBase;\n  scope.api.instance.base = base;\n  \n})(Polymer);\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  // imports\n\n  var log = window.logFlags || {};\n  \n  // magic words\n  \n  var STYLE_SCOPE_ATTRIBUTE = 'element';\n  var STYLE_CONTROLLER_SCOPE = 'controller';\n  \n  var styles = {\n    STYLE_SCOPE_ATTRIBUTE: STYLE_SCOPE_ATTRIBUTE,\n    /**\n     * Installs external stylesheets and <style> elements with the attribute \n     * polymer-scope='controller' into the scope of element. This is intended\n     * to be a called during custom element construction.\n    */\n    installControllerStyles: function() {\n      // apply controller styles, but only if they are not yet applied\n      var scope = this.findStyleScope();\n      if (scope && !this.scopeHasNamedStyle(scope, this.localName)) {\n        // allow inherited controller styles\n        var proto = getPrototypeOf(this), cssText = '';\n        while (proto && proto.element) {\n          cssText += proto.element.cssTextForScope(STYLE_CONTROLLER_SCOPE);\n          proto = getPrototypeOf(proto);\n        }\n        if (cssText) {\n          this.installScopeCssText(cssText, scope);\n        }\n      }\n    },\n    installScopeStyle: function(style, name, scope) {\n      var scope = scope || this.findStyleScope(), name = name || '';\n      if (scope && !this.scopeHasNamedStyle(scope, this.localName + name)) {\n        var cssText = '';\n        if (style instanceof Array) {\n          for (var i=0, l=style.length, s; (i<l) && (s=style[i]); i++) {\n            cssText += s.textContent + '\\n\\n';\n          }\n        } else {\n          cssText = style.textContent;\n        }\n        this.installScopeCssText(cssText, scope, name);\n      }\n    },\n    installScopeCssText: function(cssText, scope, name) {\n      scope = scope || this.findStyleScope();\n      name = name || '';\n      if (!scope) {\n        return;\n      }\n      if (window.ShadowDOMPolyfill) {\n        cssText = shimCssText(cssText, scope.host);\n      }\n      var style = this.element.cssTextToScopeStyle(cssText,\n          STYLE_CONTROLLER_SCOPE);\n      Polymer.applyStyleToScope(style, scope);\n      // cache that this style has been applied\n      scope._scopeStyles[this.localName + name] = true;\n    },\n    findStyleScope: function(node) {\n      // find the shadow root that contains this element\n      var n = node || this;\n      while (n.parentNode) {\n        n = n.parentNode;\n      }\n      return n;\n    },\n    scopeHasNamedStyle: function(scope, name) {\n      scope._scopeStyles = scope._scopeStyles || {};\n      return scope._scopeStyles[name];\n    }\n  };\n  \n  // NOTE: use raw prototype traversal so that we ensure correct traversal\n  // on platforms where the protoype chain is simulated via __proto__ (IE10)\n  function getPrototypeOf(prototype) {\n    return prototype.__proto__;\n  }\n\n  function shimCssText(cssText, host) {\n    var name = '', is = false;\n    if (host) {\n      name = host.localName;\n      is = host.hasAttribute('is');\n    }\n    var selector = Platform.ShadowCSS.makeScopeSelector(name, is);\n    return Platform.ShadowCSS.shimCssText(cssText, selector);\n  }\n\n  // exports\n\n  scope.api.instance.styles = styles;\n  \n})(Polymer);\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  // imports\n\n  var extend = scope.extend;\n  var api = scope.api;\n\n  // imperative implementation: Polymer()\n\n  // specify an 'own' prototype for tag `name`\n  function element(name, prototype) {\n    if (arguments.length === 1 && typeof arguments[0] !== 'string') {\n      prototype = name;\n      var script = document._currentScript;\n      name = script && script.parentNode && script.parentNode.getAttribute ?\n          script.parentNode.getAttribute('name') : '';\n      if (!name) {\n        throw 'Element name could not be inferred.';\n      }\n    }\n    if (getRegisteredPrototype[name]) {\n      throw 'Already registered (Polymer) prototype for element ' + name;\n    }\n    // cache the prototype\n    registerPrototype(name, prototype);\n    // notify the registrar waiting for 'name', if any\n    notifyPrototype(name);\n  }\n\n  // async prototype source\n\n  function waitingForPrototype(name, client) {\n    waitPrototype[name] = client;\n  }\n\n  var waitPrototype = {};\n\n  function notifyPrototype(name) {\n    if (waitPrototype[name]) {\n      waitPrototype[name].registerWhenReady();\n      delete waitPrototype[name];\n    }\n  }\n\n  // utility and bookkeeping\n\n  // maps tag names to prototypes, as registered with\n  // Polymer. Prototypes associated with a tag name\n  // using document.registerElement are available from\n  // HTMLElement.getPrototypeForTag().\n  // If an element was fully registered by Polymer, then\n  // Polymer.getRegisteredPrototype(name) === \n  //   HTMLElement.getPrototypeForTag(name)\n\n  var prototypesByName = {};\n\n  function registerPrototype(name, prototype) {\n    return prototypesByName[name] = prototype || {};\n  }\n\n  function getRegisteredPrototype(name) {\n    return prototypesByName[name];\n  }\n\n  // exports\n\n  scope.getRegisteredPrototype = getRegisteredPrototype;\n  scope.waitingForPrototype = waitingForPrototype;\n\n  // namespace shenanigans so we can expose our scope on the registration \n  // function\n\n  // make window.Polymer reference `element()`\n\n  window.Polymer = element;\n\n  // TODO(sjmiles): find a way to do this that is less terrible\n  // copy window.Polymer properties onto `element()`\n\n  extend(Polymer, scope);\n\n  // Under the HTMLImports polyfill, scripts in the main document\n  // do not block on imports; we want to allow calls to Polymer in the main\n  // document. Platform collects those calls until we can process them, which\n  // we do here.\n\n  var declarations = Platform.deliverDeclarations();\n  if (declarations) {\n    for (var i=0, l=declarations.length, d; (i<l) && (d=declarations[i]); i++) {\n      element.apply(null, d);\n    }\n  }\n\n})(Polymer);\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 path = {\n  resolveElementPaths: function(node) {\n    Platform.urlResolver.resolveDom(node);\n  },\n  addResolvePathApi: function() {\n    // let assetpath attribute modify the resolve path\n    var assetPath = this.getAttribute('assetpath') || '';\n    var root = new URL(assetPath, this.ownerDocument.baseURI);\n    this.prototype.resolvePath = function(urlPath, base) {\n      var u = new URL(urlPath, base || root);\n      return u.href;\n    };\n  }\n};\n\n// exports\nscope.api.declaration.path = path;\n\n})(Polymer);\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  // imports\n\n  var log = window.logFlags || {};\n  var api = scope.api.instance.styles;\n  var STYLE_SCOPE_ATTRIBUTE = api.STYLE_SCOPE_ATTRIBUTE;\n\n  // magic words\n\n  var STYLE_SELECTOR = 'style';\n  var STYLE_LOADABLE_MATCH = '@import';\n  var SHEET_SELECTOR = 'link[rel=stylesheet]';\n  var STYLE_GLOBAL_SCOPE = 'global';\n  var SCOPE_ATTR = 'polymer-scope';\n\n  var styles = {\n    // returns true if resources are loading\n    loadStyles: function(callback) {\n      var content = this.templateContent();\n      if (content) {\n        this.convertSheetsToStyles(content);\n      }\n      var styles = this.findLoadableStyles(content);\n      if (styles.length) {\n        Platform.styleResolver.loadStyles(styles, callback);\n      } else if (callback) {\n        callback();\n      }\n    },\n    convertSheetsToStyles: function(root) {\n      var s$ = root.querySelectorAll(SHEET_SELECTOR);\n      for (var i=0, l=s$.length, s, c; (i<l) && (s=s$[i]); i++) {\n        c = createStyleElement(importRuleForSheet(s, this.ownerDocument.baseURI),\n            this.ownerDocument);\n        this.copySheetAttributes(c, s);\n        s.parentNode.replaceChild(c, s);\n      }\n    },\n    copySheetAttributes: function(style, link) {\n      for (var i=0, a$=link.attributes, l=a$.length, a; (a=a$[i]) && i<l; i++) {\n        if (a.name !== 'rel' && a.name !== 'href') {\n          style.setAttribute(a.name, a.value);\n        }\n      }\n    },\n    findLoadableStyles: function(root) {\n      var loadables = [];\n      if (root) {\n        var s$ = root.querySelectorAll(STYLE_SELECTOR);\n        for (var i=0, l=s$.length, s; (i<l) && (s=s$[i]); i++) {\n          if (s.textContent.match(STYLE_LOADABLE_MATCH)) {\n            loadables.push(s);\n          }\n        }\n      }\n      return loadables;\n    },\n    /**\n     * Install external stylesheets loaded in <polymer-element> elements into the \n     * element's template.\n     * @param elementElement The <element> element to style.\n     */\n    installSheets: function() {\n      this.cacheSheets();\n      this.cacheStyles();\n      this.installLocalSheets();\n      this.installGlobalStyles();\n    },\n    /**\n     * Remove all sheets from element and store for later use.\n     */\n    cacheSheets: function() {\n      this.sheets = this.findNodes(SHEET_SELECTOR);\n      this.sheets.forEach(function(s) {\n        if (s.parentNode) {\n          s.parentNode.removeChild(s);\n        }\n      });\n    },\n    cacheStyles: function() {\n      this.styles = this.findNodes(STYLE_SELECTOR + '[' + SCOPE_ATTR + ']');\n      this.styles.forEach(function(s) {\n        if (s.parentNode) {\n          s.parentNode.removeChild(s);\n        }\n      });\n    },\n    /**\n     * Takes external stylesheets loaded in an <element> element and moves\n     * their content into a <style> element inside the <element>'s template.\n     * The sheet is then removed from the <element>. This is done only so \n     * that if the element is loaded in the main document, the sheet does\n     * not become active.\n     * Note, ignores sheets with the attribute 'polymer-scope'.\n     * @param elementElement The <element> element to style.\n     */\n    installLocalSheets: function () {\n      var sheets = this.sheets.filter(function(s) {\n        return !s.hasAttribute(SCOPE_ATTR);\n      });\n      var content = this.templateContent();\n      if (content) {\n        var cssText = '';\n        sheets.forEach(function(sheet) {\n          cssText += cssTextFromSheet(sheet) + '\\n';\n        });\n        if (cssText) {\n          var style = createStyleElement(cssText, this.ownerDocument);\n          content.insertBefore(style, content.firstChild);\n        }\n      }\n    },\n    findNodes: function(selector, matcher) {\n      var nodes = this.querySelectorAll(selector).array();\n      var content = this.templateContent();\n      if (content) {\n        var templateNodes = content.querySelectorAll(selector).array();\n        nodes = nodes.concat(templateNodes);\n      }\n      return matcher ? nodes.filter(matcher) : nodes;\n    },\n    templateContent: function() {\n      var template = this.querySelector('template');\n      return template && templateContent(template);\n    },\n    /**\n     * Promotes external stylesheets and <style> elements with the attribute \n     * polymer-scope='global' into global scope.\n     * This is particularly useful for defining @keyframe rules which \n     * currently do not function in scoped or shadow style elements.\n     * (See wkb.ug/72462)\n     * @param elementElement The <element> element to style.\n    */\n    // TODO(sorvell): remove when wkb.ug/72462 is addressed.\n    installGlobalStyles: function() {\n      var style = this.styleForScope(STYLE_GLOBAL_SCOPE);\n      applyStyleToScope(style, document.head);\n    },\n    cssTextForScope: function(scopeDescriptor) {\n      var cssText = '';\n      // handle stylesheets\n      var selector = '[' + SCOPE_ATTR + '=' + scopeDescriptor + ']';\n      var matcher = function(s) {\n        return matchesSelector(s, selector);\n      };\n      var sheets = this.sheets.filter(matcher);\n      sheets.forEach(function(sheet) {\n        cssText += cssTextFromSheet(sheet) + '\\n\\n';\n      });\n      // handle cached style elements\n      var styles = this.styles.filter(matcher);\n      styles.forEach(function(style) {\n        cssText += style.textContent + '\\n\\n';\n      });\n      return cssText;\n    },\n    styleForScope: function(scopeDescriptor) {\n      var cssText = this.cssTextForScope(scopeDescriptor);\n      return this.cssTextToScopeStyle(cssText, scopeDescriptor);\n    },\n    cssTextToScopeStyle: function(cssText, scopeDescriptor) {\n      if (cssText) {\n        var style = createStyleElement(cssText);\n        style.setAttribute(STYLE_SCOPE_ATTRIBUTE, this.getAttribute('name') +\n            '-' + scopeDescriptor);\n        return style;\n      }\n    }\n  };\n\n  function importRuleForSheet(sheet, baseUrl) {\n    var href = new URL(sheet.getAttribute('href'), baseUrl).href;\n    return '@import \\'' + href + '\\';';\n  }\n\n  function applyStyleToScope(style, scope) {\n    if (style) {\n      if (scope === document) {\n        scope = document.head;\n      }\n      if (window.ShadowDOMPolyfill) {\n        scope = document.head;\n      }\n      // TODO(sorvell): necessary for IE\n      // see https://connect.microsoft.com/IE/feedback/details/790212/\n      // cloning-a-style-element-and-adding-to-document-produces\n      // -unexpected-result#details\n      // var clone = style.cloneNode(true);\n      var clone = createStyleElement(style.textContent);\n      var attr = style.getAttribute(STYLE_SCOPE_ATTRIBUTE);\n      if (attr) {\n        clone.setAttribute(STYLE_SCOPE_ATTRIBUTE, attr);\n      }\n      // TODO(sorvell): probably too brittle; try to figure out \n      // where to put the element.\n      var refNode = scope.firstElementChild;\n      if (scope === document.head) {\n        var selector = 'style[' + STYLE_SCOPE_ATTRIBUTE + ']';\n        var s$ = document.head.querySelectorAll(selector);\n        if (s$.length) {\n          refNode = s$[s$.length-1].nextElementSibling;\n        }\n      }\n      scope.insertBefore(clone, refNode);\n    }\n  }\n\n  function 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  function cssTextFromSheet(sheet) {\n    return (sheet && sheet.__resource) || '';\n  }\n\n  function matchesSelector(node, inSelector) {\n    if (matches) {\n      return matches.call(node, inSelector);\n    }\n  }\n  var p = HTMLElement.prototype;\n  var matches = p.matches || p.matchesSelector || p.webkitMatchesSelector \n      || p.mozMatchesSelector;\n  \n  // exports\n\n  scope.api.declaration.styles = styles;\n  scope.applyStyleToScope = applyStyleToScope;\n  \n})(Polymer);\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  // imports\n\n  var log = window.logFlags || {};\n  var api = scope.api.instance.events;\n  var EVENT_PREFIX = api.EVENT_PREFIX;\n  // polymer-element declarative api: events feature\n\n  var events = { \n    parseHostEvents: function() {\n      // our delegates map\n      var delegates = this.prototype.eventDelegates;\n      // extract data from attributes into delegates\n      this.addAttributeDelegates(delegates);\n    },\n    addAttributeDelegates: function(delegates) {\n      // for each attribute\n      for (var i=0, a; a=this.attributes[i]; i++) {\n        // does it have magic marker identifying it as an event delegate?\n        if (this.hasEventPrefix(a.name)) {\n          // if so, add the info to delegates\n          delegates[this.removeEventPrefix(a.name)] = a.value.replace('{{', '')\n              .replace('}}', '').trim();\n        }\n      }\n    },\n    // starts with 'on-'\n    hasEventPrefix: function (n) {\n      return n && (n[0] === 'o') && (n[1] === 'n') && (n[2] === '-');\n    },\n    removeEventPrefix: function(n) {\n      return n.slice(prefixLength);\n    }\n  };\n\n  var prefixLength = EVENT_PREFIX.length;\n\n  // exports\n  scope.api.declaration.events = events;\n\n})(Polymer);",
-    "/*\r\n * Copyright 2013 The Polymer Authors. All rights reserved.\r\n * Use of this source code is governed by a BSD-style\r\n * license that can be found in the LICENSE file.\r\n */\r\n(function(scope) {\r\n\r\n  // element api\r\n\r\n  var properties = {\r\n    inferObservers: function(prototype) {\r\n      // called before prototype.observe is chained to inherited object\r\n      var observe = prototype.observe, property;\r\n      for (var n in prototype) {\r\n        if (n.slice(-7) === 'Changed') {\r\n          if (!observe) {\r\n            observe  = (prototype.observe = {});\r\n          }\r\n          property = n.slice(0, -7)\r\n          observe[property] = observe[property] || n;\r\n        }\r\n      }\r\n    },\r\n    explodeObservers: function(prototype) {\r\n      // called before prototype.observe is chained to inherited object\r\n      var o = prototype.observe;\r\n      if (o) {\r\n        var exploded = {};\r\n        for (var n in o) {\r\n          var names = n.split(' ');\r\n          for (var i=0, ni; ni=names[i]; i++) {\r\n            exploded[ni] = o[n];\r\n          }\r\n        }\r\n        prototype.observe = exploded;\r\n      }\r\n    },\r\n    optimizePropertyMaps: function(prototype) {\r\n      if (prototype.observe) {\r\n        // construct name list\r\n        var a = prototype._observeNames = [];\r\n        for (var n in prototype.observe) {\r\n          var names = n.split(' ');\r\n          for (var i=0, ni; ni=names[i]; i++) {\r\n            a.push(ni);\r\n          }\r\n        }\r\n      }\r\n      if (prototype.publish) {\r\n        // construct name list\r\n        var a = prototype._publishNames = [];\r\n        for (var n in prototype.publish) {\r\n          a.push(n);\r\n        }\r\n      }\r\n    },\r\n    publishProperties: function(prototype, base) {\r\n      // if we have any properties to publish\r\n      var publish = prototype.publish;\r\n      if (publish) {\r\n        // transcribe `publish` entries onto own prototype\r\n        this.requireProperties(publish, prototype, base);\r\n        // construct map of lower-cased property names\r\n        prototype._publishLC = this.lowerCaseMap(publish);\r\n      }\r\n    },\r\n    requireProperties: function(properties, prototype, base) {\r\n      // ensure a prototype value for each property\r\n      for (var n in properties) {\r\n        if (prototype[n] === undefined && base[n] === undefined) {\r\n          prototype[n] = properties[n];\r\n        }\r\n      }\r\n    },\r\n    lowerCaseMap: function(properties) {\r\n      var map = {};\r\n      for (var n in properties) {\r\n        map[n.toLowerCase()] = n;\r\n      }\r\n      return map;\r\n    }\r\n  };\r\n\r\n  // exports\r\n\r\n  scope.api.declaration.properties = properties;\r\n\r\n})(Polymer);\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(function(scope) {\n\n  // magic words\n\n  var ATTRIBUTES_ATTRIBUTE = 'attributes';\n  var ATTRIBUTES_REGEX = /\\s|,/;\n\n  // attributes api\n\n  var attributes = {\n    inheritAttributesObjects: function(prototype) {\n      // chain our lower-cased publish map to the inherited version\n      this.inheritObject(prototype, 'publishLC');\n      // chain our instance attributes map to the inherited version\n      this.inheritObject(prototype, '_instanceAttributes');\n    },\n    publishAttributes: function(prototype, base) {\n      // merge names from 'attributes' attribute\n      var attributes = this.getAttribute(ATTRIBUTES_ATTRIBUTE);\n      if (attributes) {\n        // get properties to publish\n        var publish = prototype.publish || (prototype.publish = {});\n        // names='a b c' or names='a,b,c'\n        var names = attributes.split(ATTRIBUTES_REGEX);\n        // record each name for publishing\n        for (var i=0, l=names.length, n; i<l; i++) {\n          // remove excess ws\n          n = names[i].trim();\n          // do not override explicit entries\n          if (n && publish[n] === undefined && base[n] === undefined) {\n            publish[n] = null;\n          }\n        }\n      }\n    },\n    // record clonable attributes from <element>\n    accumulateInstanceAttributes: function() {\n      // inherit instance attributes\n      var clonable = this.prototype._instanceAttributes;\n      // merge attributes from element\n      var a$ = this.attributes;\n      for (var i=0, l=a$.length, a; (i<l) && (a=a$[i]); i++) {  \n        if (this.isInstanceAttribute(a.name)) {\n          clonable[a.name] = a.value;\n        }\n      }\n    },\n    isInstanceAttribute: function(name) {\n      return !this.blackList[name] && name.slice(0,3) !== 'on-';\n    },\n    // do not clone these attributes onto instances\n    blackList: {\n      name: 1,\n      'extends': 1,\n      constructor: 1,\n      noscript: 1,\n      assetpath: 1,\n      'cache-csstext': 1\n    }\n  };\n\n  // add ATTRIBUTES_ATTRIBUTE to the blacklist\n  attributes.blackList[ATTRIBUTES_ATTRIBUTE] = 1;\n\n  // exports\n\n  scope.api.declaration.attributes = attributes;\n\n})(Polymer);\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  // imports\n  \n  var api = scope.api;\n  var isBase = scope.isBase;\n  var extend = scope.extend;\n\n  // prototype api\n\n  var prototype = {\n\n    register: function(name, extendeeName) {\n      // build prototype combining extendee, Polymer base, and named api\n      this.buildPrototype(name, extendeeName);\n      // register our custom element with the platform\n      this.registerPrototype(name, extendeeName);\n      // reference constructor in a global named by 'constructor' attribute\n      this.publishConstructor();\n    },\n\n    buildPrototype: function(name, extendeeName) {\n      // get our custom prototype (before chaining)\n      var extension = scope.getRegisteredPrototype(name);\n      // get basal prototype\n      var base = this.generateBasePrototype(extendeeName);\n      // implement declarative features\n      this.desugarBeforeChaining(extension, base);\n      // join prototypes\n      this.prototype = this.chainPrototypes(extension, base);\n      // more declarative features\n      this.desugarAfterChaining(name, extendeeName);\n    },\n\n    desugarBeforeChaining: function(prototype, base) {\n      // back reference declaration element\n      // TODO(sjmiles): replace `element` with `elementElement` or `declaration`\n      prototype.element = this;\n      // transcribe `attributes` declarations onto own prototype's `publish`\n      this.publishAttributes(prototype, base);\n      // `publish` properties to the prototype and to attribute watch\n      this.publishProperties(prototype, base);\n      // infer observers for `observe` list based on method names\n      this.inferObservers(prototype);\n      // desugar compound observer syntax, e.g. 'a b c' \n      this.explodeObservers(prototype);\n    },\n\n    chainPrototypes: function(prototype, base) {\n      // chain various meta-data objects to inherited versions\n      this.inheritMetaData(prototype, base);\n      // chain custom api to inherited\n      var chained = this.chainObject(prototype, base);\n      // x-platform fixup\n      ensurePrototypeTraversal(chained);\n      return chained;\n    },\n\n    inheritMetaData: function(prototype, base) {\n      // chain observe object to inherited\n      this.inheritObject('observe', prototype, base);\n      // chain publish object to inherited\n      this.inheritObject('publish', prototype, base);\n      // chain our lower-cased publish map to the inherited version\n      this.inheritObject('_publishLC', prototype, base);\n      // chain our instance attributes map to the inherited version\n      this.inheritObject('_instanceAttributes', prototype, base);\n      // chain our event delegates map to the inherited version\n      this.inheritObject('eventDelegates', prototype, base);\n    },\n\n    // implement various declarative features\n    desugarAfterChaining: function(name, extendee) {\n      // build side-chained lists to optimize iterations\n      this.optimizePropertyMaps(this.prototype);\n      // install external stylesheets as if they are inline\n      this.installSheets();\n      // adjust any paths in dom from imports\n      this.resolveElementPaths(this);\n      // compile list of attributes to copy to instances\n      this.accumulateInstanceAttributes();\n      // parse on-* delegates declared on `this` element\n      this.parseHostEvents();\n      //\n      // install a helper method this.resolvePath to aid in \n      // setting resource urls. e.g.\n      // this.$.image.src = this.resolvePath('images/foo.png')\n      this.addResolvePathApi();\n      // under ShadowDOMPolyfill, transforms to approximate missing CSS features\n      if (window.ShadowDOMPolyfill) {\n        Platform.ShadowCSS.shimStyling(this.templateContent(), name, extendee);\n      }\n      // allow custom element access to the declarative context\n      if (this.prototype.registerCallback) {\n        this.prototype.registerCallback(this);\n      }\n    },\n\n    // if a named constructor is requested in element, map a reference\n    // to the constructor to the given symbol\n    publishConstructor: function() {\n      var symbol = this.getAttribute('constructor');\n      if (symbol) {\n        window[symbol] = this.ctor;\n      }\n    },\n\n    // build prototype combining extendee, Polymer base, and named api\n    generateBasePrototype: function(extnds) {\n      var prototype = this.findBasePrototype(extnds);\n      if (!prototype) {\n        // create a prototype based on tag-name extension\n        var prototype = HTMLElement.getPrototypeForTag(extnds);\n        // insert base api in inheritance chain (if needed)\n        prototype = this.ensureBaseApi(prototype);\n        // memoize this base\n        memoizedBases[extnds] = prototype;\n      }\n      return prototype;\n    },\n\n    findBasePrototype: function(name) {\n      return memoizedBases[name];\n    },\n\n    // install Polymer instance api into prototype chain, as needed \n    ensureBaseApi: function(prototype) {\n      if (prototype.PolymerBase) {\n        return prototype;\n      }\n      var extended = Object.create(prototype);\n      // we need a unique copy of base api for each base prototype\n      // therefore we 'extend' here instead of simply chaining\n      api.publish(api.instance, extended);\n      // TODO(sjmiles): sharing methods across prototype chains is\n      // not supported by 'super' implementation which optimizes\n      // by memoizing prototype relationships.\n      // Probably we should have a version of 'extend' that is \n      // share-aware: it could study the text of each function,\n      // look for usage of 'super', and wrap those functions in\n      // closures.\n      // As of now, there is only one problematic method, so \n      // we just patch it manually.\n      // To avoid re-entrancy problems, the special super method\n      // installed is called `mixinSuper` and the mixin method\n      // must use this method instead of the default `super`.\n      this.mixinMethod(extended, prototype, api.instance.mdv, 'bind');\n      // return buffed-up prototype\n      return extended;\n    },\n\n    mixinMethod: function(extended, prototype, api, name) {\n      var $super = function(args) {\n        return prototype[name].apply(this, args);\n      };\n      extended[name] = function() {\n        this.mixinSuper = $super;\n        return api[name].apply(this, arguments);\n      }\n    },\n\n    // ensure prototype[name] inherits from a prototype.prototype[name]\n    inheritObject: function(name, prototype, base) {\n      // require an object\n      var source = prototype[name] || {};\n      // chain inherited properties onto a new object\n      prototype[name] = this.chainObject(source, base[name]);\n    },\n\n    // register 'prototype' to custom element 'name', store constructor \n    registerPrototype: function(name, extendee) { \n      var info = {\n        prototype: this.prototype\n      }\n      // native element must be specified in extends\n      var typeExtension = this.findTypeExtension(extendee);\n      if (typeExtension) {\n        info.extends = typeExtension;\n      }\n      // register the prototype with HTMLElement for name lookup\n      HTMLElement.register(name, this.prototype);\n      // register the custom type\n      this.ctor = document.registerElement(name, info);\n    },\n\n    findTypeExtension: function(name) {\n      if (name && name.indexOf('-') < 0) {\n        return name;\n      } else {\n        var p = this.findBasePrototype(name);\n        if (p.element) {\n          return this.findTypeExtension(p.element.extends);\n        }\n      }\n    }\n\n  };\n\n  // memoize base prototypes\n  var memoizedBases = {};\n\n  // implementation of 'chainObject' depends on support for __proto__\n  if (Object.__proto__) {\n    prototype.chainObject = function(object, inherited) {\n      if (object && inherited && object !== inherited) {\n        object.__proto__ = inherited;\n      }\n      return object;\n    }\n  } else {\n    prototype.chainObject = function(object, inherited) {\n      if (object && inherited && object !== inherited) {\n        var chained = Object.create(inherited);\n        object = extend(chained, object);\n      }\n      return object;\n    }\n  }\n\n  // On platforms that do not support __proto__ (versions of IE), the prototype\n  // chain of a custom element is simulated via installation of __proto__.\n  // Although custom elements manages this, we install it here so it's\n  // available during desugaring.\n  function ensurePrototypeTraversal(prototype) {\n    if (!Object.__proto__) {\n      var ancestor = Object.getPrototypeOf(prototype);\n      prototype.__proto__ = ancestor;\n      if (isBase(ancestor)) {\n        ancestor.__proto__ = Object.getPrototypeOf(ancestor);\n      }\n    }\n  }\n\n  // exports\n\n  api.declaration.prototype = prototype;\n\n})(Polymer);\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  var queue = {\n    // tell the queue to wait for an element to be ready\n    wait: function(element, check, go) {\n      if (this.indexOf(element) === -1) {\n        this.add(element);\n        element.__check = check;\n        element.__go = go;\n      }\n      return (this.indexOf(element) !== 0);\n    },\n    add: function(element) {\n      //console.log('queueing', element.name);\n      queueForElement(element).push(element);\n    },\n    indexOf: function(element) {\n      var i = queueForElement(element).indexOf(element);\n      if (i >= 0 && document.contains(element)) {\n        i += (HTMLImports.useNative || HTMLImports.ready) ? \n          importQueue.length : 1e9;\n      }\n      return i;  \n    },\n    // tell the queue an element is ready to be registered\n    go: function(element) {\n      var readied = this.remove(element);\n      if (readied) {\n        readied.__go.call(readied);\n        readied.__check = readied.__go = null;\n        this.check();\n      }\n    },\n    remove: function(element) {\n      var i = this.indexOf(element);\n      if (i !== 0) {\n        //console.warn('queue order wrong', i);\n        return;\n      }\n      return queueForElement(element).shift();\n    },\n    check: function() {\n      // next\n      var element = this.nextElement();\n      if (element) {\n        element.__check.call(element);\n      }\n      if (this.canReady()) {\n        this.ready();\n        return true;\n      }\n    },\n    nextElement: function() {\n      return nextQueued();\n    },\n    canReady: function() {\n      return !this.waitToReady && this.isEmpty();\n    },\n    isEmpty: function() {\n      return !importQueue.length && !mainQueue.length;\n    },\n    ready: function() {\n      // TODO(sorvell): As an optimization, turn off CE polyfill upgrading\n      // while registering. This way we avoid having to upgrade each document\n      // piecemeal per registration and can instead register all elements\n      // and upgrade once in a batch. Without this optimization, upgrade time\n      // degrades significantly when SD polyfill is used. This is mainly because\n      // querying the document tree for elements is slow under the SD polyfill.\n      if (CustomElements.ready === false) {\n        CustomElements.upgradeDocumentTree(document);\n        CustomElements.ready = true;\n      }\n      if (readyCallbacks) {\n        var fn;\n        while (readyCallbacks.length) {\n          fn = readyCallbacks.shift();\n          fn();\n        }\n      }\n    },\n    addReadyCallback: function(callback) {\n      if (callback) {\n        readyCallbacks.push(callback);\n      }\n    },\n    waitToReady: true\n  };\n\n  var importQueue = [];\n  var mainQueue = [];\n  var readyCallbacks = [];\n\n  function queueForElement(element) {\n    return document.contains(element) ? mainQueue : importQueue;\n  }\n\n  function nextQueued() {\n    return importQueue.length ? importQueue[0] : mainQueue[0];\n  }\n\n  var polymerReadied = false; \n\n  document.addEventListener('WebComponentsReady', function() {\n    CustomElements.ready = false;\n  });\n  \n  function whenPolymerReady(callback) {\n    queue.waitToReady = true;\n    CustomElements.ready = false;\n    HTMLImports.whenImportsReady(function() {\n      queue.addReadyCallback(callback);\n      queue.waitToReady = false;\n      queue.check();\n    });\n  }\n\n  // exports\n  scope.queue = queue;\n  scope.whenPolymerReady = whenPolymerReady;\n})(Polymer);\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  var whenPolymerReady = scope.whenPolymerReady;\n\n  function importElements(elementOrFragment, callback) {\n    if (elementOrFragment) {\n      document.head.appendChild(elementOrFragment);\n      whenPolymerReady(callback);\n    } else if (callback) {\n      callback();\n    }\n  }\n\n  function importUrls(urls, callback) {\n    if (urls && urls.length) {\n        var frag = document.createDocumentFragment();\n        for (var i=0, l=urls.length, url, link; (i<l) && (url=urls[i]); i++) {\n          link = document.createElement('link');\n          link.rel = 'import';\n          link.href = url;\n          frag.appendChild(link);\n        }\n        importElements(frag, callback);\n    } else if (callback) {\n      callback();\n    }\n  }\n\n  // exports\n  scope.import = importUrls;\n  scope.importElements = importElements;\n\n})(Polymer);\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  // imports\n\n  var extend = scope.extend;\n  var api = scope.api;\n  var queue = scope.queue;\n  var whenPolymerReady = scope.whenPolymerReady;\n  var getRegisteredPrototype = scope.getRegisteredPrototype;\n  var waitingForPrototype = scope.waitingForPrototype;\n\n  // declarative implementation: <polymer-element>\n\n  var prototype = extend(Object.create(HTMLElement.prototype), {\n\n    createdCallback: function() {\n      if (this.getAttribute('name')) {\n        this.init();\n      }\n    },\n\n    init: function() {\n      // fetch declared values\n      this.name = this.getAttribute('name');\n      this.extends = this.getAttribute('extends');\n      // initiate any async resource fetches\n      this.loadResources();\n      // register when all constraints are met\n      this.registerWhenReady();\n    },\n\n    registerWhenReady: function() {\n     if (this.registered\n       || this.waitingForPrototype(this.name)\n       || this.waitingForQueue()\n       || this.waitingForResources()) {\n          return;\n      }\n      // TODO(sorvell): ends up calling '_register' by virtue\n      // of `waitingForQueue` (see below)\n      queue.go(this);\n    },\n\n    // TODO(sorvell): refactor, this method is private-ish, but it's being\n    // called by the queue object.\n    _register: function() {\n      //console.log('registering', this.name);\n      //console.group('registering', this.name);\n      // warn if extending from a custom element not registered via Polymer\n      if (isCustomTag(this.extends) && !isRegistered(this.extends)) {\n        console.warn('%s is attempting to extend %s, an unregistered element ' +\n            'or one that was not registered with Polymer.', this.name,\n            this.extends);\n      }\n      this.register(this.name, this.extends);\n      this.registered = true;\n      //console.groupEnd();\n    },\n\n    waitingForPrototype: function(name) {\n      if (!getRegisteredPrototype(name)) {\n        // then wait for a prototype\n        waitingForPrototype(name, this);\n        // emulate script if user is not supplying one\n        this.handleNoScript(name);\n        // prototype not ready yet\n        return true;\n      }\n    },\n\n    handleNoScript: function(name) {\n      // if explicitly marked as 'noscript'\n      if (this.hasAttribute('noscript') && !this.noscript) {\n        this.noscript = true;\n        // TODO(sorvell): CustomElements polyfill awareness:\n        // noscript elements should upgrade in logical order\n        // script injection ensures this under native custom elements;\n        // under imports + ce polyfills, scripts run before upgrades.\n        // dependencies should be ready at upgrade time so register\n        // prototype at this time.\n        if (window.CustomElements && !CustomElements.useNative) {\n          Polymer(name);\n        } else {\n          var script = document.createElement('script');\n          script.textContent = 'Polymer(\\'' + name + '\\');';\n          this.appendChild(script);\n        }\n      }\n    },\n\n    waitingForResources: function() {\n      return this._needsResources;\n    },\n\n    // NOTE: Elements must be queued in proper order for inheritance/composition\n    // dependency resolution. Previously this was enforced for inheritance,\n    // and by rule for composition. It's now entirely by rule.\n    waitingForQueue: function() {\n      return queue.wait(this, this.registerWhenReady, this._register);\n    },\n\n    loadResources: function() {\n      this._needsResources = true;\n      this.loadStyles(function() {\n        this._needsResources = false;\n        this.registerWhenReady();\n      }.bind(this));\n    }\n\n  });\n\n  // semi-pluggable APIs \n\n  // TODO(sjmiles): should be fully pluggable (aka decoupled, currently\n  // the various plugins are allowed to depend on each other directly)\n  api.publish(api.declaration, prototype);\n\n  // utility and bookkeeping\n\n  function isRegistered(name) {\n    return Boolean(HTMLElement.getPrototypeForTag(name));\n  }\n\n  function isCustomTag(name) {\n    return (name && name.indexOf('-') >= 0);\n  }\n\n  // exports\n\n  scope.getRegisteredPrototype = getRegisteredPrototype;\n  \n  // boot tasks\n\n  whenPolymerReady(function() {\n    document.body.removeAttribute('unresolved');\n    document.dispatchEvent(\n      new CustomEvent('polymer-ready', {bubbles: true})\n    );\n  });\n\n  // register polymer-element with document\n\n  document.registerElement('polymer-element', {prototype: prototype});\n\n})(Polymer);\n"
-  ]
-}
\ No newline at end of file
diff --git a/runtime/bin/vmservice/client/deployed/web/packages/polymer/src/js/polymer/polymer.js.map b/runtime/bin/vmservice/client/deployed/web/packages/polymer/src/js/polymer/polymer.js.map
deleted file mode 100644
index 81a7e7a..0000000
--- a/runtime/bin/vmservice/client/deployed/web/packages/polymer/src/js/polymer/polymer.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"file":"polymer.js","sources":["../src/polymer.js","../src/boot.js","../src/lib/lang.js","../src/lib/job.js","../src/lib/dom.js","../src/lib/super.js","../src/lib/deserialize.js","../src/api.js","../src/instance/utils.js","../src/instance/events.js","../src/instance/attributes.js","../src/instance/properties.js","../src/instance/mdv.js","../src/instance/base.js","../src/instance/styles.js","../src/declaration/polymer.js","../src/declaration/path.js","../src/declaration/styles.js","../src/declaration/events.js","../src/declaration/properties.js","../src/declaration/attributes.js","../src/declaration/prototype.js","../src/declaration/queue.js","../src/declaration/import.js","../src/declaration/polymer-element.js"],"names":["Polymer","window","scope","extend","prototype","api","Object","getOwnPropertyNames","forEach","n","pd","getOwnPropertyDescriptor","defineProperty","value","nom","job","callback","wait","stop","Job","this","go","inContext","context","boundComplete","complete","bind","h","setTimeout","handle","clearTimeout","requestAnimationFrame","cancelAnimationFrame","call","registry","HTMLElement","register","tag","getPrototypeForTag","getPrototypeOf","document","createElement","originalStopPropagation","Event","stopPropagation","cancelBubble","apply","arguments","$super","arrayOfArgs","caller","_super","nameInThis","console","warn","memoizeSuper","fn","nextSuper","proto","name","method","p","__proto__","n$","i","l","length","d","super","deserializeValue","currentValue","inferredType","Date","typeHandlers","string","date","parse","now","boolean","number","parseFloat","parseInt","isNaN","object","JSON","replace","e","function","declaration","instance","publish","apis","utils","async","args","timeout","Platform","flush","cancelAsync","fire","type","detail","onNode","bubbles","cancelable","node","event","CustomEvent","undefined","dispatchEvent","asyncFire","classFollows","anew","old","className","classList","remove","add","nop","nob","asyncMethod","log","logFlags","EVENT_PREFIX","events","addHostListeners","eventDelegates","keys","localName","bindable","eventName","self","PolymerExpressions","prepareEventBinding","Path","get","resolveEventHandler","model","path","getValueFrom","dispatchMethod","obj","group","groupEnd","attributes","copyInstanceAttributes","a$","_instanceAttributes","k","hasAttribute","setAttribute","takeAttributes","_publishLC","a","attributeToProperty","propertyForAttribute","search","bindPattern","match","stringValue","serializeValue","reflectPropertyToAttribute","serializedValue","removeAttribute","bindProperties","inA","inProperty","observable","LOG_BIND_PROPS","inB","inPath","v","discardChanges","setValue","Observer","defineComputedProperty","properties","observeProperties","_observeNames","pn$","_publishNames","o","_propertyObserver","CompoundObserver","registerObservers","addPath","observeArrayValue","observe","open","notifyPropertyChanges","newValues","oldValues","paths","called","invokeMethod","callbackName","Array","isArray","closeNamedObserver","observer","ArrayObserver","registerNamedObserver","bindProperty","property","observers","_observers","push","closeObservers","closeObserverArray","observerArray","close","o$","_namedObservers","closeNamedObservers","findEventController","parentNode","lightDomController","host","syntax","ctlr","mdv","instanceTemplate","template","dom","createInstance","bindings_","enableBindingsReflection","path_","mixinSuper","asyncUnbindAll","_unbound","unbind","_unbindAllJob","unbindAll","cancelUnbindAll","mustachePattern","isBase","hasOwnProperty","PolymerBase","base","created","ready","createdCallback","templateInstance","prepareElement","_elementPrepared","shadowRoots","parseDeclarations","attachedCallback","attached","enteredView","hasBeenAttached","domReady","detachedCallback","preventDispose","detached","leftView","enteredViewCallback","leftViewCallback","enteredDocumentCallback","leftDocumentCallback","element","parseDeclaration","elementElement","fetchTemplate","root","shadowFromTemplate","querySelector","createShadowRoot","appendChild","shadowRootReady","lightFromTemplate","refNode","insertBefore","marshalNodeReferences","PointerGestures","$","querySelectorAll","id","attributeChangedCallback","getAttribute","attributeChanged","onMutation","listener","MutationObserver","mutations","disconnect","childList","subtree","constructor","Base","shimCssText","cssText","is","selector","ShadowCSS","makeScopeSelector","STYLE_SCOPE_ATTRIBUTE","STYLE_CONTROLLER_SCOPE","styles","installControllerStyles","findStyleScope","scopeHasNamedStyle","cssTextForScope","installScopeCssText","installScopeStyle","style","s","textContent","ShadowDOMPolyfill","cssTextToScopeStyle","applyStyleToScope","_scopeStyles","script","_currentScript","getRegisteredPrototype","registerPrototype","notifyPrototype","waitingForPrototype","client","waitPrototype","registerWhenReady","prototypesByName","declarations","deliverDeclarations","resolveElementPaths","urlResolver","resolveDom","addResolvePathApi","assetPath","URL","ownerDocument","baseURI","resolvePath","urlPath","u","href","importRuleForSheet","sheet","baseUrl","head","clone","createStyleElement","attr","firstElementChild","s$","nextElementSibling","cssTextFromSheet","__resource","matchesSelector","inSelector","matches","STYLE_SELECTOR","STYLE_LOADABLE_MATCH","SHEET_SELECTOR","STYLE_GLOBAL_SCOPE","SCOPE_ATTR","loadStyles","content","templateContent","convertSheetsToStyles","findLoadableStyles","styleResolver","c","copySheetAttributes","replaceChild","link","loadables","installSheets","cacheSheets","cacheStyles","installLocalSheets","installGlobalStyles","sheets","findNodes","removeChild","filter","firstChild","matcher","nodes","array","templateNodes","concat","styleForScope","scopeDescriptor","webkitMatchesSelector","mozMatchesSelector","parseHostEvents","delegates","addAttributeDelegates","hasEventPrefix","removeEventPrefix","trim","slice","prefixLength","inferObservers","explodeObservers","exploded","ni","names","split","optimizePropertyMaps","publishProperties","requireProperties","lowerCaseMap","map","toLowerCase","ATTRIBUTES_ATTRIBUTE","ATTRIBUTES_REGEX","inheritAttributesObjects","inheritObject","publishAttributes","accumulateInstanceAttributes","clonable","isInstanceAttribute","blackList","extends","noscript","assetpath","cache-csstext","ensurePrototypeTraversal","ancestor","extendeeName","buildPrototype","publishConstructor","extension","generateBasePrototype","desugarBeforeChaining","chainPrototypes","desugarAfterChaining","inheritMetaData","chained","chainObject","extendee","shimStyling","registerCallback","symbol","ctor","extnds","findBasePrototype","ensureBaseApi","memoizedBases","extended","create","mixinMethod","source","info","typeExtension","findTypeExtension","registerElement","indexOf","inherited","queueForElement","contains","mainQueue","importQueue","nextQueued","whenPolymerReady","queue","waitToReady","CustomElements","HTMLImports","whenImportsReady","addReadyCallback","check","__check","__go","useNative","readied","shift","nextElement","canReady","isEmpty","upgradeDocumentTree","readyCallbacks","addEventListener","importElements","elementOrFragment","importUrls","urls","url","frag","createDocumentFragment","rel","import","isRegistered","Boolean","isCustomTag","init","loadResources","registered","waitingForQueue","waitingForResources","_register","handleNoScript","_needsResources","body"],"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 */\nPolymer = {};\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// TODO(sorvell): this ensures Polymer is an object and not a function\n// Platform is currently defining it as a function to allow for async loading\n// of polymer; once we refine the loading process this likely goes away.\nif (typeof window.Polymer === 'function') {\n  Polymer = {};\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  // copy own properties from 'api' to 'prototype, with name hinting for 'super'\n  function extend(prototype, api) {\n    if (prototype && api) {\n      // use only own properties of 'api'\n      Object.getOwnPropertyNames(api).forEach(function(n) {\n        // acquire property descriptor\n        var pd = Object.getOwnPropertyDescriptor(api, n);\n        if (pd) {\n          // clone property via descriptor\n          Object.defineProperty(prototype, n, pd);\n          // cache name-of-method for 'super' engine\n          if (typeof pd.value == 'function') {\n            // hint the 'super' engine\n            pd.value.nom = n;\n          }\n        }\n      });\n    }\n    return prototype;\n  }\n  \n  // exports\n\n  scope.extend = extend;\n\n})(Polymer);\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  // usage\n  \n  // invoke cb.call(this) in 100ms, unless the job is re-registered,\n  // which resets the timer\n  // \n  // this.myJob = this.job(this.myJob, cb, 100)\n  //\n  // returns a job handle which can be used to re-register a job\n\n  var Job = function(inContext) {\n    this.context = inContext;\n    this.boundComplete = this.complete.bind(this)\n  };\n  Job.prototype = {\n    go: function(callback, wait) {\n      this.callback = callback;\n      var h;\n      if (!wait) {\n        h = requestAnimationFrame(this.boundComplete);\n        this.handle = function() {\n          cancelAnimationFrame(h);\n        }\n      } else {\n        h = setTimeout(this.boundComplete, wait);\n        this.handle = function() {\n          clearTimeout(h);\n        }\n      }\n    },\n    stop: function() {\n      if (this.handle) {\n        this.handle();\n        this.handle = null;\n      }\n    },\n    complete: function() {\n      if (this.handle) {\n        this.stop();\n        this.callback.call(this.context);\n      }\n    }\n  };\n  \n  function job(job, callback, wait) {\n    if (job) {\n      job.stop();\n    } else {\n      job = new Job(this);\n    }\n    job.go(callback, wait);\n    return job;\n  }\n  \n  // exports \n\n  scope.job = job;\n  \n})(Polymer);\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  var registry = {};\n\n  HTMLElement.register = function(tag, prototype) {\n    registry[tag] = prototype;\n  }\n\n  // get prototype mapped to node <tag>\n  HTMLElement.getPrototypeForTag = function(tag) {\n    var prototype = !tag ? HTMLElement.prototype : registry[tag];\n    // TODO(sjmiles): creating <tag> is likely to have wasteful side-effects\n    return prototype || Object.getPrototypeOf(document.createElement(tag));\n  };\n\n  // we have to flag propagation stoppage for the event dispatcher\n  var originalStopPropagation = Event.prototype.stopPropagation;\n  Event.prototype.stopPropagation = function() {\n    this.cancelBubble = true;\n    originalStopPropagation.apply(this, arguments);\n  };\n  \n  // TODO(sorvell): remove when we're sure imports does not need\n  // to load stylesheets\n  /*\n  HTMLImports.importer.preloadSelectors += \n      ', polymer-element link[rel=stylesheet]';\n  */\n})(Polymer);\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    // super\n\n    // `arrayOfArgs` is an optional array of args like one might pass\n    // to `Function.apply`\n\n    // TODO(sjmiles):\n    //    $super must be installed on an instance or prototype chain\n    //    as `super`, and invoked via `this`, e.g.\n    //      `this.super();`\n\n    //    will not work if function objects are not unique, for example,\n    //    when using mixins.\n    //    The memoization strategy assumes each function exists on only one \n    //    prototype chain i.e. we use the function object for memoizing)\n    //    perhaps we can bookkeep on the prototype itself instead\n    function $super(arrayOfArgs) {\n      // since we are thunking a method call, performance is important here: \n      // memoize all lookups, once memoized the fast path calls no other \n      // functions\n      //\n      // find the caller (cannot be `strict` because of 'caller')\n      var caller = $super.caller;\n      // memoized 'name of method' \n      var nom = caller.nom;\n      // memoized next implementation prototype\n      var _super = caller._super;\n      if (!_super) {\n        if (!nom) {\n          nom = caller.nom = nameInThis.call(this, caller);\n        }\n        if (!nom) {\n          console.warn('called super() on a method not installed declaratively (has no .nom property)');\n        }\n        // super prototype is either cached or we have to find it\n        // by searching __proto__ (at the 'top')\n        _super = memoizeSuper(caller, nom, getPrototypeOf(this));\n      }\n      if (!_super) {\n        // if _super is falsey, there is no super implementation\n        //console.warn('called $super(' + nom + ') where there is no super implementation');\n      } else {\n        // our super function\n        var fn = _super[nom];\n        // memoize information so 'fn' can call 'super'\n        if (!fn._super) {\n          memoizeSuper(fn, nom, _super);\n        }\n        // invoke the inherited method\n        // if 'fn' is not function valued, this will throw\n        return fn.apply(this, arrayOfArgs || []);\n      }\n    }\n\n    function nextSuper(proto, name, caller) {\n      // look for an inherited prototype that implements name\n      while (proto) {\n        if ((proto[name] !== caller) && proto[name]) {\n          return proto;\n        }\n        proto = getPrototypeOf(proto);\n      }\n    }\n\n    function memoizeSuper(method, name, proto) {\n      // find and cache next prototype containing `name`\n      // we need the prototype so we can do another lookup\n      // from here\n      method._super = nextSuper(proto, name, method);\n      if (method._super) {\n        // _super is a prototype, the actual method is _super[name]\n        // tag super method with it's name for further lookups\n        method._super[name].nom = name;\n      }\n      return method._super;\n    }\n\n    function nameInThis(value) {\n      var p = this.__proto__;\n      while (p && p !== HTMLElement.prototype) {\n        // TODO(sjmiles): getOwnPropertyNames is absurdly expensive\n        var n$ = Object.getOwnPropertyNames(p);\n        for (var i=0, l=n$.length, n; i<l && (n=n$[i]); i++) {\n          var d = Object.getOwnPropertyDescriptor(p, n);\n          if (typeof d.value === 'function' && d.value === value) {\n            return n;\n          }\n        }\n        p = p.__proto__;\n      }\n    }\n\n    // NOTE: In some platforms (IE10) the prototype chain is faked via \n    // __proto__. Therefore, always get prototype via __proto__ instead of\n    // the more standard Object.getPrototypeOf.\n    function getPrototypeOf(prototype) {\n      return prototype.__proto__;\n    }\n\n    // utility function to precompute name tags for functions\n    // in a (unchained) prototype\n    function hintSuper(prototype) {\n      // tag functions with their prototype name to optimize\n      // super call invocations\n      for (var n in prototype) {\n        var pd = Object.getOwnPropertyDescriptor(prototype, n);\n        if (pd && typeof pd.value === 'function') {\n          pd.value.nom = n;\n        }\n      }\n    }\n\n    // exports\n\n    scope.super = $super;\n\n})(Polymer);\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  var typeHandlers = {\n    string: function(value) {\n      return value;\n    },\n    date: function(value) {\n      return new Date(Date.parse(value) || Date.now());\n    },\n    boolean: function(value) {\n      if (value === '') {\n        return true;\n      }\n      return value === 'false' ? false : !!value;\n    },\n    number: function(value) {\n      var n = parseFloat(value);\n      // hex values like \"0xFFFF\" parseFloat as 0\n      if (n === 0) {\n        n = parseInt(value);\n      }\n      return isNaN(n) ? value : n;\n      // this code disabled because encoded values (like \"0xFFFF\")\n      // do not round trip to their original format\n      //return (String(floatVal) === value) ? floatVal : value;\n    },\n    object: function(value, currentValue) {\n      if (currentValue === null) {\n        return value;\n      }\n      try {\n        // If the string is an object, we can parse is with the JSON library.\n        // include convenience replace for single-quotes. If the author omits\n        // quotes altogether, parse will fail.\n        return JSON.parse(value.replace(/'/g, '\"'));\n      } catch(e) {\n        // The object isn't valid JSON, return the raw value\n        return value;\n      }\n    },\n    // avoid deserialization of functions\n    'function': function(value, currentValue) {\n      return currentValue;\n    }\n  };\n\n  function deserializeValue(value, currentValue) {\n    // attempt to infer type from default value\n    var inferredType = typeof currentValue;\n    // invent 'date' type value for Date\n    if (currentValue instanceof Date) {\n      inferredType = 'date';\n    }\n    // delegate deserialization via type string\n    return typeHandlers[inferredType](value, currentValue);\n  }\n\n  // exports\n\n  scope.deserializeValue = deserializeValue;\n\n})(Polymer);\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  // imports\n\n  var extend = scope.extend;\n\n  // module\n\n  var api = {};\n\n  api.declaration = {};\n  api.instance = {};\n\n  api.publish = function(apis, prototype) {\n    for (var n in apis) {\n      extend(prototype, apis[n]);\n    }\n  }\n\n  // exports\n\n  scope.api = api;\n\n})(Polymer);\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  var utils = {\n    /**\n      * Invokes a function asynchronously. The context of the callback\n      * function is bound to 'this' automatically.\n      * @method async\n      * @param {Function|String} method\n      * @param {any|Array} args\n      * @param {number} timeout\n      */\n    async: function(method, args, timeout) {\n      // when polyfilling Object.observe, ensure changes \n      // propagate before executing the async method\n      Platform.flush();\n      // second argument to `apply` must be an array\n      args = (args && args.length) ? args : [args];\n      // function to invoke\n      var fn = function() {\n        (this[method] || method).apply(this, args);\n      }.bind(this);\n      // execute `fn` sooner or later\n      var handle = timeout ? setTimeout(fn, timeout) :\n          requestAnimationFrame(fn);\n      // NOTE: switch on inverting handle to determine which time is used.\n      return timeout ? handle : ~handle;\n    },\n    cancelAsync: function(handle) {\n      if (handle < 0) {\n        cancelAnimationFrame(~handle);\n      } else {\n        clearTimeout(handle);\n      }\n    },\n    /**\n      * Fire an event.\n      * @method fire\n      * @returns {Object} event\n      * @param {string} type An event name.\n      * @param {any} detail\n      * @param {Node} onNode Target node.\n      */\n    fire: function(type, detail, onNode, bubbles, cancelable) {\n      var node = onNode || this;\n      var detail = detail || {};\n      var event = new CustomEvent(type, {\n        bubbles: (bubbles !== undefined ? bubbles : true), \n        cancelable: (cancelable !== undefined ? cancelable : true), \n        detail: detail\n      });\n      node.dispatchEvent(event);\n      return event;\n    },\n    /**\n      * Fire an event asynchronously.\n      * @method asyncFire\n      * @param {string} type An event name.\n      * @param detail\n      * @param {Node} toNode Target node.\n      */\n    asyncFire: function(/*inType, inDetail*/) {\n      this.async(\"fire\", arguments);\n    },\n    /**\n      * Remove class from old, add class to anew, if they exist\n      * @param classFollows\n      * @param anew A node.\n      * @param old A node\n      * @param className\n      */\n    classFollows: function(anew, old, className) {\n      if (old) {\n        old.classList.remove(className);\n      }\n      if (anew) {\n        anew.classList.add(className);\n      }\n    }\n  };\n\n  // no-operation function for handy stubs\n  var nop = function() {};\n\n  // null-object for handy stubs\n  var nob = {};\n\n  // deprecated\n\n  utils.asyncMethod = utils.async;\n\n  // exports\n\n  scope.api.instance.utils = utils;\n  scope.nop = nop;\n  scope.nob = nob;\n\n})(Polymer);\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  // imports\n\n  var log = window.logFlags || {};\n  var EVENT_PREFIX = 'on-';\n\n  // instance events api\n  var events = {\n    // read-only\n    EVENT_PREFIX: EVENT_PREFIX,\n    // event listeners on host\n    addHostListeners: function() {\n      var events = this.eventDelegates;\n      log.events && (Object.keys(events).length > 0) && console.log('[%s] addHostListeners:', this.localName, events);\n      // NOTE: host events look like bindings but really are not;\n      // (1) we don't want the attribute to be set and (2) we want to support\n      // multiple event listeners ('host' and 'instance') and Node.bind\n      // by default supports 1 thing being bound.\n      // We do, however, leverage the event hookup code in PolymerExpressions\n      // so that we have a common code path for handling declarative events.\n      var self = this, bindable, eventName;\n      for (var n in events) {\n        eventName = EVENT_PREFIX + n;\n        bindable = PolymerExpressions.prepareEventBinding(\n          Path.get(events[n]),\n          eventName, \n          {\n            resolveEventHandler: function(model, path, node) {\n              var fn = path.getValueFrom(self);\n              if (fn) {\n                return fn.bind(self);\n              }\n            }\n          }\n        );\n        bindable(this, this, false);\n      }\n    },\n    // call 'method' or function method on 'obj' with 'args', if the method exists\n    dispatchMethod: function(obj, method, args) {\n      if (obj) {\n        log.events && console.group('[%s] dispatch [%s]', obj.localName, method);\n        var fn = typeof method === 'function' ? method : obj[method];\n        if (fn) {\n          fn[args ? 'apply' : 'call'](obj, args);\n        }\n        log.events && console.groupEnd();\n        Platform.flush();\n      }\n    }\n  };\n\n  // exports\n\n  scope.api.instance.events = events;\n\n})(Polymer);\n","/*\r\n * Copyright 2013 The Polymer Authors. All rights reserved.\r\n * Use of this source code is governed by a BSD-style\r\n * license that can be found in the LICENSE file.\r\n */\r\n(function(scope) {\r\n\r\n  // instance api for attributes\r\n\r\n  var attributes = {\r\n    copyInstanceAttributes: function () {\r\n      var a$ = this._instanceAttributes;\r\n      for (var k in a$) {\r\n        if (!this.hasAttribute(k)) {\r\n          this.setAttribute(k, a$[k]);\r\n        }\r\n      }\r\n    },\r\n    // for each attribute on this, deserialize value to property as needed\r\n    takeAttributes: function() {\r\n      // if we have no publish lookup table, we have no attributes to take\r\n      // TODO(sjmiles): ad hoc\r\n      if (this._publishLC) {\r\n        for (var i=0, a$=this.attributes, l=a$.length, a; (a=a$[i]) && i<l; i++) {\r\n          this.attributeToProperty(a.name, a.value);\r\n        }\r\n      }\r\n    },\r\n    // if attribute 'name' is mapped to a property, deserialize\r\n    // 'value' into that property\r\n    attributeToProperty: function(name, value) {\r\n      // try to match this attribute to a property (attributes are\r\n      // all lower-case, so this is case-insensitive search)\r\n      var name = this.propertyForAttribute(name);\r\n      if (name) {\r\n        // filter out 'mustached' values, these are to be\r\n        // replaced with bound-data and are not yet values\r\n        // themselves\r\n        if (value && value.search(scope.bindPattern) >= 0) {\r\n          return;\r\n        }\r\n        // get original value\r\n        var currentValue = this[name];\r\n        // deserialize Boolean or Number values from attribute\r\n        var value = this.deserializeValue(value, currentValue);\r\n        // only act if the value has changed\r\n        if (value !== currentValue) {\r\n          // install new value (has side-effects)\r\n          this[name] = value;\r\n        }\r\n      }\r\n    },\r\n    // return the published property matching name, or undefined\r\n    propertyForAttribute: function(name) {\r\n      var match = this._publishLC && this._publishLC[name];\r\n      //console.log('propertyForAttribute:', name, 'matches', match);\r\n      return match;\r\n    },\r\n    // convert representation of 'stringValue' based on type of 'currentValue'\r\n    deserializeValue: function(stringValue, currentValue) {\r\n      return scope.deserializeValue(stringValue, currentValue);\r\n    },\r\n    serializeValue: function(value, inferredType) {\r\n      if (inferredType === 'boolean') {\r\n        return value ? '' : undefined;\r\n      } else if (inferredType !== 'object' && inferredType !== 'function'\r\n          && value !== undefined) {\r\n        return value;\r\n      }\r\n    },\r\n    reflectPropertyToAttribute: function(name) {\r\n      var inferredType = typeof this[name];\r\n      // try to intelligently serialize property value\r\n      var serializedValue = this.serializeValue(this[name], inferredType);\r\n      // boolean properties must reflect as boolean attributes\r\n      if (serializedValue !== undefined) {\r\n        this.setAttribute(name, serializedValue);\r\n        // TODO(sorvell): we should remove attr for all properties\r\n        // that have undefined serialization; however, we will need to\r\n        // refine the attr reflection system to achieve this; pica, for example,\r\n        // relies on having inferredType object properties not removed as\r\n        // attrs.\r\n      } else if (inferredType === 'boolean') {\r\n        this.removeAttribute(name);\r\n      }\r\n    }\r\n  };\r\n\r\n  // exports\r\n\r\n  scope.api.instance.attributes = attributes;\r\n\r\n})(Polymer);\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(function(scope) {\n\n  // imports\n\n  var log = window.logFlags || {};\n\n  // magic words\n\n  var OBSERVE_SUFFIX = 'Changed';\n\n  // element api\n\n  var empty = [];\n\n  var properties = {\n    observeProperties: function() {\n      var n$ = this._observeNames, pn$ = this._publishNames;\n      if ((n$ && n$.length) || (pn$ && pn$.length)) {\n        var self = this;\n        var o = this._propertyObserver = new CompoundObserver();\n        // keep track of property observer so we can shut it down\n        this.registerObservers([o]);\n        for (var i=0, l=n$.length, n; (i<l) && (n=n$[i]); i++) {\n          o.addPath(this, n);\n          // observer array properties\n          var pd = Object.getOwnPropertyDescriptor(this.__proto__, n);\n          if (pd && pd.value) {\n            this.observeArrayValue(n, pd.value, null);\n          }\n        }\n        for (var i=0, l=pn$.length, n; (i<l) && (n=pn$[i]); i++) {\n          if (!this.observe || (this.observe[n] === undefined)) {\n            o.addPath(this, n);\n          }\n        }\n        o.open(this.notifyPropertyChanges, this);\n      }\n    },\n    notifyPropertyChanges: function(newValues, oldValues, paths) {\n      var name, method, called = {};\n      for (var i in oldValues) {\n        // note: paths is of form [object, path, object, path]\n        name = paths[2 * i + 1];\n        if (this.publish[name] !== undefined) {\n          this.reflectPropertyToAttribute(name);\n        }\n        method = this.observe[name];\n        if (method) {\n          this.observeArrayValue(name, newValues[i], oldValues[i]);\n          if (!called[method]) {\n            called[method] = true;\n            // observes the value if it is an array\n            this.invokeMethod(method, [oldValues[i], newValues[i], arguments]);\n          }\n        }\n      }\n    },\n    observeArrayValue: function(name, value, old) {\n      // we only care if there are registered side-effects\n      var callbackName = this.observe[name];\n      if (callbackName) {\n        // if we are observing the previous value, stop\n        if (Array.isArray(old)) {\n          log.observe && console.log('[%s] observeArrayValue: unregister observer [%s]', this.localName, name);\n          this.closeNamedObserver(name + '__array');\n        }\n        // if the new value is an array, being observing it\n        if (Array.isArray(value)) {\n          log.observe && console.log('[%s] observeArrayValue: register observer [%s]', this.localName, name, value);\n          var observer = new ArrayObserver(value);\n          observer.open(function(value, old) {\n            this.invokeMethod(callbackName, [old]);\n          }, this);\n          this.registerNamedObserver(name + '__array', observer);\n        }\n      }\n    },\n    bindProperty: function(property, observable) {\n      // apply Polymer two-way reference binding\n      return bindProperties(this, property, observable);\n    },\n    invokeMethod: function(method, args) {\n      var fn = this[method] || method;\n      if (typeof fn === 'function') {\n        fn.apply(this, args);\n      }\n    },\n    registerObservers: function(observers) {\n      this._observers.push(observers);\n    },\n    // observer array items are arrays of observers.\n    closeObservers: function() {\n      for (var i=0, l=this._observers.length; i<l; i++) {\n        this.closeObserverArray(this._observers[i]);\n      }\n      this._observers = [];\n    },\n    closeObserverArray: function(observerArray) {\n      for (var i=0, l=observerArray.length, o; i<l; i++) {\n        o = observerArray[i];\n        if (o && o.close) {\n          o.close();\n        }\n      }\n    },\n    // bookkeeping observers for memory management\n    registerNamedObserver: function(name, observer) {\n      var o$ = this._namedObservers || (this._namedObservers = {});\n      o$[name] = observer;\n    },\n    closeNamedObserver: function(name) {\n      var o$ = this._namedObservers;\n      if (o$ && o$[name]) {\n        o$[name].close();\n        o$[name] = null;\n        return true;\n      }\n    },\n    closeNamedObservers: function() {\n      if (this._namedObservers) {\n        var keys=Object.keys(this._namedObservers);\n        for (var i=0, l=keys.length, k, o; (i < l) && (k=keys[i]); i++) {\n          o = this._namedObservers[k];\n          o.close();\n        }\n        this._namedObservers = {};\n      }\n    }\n  };\n\n  // property binding\n  // bind a property in A to a path in B by converting A[property] to a\n  // getter/setter pair that accesses B[...path...]\n  function bindProperties(inA, inProperty, observable) {\n    log.bind && console.log(LOG_BIND_PROPS, inB.localName || 'object', inPath, inA.localName, inProperty);\n    // capture A's value if B's value is null or undefined,\n    // otherwise use B's value\n    // TODO(sorvell): need to review, can do with ObserverTransform\n    var v = observable.discardChanges();\n    if (v === null || v === undefined) {\n      observable.setValue(inA[inProperty]);\n    }\n    return Observer.defineComputedProperty(inA, inProperty, observable);\n  }\n\n  // logging\n  var LOG_OBSERVE = '[%s] watching [%s]';\n  var LOG_OBSERVED = '[%s#%s] watch: [%s] now [%s] was [%s]';\n  var LOG_CHANGED = '[%s#%s] propertyChanged: [%s] now [%s] was [%s]';\n  var LOG_BIND_PROPS = \"[%s]: bindProperties: [%s] to [%s].[%s]\";\n\n  // exports\n\n  scope.api.instance.properties = properties;\n\n})(Polymer);\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  // imports\n\n  var log = window.logFlags || 0;\n  var events = scope.api.instance.events;\n\n  var syntax = new PolymerExpressions();\n  syntax.resolveEventHandler = function(model, path, node) {\n    var ctlr = findEventController(node);\n    if (ctlr) {\n      var fn = path.getValueFrom(ctlr);\n      if (fn) {\n        return fn.bind(ctlr);\n      }\n    }\n  }\n\n  // An event controller is the host element for the shadowRoot in which \n  // the node exists, or the first ancestor with a 'lightDomController'\n  // property.\n  function findEventController(node) {\n    while (node.parentNode) {\n      if (node.lightDomController) {\n        return node;\n      }\n      node = node.parentNode;\n    }\n    return node.host;\n  };\n\n  // element api supporting mdv\n\n  var mdv = {\n    syntax: syntax,\n    instanceTemplate: function(template) {\n      var dom = template.createInstance(this, this.syntax);\n      this.registerObservers(dom.bindings_);\n      return dom;\n    },\n    bind: function(name, observable, oneTime) {\n      var property = this.propertyForAttribute(name);\n      if (!property) {\n        // TODO(sjmiles): this mixin method must use the special form\n        // of `super` installed by `mixinMethod` in declaration/prototype.js\n        return this.mixinSuper(arguments);\n      } else {\n        // use n-way Polymer binding\n        var observer = this.bindProperty(property, observable);\n        this.reflectPropertyToAttribute(property);\n        // NOTE: reflecting binding information is typically required only for\n        // tooling. It has a performance cost so it's opt-in in Node.bind.\n        if (Platform.enableBindingsReflection) {\n          observer.path = observable.path_;\n          this.bindings_ = this.bindings_ || {};\n          this.bindings_[name] = observer;\n        }\n        return observer;\n      }\n    },\n    // TODO(sorvell): unbind/unbindAll has been removed, as public api, from\n    // TemplateBinding. We still need to close/dispose of observers but perhaps\n    // we should choose a more explicit name.\n    asyncUnbindAll: function() {\n      if (!this._unbound) {\n        log.unbind && console.log('[%s] asyncUnbindAll', this.localName);\n        this._unbindAllJob = this.job(this._unbindAllJob, this.unbindAll, 0);\n      }\n    },\n    unbindAll: function() {\n      if (!this._unbound) {\n        this.closeObservers();\n        this.closeNamedObservers();\n        this._unbound = true;\n      }\n    },\n    cancelUnbindAll: function() {\n      if (this._unbound) {\n        log.unbind && console.warn('[%s] already unbound, cannot cancel unbindAll', this.localName);\n        return;\n      }\n      log.unbind && console.log('[%s] cancelUnbindAll', this.localName);\n      if (this._unbindAllJob) {\n        this._unbindAllJob = this._unbindAllJob.stop();\n      }\n    }\n  };\n\n  function unbindNodeTree(node) {\n    forNodeTree(node, _nodeUnbindAll);\n  }\n\n  function _nodeUnbindAll(node) {\n    node.unbindAll();\n  }\n\n  function forNodeTree(node, callback) {\n    if (node) {\n      callback(node);\n      for (var child = node.firstChild; child; child = child.nextSibling) {\n        forNodeTree(child, callback);\n      }\n    }\n  }\n\n  var mustachePattern = /\\{\\{([^{}]*)}}/;\n\n  // exports\n\n  scope.bindPattern = mustachePattern;\n  scope.api.instance.mdv = mdv;\n\n})(Polymer);\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  var base = {\n    PolymerBase: true,\n    job: function(job, callback, wait) {\n      if (typeof job === 'string') {\n        var n = '___' + job;\n        this[n] = Polymer.job.call(this, this[n], callback, wait);\n      } else {\n        return Polymer.job.call(this, job, callback, wait);\n      }\n    },\n    super: Polymer.super,\n    // user entry point for element has had its createdCallback called\n    created: function() {\n    },\n    // user entry point for element has shadowRoot and is ready for\n    // api interaction\n    ready: function() {\n    },\n    createdCallback: function() {\n      if (this.templateInstance && this.templateInstance.model) {\n        console.warn('Attributes on ' + this.localName + ' were data bound ' +\n            'prior to Polymer upgrading the element. This may result in ' +\n            'incorrect binding types.');\n      }\n      this.created();\n      this.prepareElement();\n    },\n    // system entry point, do not override\n    prepareElement: function() {\n      this._elementPrepared = true;\n      // install shadowRoots storage\n      this.shadowRoots = {};\n      // storage for closeable observers.\n      this._observers = [];\n      // install property observers\n      this.observeProperties();\n      // install boilerplate attributes\n      this.copyInstanceAttributes();\n      // process input attributes\n      this.takeAttributes();\n      // add event listeners\n      this.addHostListeners();\n      // process declarative resources\n      this.parseDeclarations(this.__proto__);\n      // TODO(sorvell): CE polyfill uses unresolved attribute to simulate\n      // :unresolved; remove this attribute to be compatible with native\n      // CE.\n      this.removeAttribute('unresolved');\n      // user entry point\n      this.ready();\n    },\n    attachedCallback: function() {\n      this.cancelUnbindAll();\n      // invoke user action\n      if (this.attached) {\n        this.attached();\n      }\n      // TODO(sorvell): bc\n      if (this.enteredView) {\n        this.enteredView();\n      }\n      // NOTE: domReady can be used to access elements in dom (descendants, \n      // ancestors, siblings) such that the developer is enured to upgrade\n      // ordering. If the element definitions have loaded, domReady\n      // can be used to access upgraded elements.\n      if (!this.hasBeenAttached) {\n        this.hasBeenAttached = true;\n        if (this.domReady) {\n          this.async('domReady');\n        }\n      }\n    },\n    detachedCallback: function() {\n      if (!this.preventDispose) {\n        this.asyncUnbindAll();\n      }\n      // invoke user action\n      if (this.detached) {\n        this.detached();\n      }\n      // TODO(sorvell): bc\n      if (this.leftView) {\n        this.leftView();\n      }\n    },\n    // TODO(sorvell): bc\n    enteredViewCallback: function() {\n      this.attachedCallback();\n    },\n    // TODO(sorvell): bc\n    leftViewCallback: function() {\n      this.detachedCallback();\n    },\n    // TODO(sorvell): bc\n    enteredDocumentCallback: function() {\n      this.attachedCallback();\n    },\n    // TODO(sorvell): bc\n    leftDocumentCallback: function() {\n      this.detachedCallback();\n    },\n    // recursive ancestral <element> initialization, oldest first\n    parseDeclarations: function(p) {\n      if (p && p.element) {\n        this.parseDeclarations(p.__proto__);\n        p.parseDeclaration.call(this, p.element);\n      }\n    },\n    // parse input <element> as needed, override for custom behavior\n    parseDeclaration: function(elementElement) {\n      var template = this.fetchTemplate(elementElement);\n      if (template) {\n        var root = this.shadowFromTemplate(template);\n        this.shadowRoots[elementElement.name] = root;\n      }\n    },\n    // return a shadow-root template (if desired), override for custom behavior\n    fetchTemplate: function(elementElement) {\n      return elementElement.querySelector('template');\n    },\n    // utility function that creates a shadow root from a <template>\n    shadowFromTemplate: function(template) {\n      if (template) {\n        // make a shadow root\n        var root = this.createShadowRoot();\n        // stamp template\n        // which includes parsing and applying MDV bindings before being \n        // inserted (to avoid {{}} in attribute values)\n        // e.g. to prevent <img src=\"images/{{icon}}\"> from generating a 404.\n        var dom = this.instanceTemplate(template);\n        // append to shadow dom\n        root.appendChild(dom);\n        // perform post-construction initialization tasks on shadow root\n        this.shadowRootReady(root, template);\n        // return the created shadow root\n        return root;\n      }\n    },\n    // utility function that stamps a <template> into light-dom\n    lightFromTemplate: function(template, refNode) {\n      if (template) {\n        // TODO(sorvell): mark this element as a lightDOMController so that\n        // event listeners on bound nodes inside it will be called on it.\n        // Note, the expectation here is that events on all descendants \n        // should be handled by this element.\n        this.lightDomController = true;\n        // stamp template\n        // which includes parsing and applying MDV bindings before being \n        // inserted (to avoid {{}} in attribute values)\n        // e.g. to prevent <img src=\"images/{{icon}}\"> from generating a 404.\n        var dom = this.instanceTemplate(template);\n        // append to shadow dom\n        if (refNode) {\n          this.insertBefore(dom, refNode);          \n        } else {\n          this.appendChild(dom);\n        }\n        // perform post-construction initialization tasks on ahem, light root\n        this.shadowRootReady(this);\n        // return the created shadow root\n        return dom;\n      }\n    },\n    shadowRootReady: function(root) {\n      // locate nodes with id and store references to them in this.$ hash\n      this.marshalNodeReferences(root);\n      // set up pointer gestures\n      PointerGestures.register(root);\n    },\n    // locate nodes with id and store references to them in this.$ hash\n    marshalNodeReferences: function(root) {\n      // establish $ instance variable\n      var $ = this.$ = this.$ || {};\n      // populate $ from nodes with ID from the LOCAL tree\n      if (root) {\n        var n$ = root.querySelectorAll(\"[id]\");\n        for (var i=0, l=n$.length, n; (i<l) && (n=n$[i]); i++) {\n          $[n.id] = n;\n        };\n      }\n    },\n    attributeChangedCallback: function(name, oldValue) {\n      // TODO(sjmiles): adhoc filter\n      if (name !== 'class' && name !== 'style') {\n        this.attributeToProperty(name, this.getAttribute(name));\n      }\n      if (this.attributeChanged) {\n        this.attributeChanged.apply(this, arguments);\n      }\n    },\n    onMutation: function(node, listener) {\n      var observer = new MutationObserver(function(mutations) {\n        listener.call(this, observer, mutations);\n        observer.disconnect();\n      }.bind(this));\n      observer.observe(node, {childList: true, subtree: true});\n    }\n  };\n\n  // true if object has own PolymerBase api\n  function isBase(object) {\n    return object.hasOwnProperty('PolymerBase') \n  }\n\n  // name a base constructor for dev tools\n\n  function PolymerBase() {};\n  PolymerBase.prototype = base;\n  base.constructor = PolymerBase;\n  \n  // exports\n\n  scope.Base = PolymerBase;\n  scope.isBase = isBase;\n  scope.api.instance.base = base;\n  \n})(Polymer);\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  // imports\n\n  var log = window.logFlags || {};\n  \n  // magic words\n  \n  var STYLE_SCOPE_ATTRIBUTE = 'element';\n  var STYLE_CONTROLLER_SCOPE = 'controller';\n  \n  var styles = {\n    STYLE_SCOPE_ATTRIBUTE: STYLE_SCOPE_ATTRIBUTE,\n    /**\n     * Installs external stylesheets and <style> elements with the attribute \n     * polymer-scope='controller' into the scope of element. This is intended\n     * to be a called during custom element construction.\n    */\n    installControllerStyles: function() {\n      // apply controller styles, but only if they are not yet applied\n      var scope = this.findStyleScope();\n      if (scope && !this.scopeHasNamedStyle(scope, this.localName)) {\n        // allow inherited controller styles\n        var proto = getPrototypeOf(this), cssText = '';\n        while (proto && proto.element) {\n          cssText += proto.element.cssTextForScope(STYLE_CONTROLLER_SCOPE);\n          proto = getPrototypeOf(proto);\n        }\n        if (cssText) {\n          this.installScopeCssText(cssText, scope);\n        }\n      }\n    },\n    installScopeStyle: function(style, name, scope) {\n      var scope = scope || this.findStyleScope(), name = name || '';\n      if (scope && !this.scopeHasNamedStyle(scope, this.localName + name)) {\n        var cssText = '';\n        if (style instanceof Array) {\n          for (var i=0, l=style.length, s; (i<l) && (s=style[i]); i++) {\n            cssText += s.textContent + '\\n\\n';\n          }\n        } else {\n          cssText = style.textContent;\n        }\n        this.installScopeCssText(cssText, scope, name);\n      }\n    },\n    installScopeCssText: function(cssText, scope, name) {\n      scope = scope || this.findStyleScope();\n      name = name || '';\n      if (!scope) {\n        return;\n      }\n      if (window.ShadowDOMPolyfill) {\n        cssText = shimCssText(cssText, scope.host);\n      }\n      var style = this.element.cssTextToScopeStyle(cssText,\n          STYLE_CONTROLLER_SCOPE);\n      Polymer.applyStyleToScope(style, scope);\n      // cache that this style has been applied\n      scope._scopeStyles[this.localName + name] = true;\n    },\n    findStyleScope: function(node) {\n      // find the shadow root that contains this element\n      var n = node || this;\n      while (n.parentNode) {\n        n = n.parentNode;\n      }\n      return n;\n    },\n    scopeHasNamedStyle: function(scope, name) {\n      scope._scopeStyles = scope._scopeStyles || {};\n      return scope._scopeStyles[name];\n    }\n  };\n  \n  // NOTE: use raw prototype traversal so that we ensure correct traversal\n  // on platforms where the protoype chain is simulated via __proto__ (IE10)\n  function getPrototypeOf(prototype) {\n    return prototype.__proto__;\n  }\n\n  function shimCssText(cssText, host) {\n    var name = '', is = false;\n    if (host) {\n      name = host.localName;\n      is = host.hasAttribute('is');\n    }\n    var selector = Platform.ShadowCSS.makeScopeSelector(name, is);\n    return Platform.ShadowCSS.shimCssText(cssText, selector);\n  }\n\n  // exports\n\n  scope.api.instance.styles = styles;\n  \n})(Polymer);\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  // imports\n\n  var extend = scope.extend;\n  var api = scope.api;\n\n  // imperative implementation: Polymer()\n\n  // specify an 'own' prototype for tag `name`\n  function element(name, prototype) {\n    if (arguments.length === 1 && typeof arguments[0] !== 'string') {\n      prototype = name;\n      var script = document._currentScript;\n      name = script && script.parentNode && script.parentNode.getAttribute ?\n          script.parentNode.getAttribute('name') : '';\n      if (!name) {\n        throw 'Element name could not be inferred.';\n      }\n    }\n    if (getRegisteredPrototype[name]) {\n      throw 'Already registered (Polymer) prototype for element ' + name;\n    }\n    // cache the prototype\n    registerPrototype(name, prototype);\n    // notify the registrar waiting for 'name', if any\n    notifyPrototype(name);\n  }\n\n  // async prototype source\n\n  function waitingForPrototype(name, client) {\n    waitPrototype[name] = client;\n  }\n\n  var waitPrototype = {};\n\n  function notifyPrototype(name) {\n    if (waitPrototype[name]) {\n      waitPrototype[name].registerWhenReady();\n      delete waitPrototype[name];\n    }\n  }\n\n  // utility and bookkeeping\n\n  // maps tag names to prototypes, as registered with\n  // Polymer. Prototypes associated with a tag name\n  // using document.registerElement are available from\n  // HTMLElement.getPrototypeForTag().\n  // If an element was fully registered by Polymer, then\n  // Polymer.getRegisteredPrototype(name) === \n  //   HTMLElement.getPrototypeForTag(name)\n\n  var prototypesByName = {};\n\n  function registerPrototype(name, prototype) {\n    return prototypesByName[name] = prototype || {};\n  }\n\n  function getRegisteredPrototype(name) {\n    return prototypesByName[name];\n  }\n\n  // exports\n\n  scope.getRegisteredPrototype = getRegisteredPrototype;\n  scope.waitingForPrototype = waitingForPrototype;\n\n  // namespace shenanigans so we can expose our scope on the registration \n  // function\n\n  // make window.Polymer reference `element()`\n\n  window.Polymer = element;\n\n  // TODO(sjmiles): find a way to do this that is less terrible\n  // copy window.Polymer properties onto `element()`\n\n  extend(Polymer, scope);\n\n  // Under the HTMLImports polyfill, scripts in the main document\n  // do not block on imports; we want to allow calls to Polymer in the main\n  // document. Platform collects those calls until we can process them, which\n  // we do here.\n\n  var declarations = Platform.deliverDeclarations();\n  if (declarations) {\n    for (var i=0, l=declarations.length, d; (i<l) && (d=declarations[i]); i++) {\n      element.apply(null, d);\n    }\n  }\n\n})(Polymer);\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 path = {\n  resolveElementPaths: function(node) {\n    Platform.urlResolver.resolveDom(node);\n  },\n  addResolvePathApi: function() {\n    // let assetpath attribute modify the resolve path\n    var assetPath = this.getAttribute('assetpath') || '';\n    var root = new URL(assetPath, this.ownerDocument.baseURI);\n    this.prototype.resolvePath = function(urlPath, base) {\n      var u = new URL(urlPath, base || root);\n      return u.href;\n    };\n  }\n};\n\n// exports\nscope.api.declaration.path = path;\n\n})(Polymer);\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  // imports\n\n  var log = window.logFlags || {};\n  var api = scope.api.instance.styles;\n  var STYLE_SCOPE_ATTRIBUTE = api.STYLE_SCOPE_ATTRIBUTE;\n\n  // magic words\n\n  var STYLE_SELECTOR = 'style';\n  var STYLE_LOADABLE_MATCH = '@import';\n  var SHEET_SELECTOR = 'link[rel=stylesheet]';\n  var STYLE_GLOBAL_SCOPE = 'global';\n  var SCOPE_ATTR = 'polymer-scope';\n\n  var styles = {\n    // returns true if resources are loading\n    loadStyles: function(callback) {\n      var content = this.templateContent();\n      if (content) {\n        this.convertSheetsToStyles(content);\n      }\n      var styles = this.findLoadableStyles(content);\n      if (styles.length) {\n        Platform.styleResolver.loadStyles(styles, callback);\n      } else if (callback) {\n        callback();\n      }\n    },\n    convertSheetsToStyles: function(root) {\n      var s$ = root.querySelectorAll(SHEET_SELECTOR);\n      for (var i=0, l=s$.length, s, c; (i<l) && (s=s$[i]); i++) {\n        c = createStyleElement(importRuleForSheet(s, this.ownerDocument.baseURI),\n            this.ownerDocument);\n        this.copySheetAttributes(c, s);\n        s.parentNode.replaceChild(c, s);\n      }\n    },\n    copySheetAttributes: function(style, link) {\n      for (var i=0, a$=link.attributes, l=a$.length, a; (a=a$[i]) && i<l; i++) {\n        if (a.name !== 'rel' && a.name !== 'href') {\n          style.setAttribute(a.name, a.value);\n        }\n      }\n    },\n    findLoadableStyles: function(root) {\n      var loadables = [];\n      if (root) {\n        var s$ = root.querySelectorAll(STYLE_SELECTOR);\n        for (var i=0, l=s$.length, s; (i<l) && (s=s$[i]); i++) {\n          if (s.textContent.match(STYLE_LOADABLE_MATCH)) {\n            loadables.push(s);\n          }\n        }\n      }\n      return loadables;\n    },\n    /**\n     * Install external stylesheets loaded in <polymer-element> elements into the \n     * element's template.\n     * @param elementElement The <element> element to style.\n     */\n    installSheets: function() {\n      this.cacheSheets();\n      this.cacheStyles();\n      this.installLocalSheets();\n      this.installGlobalStyles();\n    },\n    /**\n     * Remove all sheets from element and store for later use.\n     */\n    cacheSheets: function() {\n      this.sheets = this.findNodes(SHEET_SELECTOR);\n      this.sheets.forEach(function(s) {\n        if (s.parentNode) {\n          s.parentNode.removeChild(s);\n        }\n      });\n    },\n    cacheStyles: function() {\n      this.styles = this.findNodes(STYLE_SELECTOR + '[' + SCOPE_ATTR + ']');\n      this.styles.forEach(function(s) {\n        if (s.parentNode) {\n          s.parentNode.removeChild(s);\n        }\n      });\n    },\n    /**\n     * Takes external stylesheets loaded in an <element> element and moves\n     * their content into a <style> element inside the <element>'s template.\n     * The sheet is then removed from the <element>. This is done only so \n     * that if the element is loaded in the main document, the sheet does\n     * not become active.\n     * Note, ignores sheets with the attribute 'polymer-scope'.\n     * @param elementElement The <element> element to style.\n     */\n    installLocalSheets: function () {\n      var sheets = this.sheets.filter(function(s) {\n        return !s.hasAttribute(SCOPE_ATTR);\n      });\n      var content = this.templateContent();\n      if (content) {\n        var cssText = '';\n        sheets.forEach(function(sheet) {\n          cssText += cssTextFromSheet(sheet) + '\\n';\n        });\n        if (cssText) {\n          var style = createStyleElement(cssText, this.ownerDocument);\n          content.insertBefore(style, content.firstChild);\n        }\n      }\n    },\n    findNodes: function(selector, matcher) {\n      var nodes = this.querySelectorAll(selector).array();\n      var content = this.templateContent();\n      if (content) {\n        var templateNodes = content.querySelectorAll(selector).array();\n        nodes = nodes.concat(templateNodes);\n      }\n      return matcher ? nodes.filter(matcher) : nodes;\n    },\n    templateContent: function() {\n      var template = this.querySelector('template');\n      return template && templateContent(template);\n    },\n    /**\n     * Promotes external stylesheets and <style> elements with the attribute \n     * polymer-scope='global' into global scope.\n     * This is particularly useful for defining @keyframe rules which \n     * currently do not function in scoped or shadow style elements.\n     * (See wkb.ug/72462)\n     * @param elementElement The <element> element to style.\n    */\n    // TODO(sorvell): remove when wkb.ug/72462 is addressed.\n    installGlobalStyles: function() {\n      var style = this.styleForScope(STYLE_GLOBAL_SCOPE);\n      applyStyleToScope(style, document.head);\n    },\n    cssTextForScope: function(scopeDescriptor) {\n      var cssText = '';\n      // handle stylesheets\n      var selector = '[' + SCOPE_ATTR + '=' + scopeDescriptor + ']';\n      var matcher = function(s) {\n        return matchesSelector(s, selector);\n      };\n      var sheets = this.sheets.filter(matcher);\n      sheets.forEach(function(sheet) {\n        cssText += cssTextFromSheet(sheet) + '\\n\\n';\n      });\n      // handle cached style elements\n      var styles = this.styles.filter(matcher);\n      styles.forEach(function(style) {\n        cssText += style.textContent + '\\n\\n';\n      });\n      return cssText;\n    },\n    styleForScope: function(scopeDescriptor) {\n      var cssText = this.cssTextForScope(scopeDescriptor);\n      return this.cssTextToScopeStyle(cssText, scopeDescriptor);\n    },\n    cssTextToScopeStyle: function(cssText, scopeDescriptor) {\n      if (cssText) {\n        var style = createStyleElement(cssText);\n        style.setAttribute(STYLE_SCOPE_ATTRIBUTE, this.getAttribute('name') +\n            '-' + scopeDescriptor);\n        return style;\n      }\n    }\n  };\n\n  function importRuleForSheet(sheet, baseUrl) {\n    var href = new URL(sheet.getAttribute('href'), baseUrl).href;\n    return '@import \\'' + href + '\\';';\n  }\n\n  function applyStyleToScope(style, scope) {\n    if (style) {\n      if (scope === document) {\n        scope = document.head;\n      }\n      if (window.ShadowDOMPolyfill) {\n        scope = document.head;\n      }\n      // TODO(sorvell): necessary for IE\n      // see https://connect.microsoft.com/IE/feedback/details/790212/\n      // cloning-a-style-element-and-adding-to-document-produces\n      // -unexpected-result#details\n      // var clone = style.cloneNode(true);\n      var clone = createStyleElement(style.textContent);\n      var attr = style.getAttribute(STYLE_SCOPE_ATTRIBUTE);\n      if (attr) {\n        clone.setAttribute(STYLE_SCOPE_ATTRIBUTE, attr);\n      }\n      // TODO(sorvell): probably too brittle; try to figure out \n      // where to put the element.\n      var refNode = scope.firstElementChild;\n      if (scope === document.head) {\n        var selector = 'style[' + STYLE_SCOPE_ATTRIBUTE + ']';\n        var s$ = document.head.querySelectorAll(selector);\n        if (s$.length) {\n          refNode = s$[s$.length-1].nextElementSibling;\n        }\n      }\n      scope.insertBefore(clone, refNode);\n    }\n  }\n\n  function 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  function cssTextFromSheet(sheet) {\n    return (sheet && sheet.__resource) || '';\n  }\n\n  function matchesSelector(node, inSelector) {\n    if (matches) {\n      return matches.call(node, inSelector);\n    }\n  }\n  var p = HTMLElement.prototype;\n  var matches = p.matches || p.matchesSelector || p.webkitMatchesSelector \n      || p.mozMatchesSelector;\n  \n  // exports\n\n  scope.api.declaration.styles = styles;\n  scope.applyStyleToScope = applyStyleToScope;\n  \n})(Polymer);\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  // imports\n\n  var log = window.logFlags || {};\n  var api = scope.api.instance.events;\n  var EVENT_PREFIX = api.EVENT_PREFIX;\n  // polymer-element declarative api: events feature\n\n  var events = { \n    parseHostEvents: function() {\n      // our delegates map\n      var delegates = this.prototype.eventDelegates;\n      // extract data from attributes into delegates\n      this.addAttributeDelegates(delegates);\n    },\n    addAttributeDelegates: function(delegates) {\n      // for each attribute\n      for (var i=0, a; a=this.attributes[i]; i++) {\n        // does it have magic marker identifying it as an event delegate?\n        if (this.hasEventPrefix(a.name)) {\n          // if so, add the info to delegates\n          delegates[this.removeEventPrefix(a.name)] = a.value.replace('{{', '')\n              .replace('}}', '').trim();\n        }\n      }\n    },\n    // starts with 'on-'\n    hasEventPrefix: function (n) {\n      return n && (n[0] === 'o') && (n[1] === 'n') && (n[2] === '-');\n    },\n    removeEventPrefix: function(n) {\n      return n.slice(prefixLength);\n    }\n  };\n\n  var prefixLength = EVENT_PREFIX.length;\n\n  // exports\n  scope.api.declaration.events = events;\n\n})(Polymer);","/*\r\n * Copyright 2013 The Polymer Authors. All rights reserved.\r\n * Use of this source code is governed by a BSD-style\r\n * license that can be found in the LICENSE file.\r\n */\r\n(function(scope) {\r\n\r\n  // element api\r\n\r\n  var properties = {\r\n    inferObservers: function(prototype) {\r\n      // called before prototype.observe is chained to inherited object\r\n      var observe = prototype.observe, property;\r\n      for (var n in prototype) {\r\n        if (n.slice(-7) === 'Changed') {\r\n          if (!observe) {\r\n            observe  = (prototype.observe = {});\r\n          }\r\n          property = n.slice(0, -7)\r\n          observe[property] = observe[property] || n;\r\n        }\r\n      }\r\n    },\r\n    explodeObservers: function(prototype) {\r\n      // called before prototype.observe is chained to inherited object\r\n      var o = prototype.observe;\r\n      if (o) {\r\n        var exploded = {};\r\n        for (var n in o) {\r\n          var names = n.split(' ');\r\n          for (var i=0, ni; ni=names[i]; i++) {\r\n            exploded[ni] = o[n];\r\n          }\r\n        }\r\n        prototype.observe = exploded;\r\n      }\r\n    },\r\n    optimizePropertyMaps: function(prototype) {\r\n      if (prototype.observe) {\r\n        // construct name list\r\n        var a = prototype._observeNames = [];\r\n        for (var n in prototype.observe) {\r\n          var names = n.split(' ');\r\n          for (var i=0, ni; ni=names[i]; i++) {\r\n            a.push(ni);\r\n          }\r\n        }\r\n      }\r\n      if (prototype.publish) {\r\n        // construct name list\r\n        var a = prototype._publishNames = [];\r\n        for (var n in prototype.publish) {\r\n          a.push(n);\r\n        }\r\n      }\r\n    },\r\n    publishProperties: function(prototype, base) {\r\n      // if we have any properties to publish\r\n      var publish = prototype.publish;\r\n      if (publish) {\r\n        // transcribe `publish` entries onto own prototype\r\n        this.requireProperties(publish, prototype, base);\r\n        // construct map of lower-cased property names\r\n        prototype._publishLC = this.lowerCaseMap(publish);\r\n      }\r\n    },\r\n    requireProperties: function(properties, prototype, base) {\r\n      // ensure a prototype value for each property\r\n      for (var n in properties) {\r\n        if (prototype[n] === undefined && base[n] === undefined) {\r\n          prototype[n] = properties[n];\r\n        }\r\n      }\r\n    },\r\n    lowerCaseMap: function(properties) {\r\n      var map = {};\r\n      for (var n in properties) {\r\n        map[n.toLowerCase()] = n;\r\n      }\r\n      return map;\r\n    }\r\n  };\r\n\r\n  // exports\r\n\r\n  scope.api.declaration.properties = properties;\r\n\r\n})(Polymer);\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(function(scope) {\n\n  // magic words\n\n  var ATTRIBUTES_ATTRIBUTE = 'attributes';\n  var ATTRIBUTES_REGEX = /\\s|,/;\n\n  // attributes api\n\n  var attributes = {\n    inheritAttributesObjects: function(prototype) {\n      // chain our lower-cased publish map to the inherited version\n      this.inheritObject(prototype, 'publishLC');\n      // chain our instance attributes map to the inherited version\n      this.inheritObject(prototype, '_instanceAttributes');\n    },\n    publishAttributes: function(prototype, base) {\n      // merge names from 'attributes' attribute\n      var attributes = this.getAttribute(ATTRIBUTES_ATTRIBUTE);\n      if (attributes) {\n        // get properties to publish\n        var publish = prototype.publish || (prototype.publish = {});\n        // names='a b c' or names='a,b,c'\n        var names = attributes.split(ATTRIBUTES_REGEX);\n        // record each name for publishing\n        for (var i=0, l=names.length, n; i<l; i++) {\n          // remove excess ws\n          n = names[i].trim();\n          // do not override explicit entries\n          if (n && publish[n] === undefined && base[n] === undefined) {\n            publish[n] = null;\n          }\n        }\n      }\n    },\n    // record clonable attributes from <element>\n    accumulateInstanceAttributes: function() {\n      // inherit instance attributes\n      var clonable = this.prototype._instanceAttributes;\n      // merge attributes from element\n      var a$ = this.attributes;\n      for (var i=0, l=a$.length, a; (i<l) && (a=a$[i]); i++) {  \n        if (this.isInstanceAttribute(a.name)) {\n          clonable[a.name] = a.value;\n        }\n      }\n    },\n    isInstanceAttribute: function(name) {\n      return !this.blackList[name] && name.slice(0,3) !== 'on-';\n    },\n    // do not clone these attributes onto instances\n    blackList: {\n      name: 1,\n      'extends': 1,\n      constructor: 1,\n      noscript: 1,\n      assetpath: 1,\n      'cache-csstext': 1\n    }\n  };\n\n  // add ATTRIBUTES_ATTRIBUTE to the blacklist\n  attributes.blackList[ATTRIBUTES_ATTRIBUTE] = 1;\n\n  // exports\n\n  scope.api.declaration.attributes = attributes;\n\n})(Polymer);\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  // imports\n  \n  var api = scope.api;\n  var isBase = scope.isBase;\n  var extend = scope.extend;\n\n  // prototype api\n\n  var prototype = {\n\n    register: function(name, extendeeName) {\n      // build prototype combining extendee, Polymer base, and named api\n      this.buildPrototype(name, extendeeName);\n      // register our custom element with the platform\n      this.registerPrototype(name, extendeeName);\n      // reference constructor in a global named by 'constructor' attribute\n      this.publishConstructor();\n    },\n\n    buildPrototype: function(name, extendeeName) {\n      // get our custom prototype (before chaining)\n      var extension = scope.getRegisteredPrototype(name);\n      // get basal prototype\n      var base = this.generateBasePrototype(extendeeName);\n      // implement declarative features\n      this.desugarBeforeChaining(extension, base);\n      // join prototypes\n      this.prototype = this.chainPrototypes(extension, base);\n      // more declarative features\n      this.desugarAfterChaining(name, extendeeName);\n    },\n\n    desugarBeforeChaining: function(prototype, base) {\n      // back reference declaration element\n      // TODO(sjmiles): replace `element` with `elementElement` or `declaration`\n      prototype.element = this;\n      // transcribe `attributes` declarations onto own prototype's `publish`\n      this.publishAttributes(prototype, base);\n      // `publish` properties to the prototype and to attribute watch\n      this.publishProperties(prototype, base);\n      // infer observers for `observe` list based on method names\n      this.inferObservers(prototype);\n      // desugar compound observer syntax, e.g. 'a b c' \n      this.explodeObservers(prototype);\n    },\n\n    chainPrototypes: function(prototype, base) {\n      // chain various meta-data objects to inherited versions\n      this.inheritMetaData(prototype, base);\n      // chain custom api to inherited\n      var chained = this.chainObject(prototype, base);\n      // x-platform fixup\n      ensurePrototypeTraversal(chained);\n      return chained;\n    },\n\n    inheritMetaData: function(prototype, base) {\n      // chain observe object to inherited\n      this.inheritObject('observe', prototype, base);\n      // chain publish object to inherited\n      this.inheritObject('publish', prototype, base);\n      // chain our lower-cased publish map to the inherited version\n      this.inheritObject('_publishLC', prototype, base);\n      // chain our instance attributes map to the inherited version\n      this.inheritObject('_instanceAttributes', prototype, base);\n      // chain our event delegates map to the inherited version\n      this.inheritObject('eventDelegates', prototype, base);\n    },\n\n    // implement various declarative features\n    desugarAfterChaining: function(name, extendee) {\n      // build side-chained lists to optimize iterations\n      this.optimizePropertyMaps(this.prototype);\n      // install external stylesheets as if they are inline\n      this.installSheets();\n      // adjust any paths in dom from imports\n      this.resolveElementPaths(this);\n      // compile list of attributes to copy to instances\n      this.accumulateInstanceAttributes();\n      // parse on-* delegates declared on `this` element\n      this.parseHostEvents();\n      //\n      // install a helper method this.resolvePath to aid in \n      // setting resource urls. e.g.\n      // this.$.image.src = this.resolvePath('images/foo.png')\n      this.addResolvePathApi();\n      // under ShadowDOMPolyfill, transforms to approximate missing CSS features\n      if (window.ShadowDOMPolyfill) {\n        Platform.ShadowCSS.shimStyling(this.templateContent(), name, extendee);\n      }\n      // allow custom element access to the declarative context\n      if (this.prototype.registerCallback) {\n        this.prototype.registerCallback(this);\n      }\n    },\n\n    // if a named constructor is requested in element, map a reference\n    // to the constructor to the given symbol\n    publishConstructor: function() {\n      var symbol = this.getAttribute('constructor');\n      if (symbol) {\n        window[symbol] = this.ctor;\n      }\n    },\n\n    // build prototype combining extendee, Polymer base, and named api\n    generateBasePrototype: function(extnds) {\n      var prototype = this.findBasePrototype(extnds);\n      if (!prototype) {\n        // create a prototype based on tag-name extension\n        var prototype = HTMLElement.getPrototypeForTag(extnds);\n        // insert base api in inheritance chain (if needed)\n        prototype = this.ensureBaseApi(prototype);\n        // memoize this base\n        memoizedBases[extnds] = prototype;\n      }\n      return prototype;\n    },\n\n    findBasePrototype: function(name) {\n      return memoizedBases[name];\n    },\n\n    // install Polymer instance api into prototype chain, as needed \n    ensureBaseApi: function(prototype) {\n      if (prototype.PolymerBase) {\n        return prototype;\n      }\n      var extended = Object.create(prototype);\n      // we need a unique copy of base api for each base prototype\n      // therefore we 'extend' here instead of simply chaining\n      api.publish(api.instance, extended);\n      // TODO(sjmiles): sharing methods across prototype chains is\n      // not supported by 'super' implementation which optimizes\n      // by memoizing prototype relationships.\n      // Probably we should have a version of 'extend' that is \n      // share-aware: it could study the text of each function,\n      // look for usage of 'super', and wrap those functions in\n      // closures.\n      // As of now, there is only one problematic method, so \n      // we just patch it manually.\n      // To avoid re-entrancy problems, the special super method\n      // installed is called `mixinSuper` and the mixin method\n      // must use this method instead of the default `super`.\n      this.mixinMethod(extended, prototype, api.instance.mdv, 'bind');\n      // return buffed-up prototype\n      return extended;\n    },\n\n    mixinMethod: function(extended, prototype, api, name) {\n      var $super = function(args) {\n        return prototype[name].apply(this, args);\n      };\n      extended[name] = function() {\n        this.mixinSuper = $super;\n        return api[name].apply(this, arguments);\n      }\n    },\n\n    // ensure prototype[name] inherits from a prototype.prototype[name]\n    inheritObject: function(name, prototype, base) {\n      // require an object\n      var source = prototype[name] || {};\n      // chain inherited properties onto a new object\n      prototype[name] = this.chainObject(source, base[name]);\n    },\n\n    // register 'prototype' to custom element 'name', store constructor \n    registerPrototype: function(name, extendee) { \n      var info = {\n        prototype: this.prototype\n      }\n      // native element must be specified in extends\n      var typeExtension = this.findTypeExtension(extendee);\n      if (typeExtension) {\n        info.extends = typeExtension;\n      }\n      // register the prototype with HTMLElement for name lookup\n      HTMLElement.register(name, this.prototype);\n      // register the custom type\n      this.ctor = document.registerElement(name, info);\n    },\n\n    findTypeExtension: function(name) {\n      if (name && name.indexOf('-') < 0) {\n        return name;\n      } else {\n        var p = this.findBasePrototype(name);\n        if (p.element) {\n          return this.findTypeExtension(p.element.extends);\n        }\n      }\n    }\n\n  };\n\n  // memoize base prototypes\n  var memoizedBases = {};\n\n  // implementation of 'chainObject' depends on support for __proto__\n  if (Object.__proto__) {\n    prototype.chainObject = function(object, inherited) {\n      if (object && inherited && object !== inherited) {\n        object.__proto__ = inherited;\n      }\n      return object;\n    }\n  } else {\n    prototype.chainObject = function(object, inherited) {\n      if (object && inherited && object !== inherited) {\n        var chained = Object.create(inherited);\n        object = extend(chained, object);\n      }\n      return object;\n    }\n  }\n\n  // On platforms that do not support __proto__ (versions of IE), the prototype\n  // chain of a custom element is simulated via installation of __proto__.\n  // Although custom elements manages this, we install it here so it's\n  // available during desugaring.\n  function ensurePrototypeTraversal(prototype) {\n    if (!Object.__proto__) {\n      var ancestor = Object.getPrototypeOf(prototype);\n      prototype.__proto__ = ancestor;\n      if (isBase(ancestor)) {\n        ancestor.__proto__ = Object.getPrototypeOf(ancestor);\n      }\n    }\n  }\n\n  // exports\n\n  api.declaration.prototype = prototype;\n\n})(Polymer);\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  var queue = {\n    // tell the queue to wait for an element to be ready\n    wait: function(element, check, go) {\n      if (this.indexOf(element) === -1) {\n        this.add(element);\n        element.__check = check;\n        element.__go = go;\n      }\n      return (this.indexOf(element) !== 0);\n    },\n    add: function(element) {\n      //console.log('queueing', element.name);\n      queueForElement(element).push(element);\n    },\n    indexOf: function(element) {\n      var i = queueForElement(element).indexOf(element);\n      if (i >= 0 && document.contains(element)) {\n        i += (HTMLImports.useNative || HTMLImports.ready) ? \n          importQueue.length : 1e9;\n      }\n      return i;  \n    },\n    // tell the queue an element is ready to be registered\n    go: function(element) {\n      var readied = this.remove(element);\n      if (readied) {\n        readied.__go.call(readied);\n        readied.__check = readied.__go = null;\n        this.check();\n      }\n    },\n    remove: function(element) {\n      var i = this.indexOf(element);\n      if (i !== 0) {\n        //console.warn('queue order wrong', i);\n        return;\n      }\n      return queueForElement(element).shift();\n    },\n    check: function() {\n      // next\n      var element = this.nextElement();\n      if (element) {\n        element.__check.call(element);\n      }\n      if (this.canReady()) {\n        this.ready();\n        return true;\n      }\n    },\n    nextElement: function() {\n      return nextQueued();\n    },\n    canReady: function() {\n      return !this.waitToReady && this.isEmpty();\n    },\n    isEmpty: function() {\n      return !importQueue.length && !mainQueue.length;\n    },\n    ready: function() {\n      // TODO(sorvell): As an optimization, turn off CE polyfill upgrading\n      // while registering. This way we avoid having to upgrade each document\n      // piecemeal per registration and can instead register all elements\n      // and upgrade once in a batch. Without this optimization, upgrade time\n      // degrades significantly when SD polyfill is used. This is mainly because\n      // querying the document tree for elements is slow under the SD polyfill.\n      if (CustomElements.ready === false) {\n        CustomElements.upgradeDocumentTree(document);\n        CustomElements.ready = true;\n      }\n      if (readyCallbacks) {\n        var fn;\n        while (readyCallbacks.length) {\n          fn = readyCallbacks.shift();\n          fn();\n        }\n      }\n    },\n    addReadyCallback: function(callback) {\n      if (callback) {\n        readyCallbacks.push(callback);\n      }\n    },\n    waitToReady: true\n  };\n\n  var importQueue = [];\n  var mainQueue = [];\n  var readyCallbacks = [];\n\n  function queueForElement(element) {\n    return document.contains(element) ? mainQueue : importQueue;\n  }\n\n  function nextQueued() {\n    return importQueue.length ? importQueue[0] : mainQueue[0];\n  }\n\n  var polymerReadied = false; \n\n  document.addEventListener('WebComponentsReady', function() {\n    CustomElements.ready = false;\n  });\n  \n  function whenPolymerReady(callback) {\n    queue.waitToReady = true;\n    CustomElements.ready = false;\n    HTMLImports.whenImportsReady(function() {\n      queue.addReadyCallback(callback);\n      queue.waitToReady = false;\n      queue.check();\n    });\n  }\n\n  // exports\n  scope.queue = queue;\n  scope.whenPolymerReady = whenPolymerReady;\n})(Polymer);\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  var whenPolymerReady = scope.whenPolymerReady;\n\n  function importElements(elementOrFragment, callback) {\n    if (elementOrFragment) {\n      document.head.appendChild(elementOrFragment);\n      whenPolymerReady(callback);\n    } else if (callback) {\n      callback();\n    }\n  }\n\n  function importUrls(urls, callback) {\n    if (urls && urls.length) {\n        var frag = document.createDocumentFragment();\n        for (var i=0, l=urls.length, url, link; (i<l) && (url=urls[i]); i++) {\n          link = document.createElement('link');\n          link.rel = 'import';\n          link.href = url;\n          frag.appendChild(link);\n        }\n        importElements(frag, callback);\n    } else if (callback) {\n      callback();\n    }\n  }\n\n  // exports\n  scope.import = importUrls;\n  scope.importElements = importElements;\n\n})(Polymer);\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  // imports\n\n  var extend = scope.extend;\n  var api = scope.api;\n  var queue = scope.queue;\n  var whenPolymerReady = scope.whenPolymerReady;\n  var getRegisteredPrototype = scope.getRegisteredPrototype;\n  var waitingForPrototype = scope.waitingForPrototype;\n\n  // declarative implementation: <polymer-element>\n\n  var prototype = extend(Object.create(HTMLElement.prototype), {\n\n    createdCallback: function() {\n      if (this.getAttribute('name')) {\n        this.init();\n      }\n    },\n\n    init: function() {\n      // fetch declared values\n      this.name = this.getAttribute('name');\n      this.extends = this.getAttribute('extends');\n      // initiate any async resource fetches\n      this.loadResources();\n      // register when all constraints are met\n      this.registerWhenReady();\n    },\n\n    registerWhenReady: function() {\n     if (this.registered\n       || this.waitingForPrototype(this.name)\n       || this.waitingForQueue()\n       || this.waitingForResources()) {\n          return;\n      }\n      // TODO(sorvell): ends up calling '_register' by virtue\n      // of `waitingForQueue` (see below)\n      queue.go(this);\n    },\n\n    // TODO(sorvell): refactor, this method is private-ish, but it's being\n    // called by the queue object.\n    _register: function() {\n      //console.log('registering', this.name);\n      //console.group('registering', this.name);\n      // warn if extending from a custom element not registered via Polymer\n      if (isCustomTag(this.extends) && !isRegistered(this.extends)) {\n        console.warn('%s is attempting to extend %s, an unregistered element ' +\n            'or one that was not registered with Polymer.', this.name,\n            this.extends);\n      }\n      this.register(this.name, this.extends);\n      this.registered = true;\n      //console.groupEnd();\n    },\n\n    waitingForPrototype: function(name) {\n      if (!getRegisteredPrototype(name)) {\n        // then wait for a prototype\n        waitingForPrototype(name, this);\n        // emulate script if user is not supplying one\n        this.handleNoScript(name);\n        // prototype not ready yet\n        return true;\n      }\n    },\n\n    handleNoScript: function(name) {\n      // if explicitly marked as 'noscript'\n      if (this.hasAttribute('noscript') && !this.noscript) {\n        this.noscript = true;\n        // TODO(sorvell): CustomElements polyfill awareness:\n        // noscript elements should upgrade in logical order\n        // script injection ensures this under native custom elements;\n        // under imports + ce polyfills, scripts run before upgrades.\n        // dependencies should be ready at upgrade time so register\n        // prototype at this time.\n        if (window.CustomElements && !CustomElements.useNative) {\n          Polymer(name);\n        } else {\n          var script = document.createElement('script');\n          script.textContent = 'Polymer(\\'' + name + '\\');';\n          this.appendChild(script);\n        }\n      }\n    },\n\n    waitingForResources: function() {\n      return this._needsResources;\n    },\n\n    // NOTE: Elements must be queued in proper order for inheritance/composition\n    // dependency resolution. Previously this was enforced for inheritance,\n    // and by rule for composition. It's now entirely by rule.\n    waitingForQueue: function() {\n      return queue.wait(this, this.registerWhenReady, this._register);\n    },\n\n    loadResources: function() {\n      this._needsResources = true;\n      this.loadStyles(function() {\n        this._needsResources = false;\n        this.registerWhenReady();\n      }.bind(this));\n    }\n\n  });\n\n  // semi-pluggable APIs \n\n  // TODO(sjmiles): should be fully pluggable (aka decoupled, currently\n  // the various plugins are allowed to depend on each other directly)\n  api.publish(api.declaration, prototype);\n\n  // utility and bookkeeping\n\n  function isRegistered(name) {\n    return Boolean(HTMLElement.getPrototypeForTag(name));\n  }\n\n  function isCustomTag(name) {\n    return (name && name.indexOf('-') >= 0);\n  }\n\n  // exports\n\n  scope.getRegisteredPrototype = getRegisteredPrototype;\n  \n  // boot tasks\n\n  whenPolymerReady(function() {\n    document.body.removeAttribute('unresolved');\n    document.dispatchEvent(\n      new CustomEvent('polymer-ready', {bubbles: true})\n    );\n  });\n\n  // register polymer-element with document\n\n  document.registerElement('polymer-element', {prototype: prototype});\n\n})(Polymer);\n"]}
\ No newline at end of file
diff --git a/runtime/bin/vmservice/client/deployed/web/packages/web_components/platform.concat.js.map b/runtime/bin/vmservice/client/deployed/web/packages/web_components/platform.concat.js.map
deleted file mode 100644
index 93e18ca..0000000
--- a/runtime/bin/vmservice/client/deployed/web/packages/web_components/platform.concat.js.map
+++ /dev/null
@@ -1,210 +0,0 @@
-{
-  "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/TreeScope.js",
-    "../ShadowDOM/src/wrappers/events.js",
-    "../ShadowDOM/src/wrappers/NodeList.js",
-    "../ShadowDOM/src/wrappers/HTMLCollection.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/HTMLSelectElement.js",
-    "../ShadowDOM/src/wrappers/HTMLTableElement.js",
-    "../ShadowDOM/src/wrappers/HTMLTableSectionElement.js",
-    "../ShadowDOM/src/wrappers/HTMLTableRowElement.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/DataTransfer.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",
-    "src/styleloader.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",
-    "../PointerGestures/src/registerScopes.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;;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;;ACzjDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5YA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;;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;;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtzBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3tBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;AACA;AACA;AACA;AACA;AACA;AACA;;AC1EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;;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;;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;;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;;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;;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;;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;;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;;ACtEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;;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;;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;;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;;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;;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;;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;;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;;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;;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;;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;AACA;AACA;AACA;AACA;;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrqBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;ACjuBA,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,K;AC9CA,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;;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;;ACjJA;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;;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;;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;;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;AACA;AACA;AACA;;AClHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/PA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;;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;;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;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;;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;;AC5BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;;ACvGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;AACA;AACA;AACA;AACA;AACA;AACA;;ACtUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3VA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;;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;;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;;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;;ACvOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;;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;AACA;;AC1JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzsCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjrBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA",
-  "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  // 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    var arr = [];\n    Object.observe(test, callback);\n    Array.observe(arr, callback);\n    test.id = 1;\n    test.id = 2;\n    delete test.id;\n    arr.push(1, 2);\n    arr.length = 0;\n\n    Object.deliverChangeRecords(callback);\n    if (records.length !== 5)\n      return false;\n\n    if (records[0].type != 'add' ||\n        records[1].type != 'update' ||\n        records[2].type != 'delete' ||\n        records[3].type != 'splice' ||\n        records[4].type != 'splice') {\n      return false;\n    }\n\n    Object.unobserve(test, callback);\n    Array.unobserve(arr, 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 (!isObject(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 (!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      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 scheduledReset() {\n      resetScheduled = false;\n      if (!resetNeeded)\n        return;\n\n      reset();\n    }\n\n    function scheduleReset() {\n      if (resetScheduled)\n        return;\n\n      resetNeeded = true;\n      resetScheduled = true;\n      runEOM(scheduledReset);\n    }\n\n    function callback() {\n      reset();\n\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\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 = hasObserve && (function() {\n    try {\n      eval('%RunMicrotasks()');\n      return true;\n    } catch (ex) {\n      return false;\n    }\n  })();\n\n  global.Platform = global.Platform || {};\n\n  global.Platform.performMicrotaskCheckpoint = function() {\n    if (runningMicrotaskCheckpoint)\n      return;\n\n    if (hasDebugForceFullDelivery) {\n      eval('%RunMicrotasks()');\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    add: true,\n    update: true,\n    delete: true\n  };\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('update', 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 == 'update')\n        continue;\n\n      if (record.type == 'add') {\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 'splice':\n          mergeSplice(splices, record.index, record.removed.slice(), record.addedCount);\n          break;\n        case 'add':\n        case 'update':\n        case 'delete':\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})(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 ||\r\n      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  if (flags.shadow && document.querySelectorAll('script').length > 1) {\r\n    console.warn('platform.js is not the first script on the page. ' +\r\n        'See http://www.polymer-project.org/docs/start/platform.html#setup ' +\r\n        'for details.');\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    // Set it again. Some VMs optimizes objects that are used as prototypes.\n    wrapperConstructor.prototype = wrapperPrototype;\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    var p = Object.create(superWrapperConstructor.prototype);\n    p.constructor = GeneratedWrapper;\n    GeneratedWrapper.prototype = p;\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",
-    "/**\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\n(function(scope) {\n  'use strict';\n\n  /**\n   * A tree scope represents the root of a tree. All nodes in a tree point to\n   * the same TreeScope object. The tree scope of a node get set the first time\n   * it is accessed or when a node is added or remove to a tree.\n   * @constructor\n   */\n  function TreeScope(root, parent) {\n    this.root = root;\n    this.parent = parent;\n  }\n\n  TreeScope.prototype = {\n    get renderer() {\n      if (this.root instanceof scope.wrappers.ShadowRoot) {\n        return scope.getRendererForHost(this.root.host);\n      }\n      return null;\n    },\n\n    contains: function(treeScope) {\n      for (; treeScope; treeScope = treeScope.parent) {\n        if (treeScope === this)\n          return true;\n      }\n      return false;\n    }\n  };\n\n  function setTreeScope(node, treeScope) {\n    if (node.treeScope_ !== treeScope) {\n      node.treeScope_ = treeScope;\n      for (var sr = node.shadowRoot; sr; sr = sr.olderShadowRoot) {\n        sr.treeScope_.parent = treeScope;\n      }\n      for (var child = node.firstChild; child; child = child.nextSibling) {\n        setTreeScope(child, treeScope);\n      }\n    }\n  }\n\n  function getTreeScope(node) {\n    if (node.treeScope_)\n      return node.treeScope_;\n    var parent = node.parentNode;\n    var treeScope;\n    if (parent)\n      treeScope = getTreeScope(parent);\n    else\n      treeScope = new TreeScope(node, null);\n    return node.treeScope_ = treeScope;\n  }\n\n  scope.TreeScope = TreeScope;\n  scope.getTreeScope = getTreeScope;\n  scope.setTreeScope = setTreeScope;\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 getTreeScope = scope.getTreeScope;\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 inSameTree(a, b) {\n    return getTreeScope(a) === getTreeScope(b);\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    dispatchEvent(wrap(originalEvent), wrap(originalEvent.target));\n  }\n\n  function isLoadLikeEvent(event) {\n    switch (event.type) {\n      case 'beforeunload':\n      case 'load':\n      case 'unload':\n        return true;\n    }\n    return false;\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 (eventPath.length === 2 &&\n        eventPath[0].target instanceof wrappers.Document &&\n        isLoadLikeEvent(event)) {\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      var unwrappedRelatedTarget = originalEvent.relatedTarget;\n\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 (unwrappedRelatedTarget) {\n        // In IE we can get objects that are not EventTargets at this point.\n        // Safari does not have an EventTarget interface so revert to checking\n        // for addEventListener as an approximation.\n        if (unwrappedRelatedTarget instanceof Object &&\n            unwrappedRelatedTarget.addEventListener) {\n          var relatedTarget = wrap(unwrappedRelatedTarget);\n\n          var adjusted = adjustRelatedTarget(currentTarget, relatedTarget);\n          if (adjusted === target)\n            return true;\n        } else {\n          adjusted = null;\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      var impl = type;\n      if (!OriginalBeforeUnloadEvent && impl.type === 'beforeunload')\n        return new BeforeUnloadEvent(impl);\n      this.impl = impl;\n    } else {\n      return wrap(constructEvent(OriginalEvent, 'Event', type, options));\n    }\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 = getTreeScope(currentTargetTable.get(this));\n\n        for (var i = 0; i <= lastIndex; i++) {\n          var currentTarget = eventPath[i].currentTarget;\n          var currentRoot = getTreeScope(currentTarget);\n          if (currentRoot.contains(baseRoot) &&\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      var relatedTarget = relatedTargetTable.get(this);\n      // relatedTarget can be null.\n      if (relatedTarget !== undefined)\n        return relatedTarget;\n      return 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  // Safari 7 does not yet have BeforeUnloadEvent.\n  // https://bugs.webkit.org/show_bug.cgi?id=120849\n  var OriginalBeforeUnloadEvent = window.BeforeUnloadEvent;\n\n  function BeforeUnloadEvent(impl) {\n    Event.call(this, impl);\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  if (OriginalBeforeUnloadEvent)\n    registerWrapper(OriginalBeforeUnloadEvent, BeforeUnloadEvent);\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",
-    "/*\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\n(function(scope) {\n  'use strict';\n\n  // TODO(arv): Implement.\n\n  scope.wrapHTMLCollection = scope.wrapNodeList;\n  scope.wrappers.HTMLCollection = scope.wrappers.NodeList;\n\n})(window.ShadowDOMPolyfill);\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(scope) {\n  'use strict';\n\n  var EventTarget = scope.wrappers.EventTarget;\n  var NodeList = scope.wrappers.NodeList;\n  var TreeScope = scope.TreeScope;\n  var assert = scope.assert;\n  var defineWrapGetter = scope.defineWrapGetter;\n  var enqueueMutation = scope.enqueueMutation;\n  var getTreeScope = scope.getTreeScope;\n  var isWrapper = scope.isWrapper;\n  var mixin = scope.mixin;\n  var registerTransientObservers = scope.registerTransientObservers;\n  var registerWrapper = scope.registerWrapper;\n  var setTreeScope = scope.setTreeScope;\n  var unwrap = scope.unwrap;\n  var unwrapIfNeeded = scope.unwrapIfNeeded;\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, treeScope) {\n    setTreeScope(node, treeScope);\n    node.nodeIsInserted_();\n  }\n\n  function nodesWereAdded(nodes, parent) {\n    var treeScope = getTreeScope(parent);\n    for (var i = 0; i < nodes.length; i++) {\n      nodeWasAdded(nodes[i], treeScope);\n    }\n  }\n\n  // http://dom.spec.whatwg.org/#node-is-removed\n  function nodeWasRemoved(node) {\n    setTreeScope(node, new TreeScope(node, null));\n  }\n\n  function nodesWereRemoved(nodes) {\n    for (var i = 0; i < nodes.length; i++) {\n      nodeWasRemoved(nodes[i]);\n    }\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  function contains(self, child) {\n    if (!child || getTreeScope(self) !== getTreeScope(child))\n      return false;\n\n    for (var node = child; node; node = node.parentNode) {\n      if (node === self)\n        return true;\n    }\n    return false;\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    this.treeScope_ = 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, this);\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, this);\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, this);\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      return contains(this, wrapIfNeeded(child));\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,\n                                                  unwrapIfNeeded(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.cloneNode = cloneNode;\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\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    remove: function() {\n      var p = this.parentNode;\n      if (p)\n        p.removeChild(this);\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, this);\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 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 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 OriginalHTMLSelectElement = window.HTMLSelectElement;\n\n  function HTMLSelectElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLSelectElement.prototype = Object.create(HTMLElement.prototype);\n  mixin(HTMLSelectElement.prototype, {\n    add: function(element, before) {\n      if (typeof before === 'object')  // also includes null\n        before = unwrap(before);\n      unwrap(this).add(unwrap(element), before);\n    },\n\n    remove: function(indexOrNode) {\n      // Spec only allows index but implementations allow index or node.\n      // remove() is also allowed which is same as remove(undefined)\n      if (indexOrNode === undefined) {\n        HTMLElement.prototype.remove.call(this);\n        return;\n      }\n\n      if (typeof indexOrNode === 'object')\n        indexOrNode = unwrap(indexOrNode);\n\n      unwrap(this).remove(indexOrNode);\n    },\n\n    get form() {\n      return wrap(unwrap(this).form);\n    }\n  });\n\n  registerWrapper(OriginalHTMLSelectElement, HTMLSelectElement,\n                  document.createElement('select'));\n\n  scope.wrappers.HTMLSelectElement = HTMLSelectElement;\n})(window.ShadowDOMPolyfill);\n",
-    "/*\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\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  var wrapHTMLCollection = scope.wrapHTMLCollection;\n\n  var OriginalHTMLTableElement = window.HTMLTableElement;\n\n  function HTMLTableElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLTableElement.prototype = Object.create(HTMLElement.prototype);\n  mixin(HTMLTableElement.prototype, {\n    get caption() {\n      return wrap(unwrap(this).caption);\n    },\n    createCaption: function() {\n      return wrap(unwrap(this).createCaption());\n    },\n\n    get tHead() {\n      return wrap(unwrap(this).tHead);\n    },\n    createTHead: function() {\n      return wrap(unwrap(this).createTHead());\n    },\n\n    createTFoot: function() {\n      return wrap(unwrap(this).createTFoot());\n    },\n    get tFoot() {\n      return wrap(unwrap(this).tFoot);\n    },\n\n    get tBodies() {\n      return wrapHTMLCollection(unwrap(this).tBodies);\n    },\n    createTBody: function() {\n      return wrap(unwrap(this).createTBody());\n    },\n\n    get rows() {\n      return wrapHTMLCollection(unwrap(this).rows);\n    },\n    insertRow: function(index) {\n      return wrap(unwrap(this).insertRow(index));\n    }\n  });\n\n  registerWrapper(OriginalHTMLTableElement, HTMLTableElement,\n                  document.createElement('table'));\n\n  scope.wrappers.HTMLTableElement = HTMLTableElement;\n})(window.ShadowDOMPolyfill);\n",
-    "/*\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\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 wrapHTMLCollection = scope.wrapHTMLCollection;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n\n  var OriginalHTMLTableSectionElement = window.HTMLTableSectionElement;\n\n  function HTMLTableSectionElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLTableSectionElement.prototype = Object.create(HTMLElement.prototype);\n  mixin(HTMLTableSectionElement.prototype, {\n    get rows() {\n      return wrapHTMLCollection(unwrap(this).rows);\n    },\n    insertRow: function(index) {\n      return wrap(unwrap(this).insertRow(index));\n    }\n  });\n\n  registerWrapper(OriginalHTMLTableSectionElement, HTMLTableSectionElement,\n                  document.createElement('thead'));\n\n  scope.wrappers.HTMLTableSectionElement = HTMLTableSectionElement;\n})(window.ShadowDOMPolyfill);\n",
-    "/*\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\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 wrapHTMLCollection = scope.wrapHTMLCollection;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n\n  var OriginalHTMLTableRowElement = window.HTMLTableRowElement;\n\n  function HTMLTableRowElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLTableRowElement.prototype = Object.create(HTMLElement.prototype);\n  mixin(HTMLTableRowElement.prototype, {\n    get cells() {\n      return wrapHTMLCollection(unwrap(this).cells);\n    },\n\n    insertCell: function(index) {\n      return wrap(unwrap(this).insertCell(index));\n    }\n  });\n\n  registerWrapper(OriginalHTMLTableRowElement, HTMLTableRowElement,\n                  document.createElement('tr'));\n\n  scope.wrappers.HTMLTableRowElement = HTMLTableRowElement;\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 TreeScope = scope.TreeScope;\n  var elementFromPoint = scope.elementFromPoint;\n  var getInnerHTML = scope.getInnerHTML;\n  var getTreeScope = scope.getTreeScope;\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    this.treeScope_ = new TreeScope(this, getTreeScope(hostWrapper));\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 getTreeScope = scope.getTreeScope;\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    var rv = distributedChildNodesTable.get(insertionPoint);\n    if (!rv)\n      distributedChildNodesTable.set(insertionPoint, rv = []);\n    return rv;\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    // TODO(arv): Order these in document order. That way we do not have to\n    // render something twice.\n    for (var i = 0; i < pendingDirtyRenderers.length; i++) {\n      var renderer = pendingDirtyRenderers[i];\n      var parentRenderer = renderer.parentRenderer;\n      if (parentRenderer && parentRenderer.dirty)\n        continue;\n      renderer.render();\n    }\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    var root = getTreeScope(node).root;\n    if (root instanceof ShadowRoot)\n      return root;\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    get parentRenderer() {\n      return getTreeScope(this.host).renderer;\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 is handled in HTMLSelectElement.js\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 TreeScope = scope.TreeScope;\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    this.treeScope_ = new TreeScope(this, null);\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, extendsOption;\n      if (object !== undefined) {\n        prototype = object.prototype;\n        extendsOption = object.extends;\n      }\n\n      if (!prototype)\n        prototype = Object.create(HTMLElement.prototype);\n\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 (extendsOption)\n        p.extends = extendsOption;\n\n      function CustomElementConstructor(node) {\n        if (!node) {\n          if (extendsOption) {\n            return document.createElement(extendsOption, 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",
-    "/**\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\n(function(scope) {\n  'use strict';\n\n  var unwrap = scope.unwrap;\n\n  // DataTransfer (Clipboard in old Blink/WebKit) has a single method that\n  // requires wrapping. Since it is only a method we do not need a real wrapper,\n  // we can just override the method.\n\n  var OriginalDataTransfer = window.DataTransfer || window.Clipboard;\n  var OriginalDataTransferSetDragImage =\n      OriginalDataTransfer.prototype.setDragImage;\n\n  OriginalDataTransfer.prototype.setDragImage = function(image, x, y) {\n    OriginalDataTransferSetDragImage.call(this, unwrap(image), x, y);\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 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    // 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    'area': 'HTMLAreaElement',\n    'audio': 'HTMLAudioElement',\n    'base': 'HTMLBaseElement',\n    'body': 'HTMLBodyElement',\n    'br': 'HTMLBRElement',\n    'button': 'HTMLButtonElement',\n    'canvas': 'HTMLCanvasElement',\n    'caption': 'HTMLTableCaptionElement',\n    'col': 'HTMLTableColElement',\n    // 'command': 'HTMLCommandElement',  // Not fully implemented in Gecko.\n    'content': 'HTMLContentElement',\n    'data': 'HTMLDataElement',\n    'datalist': 'HTMLDataListElement',\n    'del': 'HTMLModElement',\n    'dir': 'HTMLDirectoryElement',\n    'div': 'HTMLDivElement',\n    'dl': 'HTMLDListElement',\n    'embed': 'HTMLEmbedElement',\n    'fieldset': 'HTMLFieldSetElement',\n    'font': 'HTMLFontElement',\n    'form': 'HTMLFormElement',\n    'frame': 'HTMLFrameElement',\n    'frameset': 'HTMLFrameSetElement',\n    'h1': 'HTMLHeadingElement',\n    'head': 'HTMLHeadElement',\n    'hr': 'HTMLHRElement',\n    'html': 'HTMLHtmlElement',\n    'iframe': 'HTMLIFrameElement',\n    'img': 'HTMLImageElement',\n    'input': 'HTMLInputElement',\n    'keygen': 'HTMLKeygenElement',\n    'label': 'HTMLLabelElement',\n    'legend': 'HTMLLegendElement',\n    'li': 'HTMLLIElement',\n    'link': 'HTMLLinkElement',\n    'map': 'HTMLMapElement',\n    'marquee': 'HTMLMarqueeElement',\n    'menu': 'HTMLMenuElement',\n    'menuitem': 'HTMLMenuItemElement',\n    'meta': 'HTMLMetaElement',\n    'meter': 'HTMLMeterElement',\n    'object': 'HTMLObjectElement',\n    'ol': 'HTMLOListElement',\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    'shadow': 'HTMLShadowElement',\n    'source': 'HTMLSourceElement',\n    'span': 'HTMLSpanElement',\n    'style': 'HTMLStyleElement',\n    'table': 'HTMLTableElement',\n    'tbody': 'HTMLTableSectionElement',\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    'template': 'HTMLTemplateElement',\n    'textarea': 'HTMLTextAreaElement',\n    'thead': 'HTMLTableSectionElement',\n    'time': 'HTMLTimeElement',\n    'title': 'HTMLTitleElement',\n    'tr': 'HTMLTableRowElement',\n    'track': 'HTMLTrackElement',\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})(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, :host-context: 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 scopeStyles = this.prepareRoot(root, name, extendsName);\n    var typeExtension = this.isTypeExtension(extendsName);\n    var scopeSelector = this.makeScopeSelector(name, typeExtension);\n    // use caching to make working with styles nodes easier and to facilitate\n    // lookup of extendee\n    var cssText = stylesToCssText(scopeStyles, true);\n    cssText = this.scopeCssText(cssText, scopeSelector);\n    // cache shimmed css on root for user extensibility\n    if (root) {\n      root.shimmedStyle = cssText;\n    }\n    // add style to document\n    this.addCssToDocument(cssText, name);\n  },\n  /*\n  * Shim a style element with the given selector. Returns cssText that can\n  * be included in the document via Platform.ShadowCSS.addCssToDocument(css).\n  */\n  shimStyle: function(style, selector) {\n    return this.shimCssText(style.textContent, selector);\n  },\n  /*\n  * Shim some cssText with the given selector. Returns cssText that can\n  * be included in the document via Platform.ShadowCSS.addCssToDocument(css).\n  */\n  shimCssText: function(cssText, selector) {\n    cssText = this.insertDirectives(cssText);\n    return this.scopeCssText(cssText, selector);\n  },\n  makeScopeSelector: function(name, typeExtension) {\n    if (name) {\n      return typeExtension ? '[is=' + name + ']' : name;\n    }\n    return '';\n  },\n  isTypeExtension: function(extendsName) {\n    return extendsName && extendsName.indexOf('-') < 0;\n  },\n  prepareRoot: function(root, name, extendsName) {\n    var def = this.registerRoot(root, name, extendsName);\n    this.replaceTextInStyles(def.rootStyles, this.insertDirectives);\n    // remove existing style elements\n    this.removeStyles(root, def.rootStyles);\n    // apply strict attr\n    if (this.strictStyling) {\n      this.applyScopeToContent(root, name);\n    }\n    return def.scopeStyles;\n  },\n  removeStyles: function(root, styles) {\n    for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) {\n      s.parentNode.removeChild(s);\n    }\n  },\n  registerRoot: function(root, name, extendsName) {\n    var def = this.registry[name] = {\n      root: root,\n      name: name,\n      extendsName: extendsName\n    }\n    var styles = this.findStyles(root);\n    def.rootStyles = styles;\n    def.scopeStyles = def.rootStyles;\n    var extendee = this.registry[def.extendsName];\n    if (extendee) {\n      def.scopeStyles = extendee.scopeStyles.concat(def.scopeStyles);\n    }\n    return def;\n  },\n  findStyles: function(root) {\n    if (!root) {\n      return [];\n    }\n    var styles = root.querySelectorAll('style');\n    return Array.prototype.filter.call(styles, function(s) {\n      return !s.hasAttribute(NO_SHIM_ATTRIBUTE);\n    });\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  insertDirectives: function(cssText) {\n    cssText = this.insertPolyfillDirectivesInCssText(cssText);\n    return this.insertPolyfillRulesInCssText(cssText);\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 inert rules.\n   * \n   * For example, we convert this rule:\n   * \n   * polyfill-next-selector { content: ':host menu-item'; }\n   * ::content menu-item {\n   * \n   * to this:\n   * \n   * scopeName menu-item {\n   *\n  **/\n  insertPolyfillDirectivesInCssText: function(cssText) {\n    // TODO(sorvell): remove either content or comment\n    cssText = cssText.replace(cssCommentNextSelectorRe, function(match, p1) {\n      // remove end comment delimiter and add block start\n      return p1.slice(0, -2) + '{';\n    });\n    return cssText.replace(cssContentNextSelectorRe, function(match, p1) {\n      return p1 + ' {';\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   * polyfill-rule {\n   *   content: ':host menu-item';\n   * ...\n   * }\n   * \n   * to this:\n   * \n   * scopeName menu-item {...}\n   *\n  **/\n  insertPolyfillRulesInCssText: function(cssText) {\n    // TODO(sorvell): remove either content or comment\n    cssText = cssText.replace(cssCommentRuleRe, function(match, p1) {\n      // remove end comment delimiter\n      return p1.slice(0, -1);\n    });\n    return cssText.replace(cssContentRuleRe, function(match, p1, p2, p3) {\n      var rule = match.replace(p1, '').replace(p2, '');\n      return p3 + rule;\n    });\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  scopeCssText: function(cssText, scopeSelector) {\n    var unscoped = this.extractUnscopedRulesFromCssText(cssText);\n    cssText = this.insertPolyfillHostInCssText(cssText);\n    cssText = this.convertColonHost(cssText);\n    cssText = this.convertColonHostContext(cssText);\n    cssText = this.convertCombinators(cssText);\n    if (scopeSelector) {\n      var self = this, cssText;\n      withCssRules(cssText, function(rules) {\n        cssText = self.scopeRules(rules, scopeSelector);\n      });\n\n    }\n    cssText = cssText + '\\n' + unscoped;\n    return cssText.trim();\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  extractUnscopedRulesFromCssText: function(cssText) {\n    // TODO(sorvell): remove either content or comment\n    var r = '', m;\n    while (m = cssCommentUnscopedRuleRe.exec(cssText)) {\n      r += m[1].slice(0, -1) + '\\n\\n';\n    }\n    while (m = cssContentUnscopedRuleRe.exec(cssText)) {\n      r += m[0].replace(m[2], '').replace(m[1], m[3]) + '\\n\\n';\n    }\n    return r;\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 :host-context(.foo) > .bar { }\n   *\n   * to\n   *\n   * scopeName.foo > .bar, .foo scopeName > .bar { }\n   * \n   * and\n   *\n   * :host-context(.foo:host) .bar { ... }\n   * \n   * to\n   * \n   * scopeName.foo .bar { ... }\n  */\n  convertColonHostContext: function(cssText) {\n    return this.convertColonRule(cssText, cssColonHostContextRe,\n        this.colonHostContextPartReplacer);\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  colonHostContextPartReplacer: 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    for (var i=0; i < combinatorsRe.length; i++) {\n      cssText = cssText.replace(combinatorsRe[i], ' ');\n    }\n    return cssText;\n  },\n  // change a selector like 'div' to 'name div'\n  scopeRules: function(cssRules, scopeSelector) {\n    var cssText = '';\n    if (cssRules) {\n      Array.prototype.forEach.call(cssRules, function(rule) {\n        if (rule.selectorText && (rule.style && rule.style.cssText)) {\n          cssText += this.scopeSelector(rule.selectorText, scopeSelector, \n            this.strictStyling) + ' {\\n\\t';\n          cssText += this.propertiesFromRule(rule) + '\\n}\\n\\n';\n        } else if (rule.type === CSSRule.MEDIA_RULE) {\n          cssText += '@media ' + rule.media.mediaText + ' {\\n';\n          cssText += this.scopeRules(rule.cssRules, scopeSelector);\n          cssText += '\\n}\\n\\n';\n        } else if (rule.cssText) {\n          cssText += rule.cssText + '\\n\\n';\n        }\n      }, this);\n    }\n    return cssText;\n  },\n  scopeSelector: function(selector, scopeSelector, strict) {\n    var r = [], parts = selector.split(',');\n    parts.forEach(function(p) {\n      p = p.trim();\n      if (this.selectorNeedsScoping(p, scopeSelector)) {\n        p = (strict && !p.match(polyfillHostNoCombinator)) ? \n            this.applyStrictSelectorScope(p, scopeSelector) :\n            this.applySimpleSelectorScope(p, scopeSelector);\n      }\n      r.push(p);\n    }, this);\n    return r.join(', ');\n  },\n  selectorNeedsScoping: function(selector, scopeSelector) {\n    var re = this.makeScopeMatcher(scopeSelector);\n    return !selector.match(re);\n  },\n  makeScopeMatcher: function(scopeSelector) {\n    scopeSelector = scopeSelector.replace(/\\[/g, '\\\\[').replace(/\\[/g, '\\\\]');\n    return new RegExp('^(' + scopeSelector + ')' + selectorReSuffix, 'm');\n  },\n  // scope via name and [is=name]\n  applySimpleSelectorScope: function(selector, scopeSelector) {\n    if (selector.match(polyfillHostRe)) {\n      selector = selector.replace(polyfillHostNoCombinator, scopeSelector);\n      return selector.replace(polyfillHostRe, scopeSelector + ' ');\n    } else {\n      return scopeSelector + ' ' + 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, scopeSelector) {\n    scopeSelector = scopeSelector.replace(/\\[is=([^\\]]*)\\]/g, '$1');\n    var splits = [' ', '>', '+', '~'],\n      scoped = selector,\n      attrName = '[' + scopeSelector + ']';\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(colonHostContextRe, polyfillHostContext).replace(\n        colonHostRe, polyfillHost);\n  },\n  propertiesFromRule: function(rule) {\n    var cssText = rule.style.cssText;\n    // TODO(sorvell): Safari cssom incorrectly removes quotes from the content\n    // property. (https://bugs.webkit.org/show_bug.cgi?id=118045)\n    // don't replace attr rules\n    if (rule.style.content && !rule.style.content.match(/['\"]+|attr/)) {\n      cssText = cssText.replace(/content:[^;]*;/g, 'content: \\'' + \n          rule.style.content + '\\';');\n    }\n    // TODO(sorvell): we can workaround this issue here, but we need a list\n    // of troublesome properties to fix https://github.com/Polymer/platform/issues/53\n    //\n    // inherit rules can be omitted from cssText\n    // TODO(sorvell): remove when Blink bug is fixed:\n    // https://code.google.com/p/chromium/issues/detail?id=358273\n    var style = rule.style;\n    for (var i in style) {\n      if (style[i] === 'initial') {\n        cssText += i + ': initial; ';\n      }\n    }\n    return cssText;\n  },\n  replaceTextInStyles: function(styles, action) {\n    if (styles && action) {\n      if (!(styles instanceof Array)) {\n        styles = [styles];\n      }\n      Array.prototype.forEach.call(styles, function(s) {\n        s.textContent = action.call(this, s.textContent);\n      }, this);\n    }\n  },\n  addCssToDocument: function(cssText, name) {\n    if (cssText.match('@import')) {\n      addOwnSheet(cssText, name);\n    } else {\n      addCssToDocument(cssText);\n    }\n  }\n};\n\nvar selectorRe = /([^{]*)({[\\s\\S]*?})/gim,\n    cssCommentRe = /\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\//gim,\n    // TODO(sorvell): remove either content or comment\n    cssCommentNextSelectorRe = /\\/\\*\\s*@polyfill ([^*]*\\*+([^/*][^*]*\\*+)*\\/)([^{]*?){/gim,\n    cssContentNextSelectorRe = /polyfill-next-selector[^}]*content\\:[\\s]*'([^']*)'[^}]*}([^{]*?){/gim,\n    // TODO(sorvell): remove either content or comment\n    cssCommentRuleRe = /\\/\\*\\s@polyfill-rule([^*]*\\*+([^/*][^*]*\\*+)*)\\//gim,\n    cssContentRuleRe = /(polyfill-rule)[^}]*(content\\:[\\s]*'([^']*)'[^;]*;)[^}]*}/gim,\n    // TODO(sorvell): remove either content or comment\n    cssCommentUnscopedRuleRe = /\\/\\*\\s@polyfill-unscoped-rule([^*]*\\*+([^/*][^*]*\\*+)*)\\//gim,\n    cssContentUnscopedRuleRe = /(polyfill-unscoped-rule)[^}]*(content\\:[\\s]*'([^']*)'[^;]*;)[^}]*}/gim,\n    cssPseudoRe = /::(x-[^\\s{,(]*)/gim,\n    cssPartRe = /::part\\(([^)]*)\\)/gim,\n    // note: :host pre-processed to -shadowcsshost.\n    polyfillHost = '-shadowcsshost',\n    // note: :host-context pre-processed to -shadowcsshostcontext.\n    polyfillHostContext = '-shadowcsscontext',\n    parenSuffix = ')(?:\\\\((' +\n        '(?:\\\\([^)(]*\\\\)|[^)(]*)+?' +\n        ')\\\\))?([^,{]*)';\n    cssColonHostRe = new RegExp('(' + polyfillHost + parenSuffix, 'gim'),\n    cssColonHostContextRe = new RegExp('(' + polyfillHostContext + parenSuffix, 'gim'),\n    selectorReSuffix = '([>\\\\s~+\\[.,{:][\\\\s\\\\S]*)?$',\n    colonHostRe = /\\:host/gim,\n    colonHostContextRe = /\\:host-context/gim,\n    /* host name without combinator */\n    polyfillHostNoCombinator = polyfillHost + '-no-combinator',\n    polyfillHostRe = new RegExp(polyfillHost, 'gim'),\n    polyfillHostContextRe = new RegExp(polyfillHostContext, 'gim'),\n    combinatorsRe = [\n      /\\^\\^/g,\n      /\\^/g,\n      /\\/shadow\\//g,\n      /\\/shadow-deep\\//g,\n      /::shadow/g,\n      /\\/deep\\//g\n    ];\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 = [];\n  if (style.sheet) {\n    // TODO(sorvell): Firefox throws when accessing the rules of a stylesheet\n    // with an @import\n    // https://bugzilla.mozilla.org/show_bug.cgi?id=625013\n    try {\n      rules = style.sheet.cssRules;\n    } catch(e) {\n      //\n    }\n  } else {\n    console.warn('sheet not found', style);\n  }\n  style.parentNode.removeChild(style);\n  return rules;\n}\n\nvar frame = document.createElement('iframe');\nframe.style.display = 'none';\n\nfunction initFrame() {\n  frame.initialized = true;\n  document.body.appendChild(frame);\n  var doc = frame.contentDocument;\n  var base = doc.createElement('base');\n  base.href = document.baseURI;\n  doc.head.appendChild(base);\n}\n\nfunction inFrame(fn) {\n  if (!frame.initialized) {\n    initFrame();\n  }\n  document.body.appendChild(frame);\n  fn(frame.contentDocument);\n  document.body.removeChild(frame);\n}\n\n// TODO(sorvell): use an iframe if the cssText contains an @import to workaround\n// https://code.google.com/p/chromium/issues/detail?id=345114\nvar isChrome = navigator.userAgent.match('Chrome');\nfunction withCssRules(cssText, callback) {\n  if (!callback) {\n    return;\n  }\n  var rules;\n  if (cssText.match('@import') && isChrome) {\n    var style = cssTextToStyle(cssText);\n    inFrame(function(doc) {\n      doc.head.appendChild(style.impl);\n      rules = style.sheet.cssRules;\n      callback(rules);\n    });\n  } else {\n    rules = cssToRules(cssText);\n    callback(rules);\n  }\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\nfunction addOwnSheet(cssText, name) {\n  var style = cssTextToStyle(cssText);\n  style.setAttribute(name, '');\n  style.setAttribute(SHIMMED_ATTRIBUTE, '');\n  document.head.appendChild(style);\n}\n\nvar SHIM_ATTRIBUTE = 'shim-shadowdom';\nvar SHIMMED_ATTRIBUTE = 'shim-shadowdom-css';\nvar NO_SHIM_ATTRIBUTE = 'no-shim';\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        style.textContent = ShadowCSS.shimStyle(style);\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  addEventListener('DOMContentLoaded', function() {\n    if (CustomElements.useNative === false) {\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  });\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  // 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 = function() {\n     throw 'Possible attempt to load Polymer twice';\n    };\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  resolveTemplate: function(template) {\n    this.resolveDom(template.content, template.ownerDocument.baseURI);\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      if (url.match(/^data:/)) {\n        // Handle Data URI Scheme\n        var pieces = url.split(',');\n        var header = pieces[0];\n        var body = pieces[1];\n        if(header.indexOf(';base64') > -1) {\n          body = atob(body);\n        } else {\n          body = decodeURIComponent(body);\n        }\n        setTimeout(function() {\n            this.receive(url, elt, null, body);\n        }.bind(this), 0);\n      } else {\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    },\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, callback) {\n    var self = this;\n    var done = function(e) {\n      if (callback) {\n        callback(e);\n      }\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  // NOTE: execute scripts by injecting them and watching for the load/error\n  // event. Inline scripts are handled via dataURL's because browsers tend to\n  // provide correct parsing errors in this case. If this has any compatibility\n  // issues, we can switch to injecting the inline script with textContent.\n  // Scripts with dataURL's do not appear to generate load events and therefore\n  // we assume they execute synchronously.\n  parseScript: function(scriptElt) {\n    var script = document.createElement('script');\n    script.__importElement = scriptElt;\n    script.src = scriptElt.src ? scriptElt.src : \n        generateScriptDataUrl(scriptElt);\n    scope.currentScript = scriptElt;\n    this.trackElement(script, function(e) {\n      script.parentNode.removeChild(script);\n      scope.currentScript = null;  \n    });\n    document.head.appendChild(script);\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    return true;\n  }\n};\n\nfunction nodeIsImport(elt) {\n  return (elt.localName === 'link') && (elt.rel === IMPORT_LINK_TYPE);\n}\n\nfunction generateScriptDataUrl(script) {\n  var scriptContent = generateScriptContent(script), b64;\n  try {\n    b64 = btoa(scriptContent);\n  } catch(e) {\n    b64 = btoa(unescape(encodeURIComponent(scriptContent)));\n    console.warn('Script contained non-latin characters that were forced ' +\n      'to latin. Some characters may be wrong.', script);\n  }\n  return 'data:text/javascript;base64,' + b64;\n}\n\nfunction generateScriptContent(script) {\n  return script.textContent + generateSourceMapHint(script);\n}\n\n// calculate source map hint\nfunction generateSourceMapHint(script) {\n  var moniker = script.__nodeUrl;\n  if (!moniker) {\n    moniker = script.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 = script.textContent.match(/Polymer\\(['\"]([^'\"]*)/);\n    tag = matches && matches[1] || tag;\n    // tag the moniker\n    moniker += '/' + tag + '.js';\n  }\n  return '\\n//# sourceURL=' + moniker + '\\n';\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\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    ].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    // ensure UTF-8 charset\n    var meta = doc.createElement('meta');\n    meta.setAttribute('charset', 'utf-8');\n\n    doc.head.appendChild(meta);\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  //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  upgradeDocument(doc);\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  scope.reservedTagList = [];\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    // prevent registering reserved names\n    if (isReservedTag(name)) {\n      throw new Error('Failed to execute \\'registerElement\\' on \\'Document\\': Registration failed for type \\'' + String(name) + '\\'. The type name is invalid.');\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 isReservedTag(name) {\n    for (var i = 0; i < reservedTagList.length; i++) {\n      if (name === reservedTagList[i]) {\n        return true;\n      }\n    }\n  }\n\n  var reservedTagList = [\n    'annotation-xml', 'color-profile', 'font-face', 'font-face-src',\n    'font-face-uri', 'font-face-format', 'font-face-name', 'missing-glyph'\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    // The default is HTMLElement.prototype, so we add a test to avoid mixing in\n    // native prototypes\n    while (p !== inNative && p !== HTMLElement.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  var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';\n  function createElementNS(namespace, tag, typeExtension) {\n    // NOTE: we do not support non-HTML elements,\n    // just call createElementNS for non HTML Elements\n    if (namespace === HTML_NAMESPACE) {\n      return createElement(tag, typeExtension);\n    } else {\n      return domCreateElementNS(namespace, tag);\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  var domCreateElementNS = document.createElementNS.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  document.createElementNS = createElementNS; // 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// Create a custom 'instanceof'. This is necessary when CustomElements\n// are implemented via a mixin strategy, as for example on IE10.\nvar isInstance;\nif (!Object.__proto__ && !useNative) {\n  isInstance = function(obj, ctor) {\n    var p = obj;\n    while (p) {\n      // NOTE: this is not technically correct since we're not checking if\n      // an object is an instance of a constructor; however, this should\n      // be good enough for the mixin strategy.\n      if (p === ctor.prototype) {\n        return true;\n      }\n      p = p.__proto__;\n    }\n    return false;\n  }\n} else {\n  isInstance = function(obj, base) {\n    return obj instanceof base;\n  }\n}\n\n// exports\nscope.instanceof = isInstance;\nscope.reservedTagList = reservedTagList;\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\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  var endOfMicrotask = scope.endOfMicrotask;\n\n  // Generic url loader\n  function Loader(regex) {\n    this.regex = regex;\n  }\n  Loader.prototype = {\n    // TODO(dfreedm): there may be a better factoring here\n    // extract absolute urls from the text (full of relative urls)\n    extractUrls: function(text, base) {\n      var matches = [];\n      var matched, u;\n      while ((matched = this.regex.exec(text))) {\n        u = new URL(matched[1], base);\n        matches.push({matched: matched[0], url: u.href});\n      }\n      return matches;\n    },\n    // take a text blob, a root url, and a callback and load all the urls found within the text\n    // returns a map of absolute url to text\n    process: function(text, root, callback) {\n      var matches = this.extractUrls(text, root);\n      this.fetch(matches, {}, callback);\n    },\n    // build a mapping of url -> text from matches\n    fetch: function(matches, map, callback) {\n      var inflight = matches.length;\n\n      // return early if there is no fetching to be done\n      if (!inflight) {\n        return callback(map);\n      }\n\n      var done = function() {\n        if (--inflight === 0) {\n          callback(map);\n        }\n      };\n\n      // map url -> responseText\n      var handleXhr = function(err, request) {\n        var match = request.match;\n        var key = match.url;\n        // handle errors with an empty string\n        if (err) {\n          map[key] = '';\n          return done();\n        }\n        var response = request.response || request.responseText;\n        map[key] = response;\n        this.fetch(this.extractUrls(response, key), map, done);\n      };\n\n      var m, req, url;\n      for (var i = 0; i < inflight; i++) {\n        m = matches[i];\n        url = m.url;\n        // if this url has already been requested, skip requesting it again\n        if (map[url]) {\n          // Async call to done to simplify the inflight logic\n          endOfMicrotask(done);\n          continue;\n        }\n        req = this.xhr(url, handleXhr, this);\n        req.match = m;\n        // tag the map with an XHR request to deduplicate at the same level\n        map[url] = req;\n      }\n    },\n    xhr: function(url, callback, scope) {\n      var request = new XMLHttpRequest();\n      request.open('GET', url, true);\n      request.send();\n      request.onload = function() {\n        callback.call(scope, null, request);\n      };\n      request.onerror = function() {\n        callback.call(scope, null, request);\n      };\n      return request;\n    }\n  };\n\n  scope.Loader = Loader;\n})(window.Platform);\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 urlResolver = scope.urlResolver;\nvar Loader = scope.Loader;\n\nfunction StyleResolver() {\n  this.loader = new Loader(this.regex);\n}\nStyleResolver.prototype = {\n  regex: /@import\\s+(?:url)?[\"'\\(]*([^'\"\\)]*)['\"\\)]*;/g,\n  // Recursively replace @imports with the text at that url\n  resolve: function(text, url, callback) {\n    var done = function(map) {\n      callback(this.flatten(text, url, map));\n    }.bind(this);\n    this.loader.process(text, url, done);\n  },\n  // resolve the textContent of a style node\n  resolveNode: function(style, callback) {\n    var text = style.textContent;\n    var url = style.ownerDocument.baseURI;\n    var done = function(text) {\n      style.textContent = text;\n      callback(style);\n    };\n    this.resolve(text, url, done);\n  },\n  // flatten all the @imports to text\n  flatten: function(text, base, map) {\n    var matches = this.loader.extractUrls(text, base);\n    var match, url, intermediate;\n    for (var i = 0; i < matches.length; i++) {\n      match = matches[i];\n      url = match.url;\n      // resolve any css text to be relative to the importer\n      intermediate = urlResolver.resolveCssText(map[url], url);\n      // flatten intermediate @imports\n      intermediate = this.flatten(intermediate, url, map);\n      text = text.replace(match.matched, intermediate);\n    }\n    return text;\n  },\n  loadStyles: function(styles, callback) {\n    var loaded=0, l = styles.length;\n    // called in the context of the style\n    function loadedStyle(style) {\n      loaded++;\n      if (loaded === l && callback) {\n        callback();\n      }\n    }\n    for (var i=0, s; (i<l) && (s=styles[i]); i++) {\n      this.resolveNode(s, loadedStyle);\n    }\n  }\n};\n\nvar styleResolver = new StyleResolver();\n\n// exports\nscope.styleResolver = styleResolver;\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 /shadow-deep/ ' + 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  // only install stylesheet if the browser has touch action support\n  var head = document.head;\n  var hasNativePE = window.PointerEvent || window.MSPointerEvent;\n  // only add shadow selectors if shadowdom is supported\n  var hasShadowRoot = !window.ShadowDOMPolyfill && document.head.createShadowRoot;\n\n  if (hasNativePE) {\n    attrib2css.forEach(function(r) {\n      if (String(r) === r) {\n        styles += selector(r) + rule(r) + '\\n';\n        if (hasShadowRoot) {\n          styles += shadowSelector(r) + rule(r) + '\\n';\n        }\n      } else {\n        styles += r.selectors.map(selector) + rule(r.rule) + '\\n';\n        if (hasShadowRoot) {\n          styles += r.selectors.map(shadowSelector) + rule(r.rule) + '\\n';\n        }\n      }\n    });\n\n    var el = document.createElement('style');\n    el.textContent = styles;\n    document.head.appendChild(el);\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/**\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\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    'pageX',\n    'pageY'\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    0,\n    0\n  ];\n\n  function PointerEvent(inType, inDict) {\n    inDict = inDict || Object.create(null);\n\n    var e = document.createEvent('Event');\n    e.initEvent(inType, inDict.bubbles || false, inDict.cancelable || false);\n\n    // define inherited MouseEvent properties\n    for(var i = 0, p; i < MOUSE_PROPS.length; i++) {\n      p = MOUSE_PROPS[i];\n      e[p] = inDict[p] || MOUSE_DEFAULTS[i];\n    }\n    e.buttons = inDict.buttons || 0;\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 = e.buttons ? 0.5 : 0;\n    }\n\n    // add x/y properties aliased to clientX/Y\n    e.x = e.clientX;\n    e.y = e.clientY;\n\n    // define the properties of the PointerEvent interface\n    e.pointerId = inDict.pointerId || 0;\n    e.width = inDict.width || 0;\n    e.height = inDict.height || 0;\n    e.pressure = pressure;\n    e.tiltX = inDict.tiltX || 0;\n    e.tiltY = inDict.tiltY || 0;\n    e.pointerType = inDict.pointerType || '';\n    e.hwTimestamp = inDict.hwTimestamp || 0;\n    e.isPrimary = inDict.isPrimary || false;\n    return e;\n  }\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    'pageX',\n    'pageY'\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  ];\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    pointermap: new scope.PointerMap(),\n    eventMap: Object.create(null),\n    captureInfo: Object.create(null),\n    // Scope objects for native events.\n    // This exists for ease of testing.\n    eventSources: Object.create(null),\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      inEvent.bubbles = true;\n      this.fireEvent('pointerdown', inEvent);\n    },\n    move: function(inEvent) {\n      inEvent.bubbles = true;\n      this.fireEvent('pointermove', inEvent);\n    },\n    up: function(inEvent) {\n      inEvent.bubbles = true;\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      inEvent.bubbles = true;\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 (inEvent._handledByPE) {\n        return;\n      }\n      var type = inEvent.type;\n      var fn = this.eventMap && this.eventMap[type];\n      if (fn) {\n        fn(inEvent);\n      }\n      inEvent._handledByPE = 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[inEvent.pointerId]) {\n        inEvent.relatedTarget = null;\n      }\n      var e = new PointerEvent(inType, inEvent);\n      if (inEvent.preventDefault) {\n        e.preventDefault = inEvent.preventDefault;\n      }\n      e._target = e._target || 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 = Object.create(null), 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      return this.captureInfo[inEvent.pointerId] || inEvent._target;\n    },\n    setCapture: function(inPointerId, inTarget) {\n      if (this.captureInfo[inPointerId]) {\n        this.releaseCapture(inPointerId);\n      }\n      this.captureInfo[inPointerId] = inTarget;\n      var e = document.createEvent('Event');\n      e.initEvent('gotpointercapture', true, false);\n      e.pointerId = inPointerId;\n      this.implicitRelease = this.releaseCapture.bind(this, inPointerId);\n      document.addEventListener('pointerup', this.implicitRelease);\n      document.addEventListener('pointercancel', this.implicitRelease);\n      e._target = inTarget;\n      this.asyncDispatchEvent(e);\n    },\n    releaseCapture: function(inPointerId) {\n      var t = this.captureInfo[inPointerId];\n      if (t) {\n        var e = document.createEvent('Event');\n        e.initEvent('lostpointercapture', true, false);\n        e.pointerId = inPointerId;\n        this.captureInfo[inPointerId] = undefined;\n        document.removeEventListener('pointerup', this.implicitRelease);\n        document.removeEventListener('pointercancel', this.implicitRelease);\n        e._target = 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      requestAnimationFrame(this.dispatchEvent.bind(this, inEvent));\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('readystatechange', function() {\n        if (document.readyState === 'complete') {\n          this.installNewSubtree(document);\n        }\n      }.bind(this));\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  var WHICH_TO_BUTTONS = [0, 1, 4, 2];\n\n  var HAS_BUTTONS = false;\n  try {\n    HAS_BUTTONS = new MouseEvent('test', {buttons: 1}).buttons === 1;\n  } catch (e) {}\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      if (!HAS_BUTTONS) {\n        e.buttons = WHICH_TO_BUTTONS[e.which] || 0;\n      }\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 captureInfo = dispatcher.captureInfo;\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    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        el._scrollType = st;\n        dispatcher.listen(el, this.events);\n        // set touch-action on shadows as well\n        allShadows(el).forEach(function(s) {\n          s._scrollType = st;\n          dispatcher.listen(s, this.events);\n        }, this);\n      }\n    },\n    elementRemoved: function(el) {\n      el._scrollType = undefined;\n      dispatcher.unlisten(el, this.events);\n      // remove touch-action from shadow\n      allShadows(el).forEach(function(s) {\n        s._scrollType = undefined;\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        el._scrollType = st;\n        allShadows(el).forEach(function(s) {\n          s._scrollType = 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    typeToButtons: function(type) {\n      var ret = 0;\n      if (type === 'touchstart' || type === 'touchmove') {\n        ret = 1;\n      }\n      return ret;\n    },\n    touchToPointer: function(inTouch) {\n      var cte = this.currentTouchEvent;\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      var id = e.pointerId = inTouch.identifier + 2;\n      e.target = captureInfo[id] || findTarget(e);\n      e.bubbles = true;\n      e.cancelable = true;\n      e.detail = this.clickCount;\n      e.button = 0;\n      e.buttons = this.typeToButtons(cte.type);\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      // forward touch preventDefaults\n      var self = this;\n      e.preventDefault = function() {\n        self.scrolling = false;\n        self.firstXY = null;\n        cte.preventDefault();\n      };\n      return e;\n    },\n    processTouches: function(inEvent, inFunction) {\n      var tl = inEvent.changedTouches;\n      this.currentTouchEvent = inEvent;\n      for (var i = 0, t; i < tl.length; i++) {\n        t = tl[i];\n        inFunction.call(this, this.touchToPointer(t));\n      }\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 = inEvent.currentTarget._scrollType;\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(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.PointerEvent !== scope.PointerEvent) {\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      requestAnimationFrame(this.runQueue.bind(this, inHandlerFns, e));\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      requestAnimationFrame(this.dispatchEvent.bind(this, inEvent, inTarget));\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  // recognizers call into the dispatcher and load later\n  // solve the chicken and egg problem by having registerScopes module run last\n  dispatcher.registerQueue = [];\n  dispatcher.immediateRegister = false;\n  scope.dispatcher = dispatcher;\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 (dispatcher.immediateRegister) {\n      var pe = window.PointerEventsPolyfill;\n      if (pe) {\n        pe.register(inScope);\n      }\n      scope.dispatcher.registerTarget(inScope);\n    } else {\n      dispatcher.registerQueue.push(inScope);\n    }\n  };\n  scope.register(document);\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 * Type of pointer that made the holding event.\n * @type String\n * @property pointerType\n */\n/**\n * Screen X axis position of the held pointer\n * @type Number\n * @property clientX\n */\n/**\n * Screen Y axis position of the held pointer\n * @type Number\n * @property clientY\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 * Milliseconds pointer has been held down.\n * @type Number\n * @property holdTime\n */\n/**\n * This event is fired when a held pointer is released or moved.\n *\n * @class released\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        clientX: this.heldPointer.clientX,\n        clientY: this.heldPointer.clientY\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      // start with at least two pointers\n      var points = {a: pointers[0], b: pointers[1]};\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          buttons: inEvent.buttons,\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    shouldTap: function(e, downState) {\n      if (!e.tapPrevented) {\n        if (e.pointerType === 'mouse') {\n          // only allow left click to tap for mouse\n          return downState.buttons === 1;\n        } else {\n          return true;\n        }\n      }\n    },\n    pointerup: function(inEvent) {\n      var start = pointermap.get(inEvent.pointerId);\n      if (start && this.shouldTap(inEvent, start)) {\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",
-    "/*\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\n/**\n * Because recognizers are loaded after dispatcher, we have to wait to register\n * scopes until after all the recognizers.\n */\n(function(scope) {\n  var dispatcher = scope.dispatcher;\n  function registerScopes() {\n    dispatcher.immediateRegister = true;\n    var rq = dispatcher.registerQueue;\n    rq.forEach(scope.register);\n    rq.length = 0;\n  }\n  if (document.readyState === 'complete') {\n    registerScopes();\n  } else {\n    // register scopes after a steadystate is reached\n    // less MutationObserver churn\n    document.addEventListener('readystatechange', function() {\n      if (document.readyState === 'complete') {\n        registerScopes();\n      }\n    });\n  }\n})(window.PointerGestures);\n",
-    "// Copyright (c) 2014 The Polymer Project Authors. All rights reserved.\n// This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt\n// The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt\n// The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt\n// Code distributed by Google as part of the polymer project is also\n// subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt\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  Node.prototype.bind = function(name, observable) {\n    console.error('Unhandled binding to Node: ', this, name, observable);\n  };\n\n  function updateBindings(node, name, binding) {\n    var bindings = node.bindings_;\n    if (!bindings)\n      bindings = node.bindings_ = {};\n\n    if (bindings[name])\n      binding[name].close();\n\n    return bindings[name] = binding;\n  }\n\n  function returnBinding(node, name, binding) {\n    return binding;\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  var maybeUpdateBindings = returnBinding;\n\n  Object.defineProperty(Platform, 'enableBindingsReflection', {\n    get: function() {\n      return maybeUpdateBindings === updateBindings;\n    },\n    set: function(enable) {\n      maybeUpdateBindings = enable ? updateBindings : returnBinding;\n      return enable;\n    },\n    configurable: true\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    var observable = value;\n    updateText(this, observable.open(textBinding(this)));\n    return maybeUpdateBindings(this, name, observable);\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\n    var observable = value;\n    updateAttribute(this, name, conditional,\n        observable.open(attributeBinding(this, name, conditional)));\n\n    return maybeUpdateBindings(this, name, observable);\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      case 'range':\n        if (/Trident|MSIE/.test(navigator.userAgent))\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    return {\n      close: function() {\n        input.removeEventListener(eventType, eventHandler);\n        observable.close();\n      },\n\n      observable_: observable\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.observable_.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    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\n    var observable = value;\n    var binding = bindInputEvent(this, name, observable, postEventFn);\n    updateInput(this, name,\n                observable.open(inputBinding(this, name, sanitizeFn)),\n                sanitizeFn);\n\n    // Checkboxes may need to update bindings of other checkboxes.\n    return updateBindings(this, name, binding);\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    var observable = value;\n    var binding = bindInputEvent(this, 'value', observable);\n    updateInput(this, 'value',\n                observable.open(inputBinding(this, 'value', sanitizeValue)));\n    return maybeUpdateBindings(this, name, binding);\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.observable_.setValue(select.value);\n      selectBinding.observable_.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    var observable = value;\n    var binding = bindInputEvent(this, 'value', observable);\n    updateOption(this, observable.open(optionBinding(this)));\n    return maybeUpdateBindings(this, name, binding);\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    var observable = value;\n    var binding = bindInputEvent(this, name, observable);\n    updateInput(this, name,\n                observable.open(inputBinding(this, name)));\n\n    // Option update events may need to access select bindings.\n    return updateBindings(this, name, binding);\n  }\n})(this);\n",
-    "// Copyright (c) 2014 The Polymer Project Authors. All rights reserved.\n// This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt\n// The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt\n// The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt\n// Code distributed by Google as part of the polymer project is also\n// subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt\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  if (hasTemplateElement) {\n    // TODO(rafaelw): Remove when fix for\n    // https://codereview.chromium.org/164803002/\n    // makes it to Chrome release.\n    (function() {\n      var t = document.createElement('template');\n      var d = t.content.ownerDocument;\n      var html = d.appendChild(d.createElement('html'));\n      var head = html.appendChild(d.createElement('head'));\n      var base = d.createElement('base');\n      base.href = document.baseURI;\n      head.appendChild(base);\n    })();\n  }\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\n        // TODO(rafaelw): Remove when fix for\n        // https://codereview.chromium.org/164803002/\n        // makes it to Chrome release.\n        var base = owner.stagingDocument_.createElement('base');\n        base.href = document.baseURI;\n        owner.stagingDocument_.head.appendChild(base);\n\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      if (!this.bindings_) {\n        this.bindings_ = { ref: value };\n      } else {\n        this.bindings_.ref = value;\n      }\n\n      return 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        }\n\n        return;\n      }\n\n      if (!this.iterator_) {\n        this.iterator_ = new TemplateIterator(this);\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      if (bindingDelegate)\n        delegate_ = this.newDelegate_(bindingDelegate);\n\n      if (!this.refContent_)\n        this.refContent_ = this.ref_.content;\n      var content = this.refContent_;\n      if (content.firstChild === null)\n        return emptyInstance;\n\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      instance.bindings_ = [];\n      instance.terminator_ = null;\n      var instanceRecord = instance.templateInstance_ = {\n        firstNode: null,\n        lastNode: null,\n        model: model\n      };\n\n      var i = 0;\n      var collectTerminator = false;\n      for (var child = content.firstChild; child; child = child.nextSibling) {\n        // The terminator of the instance is the clone of the last child of the\n        // content. If the last child is an active template, it may produce\n        // instances as a result of production, so simply collecting the last\n        // child of the instance after it has finished producing may be wrong.\n        if (child.nextSibling === null)\n          collectTerminator = true;\n\n        var clone = cloneAndBindInstance(child, instance, stagingDocument,\n                                         map.children[i++],\n                                         model,\n                                         delegate_,\n                                         instance.bindings_);\n        clone.templateInstance_ = instanceRecord;\n        if (collectTerminator)\n          instance.terminator_ = clone;\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      if (this.bindings_ && this.bindings_.ref)\n        this.bindings_.ref.close()\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      var delegateFn = prepareBindingFn &&\n                       prepareBindingFn(pathString, name, node);\n      // Don't try to parse the expression if there's a prepareBinding function\n      if (delegateFn == null) {\n        tokens.push(Path.get(pathString)); // PATH\n      } else {\n        tokens.push(null);\n      }\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  var emptyInstance = document.createDocumentFragment();\n  emptyInstance.bindings_ = [];\n  emptyInstance.terminator_ = null;\n\n  function TemplateIterator(templateElement) {\n    this.closed = false;\n    this.templateElement_ = templateElement;\n    this.instances = [];\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    getLastInstanceNode: function(index) {\n      if (index == -1)\n        return this.templateElement_;\n      var instance = this.instances[index];\n      var terminator = instance.terminator_;\n      if (!terminator)\n        return this.getLastInstanceNode(index - 1);\n\n      if (terminator.nodeType !== Node.ELEMENT_NODE ||\n          this.templateElement_ === terminator) {\n        return terminator;\n      }\n\n      var subtemplateIterator = terminator.iterator_;\n      if (!subtemplateIterator)\n        return terminator;\n\n      return subtemplateIterator.getLastTemplateNode();\n    },\n\n    getLastTemplateNode: function() {\n      return this.getLastInstanceNode(this.instances.length - 1);\n    },\n\n    insertInstanceAt: function(index, fragment) {\n      var previousInstanceLast = this.getLastInstanceNode(index - 1);\n      var parent = this.templateElement_.parentNode;\n      this.instances.splice(index, 0, fragment);\n\n      parent.insertBefore(fragment, previousInstanceLast.nextSibling);\n    },\n\n    extractInstanceAt: function(index) {\n      var previousInstanceLast = this.getLastInstanceNode(index - 1);\n      var lastNode = this.getLastInstanceNode(index);\n      var parent = this.templateElement_.parentNode;\n      var instance = this.instances.splice(index, 1)[0];\n\n      while (lastNode !== previousInstanceLast) {\n        var node = previousInstanceLast.nextSibling;\n        if (node == lastNode)\n          lastNode = previousInstanceLast;\n\n        instance.appendChild(parent.removeChild(node));\n      }\n\n      return instance;\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      // Instance Removals\n      var instanceCache = new Map;\n      var removeDelta = 0;\n      for (var i = 0; i < splices.length; i++) {\n        var splice = splices[i];\n        var removed = splice.removed;\n        for (var j = 0; j < removed.length; j++) {\n          var model = removed[j];\n          var instance = this.extractInstanceAt(splice.index + removeDelta);\n          if (instance !== emptyInstance) {\n            instanceCache.set(model, instance);\n          }\n        }\n\n        removeDelta -= splice.addedCount;\n      }\n\n      // Instance Insertions\n      for (var i = 0; i < splices.length; i++) {\n        var splice = splices[i];\n        var addIndex = splice.index;\n        for (; addIndex < splice.index + splice.addedCount; addIndex++) {\n          var model = this.iteratedValue[addIndex];\n          var instance = instanceCache.get(model);\n          if (instance) {\n            instanceCache.delete(model);\n          } else {\n            if (this.instanceModelFn_) {\n              model = this.instanceModelFn_(model);\n            }\n\n            if (model === undefined) {\n              instance = emptyInstance;\n            } else {\n              instance = template.createInstance(model, undefined, delegate);\n            }\n          }\n\n          this.insertInstanceAt(addIndex, instance);\n        }\n      }\n\n      instanceCache.forEach(function(instance) {\n        this.closeInstanceBindings(instance);\n      }, this);\n\n      if (this.instancePositionChangedFn_)\n        this.reportInstancesMoved(splices);\n    },\n\n    reportInstanceMoved: function(index) {\n      var instance = this.instances[index];\n      if (instance === emptyInstance)\n        return;\n\n      this.instancePositionChangedFn_(instance.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.instances.length;\n      while (index < length) {\n        this.reportInstanceMoved(index);\n        index++;\n      }\n    },\n\n    closeInstanceBindings: function(instance) {\n      var bindings = instance.bindings_;\n      for (var i = 0; i < bindings.length; i++) {\n        bindings[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 = 0; i < this.instances.length; i++) {\n        this.closeInstanceBindings(this.instances[i]);\n      }\n\n      this.instances.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 (c) 2014 The Polymer Project Authors. All rights reserved.\n// This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt\n// The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt\n// The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt\n// Code distributed by Google as part of the polymer project is also\n// subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt\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      // captures deps.\n      var firstValue = this.getValue(model, observer, filterRegistry);\n      var firstTime = true;\n      var self = this;\n\n      function valueFn() {\n        // deps cannot have changed on first value retrieval.\n        if (firstTime) {\n          firstTime = false;\n          return firstValue;\n        }\n\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 isLiteralExpression(pathString) {\n    switch (pathString) {\n      case '':\n        return false;\n\n      case 'false':\n      case 'null':\n      case 'true':\n        return true;\n    }\n\n    if (!isNaN(Number(pathString)))\n      return true;\n\n    return false;\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 (!isLiteralExpression(pathString) && 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        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\n// flush periodically if platform does not have object observe.\nif (!Observer.hasObjectObserve) {\n  var FLUSH_POLL_INTERVAL = 125;\n  window.addEventListener('WebComponentsReady', function() {\n    flush();\n    scope.flushPoll = setInterval(flush, FLUSH_POLL_INTERVAL);\n  });\n} else {\n  // make flush a no-op when we have Object.observe\n  flush = function() {};\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/runtime/bin/vmservice/client/deployed/web/packages/web_components/platform.js.map b/runtime/bin/vmservice/client/deployed/web/packages/web_components/platform.js.map
deleted file mode 100644
index 33e82bd..0000000
--- a/runtime/bin/vmservice/client/deployed/web/packages/web_components/platform.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"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/TreeScope.js","../ShadowDOM/src/wrappers/events.js","../ShadowDOM/src/wrappers/NodeList.js","../ShadowDOM/src/wrappers/HTMLCollection.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/HTMLSelectElement.js","../ShadowDOM/src/wrappers/HTMLTableElement.js","../ShadowDOM/src/wrappers/HTMLTableSectionElement.js","../ShadowDOM/src/wrappers/HTMLTableRowElement.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/DataTransfer.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","src/styleloader.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","../PointerGestures/src/registerScopes.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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiBA,QAAA,qBAAA,EAAA,GACA,GAAA,GAAA,MACA,EAAA,SAAA,YAAA,SACA,GACA,QAAA,QAAA,EAAA,WAAA,EAAA,UAAA,EACA,WAAA,QAAA,EAAA,cAAA,EAAA,aAAA,EAGA,GAAA,UAAA,EAAA,EAAA,QAAA,EAAA,WAGA,KAAA,GADA,GAAA,EAAA,OAAA,KAAA,GACA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,EAAA,GACA,EAAA,GAAA,EAAA,EAKA,OAFA,GAAA,WAAA,KAAA,WAEA,EC7BA,mBAAA,WACA,WACA,GAAA,GAAA,OAAA,eACA,EAAA,KAAA,MAAA,IAEA,EAAA,WACA,KAAA,KAAA,QAAA,IAAA,KAAA,WAAA,IAAA,KAAA,MAGA,GAAA,WACA,IAAA,SAAA,EAAA,GACA,GAAA,GAAA,EAAA,KAAA,KACA,IAAA,EAAA,KAAA,EACA,EAAA,GAAA,EAEA,EAAA,EAAA,KAAA,MAAA,OAAA,EAAA,GAAA,UAAA,KAEA,IAAA,SAAA,GACA,GAAA,EACA,QAAA,EAAA,EAAA,KAAA,QAAA,EAAA,KAAA,EACA,EAAA,GAAA,QAEA,SAAA,SAAA,GACA,KAAA,IAAA,EAAA,UAIA,OAAA,QAAA,KCnBA,SAAA,QACA,YAGA,SAAA,uBAQA,QAAA,GAAA,GACA,EAAA,EARA,GAAA,kBAAA,QAAA,SACA,kBAAA,OAAA,QACA,OAAA,CAGA,IAAA,MAMA,KACA,IAUA,OATA,QAAA,QAAA,EAAA,GACA,MAAA,QAAA,EAAA,GACA,EAAA,GAAA,EACA,EAAA,GAAA,QACA,GAAA,GACA,EAAA,KAAA,EAAA,GACA,EAAA,OAAA,EAEA,OAAA,qBAAA,GACA,IAAA,EAAA,QACA,EAEA,OAAA,EAAA,GAAA,MACA,UAAA,EAAA,GAAA,MACA,UAAA,EAAA,GAAA,MACA,UAAA,EAAA,GAAA,MACA,UAAA,EAAA,GAAA,MACA,GAGA,OAAA,UAAA,EAAA,GACA,MAAA,UAAA,EAAA,IAEA,GAKA,QAAA,cAIA,GAAA,OAAA,UACA,kBAAA,QAAA,WACA,OAAA,SAAA,eAAA,WACA,OAAA,CAGA,KACA,GAAA,GAAA,GAAA,UAAA,GAAA,eACA,OAAA,KACA,MAAA,GACA,OAAA,GAMA,QAAA,SAAA,GACA,OAAA,IAAA,IAAA,EAGA,QAAA,UAAA,GACA,OAAA,EAGA,QAAA,UAAA,GACA,MAAA,KAAA,OAAA,GAOA,QAAA,cAAA,EAAA,GACA,MAAA,KAAA,EACA,IAAA,GAAA,EAAA,IAAA,EAAA,EACA,YAAA,IAAA,YAAA,IACA,EAEA,IAAA,GAAA,IAAA,EAyBA,QAAA,aAAA,GACA,MAAA,gBAAA,IACA,GACA,EAAA,EAAA,OAEA,IAAA,GACA,EAEA,KAAA,EAAA,IACA,EAEA,WAAA,KAAA,IAKA,QAAA,MAAA,EAAA,GACA,GAAA,IAAA,qBACA,KAAA,OAAA,wCAEA,OAAA,IAAA,EAAA,OACA,KAEA,QAAA,IACA,KAAA,KAAA,GACA,OAGA,EAAA,MAAA,YAAA,OAAA,SAAA,GACA,MAAA,KACA,QAAA,SAAA,GACA,KAAA,KAAA,IACA,WAEA,SAAA,KAAA,SACA,KAAA,aAAA,KAAA,4BAOA,QAAA,SAAA,GACA,GAAA,YAAA,MACA,MAAA,EAEA,OAAA,IACA,EAAA,IAEA,gBAAA,KACA,EAAA,OAAA,GAEA,IAAA,GAAA,UAAA,EACA,IAAA,EACA,MAAA,EACA,KAAA,YAAA,GACA,MAAA,YACA,IAAA,GAAA,GAAA,MAAA,EAAA,qBAEA,OADA,WAAA,GAAA,EACA,EA8EA,QAAA,YAAA,GAEA,IADA,GAAA,GAAA,EACA,uBAAA,GAAA,EAAA,UACA,GAKA,OAHA,QAAA,0BACA,OAAA,qBAAA,GAEA,EAAA,EAGA,QAAA,eAAA,GACA,IAAA,GAAA,KAAA,GACA,OAAA,CACA,QAAA,EAGA,QAAA,aAAA,GACA,MAAA,eAAA,EAAA,QACA,cAAA,EAAA,UACA,cAAA,EAAA,SAGA,QAAA,yBAAA,EAAA,GACA,GAAA,MACA,KACA,IAEA,KAAA,GAAA,KAAA,GAAA,CACA,GAAA,GAAA,EAAA,IAEA,SAAA,GAAA,IAAA,EAAA,MAGA,IAAA,GAKA,IAAA,EAAA,KACA,EAAA,GAAA,GALA,EAAA,GAAA,QAQA,IAAA,GAAA,KAAA,GACA,IAAA,KAGA,EAAA,GAAA,EAAA,GAMA,OAHA,OAAA,QAAA,IAAA,EAAA,SAAA,EAAA,SACA,EAAA,OAAA,EAAA,SAGA,MAAA,EACA,QAAA,EACA,QAAA,GAKA,QAAA,eACA,IAAA,SAAA,OACA,OAAA,CAEA,KAAA,GAAA,GAAA,EAAA,EAAA,SAAA,OAAA,IACA,SAAA,IAGA,OADA,UAAA,OAAA,GACA,EA4BA,QAAA,qBAMA,QAAA,GAAA,GACA,GAAA,EAAA,SAAA,SAAA,GACA,EAAA,OAAA,GAPA,GAAA,GACA,EACA,GAAA,EACA,GAAA,CAOA,QACA,KAAA,SAAA,GACA,GAAA,EACA,KAAA,OAAA,wBAEA,IACA,OAAA,qBAAA,GAEA,EAAA,EACA,GAAA,GAEA,QAAA,SAAA,EAAA,GACA,EAAA,EACA,EACA,MAAA,QAAA,EAAA,GAEA,OAAA,QAAA,EAAA,IAEA,QAAA,SAAA,GACA,EAAA,EACA,OAAA,qBAAA,GACA,GAAA,GAEA,MAAA,WACA,EAAA,OACA,OAAA,UAAA,EAAA,GACA,oBAAA,KAAA,QAKA,QAAA,mBAAA,EAAA,EAAA,GACA,GAAA,GAAA,oBAAA,OAAA,mBAGA,OAFA,GAAA,KAAA,GACA,EAAA,QAAA,EAAA,GACA,EAMA,QAAA,kBAQA,QAAA,GAAA,GACA,GAAA,EAAA,CAGA,GAAA,GAAA,EAAA,QAAA,EACA,IAAA,GACA,EAAA,GAAA,OACA,EAAA,KAAA,IACA,EAAA,QAAA,GAAA,IACA,EAAA,KAAA,GACA,OAAA,QAAA,EAAA,IAGA,EAAA,OAAA,eAAA,KAGA,QAAA,KACA,GAAA,GAAA,IAAA,cAAA,CACA,GAAA,EACA,EAAA,CAEA,IAAA,EACA,KAAA,GAAA,KAAA,GACA,EAAA,EAAA,GACA,GAAA,EAAA,QAAA,QAGA,EAAA,gBAAA,EAGA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,EACA,IACA,OAAA,UAAA,EAAA,GAGA,EAAA,OAAA,EAGA,QAAA,KACA,GAAA,EACA,GAGA,IAGA,QAAA,KACA,IAGA,GAAA,EACA,GAAA,EACA,OAAA,IAGA,QAAA,KACA,GAEA,IAAA,EAEA,KAAA,GAAA,KAAA,GACA,EAAA,EAAA,GACA,GAAA,EAAA,QAAA,QAGA,EAAA,SAzEA,GAAA,MACA,EAAA,EACA,KACA,EAAA,WACA,GAAA,EACA,GAAA,EAwEA,GACA,OAAA,OACA,QAAA,EACA,KAAA,SAAA,GACA,EAAA,EAAA,KAAA,EACA,IACA,EAAA,gBAAA,IAEA,MAAA,SAAA,GAMA,GAHA,EAAA,EAAA,KAAA,OACA,IAEA,EAEA,WADA,IAGA,IAAA,CAEA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IACA,OAAA,UAAA,EAAA,GAAA,GACA,SAAA,iBAGA,GAAA,OAAA,EACA,EAAA,OAAA,EACA,iBAAA,KAAA,OAEA,MAAA,EAGA,OAAA,GAKA,QAAA,gBAAA,EAAA,GAMA,MALA,kBAAA,gBAAA,SAAA,IACA,gBAAA,iBAAA,OAAA,iBACA,gBAAA,OAAA,GAEA,gBAAA,KAAA,GACA,gBAUA,QAAA,YACA,KAAA,OAAA,SACA,KAAA,UAAA,OACA,KAAA,QAAA,OACA,KAAA,gBAAA,OACA,KAAA,OAAA,OACA,KAAA,IAAA,iBA2DA,QAAA,UAAA,GACA,SAAA,qBACA,kBAGA,aAAA,KAAA,GAGA,QAAA,iBACA,SAAA,qBAiEA,QAAA,gBAAA,GACA,SAAA,KAAA,MACA,KAAA,OAAA,EACA,KAAA,WAAA,OA0FA,QAAA,eAAA,GACA,IAAA,MAAA,QAAA,GACA,KAAA,OAAA,kCACA,gBAAA,KAAA,KAAA,GAgDA,QAAA,cAAA,EAAA,GACA,SAAA,KAAA,MAEA,KAAA,QAAA,EACA,KAAA,MAAA,YAAA,MAAA,EAAA,QAAA,GACA,KAAA,gBAAA,OA0CA,QAAA,oBACA,SAAA,KAAA,MAEA,KAAA,UACA,KAAA,gBAAA,OACA,KAAA,aAkIA,QAAA,SAAA,GAAA,MAAA,GAEA,QAAA,mBAAA,EAAA,EAAA,EACA,GACA,KAAA,UAAA,OACA,KAAA,QAAA,OACA,KAAA,OAAA,OACA,KAAA,YAAA,EACA,KAAA,YAAA,GAAA,QACA,KAAA,YAAA,GAAA,QAGA,KAAA,oBAAA,EAsDA,QAAA,gBAAA,EAAA,GACA,GAAA,kBAAA,QAAA,QAAA,CAGA,GAAA,GAAA,OAAA,YAAA,EACA,OAAA,UAAA,EAAA,GACA,GAAA,IACA,OAAA,EACA,KAAA,EACA,KAAA,EAEA,KAAA,UAAA,SACA,EAAA,SAAA,GACA,EAAA,OAAA,KAoCA,QAAA,6BAAA,EAAA,EAAA,GAIA,IAAA,GAHA,MACA,KAEA,EAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,EACA,qBAAA,EAAA,OAMA,EAAA,OAAA,KACA,EAAA,EAAA,MAAA,EAAA,UAEA,UAAA,EAAA,OAGA,OAAA,EAAA,KAUA,EAAA,OAAA,UACA,GAAA,EAAA,YACA,GAAA,EAAA,OAEA,EAAA,EAAA,OAAA,EAbA,EAAA,OAAA,SACA,GAAA,EAAA,MAEA,EAAA,EAAA,OAAA,KAfA,QAAA,MAAA,8BAAA,EAAA,MACA,QAAA,MAAA,IA4BA,IAAA,GAAA,KAAA,GACA,EAAA,GAAA,EAAA,EAEA,KAAA,GAAA,KAAA,GACA,EAAA,GAAA,MAEA,IAAA,KACA,KAAA,GAAA,KAAA,GACA,KAAA,IAAA,IAAA,IAAA,IAAA,CAGA,GAAA,GAAA,EAAA,EACA,GAAA,KAAA,IACA,EAAA,GAAA,GAGA,OACA,MAAA,EACA,QAAA,EACA,QAAA,GAIA,QAAA,WAAA,EAAA,EAAA,GACA,OACA,MAAA,EACA,QAAA,EACA,WAAA,GASA,QAAA,gBA0OA,QAAA,aAAA,EAAA,EAAA,EACA,EAAA,EAAA,GACA,MAAA,aAAA,YAAA,EAAA,EAAA,EACA,EAAA,EAAA,GAGA,QAAA,WAAA,EAAA,EAAA,EAAA,GAEA,MAAA,GAAA,GAAA,EAAA,EACA,GAGA,GAAA,GAAA,GAAA,EACA,EAGA,EAAA,EACA,EAAA,EACA,EAAA,EAEA,EAAA,EAGA,EAAA,EACA,EAAA,EAEA,EAAA,EAIA,QAAA,aAAA,EAAA,EAAA,EAAA,GAOA,IAAA,GALA,GAAA,UAAA,EAAA,EAAA,GAEA,GAAA,EACA,EAAA,EAEA,EAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,EAGA,IAFA,EAAA,OAAA,GAEA,EAAA,CAGA,GAAA,GAAA,UAAA,EAAA,MACA,EAAA,MAAA,EAAA,QAAA,OACA,EAAA,MACA,EAAA,MAAA,EAAA,WAEA,IAAA,GAAA,EAAA,CAGA,EAAA,OAAA,EAAA,GACA,IAEA,GAAA,EAAA,WAAA,EAAA,QAAA,OAEA,EAAA,YAAA,EAAA,WAAA,CACA,IAAA,GAAA,EAAA,QAAA,OACA,EAAA,QAAA,OAAA,CAEA,IAAA,EAAA,YAAA,EAGA,CACA,GAAA,GAAA,EAAA,OAEA,IAAA,EAAA,MAAA,EAAA,MAAA,CAEA,GAAA,GAAA,EAAA,QAAA,MAAA,EAAA,EAAA,MAAA,EAAA,MACA,OAAA,UAAA,KAAA,MAAA,EAAA,GACA,EAAA,EAGA,GAAA,EAAA,MAAA,EAAA,QAAA,OAAA,EAAA,MAAA,EAAA,WAAA,CAEA,GAAA,GAAA,EAAA,QAAA,MAAA,EAAA,MAAA,EAAA,WAAA,EAAA,MACA,OAAA,UAAA,KAAA,MAAA,EAAA,GAGA,EAAA,QAAA,EACA,EAAA,MAAA,EAAA,QACA,EAAA,MAAA,EAAA,WAnBA,IAAA,MAsBA,IAAA,EAAA,MAAA,EAAA,MAAA,CAGA,GAAA,EAEA,EAAA,OAAA,EAAA,EAAA,GACA,GAEA,IAAA,GAAA,EAAA,WAAA,EAAA,QAAA,MACA,GAAA,OAAA,EACA,GAAA,IAIA,GACA,EAAA,KAAA,GAGA,QAAA,sBAAA,EAAA,GAGA,IAAA,GAFA,MAEA,EAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,EACA,QAAA,EAAA,MACA,IAAA,SACA,YAAA,EAAA,EAAA,MAAA,EAAA,QAAA,QAAA,EAAA,WACA,MACA,KAAA,MACA,IAAA,SACA,IAAA,SACA,IAAA,QAAA,EAAA,MACA,QACA,IAAA,GAAA,SAAA,EAAA,KACA,IAAA,EAAA,EACA,QACA,aAAA,EAAA,GAAA,EAAA,UAAA,EACA,MACA,SACA,QAAA,MAAA,2BAAA,KAAA,UAAA,KAKA,MAAA,GAGA,QAAA,qBAAA,EAAA,GACA,GAAA,KAcA,OAZA,sBAAA,EAAA,GAAA,QAAA,SAAA,GACA,MAAA,IAAA,EAAA,YAAA,GAAA,EAAA,QAAA,YACA,EAAA,QAAA,KAAA,EAAA,EAAA,QACA,EAAA,KAAA,SAKA,EAAA,EAAA,OAAA,YAAA,EAAA,EAAA,MAAA,EAAA,MAAA,EAAA,WACA,EAAA,QAAA,EAAA,EAAA,QAAA,YAGA,EA9+CA,GAAA,YAAA,sBAoBA,QAAA,aAcA,YAAA,OAAA,OAAA,OAAA,SAAA,GACA,MAAA,gBAAA,IAAA,OAAA,MAAA,IAYA,aAAA,gBACA,SAAA,GAAA,MAAA,IACA,SAAA,GACA,GAAA,GAAA,EAAA,SACA,KAAA,EACA,MAAA,EACA,IAAA,GAAA,OAAA,OAAA,EAKA,OAJA,QAAA,oBAAA,GAAA,QAAA,SAAA,GACA,OAAA,eAAA,EAAA,EACA,OAAA,yBAAA,EAAA,MAEA,GAGA,WAAA,aACA,UAAA,gBACA,MAAA,WAAA,IAAA,UAAA,IACA,aAAA,yBACA,oBAAA,MAAA,MAAA,IAAA,aAAA,IACA,KAAA,MAAA,oBAAA,kBAAA,oBAAA,KACA,WAAA,GAAA,QAAA,IAAA,KAAA,KAgBA,wBA0BA,YAsBA,MAAA,IAAA,QAEA,KAAA,UAAA,cACA,aACA,OAAA,EAEA,SAAA,WACA,MAAA,MAAA,KAAA,MAGA,aAAA,SAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,KAAA,OAAA,IAAA,CACA,GAAA,MAAA,EACA,MACA,GAAA,EAAA,KAAA,IAEA,MAAA,IAGA,eAAA,SAAA,EAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,KAAA,OAAA,IAAA,CAGA,GAFA,IACA,EAAA,EAAA,KAAA,EAAA,MACA,SAAA,GACA,MACA,GAAA,KAIA,uBAAA,WACA,GAAA,GAAA,KAAA,IAAA,SAAA,GACA,MAAA,SAAA,GAAA,KAAA,EAAA,KAAA,IAAA,IAGA,EAAA,GACA,EAAA,KACA,IAAA,iBAEA,KADA,GAAA,GAAA,EACA,EAAA,KAAA,OAAA,EAAA,IAAA,CACA,CAAA,KAAA,GACA,GAAA,EAAA,GACA,GAAA,aAAA,EAAA,WAOA,MALA,IAAA,MAEA,GAAA,EAAA,GAEA,GAAA,YAAA,EAAA,+BACA,GAAA,UAAA,MAAA,IAGA,aAAA,SAAA,EAAA,GACA,IAAA,KAAA,OACA,OAAA,CAEA,KAAA,GAAA,GAAA,EAAA,EAAA,KAAA,OAAA,EAAA,IAAA,CACA,IAAA,SAAA,GACA,OAAA,CACA,GAAA,EAAA,KAAA,IAGA,MAAA,UAAA,IAGA,EAAA,KAAA,IAAA,GACA,IAHA,IAOA,IAAA,aAAA,GAAA,MAAA,GAAA,qBACA,aAAA,OAAA,EACA,YAAA,aAAA,YAAA,aAAA,YAEA,IAAA,wBAAA,IA8DA,YAYA,OAAA,WAAA,WACA,GAAA,IAAA,UAAA,GACA,GAAA,CAOA,OALA,QAAA,QAAA,EAAA,WACA,cACA,GAAA,IAGA,SAAA,GACA,SAAA,KAAA,GACA,IACA,GAAA,EACA,EAAA,UAAA,EAAA,cAIA,WACA,MAAA,UAAA,GACA,SAAA,KAAA,OAIA,uBAmDA,cACA,oBAmHA,gBAWA,SAAA,EACA,OAAA,EACA,OAAA,EACA,UAAA,EAEA,eAAA,CAWA,UAAA,WACA,KAAA,SAAA,EAAA,GACA,GAAA,KAAA,QAAA,SACA,KAAA,OAAA,oCAOA,OALA,UAAA,MACA,KAAA,UAAA,EACA,KAAA,QAAA,EACA,KAAA,OAAA,OACA,KAAA,WACA,KAAA,QAGA,MAAA,WACA,KAAA,QAAA,SAGA,cAAA,MACA,KAAA,OAAA,OACA,KAAA,cACA,KAAA,OAAA,OACA,KAAA,UAAA,OACA,KAAA,QAAA,SAGA,QAAA,WACA,KAAA,QAAA,QAGA,WAAA,OAGA,QAAA,SAAA,GACA,IACA,KAAA,UAAA,MAAA,KAAA,QAAA,GACA,MAAA,GACA,SAAA,4BAAA,EACA,QAAA,MAAA,+CACA,EAAA,OAAA,MAIA,eAAA,WAEA,MADA,MAAA,OAAA,QAAA,GACA,KAAA,QAIA,IAAA,mBAAA,WACA,YACA,UAAA,mBAAA,EAEA,mBACA,gBAeA,IAAA,6BAAA,EAEA,0BAAA,YAAA,WACA,IAEA,MADA,MAAA,qBACA,EACA,MAAA,IACA,OAAA,KAIA,QAAA,SAAA,OAAA,aAEA,OAAA,SAAA,2BAAA,WACA,IAAA,2BAAA,CAGA,GAAA,0BAEA,WADA,MAAA,mBAIA,IAAA,iBAAA,CAGA,4BAAA,CAEA,IAAA,QAAA,EACA,WAAA,OAEA,GAAA,CACA,SACA,QAAA,aACA,gBACA,YAAA,CAEA,KAAA,GAAA,GAAA,EAAA,EAAA,QAAA,OAAA,IAAA,CACA,GAAA,UAAA,QAAA,EACA,UAAA,QAAA,SAGA,SAAA,WACA,YAAA,GAEA,aAAA,KAAA,WAEA,gBACA,YAAA,SACA,uBAAA,QAAA,WAEA,QAAA,0BACA,OAAA,qBAAA,QAEA,4BAAA,KAGA,mBACA,OAAA,SAAA,eAAA,WACA,kBAUA,eAAA,UAAA,cACA,UAAA,SAAA,UAEA,cAAA,EAEA,SAAA,WACA,WACA,KAAA,gBAAA,kBAAA,KAAA,KAAA,OACA,KAAA,cAEA,KAAA,WAAA,KAAA,WAAA,KAAA,SAKA,WAAA,SAAA,GACA,GAAA,GAAA,MAAA,QAAA,QACA,KAAA,GAAA,KAAA,GACA,EAAA,GAAA,EAAA,EAIA,OAFA,OAAA,QAAA,KACA,EAAA,OAAA,EAAA,QACA,GAGA,OAAA,SAAA,GACA,GAAA,GACA,CACA,IAAA,WAAA,CACA,IAAA,EACA,OAAA,CAEA,MACA,EAAA,4BAAA,KAAA,OAAA,EACA,OAEA,GAAA,KAAA,WACA,EAAA,wBAAA,KAAA,OAAA,KAAA,WAGA,OAAA,aAAA,IACA,GAEA,aACA,KAAA,WAAA,KAAA,WAAA,KAAA,SAEA,KAAA,SACA,EAAA,UACA,EAAA,YACA,EAAA,YACA,SAAA,GACA,MAAA,GAAA,OAIA,IAGA,YAAA,WACA,YACA,KAAA,gBAAA,QACA,KAAA,gBAAA,QAEA,KAAA,WAAA,QAIA,QAAA,WACA,KAAA,QAAA,SAGA,WACA,KAAA,gBAAA,SAAA,GAEA,WAAA,QAGA,eAAA,WAMA,MALA,MAAA,gBACA,KAAA,gBAAA,SAAA,GAEA,KAAA,WAAA,KAAA,WAAA,KAAA,QAEA,KAAA,UAUA,cAAA,UAAA,cAEA,UAAA,eAAA,UAEA,cAAA,EAEA,WAAA,SAAA,GACA,MAAA,GAAA,SAGA,OAAA,SAAA,GACA,GAAA,EACA,IAAA,WAAA,CACA,IAAA,EACA,OAAA,CACA,GAAA,oBAAA,KAAA,OAAA,OAEA,GAAA,YAAA,KAAA,OAAA,EAAA,KAAA,OAAA,OACA,KAAA,WAAA,EAAA,KAAA,WAAA,OAGA,OAAA,IAAA,EAAA,QAGA,aACA,KAAA,WAAA,KAAA,WAAA,KAAA,SAEA,KAAA,SAAA,KACA,IANA,KAUA,cAAA,aAAA,SAAA,EAAA,EAAA,GACA,EAAA,QAAA,SAAA,GAGA,IAFA,GAAA,IAAA,EAAA,MAAA,EAAA,QAAA,QACA,EAAA,EAAA,MACA,EAAA,EAAA,MAAA,EAAA,YACA,EAAA,KAAA,EAAA,IACA,GAGA,OAAA,UAAA,OAAA,MAAA,EAAA,MAYA,aAAA,UAAA,cACA,UAAA,SAAA,UAEA,SAAA,WACA,aACA,KAAA,gBAAA,eAAA,KAAA,KAAA,UAEA,KAAA,OAAA,QAAA,IAGA,YAAA,WACA,KAAA,OAAA,OAEA,KAAA,kBACA,KAAA,gBAAA,MAAA,MACA,KAAA,gBAAA,SAIA,gBAAA,SAAA,GACA,KAAA,MAAA,eAAA,KAAA,QAAA,IAGA,OAAA,SAAA,EAAA,GACA,GAAA,GAAA,KAAA,MAEA,OADA,MAAA,OAAA,KAAA,MAAA,aAAA,KAAA,SACA,GAAA,aAAA,KAAA,OAAA,IACA,GAEA,KAAA,SAAA,KAAA,OAAA,KACA,IAGA,SAAA,SAAA,GACA,KAAA,OACA,KAAA,MAAA,aAAA,KAAA,QAAA,KAYA,IAAA,oBAEA,kBAAA,UAAA,cACA,UAAA,SAAA,UAEA,SAAA,WAGA,GAFA,KAAA,OAAA,QAAA,GAEA,WAAA,CAKA,IAAA,GAFA,GACA,GAAA,EACA,EAAA,EAAA,EAAA,KAAA,UAAA,OAAA,GAAA,EAEA,GADA,EAAA,KAAA,UAAA,GACA,IAAA,iBAAA,CACA,GAAA,CACA,OAIA,MAAA,MAAA,gBACA,MACA,MAAA,gBAAA,SAGA,KAAA,gBAAA,aACA,KAAA,gBAAA,cAIA,IACA,KAAA,gBAAA,eAAA,KAAA,OAGA,gBAAA,WACA,IAAA,GAAA,GAAA,EAAA,EAAA,KAAA,UAAA,OAAA,GAAA,EACA,KAAA,UAAA,KAAA,kBACA,KAAA,UAAA,EAAA,GAAA,OAEA,MAAA,UAAA,OAAA,GAGA,YAAA,WACA,KAAA,OAAA,OAEA,KAAA,kBACA,KAAA,gBAAA,MAAA,MACA,KAAA,gBAAA,QAGA,KAAA,mBAGA,QAAA,SAAA,EAAA,GACA,GAAA,KAAA,QAAA,UAAA,KAAA,QAAA,UACA,KAAA,OAAA,iCAEA,MAAA,UAAA,KAAA,EAAA,YAAA,MAAA,EAAA,QAAA,KAGA,YAAA,SAAA,GACA,GAAA,KAAA,QAAA,UAAA,KAAA,QAAA,UACA,KAAA,OAAA,qCAEA,GAAA,KAAA,KAAA,QAAA,MACA,KAAA,UAAA,KAAA,iBAAA,IAGA,WAAA,WACA,GAAA,KAAA,QAAA,OACA,KAAA,OAAA,4BAEA,MAAA,OAAA,UACA,KAAA,mBAGA,YAAA,WACA,GAAA,KAAA,QAAA,UACA,KAAA,OAAA,wCAIA,OAHA,MAAA,OAAA,OACA,KAAA,WAEA,KAAA,QAGA,gBAAA,SAAA,GAEA,IAAA,GADA,GACA,EAAA,EAAA,EAAA,KAAA,UAAA,OAAA,GAAA,EACA,EAAA,KAAA,UAAA,GACA,IAAA,kBACA,KAAA,UAAA,EAAA,GAAA,eAAA,EAAA,IAIA,OAAA,SAAA,EAAA,GAEA,IAAA,GADA,GACA,EAAA,EAAA,EAAA,KAAA,UAAA,OAAA,GAAA,EAAA,CACA,GAAA,GAAA,KAAA,UAAA,EAAA,GACA,EAAA,KAAA,UAAA,GACA,EAAA,IAAA,iBACA,EAAA,iBACA,EAAA,aAAA,EAEA,GACA,KAAA,OAAA,EAAA,GAAA,EAIA,aAAA,EAAA,KAAA,OAAA,EAAA,MAGA,EAAA,MACA,EAAA,EAAA,GAAA,KAAA,OAAA,EAAA,GACA,KAAA,OAAA,EAAA,GAAA,GAGA,MAAA,IAKA,KAAA,SAAA,KAAA,OAAA,EAAA,KAAA,aACA,IALA,KAwBA,kBAAA,WACA,KAAA,SAAA,EAAA,GAKA,MAJA,MAAA,UAAA,EACA,KAAA,QAAA,EACA,KAAA,OACA,KAAA,YAAA,KAAA,YAAA,KAAA,KAAA,kBAAA,OACA,KAAA,QAGA,kBAAA,SAAA,GAEA,GADA,EAAA,KAAA,YAAA,IACA,aAAA,EAAA,KAAA,QAAA,CAEA,GAAA,GAAA,KAAA,MACA,MAAA,OAAA,EACA,KAAA,UAAA,KAAA,KAAA,QAAA,KAAA,OAAA,KAGA,eAAA,WAEA,MADA,MAAA,OAAA,KAAA,YAAA,KAAA,YAAA,kBACA,KAAA,QAGA,QAAA,WACA,MAAA,MAAA,YAAA,WAGA,SAAA,SAAA,GAEA,MADA,GAAA,KAAA,YAAA,IACA,KAAA,qBAAA,KAAA,YAAA,SACA,KAAA,YAAA,SAAA,GADA,QAIA,MAAA,WACA,KAAA,aACA,KAAA,YAAA,QACA,KAAA,UAAA,OACA,KAAA,QAAA,OACA,KAAA,YAAA,OACA,KAAA,OAAA,OACA,KAAA,YAAA,OACA,KAAA,YAAA,QAIA,IAAA,sBACA,KAAA,EACA,QAAA,EACA,UAAA,EAoBA,UAAA,uBAAA,SAAA,EAAA,EAAA,GACA,GAAA,GAAA,eAAA,EAAA,GACA,EAAA,EAAA,KAAA,SAAA,EAAA,GACA,EAAA,EACA,GACA,EAAA,SAAA,IAeA,OAZA,QAAA,eAAA,EAAA,GACA,IAAA,WAEA,MADA,GAAA,UACA,GAEA,IAAA,SAAA,GAEA,MADA,GAAA,SAAA,GACA,GAEA,cAAA,KAIA,MAAA,WACA,EAAA,QACA,OAAA,eAAA,EAAA,GACA,MAAA,EACA,UAAA,EACA,cAAA,MAyEA,IAAA,YAAA,EACA,YAAA,EACA,SAAA,EACA,YAAA,CAIA,aAAA,WAaA,kBAAA,SAAA,EAAA,EAAA,EACA,EAAA,EAAA,GAOA,IAAA,GALA,GAAA,EAAA,EAAA,EACA,EAAA,EAAA,EAAA,EACA,EAAA,GAAA,OAAA,GAGA,EAAA,EAAA,EAAA,EAAA,IACA,EAAA,GAAA,GAAA,OAAA,GACA,EAAA,GAAA,GAAA,CAIA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,IACA,EAAA,GAAA,GAAA,CAEA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,IACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,IACA,GAAA,KAAA,OAAA,EAAA,EAAA,EAAA,GAAA,EAAA,EAAA,EAAA,IACA,EAAA,GAAA,GAAA,EAAA,EAAA,GAAA,EAAA,OACA,CACA,GAAA,GAAA,EAAA,EAAA,GAAA,GAAA,EACA,EAAA,EAAA,GAAA,EAAA,GAAA,CACA,GAAA,GAAA,GAAA,EAAA,EAAA,EAAA,EAKA,MAAA,IAMA,kCAAA,SAAA,GAKA,IAJA,GAAA,GAAA,EAAA,OAAA,EACA,EAAA,EAAA,GAAA,OAAA,EACA,EAAA,EAAA,GAAA,GACA,KACA,EAAA,GAAA,EAAA,GACA,GAAA,GAAA,EAKA,GAAA,GAAA,EAAA,CAKA,GAIA,GAJA,EAAA,EAAA,EAAA,GAAA,EAAA,GACA,EAAA,EAAA,EAAA,GAAA,GACA,EAAA,EAAA,GAAA,EAAA,EAIA,GADA,EAAA,EACA,EAAA,EAAA,EAAA,EAEA,EAAA,EAAA,EAAA,EAEA,GAAA,GACA,GAAA,EACA,EAAA,KAAA,aAEA,EAAA,KAAA,aACA,EAAA,GAEA,IACA,KACA,GAAA,GACA,EAAA,KAAA,aACA,IACA,EAAA,IAEA,EAAA,KAAA,UACA,IACA,EAAA,OA9BA,GAAA,KAAA,aACA,QANA,GAAA,KAAA,UACA,GAuCA,OADA,GAAA,UACA,GA2BA,YAAA,SAAA,EAAA,EAAA,EACA,EAAA,EAAA,GACA,GAAA,GAAA,EACA,EAAA,EAEA,EAAA,KAAA,IAAA,EAAA,EAAA,EAAA,EAYA,IAXA,GAAA,GAAA,GAAA,IACA,EAAA,KAAA,aAAA,EAAA,EAAA,IAEA,GAAA,EAAA,QAAA,GAAA,EAAA,SACA,EAAA,KAAA,aAAA,EAAA,EAAA,EAAA,IAEA,GAAA,EACA,GAAA,EACA,GAAA,EACA,GAAA,EAEA,EAAA,GAAA,GAAA,EAAA,GAAA,EACA,QAEA,IAAA,GAAA,EAAA,CAEA,IADA,GAAA,GAAA,UAAA,KAAA,GACA,EAAA,GACA,EAAA,QAAA,KAAA,EAAA,KAEA,QAAA,GACA,GAAA,GAAA,EACA,OAAA,UAAA,KAAA,EAAA,GAUA,KAAA,GARA,GAAA,KAAA,kCACA,KAAA,kBAAA,EAAA,EAAA,EACA,EAAA,EAAA,IAEA,EAAA,OACA,KACA,EAAA,EACA,EAAA,EACA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,OAAA,EAAA,IACA,IAAA,YACA,IACA,EAAA,KAAA,GACA,EAAA,QAGA,IACA,GACA,MACA,KAAA,aACA,IACA,EAAA,UAAA,KAAA,IAEA,EAAA,aACA,IAEA,EAAA,QAAA,KAAA,EAAA,IACA,GACA,MACA,KAAA,UACA,IACA,EAAA,UAAA,KAAA,IAEA,EAAA,aACA,GACA,MACA,KAAA,aACA,IACA,EAAA,UAAA,KAAA,IAEA,EAAA,QAAA,KAAA,EAAA,IACA,IAQA,MAHA,IACA,EAAA,KAAA,GAEA,GAGA,aAAA,SAAA,EAAA,EAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,IACA,IAAA,KAAA,OAAA,EAAA,GAAA,EAAA,IACA,MAAA,EACA,OAAA,IAGA,aAAA,SAAA,EAAA,EAAA,GAIA,IAHA,GAAA,GAAA,EAAA,OACA,EAAA,EAAA,OACA,EAAA,EACA,EAAA,GAAA,KAAA,OAAA,IAAA,GAAA,IAAA,KACA,GAEA,OAAA,IAGA,iBAAA,SAAA,EAAA,GACA,MAAA,MAAA,YAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EACA,EAAA,SAGA,OAAA,SAAA,EAAA,GACA,MAAA,KAAA,GAIA,IAAA,aAAA,GAAA,YAuJA,QAAA,SAAA,SACA,OAAA,SAAA,QAAA,OACA,OAAA,SAAA,iBAAA,WACA,OAAA,cAAA,cACA,OAAA,cAAA,iBAAA,SAAA,EAAA,GACA,MAAA,aAAA,iBAAA,EAAA,IAGA,OAAA,YAAA,YACA,OAAA,eAAA,eACA,OAAA,aAAA,aACA,OAAA,iBAAA,iBACA,OAAA,KAAA,KACA,OAAA,kBAAA,mBACA,mBAAA,SAAA,QAAA,mBAAA,SAAA,OAAA,OAAA,MAAA,QCxjDA,OAAA,SAAA,OAAA,aAEA,OAAA,SAAA,OAAA,aAEA,SAAA,GAEA,GAAA,GAAA,EAAA,SAEA,UAAA,OAAA,MAAA,GAAA,MAAA,KAAA,QAAA,SAAA,GACA,EAAA,EAAA,MAAA,KACA,EAAA,KAAA,EAAA,EAAA,IAAA,EAAA,KAAA,IAEA,IAAA,GAAA,SAAA,eACA,SAAA,cAAA,6BACA,IAAA,EAEA,IAAA,GAAA,GADA,EAAA,EAAA,WACA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,EAAA,GACA,QAAA,EAAA,OACA,EAAA,EAAA,MAAA,EAAA,QAAA,EAIA,GAAA,KACA,EAAA,IAAA,MAAA,KAAA,QAAA,SAAA,GACA,OAAA,SAAA,IAAA,IAMA,EAAA,OAAA,EAAA,QAAA,EAAA,WAAA,EAAA,SAEA,EAAA,OADA,WAAA,EAAA,QACA,EAEA,EAAA,SAAA,YAAA,UAAA,iBAGA,EAAA,QAAA,SAAA,iBAAA,UAAA,OAAA,GACA,QAAA,KAAA,mIAMA,EAAA,WACA,OAAA,eAAA,OAAA,iBAAA,UACA,OAAA,eAAA,MAAA,SAAA,EAAA,UAGA,EAAA,UACA,OAAA,YAAA,OAAA,cAAA,UACA,OAAA,YAAA,MAAA,QAAA,EAAA,SAIA,EAAA,MAAA,GACA,UAGA,SAAA,MAAA,QCzDA,OAAA,qBAEA,SAAA,GACA,YAoBA,SAAA,GAAA,GACA,IAAA,EACA,KAAA,IAAA,OAAA,oBAOA,QAAA,GAAA,EAAA,GAIA,MAHA,GAAA,GAAA,QAAA,SAAA,GACA,EAAA,EAAA,EAAA,EAAA,EAAA,MAEA,EAGA,QAAA,GAAA,EAAA,GAaA,MAZA,GAAA,GAAA,QAAA,SAAA,GACA,OAAA,GACA,IAAA,YACA,IAAA,SACA,IAAA,SACA,IAAA,OACA,IAAA,YACA,IAAA,WACA,OAEA,EAAA,EAAA,EAAA,EAAA,EAAA,MAEA,EAGA,QAAA,GAAA,EAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IACA,GAAA,EAAA,IAAA,GACA,MAAA,GAAA,GASA,QAAA,GAAA,GACA,GAAA,GAAA,EAAA,WAAA,OAAA,eAAA,GACA,EAAA,EAAA,IAAA,EACA,IAAA,EACA,MAAA,EAEA,IAAA,GAAA,EAAA,GAEA,EAAA,EAAA,EAGA,OAFA,GAAA,EAAA,EAAA,GAEA,EAGA,QAAA,GAAA,EAAA,GACA,EAAA,EAAA,GAAA,GAGA,QAAA,GAAA,EAAA,GACA,EAAA,EAAA,GAAA,GAcA,QAAA,GAAA,GACA,MAAA,aAAA,KAAA,GAGA,QAAA,GAAA,GACA,MAAA,oBAAA,KAAA,GAGA,QAAA,GAAA,GACA,MAAA,IAAA,EAAA,GACA,GAAA,UAAA,oBAAA,GACA,WAAA,MAAA,MAAA,KAAA,IAGA,QAAA,GAAA,GACA,MAAA,IAAA,EAAA,GACA,GAAA,UAAA,IAAA,aAAA,EAAA,QACA,SAAA,GAAA,KAAA,KAAA,GAAA,GAGA,QAAA,GAAA,GACA,MAAA,IAAA,EAAA,GACA,GAAA,UAAA,oBAAA,EACA,gCACA,WAAA,MAAA,MAAA,KAAA,GAAA,MAAA,KAAA,KAAA,YAGA,QAAA,GAAA,EAAA,GACA,IACA,MAAA,QAAA,yBAAA,EAAA,GACA,MAAA,GAIA,MAAA,IAIA,QAAA,GAAA,EAAA,EAAA,GAEA,IAAA,GADA,GAAA,EAAA,GACA,EAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,EACA,IAAA,sBAAA,KAGA,IAAA,IAGA,EAAA,mBAAA,EAAA,kBAAA,IAAA,CAGA,GAEA,EAAA,iBAAA,EAEA,IACA,GAAA,EADA,EAAA,EAAA,EAAA,EAEA,IAAA,GAAA,kBAAA,GAAA,MACA,EAAA,GAAA,EAAA,OADA,CAKA,GAAA,GAAA,EAAA,EAEA,GADA,EACA,EAAA,sBAAA,GAEA,EAAA,IAEA,EAAA,UAAA,EAAA,OAEA,EADA,EACA,EAAA,sBAAA,GAEA,EAAA,IAGA,EAAA,EAAA,GACA,IAAA,EACA,IAAA,EACA,aAAA,EAAA,aACA,WAAA,EAAA,gBAWA,QAAA,GAAA,EAAA,EAAA,GACA,GAAA,GAAA,EAAA,SACA,GAAA,EAAA,EAAA,GACA,EAAA,EAAA,GAGA,QAAA,GAAA,EAAA,EAAA,GACA,GAAA,GAAA,EAAA,SACA,GAAA,SAAA,EAAA,IAAA,IAEA,EAAA,IAAA,EAAA,GACA,EAAA,IAAA,EAAA,GAEA,EAAA,EAAA,GACA,GACA,EAAA,EAAA,GACA,EAAA,EAAA,eACA,MAAA,EACA,cAAA,EACA,YAAA,EACA,UAAA,IAGA,EAAA,UAAA,EAGA,QAAA,GAAA,EAAA,GACA,MAAA,GAAA,IAAA,EAAA,aACA,EASA,QAAA,GAAA,GACA,GAAA,GAAA,OAAA,eAAA,GAEA,EAAA,EAAA,GACA,EAAA,EAAA,EAGA,OAFA,GAAA,EAAA,EAAA,GAEA,EAGA,QAAA,GAAA,GACA,QAAA,GAAA,GACA,EAAA,KAAA,KAAA,GAEA,GAAA,GAAA,OAAA,OAAA,EAAA,UAIA,OAHA,GAAA,YAAA,EACA,EAAA,UAAA,EAEA,EAaA,QAAA,GAAA,GACA,MAAA,aAAA,GAAA,aACA,YAAA,GAAA,OACA,YAAA,GAAA,OACA,YAAA,GAAA,mBACA,YAAA,GAAA,0BACA,EAAA,uBACA,YAAA,GAAA,sBAGA,QAAA,GAAA,GACA,MAAA,IAAA,YAAA,IACA,YAAA,IACA,YAAA,IACA,YAAA,IACA,YAAA,IACA,YAAA,IACA,YAAA,IACA,GACA,YAAA,IACA,GACA,YAAA,GASA,QAAA,GAAA,GACA,MAAA,QAAA,EACA,MAEA,EAAA,EAAA,IACA,EAAA,kBACA,EAAA,gBAAA,IAAA,EAAA,IAAA,KAQA,QAAA,GAAA,GACA,MAAA,QAAA,EACA,MACA,EAAA,EAAA,IACA,EAAA,MAQA,QAAA,GAAA,GACA,MAAA,IAAA,EAAA,GAAA,EAAA,GAAA,EAQA,QAAA,GAAA,GACA,MAAA,KAAA,EAAA,GAAA,EAAA,GAAA,EASA,QAAA,GAAA,EAAA,GACA,OAAA,IAEA,EAAA,EAAA,IACA,EAAA,SAAA,GAAA,EAAA,IACA,EAAA,gBAAA,GAGA,QAAA,GAAA,EAAA,EAAA,GACA,EAAA,EAAA,UAAA,GACA,IAAA,EACA,cAAA,EACA,YAAA,IAIA,QAAA,GAAA,EAAA,GACA,EAAA,EAAA,EAAA,WACA,MAAA,GAAA,KAAA,KAAA,MAWA,QAAA,GAAA,EAAA,GACA,EAAA,QAAA,SAAA,GACA,EAAA,QAAA,SAAA,GACA,EAAA,UAAA,GAAA,WACA,GAAA,GAAA,EAAA,KACA,OAAA,GAAA,GAAA,MAAA,EAAA,gBA1WA,GAAA,GAAA,GAAA,SACA,EAAA,GAAA,SACA,EAAA,OAAA,OAAA,MAKA,IAAA,kBAAA,YACA,SAAA,eAAA,UACA,IAAA,EACA,IACA,GAAA,GAAA,GAAA,UAAA,GAAA,eACA,GAAA,IACA,MAAA,GACA,GAAA,EASA,GAAA,GAAA,OAAA,eACA,EAAA,OAAA,oBACA,EAAA,OAAA,wBAmCA,GAAA,OAwBA,IAAA,GAAA,UAAA,KAAA,UAAA,WAIA,GACA,IAAA,aACA,IAAA,aACA,cAAA,EACA,YAAA,GAuJA,EAAA,OAAA,kBACA,EAAA,OAAA,YACA,EAAA,OAAA,MACA,EAAA,OAAA,KACA,EAAA,OAAA,OACA,EAAA,OAAA,MACA,EAAA,OAAA,yBACA,EAAA,OAAA,sBACA,EAAA,OAAA,kBAqHA,GAAA,OAAA,EACA,EAAA,iBAAA,EACA,EAAA,aAAA,EACA,EAAA,iBAAA,EACA,EAAA,wBAAA,EACA,EAAA,UAAA,EACA,EAAA,aAAA,EACA,EAAA,MAAA,EACA,EAAA,qBAAA,EACA,EAAA,MAAA,EACA,EAAA,eAAA,EACA,EAAA,gBAAA,EACA,EAAA,OAAA,EACA,EAAA,OAAA,EACA,EAAA,eAAA,EACA,EAAA,KAAA,EACA,EAAA,aAAA,EACA,EAAA,SAAA,GAEA,OAAA,mBCtYA,SAAA,GACA,YAOA,SAAA,KACA,GAAA,CACA,IAAA,GAAA,EAAA,MAAA,EACA,KACA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,KAmBA,QAAA,GAAA,GACA,EAAA,KAAA,GACA,IAEA,GAAA,EACA,EAAA,EAAA,IAlCA,GAGA,GAHA,EAAA,OAAA,iBACA,KACA,GAAA,CAYA,IAAA,EAAA,CACA,GAAA,GAAA,EACA,EAAA,GAAA,GAAA,GACA,EAAA,SAAA,eAAA,EACA,GAAA,QAAA,GAAA,eAAA,IAEA,EAAA,WACA,GAAA,EAAA,GAAA,EACA,EAAA,KAAA,OAIA,GAAA,OAAA,cAAA,OAAA,UAWA,GAAA,kBAAA,GAEA,OAAA,mBC1CA,SAAA,GACA,YAUA,SAAA,KACA,IAEA,EAAA,GACA,GAAA,GAIA,QAAA,KACA,GAAA,CAEA,GAGA,KAAA,GAFA,GAAA,EAAA,QACA,GAAA,EACA,EAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,GACA,EAAA,EAAA,aACA,GAAA,GACA,EAAA,SACA,EAAA,UAAA,EAAA,GACA,GAAA,SAGA,GAQA,QAAA,GAAA,EAAA,GACA,KAAA,KAAA,EACA,KAAA,OAAA,EACA,KAAA,WAAA,GAAA,GAAA,SACA,KAAA,aAAA,GAAA,GAAA,SACA,KAAA,gBAAA,KACA,KAAA,YAAA,KACA,KAAA,cAAA,KACA,KAAA,mBAAA,KACA,KAAA,SAAA,KASA,QAAA,GAAA,EAAA,GACA,KAAA,EAAA,EAAA,EAAA,WAAA,CACA,GAAA,GAAA,EAAA,IAAA,EACA,IAAA,EAEA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,EACA,GAAA,QAAA,SACA,EAAA,qBAAA,KAKA,QAAA,GAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,OAAA,GACA,EAAA,EAAA,IAAA,EACA,KAAA,EACA,MACA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,EACA,GAAA,WAAA,GACA,EAAA,6BAMA,QAAA,GAAA,EAAA,EAAA,GAMA,IAAA,GAJA,GAAA,OAAA,OAAA,MACA,EAAA,OAAA,OAAA,MAGA,EAAA,EAAA,EAAA,EAAA,EAAA,WAAA,CAEA,GAAA,GAAA,EAAA,IAAA,EACA,IAAA,EAEA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,GACA,EAAA,EAAA,OAEA,KAAA,IAAA,GAAA,EAAA,YAIA,eAAA,IAAA,EAAA,YAMA,eAAA,GAAA,EAAA,kBACA,OAAA,EAAA,WACA,KAAA,EAAA,gBAAA,QAAA,EAAA,QAKA,kBAAA,IAAA,EAAA,eAIA,cAAA,IAAA,EAAA,WAAA,CAIA,GAAA,GAAA,EAAA,QACA,GAAA,EAAA,MAAA,GAMA,eAAA,GAAA,EAAA,mBACA,kBAAA,GAAA,EAAA,yBACA,EAAA,EAAA,MAAA,EAAA,YAKA,GAAA,IAAA,CAGA,KAAA,GAAA,KAAA,GAAA,CACA,GAAA,GAAA,EAAA,GACA,EAAA,GAAA,GAAA,EAAA,EAGA,SAAA,IAAA,aAAA,KACA,EAAA,cAAA,EAAA,KACA,EAAA,mBAAA,EAAA,WAIA,EAAA,aACA,EAAA,WAAA,EAAA,YAGA,EAAA,eACA,EAAA,aAAA,EAAA,cAGA,EAAA,kBACA,EAAA,gBAAA,EAAA,iBAGA,EAAA,cACA,EAAA,YAAA,EAAA,aAGA,SAAA,EAAA,KACA,EAAA,SAAA,EAAA,IAGA,EAAA,SAAA,KAAA,GAEA,GAAA,EAGA,GACA,IASA,QAAA,GAAA,GAqBA,GApBA,KAAA,YAAA,EAAA,UACA,KAAA,UAAA,EAAA,QAQA,KAAA,WAJA,cAAA,MACA,qBAAA,IAAA,mBAAA,MAGA,EAAA,YAFA,EAQA,KAAA,cADA,yBAAA,MAAA,iBAAA,KACA,IAEA,EAAA,eAGA,KAAA,aACA,EAAA,mBAAA,mBAAA,MAEA,KAAA,eAAA,EAAA,sBACA,KAAA,IAAA,UAMA,IAHA,KAAA,gBAAA,EAAA,cACA,KAAA,oBAAA,EAAA,kBACA,KAAA,wBAAA,EAAA,sBACA,mBAAA,GAAA,CACA,GAAA,MAAA,EAAA,iBACA,gBAAA,GAAA,gBACA,KAAA,IAAA,UAEA,MAAA,gBAAA,EAAA,KAAA,EAAA,qBAEA,MAAA,gBAAA,KAWA,QAAA,GAAA,GACA,KAAA,UAAA,EACA,KAAA,UACA,KAAA,YACA,KAAA,OAAA,EAGA,EAAA,KAAA,MAiEA,QAAA,GAAA,EAAA,EAAA,GACA,KAAA,SAAA,EACA,KAAA,OAAA,EACA,KAAA,QAAA,EACA,KAAA,0BAzTA,GAAA,GAAA,EAAA,kBACA,EAAA,EAAA,aACA,EAAA,EAAA,SAEA,EAAA,GAAA,SACA,KACA,GAAA,EAgLA,EAAA,MAAA,UAAA,MAgDA,EAAA,CAiBA,GAAA,WAEA,QAAA,SAAA,EAAA,GACA,EAAA,EAAA,EAEA,IAGA,GAHA,EAAA,GAAA,GAAA,GAIA,EAAA,EAAA,IAAA,EACA,IACA,EAAA,IAAA,EAAA,KAEA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,GAAA,WAAA,OACA,EAAA,EAAA,GAEA,EAAA,2BAEA,EAAA,QAAA,EAKA,KACA,EAAA,GAAA,GAAA,KAAA,EAAA,GACA,EAAA,KAAA,GACA,KAAA,OAAA,KAAA,KAKA,WAAA,WACA,KAAA,OAAA,QAAA,SAAA,GAEA,IAAA,GADA,GAAA,EAAA,IAAA,GACA,EAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,EACA,IAAA,EAAA,WAAA,KAAA,CACA,EAAA,OAAA,EAAA,EAGA,UAGA,MACA,KAAA,aAGA,YAAA,WACA,GAAA,GAAA,KAAA,QAEA,OADA,MAAA,YACA,IAkBA,EAAA,WAMA,qBAAA,SAAA,GAGA,GAAA,IAAA,KAAA,OAAA,CAGA,KAAA,uBAAA,KAAA,EACA,IAAA,GAAA,EAAA,IAAA,EACA,IACA,EAAA,IAAA,EAAA,MAIA,EAAA,KAAA,QAGA,yBAAA,WACA,GAAA,GAAA,KAAA,sBACA,MAAA,yBAEA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IAGA,IAAA,GAFA,GAAA,EAAA,GACA,EAAA,EAAA,IAAA,GACA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,GAAA,EAAA,KAAA,KAAA,CACA,EAAA,OAAA,EAAA,EAGA,UAOA,EAAA,gBAAA,EACA,EAAA,2BAAA,EACA,EAAA,SAAA,iBAAA,EACA,EAAA,SAAA,eAAA,GAEA,OAAA,mBC7WA,SAAA,GACA,YAQA,SAAA,GAAA,EAAA,GACA,KAAA,KAAA,EACA,KAAA,OAAA,EAoBA,QAAA,GAAA,EAAA,GACA,GAAA,EAAA,aAAA,EAAA,CACA,EAAA,WAAA,CACA,KAAA,GAAA,GAAA,EAAA,WAAA,EAAA,EAAA,EAAA,gBACA,EAAA,WAAA,OAAA,CAEA,KAAA,GAAA,GAAA,EAAA,WAAA,EAAA,EAAA,EAAA,YACA,EAAA,EAAA,IAKA,QAAA,GAAA,GACA,GAAA,EAAA,WACA,MAAA,GAAA,UACA,IACA,GADA,EAAA,EAAA,UAMA,OAHA,GADA,EACA,EAAA,GAEA,GAAA,GAAA,EAAA,MACA,EAAA,WAAA,EAtCA,EAAA,WACA,GAAA,YACA,MAAA,MAAA,eAAA,GAAA,SAAA,WACA,EAAA,mBAAA,KAAA,KAAA,MAEA,MAGA,SAAA,SAAA,GACA,KAAA,EAAA,EAAA,EAAA,OACA,GAAA,IAAA,KACA,OAAA,CAEA,QAAA,IA4BA,EAAA,UAAA,EACA,EAAA,aAAA,EACA,EAAA,aAAA,GAEA,OAAA,mBC7DA,SAAA,GACA,YAuBA,SAAA,GAAA,GACA,MAAA,aAAA,GAAA,WAGA,QAAA,GAAA,GACA,GAAA,GAAA,EAAA,SACA,OAAA,YAAA,GAAA,WAAA,EAGA,QAAA,GAAA,GACA,QAAA,EAAA,WAGA,QAAA,GAAA,GACA,GAAA,EACA,OAAA,GAAA,aAAA,EAAA,EAAA,cAAA,EAAA,IAAA,KAIA,QAAA,GAAA,EAAA,EAAA,GACA,GAAA,EAAA,OACA,MAAA,GAAA,OAGA,IAAA,EAAA,GACA,MAAA,GAAA,IAAA,EAAA,IAGA,IAAA,GAAA,EAAA,kBAAA,IAAA,EACA,IAAA,EAAA,CAEA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,EAAA,GAAA,EAAA,EAEA,OAAA,GAAA,GAIA,GAAA,GAAA,EAAA,GAAA,CACA,GAAA,GAAA,EAAA,UACA,IAAA,GAAA,EAAA,GAGA,IAAA,GAFA,GAAA,EAAA,eAAA,GACA,EAAA,EAAA,GACA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,GAAA,EAAA,GAAA,SAAA,GACA,MAAA,GAKA,MAAA,GAAA,GAIA,QAAA,GAAA,GAKA,IAJA,GAAA,MACA,EAAA,EACA,KACA,KACA,GAAA,CACA,GAAA,GAAA,IAGA,IAAA,EAAA,GAAA,CACA,EAAA,EAAA,EACA,IAAA,GAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,KAAA,OACA,GAAA,QACA,EAAA,KAAA,EAEA,IAAA,GAAA,EAAA,EAAA,OAAA,EACA,GAAA,MAAA,OAAA,EAAA,cAAA,IACA,EAAA,IACA,EAAA,MAEA,EAAA,EAAA,EAAA,EAAA,GAEA,MAAA,GAGA,QAAA,GAAA,GACA,IAAA,GAAA,GAAA,EAAA,OAAA,EAAA,GAAA,EAAA,IACA,IAAA,EAAA,EAAA,IACA,MAAA,GAAA,EAEA,OAAA,MAIA,QAAA,GAAA,EAAA,GAEA,IADA,GAAA,MACA,GAAA,CAIA,IAHA,GAAA,MACA,EAAA,EACA,EAAA,OACA,GAAA,CACA,GAAA,GAAA,IACA,IAAA,EAAA,QAGA,GAAA,EAAA,KACA,EAAA,EAAA,GAGA,EAAA,IAAA,CACA,GAAA,GAAA,EAAA,EAAA,OAAA,EACA,GAAA,KAAA,QARA,GAAA,KAAA,EAaA,IAAA,EAAA,EAAA,GACA,MAAA,GAAA,EAAA,OAAA,EAEA,GAAA,IACA,EAAA,MAEA,EAAA,EACA,EAAA,EAAA,EAAA,EAAA,GAGA,EADA,EAAA,GACA,EAAA,KAEA,EAAA,YAIA,QAAA,GAAA,GACA,MAAA,GAAA,qBAAA,IAAA,GAGA,QAAA,GAAA,GACA,MAAA,GAAA,GAGA,QAAA,GAAA,EAAA,GACA,MAAA,GAAA,KAAA,EAAA,GAGA,QAAA,GAAA,GAEA,EAAA,IAAA,KAEA,EAAA,IAAA,GAAA,GACA,EAAA,EAAA,GAAA,EAAA,EAAA,UAGA,QAAA,GAAA,GACA,OAAA,EAAA,MACA,IAAA,eACA,IAAA,OACA,IAAA,SACA,OAAA,EAEA,OAAA,EAGA,QAAA,GAAA,EAAA,GACA,GAAA,EAAA,IAAA,GACA,KAAA,IAAA,OAAA,oBACA,GAAA,IAAA,GAAA,GAGA,EAAA,kBACA,IAAA,GAAA,EAAA,EA0BA,OAlBA,KAAA,EAAA,QACA,EAAA,GAAA,iBAAA,GAAA,UACA,EAAA,IACA,EAAA,QAGA,EAAA,IAAA,EAAA,GAEA,EAAA,EAAA,IACA,EAAA,EAAA,IACA,EAAA,EAAA,GAIA,EAAA,IAAA,EAAA,EAAA,MACA,EAAA,OAAA,EAAA,MACA,EAAA,OAAA,GAEA,EAAA,iBAGA,QAAA,GAAA,EAAA,GAGA,IAAA,GAFA,GAEA,EAAA,EAAA,OAAA,EAAA,EAAA,EAAA,IAAA,CACA,GAAA,GAAA,EAAA,GAAA,OACA,EAAA,EAAA,GAAA,aACA,IAAA,IAAA,IAGA,EAAA,EAAA,iBACA,EAAA,EAAA,GAAA,EAAA,IACA,OAAA,EAGA,OAAA,EAGA,QAAA,GAAA,EAAA,GACA,GAAA,GAAA,EAAA,SACA,OAAA,GAAA,EAAA,GAAA,EAAA,GAGA,QAAA,GAAA,EAAA,GAIA,IAAA,GAFA,GADA,EAAA,EAAA,QAGA,EAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,GAAA,OACA,EAAA,EAAA,GAAA,aACA,IAAA,IAAA,EACA,EAAA,EAAA,cACA,CAAA,IAAA,GAAA,EAAA,IAAA,GAGA,QAFA,GAAA,EAAA,eAIA,IAAA,EAAA,EAAA,GAAA,EAAA,GACA,QAIA,QAAA,GAAA,EAAA,EAAA,GACA,GAAA,GAAA,EAAA,OACA,EAAA,EAAA,cAEA,EAAA,EAAA,IAAA,EACA,KAAA,EACA,OAAA,CAEA,IAAA,iBAAA,GAAA,CACA,GAAA,GAAA,EAAA,GACA,EAAA,EAAA,aAMA,IAAA,EAAA,CAIA,GAAA,YAAA,SACA,EAAA,iBAAA,CACA,GAAA,GAAA,EAAA,GAEA,EAAA,EAAA,EAAA,EACA,IAAA,IAAA,EACA,OAAA,MAEA,GAAA,IAEA,GAAA,IAAA,EAAA,IAIA,EAAA,IAAA,EAAA,EACA,IAAA,GAAA,EAAA,KAEA,GAAA,CACA,GAAA,IAAA,EAAA,GACA,EAAA,IAAA,EAAA,EAEA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,EACA,IAAA,EAAA,QACA,GAAA,MAIA,MAAA,EAAA,OAAA,IACA,EAAA,SAAA,IAAA,EAAA,iBACA,EAAA,SAAA,IAAA,EAAA,gBAIA,IAMA,GALA,kBAAA,GAAA,QACA,EAAA,QAAA,KAAA,EAAA,GAEA,EAAA,QAAA,YAAA,GAEA,EAAA,IAAA,GACA,OAAA,EAEA,MAAA,GACA,OAAA,QACA,OAAA,QAAA,EAAA,SAEA,QAAA,MAAA,EAAA,EAAA,QAIA,GAAA,EAAA,CACA,GAAA,GAAA,EAAA,OACA,GAAA,OAAA,CACA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,GAAA,SACA,EAAA,KAAA,EAAA,IAIA,OAAA,EAAA,IAAA,GAGA,QAAA,GAAA,EAAA,EAAA,GACA,KAAA,KAAA,EACA,KAAA,QAAA,EACA,KAAA,QAAA,QAAA,GA6BA,QAAA,GAAA,EAAA,GACA,KAAA,YAAA,KAMA,MAAA,GAAA,EAAA,GAAA,QAAA,EAAA,GALA;GAAA,GAAA,CACA,OAAA,KAAA,iBAAA,EAAA,UAEA,KAAA,KAAA,GADA,GAAA,GAAA,GA+CA,QAAA,GAAA,GACA,MAAA,IAAA,EAAA,cAEA,OAAA,OAAA,GACA,eAAA,MAAA,EAAA,EAAA,kBAFA,EAMA,QAAA,GAAA,EAAA,EAAA,GACA,GAAA,GAAA,OAAA,GACA,EAAA,SAAA,EAAA,GACA,MAAA,aAAA,QACA,KAAA,KAAA,GAEA,EAAA,EAAA,EAAA,EAAA,EAAA,IAKA,IAHA,EAAA,UAAA,OAAA,OAAA,EAAA,WACA,GACA,EAAA,EAAA,UAAA,GACA,EAMA,IACA,EAAA,EAAA,EAAA,GAAA,GAAA,SACA,MAAA,GACA,EAAA,EAAA,EACA,SAAA,YAAA,IAGA,MAAA,GAgBA,QAAA,GAAA,EAAA,GACA,MAAA,YACA,UAAA,GAAA,EAAA,UAAA,GACA,IAAA,GAAA,EAAA,KACA,GAAA,GAAA,MAAA,EAAA,YAgCA,QAAA,GAAA,EAAA,EAAA,EAAA,GACA,GAAA,GACA,MAAA,IAAA,GAAA,EAAA,EAAA,GAGA,IAAA,GAAA,EAAA,SAAA,YAAA,IACA,EAAA,GAAA,GACA,GAAA,EASA,OARA,QAAA,KAAA,GAAA,QAAA,SAAA,GACA,GAAA,GAAA,MAAA,GAAA,IAAA,GACA,EAAA,GAAA,EAAA,EACA,mBAAA,IACA,EAAA,EAAA,IACA,EAAA,KAAA,KAEA,EAAA,OAAA,GAAA,MAAA,EAAA,GACA,EAqCA,QAAA,GAAA,GACA,EAAA,KAAA,KAAA,GAeA,QAAA,GAAA,GACA,MAAA,kBAAA,IACA,EACA,GAAA,EAAA,YAGA,QAAA,GAAA,GACA,OAAA,GACA,IAAA,kBACA,IAAA,0BACA,IAAA,2BACA,IAAA,wBACA,IAAA,kBACA,IAAA,8BACA,IAAA,iBACA,IAAA,6BACA,IAAA,qBACA,OAAA,EAEA,OAAA,EAUA,QAAA,GAAA,GACA,KAAA,KAAA,EAkBA,QAAA,GAAA,GAGA,MAFA,aAAA,GAAA,aACA,EAAA,EAAA,MACA,EAAA,GAqFA,QAAA,GAAA,EAAA,GACA,GAAA,GAAA,EAAA,IAAA,EACA,IAAA,EACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IACA,IAAA,EAAA,GAAA,SAAA,EAAA,GAAA,OAAA,EACA,OAAA,CAGA,QAAA,EAGA,QAAA,GAAA,EAAA,GACA,IAAA,GAAA,GAAA,EAAA,GAAA,EAAA,EAAA,EAAA,WACA,GAAA,EAAA,EAAA,GAAA,GACA,OAAA,CAEA,QAAA,EAMA,QAAA,GAAA,GACA,EAAA,EAAA,IAKA,QAAA,GAAA,EAAA,EAAA,EAAA,GACA,EAAA,kBAIA,KAAA,GAFA,GAAA,EAAA,GAAA,KAAA,EAAA,KAAA,EAAA,IACA,EAAA,EAAA,EAAA,MACA,EAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,EACA,IAAA,EAAA,gBAAA,EACA,MAAA,GAAA,OAEA,MAAA,MAQA,QAAA,GAAA,GACA,MAAA,YACA,GAAA,GAAA,EAAA,IAAA,KACA,OAAA,IAAA,EAAA,IACA,EAAA,GAAA,OAAA,MASA,QAAA,GAAA,GACA,GAAA,GAAA,EAAA,MAAA,EACA,OAAA,UAAA,GACA,GAAA,GAAA,EAAA,IAAA,KACA,KACA,EAAA,OAAA,OAAA,MACA,EAAA,IAAA,KAAA,GAGA,IAAA,GAAA,EAAA,EAIA,IAHA,GACA,KAAA,oBAAA,EAAA,EAAA,SAAA,GAEA,kBAAA,GAAA,CACA,GAAA,GAAA,SAAA,GACA,GAAA,GAAA,EAAA,KAAA,KAAA,EACA,MAAA,EACA,EAAA,iBACA,mBAAA,GAAA,gBAAA,KACA,EAAA,YAAA,GAKA,MAAA,iBAAA,EAAA,GAAA,GACA,EAAA,IACA,MAAA,EACA,QAAA,KA5xBA,GAAA,GAAA,EAAA,wBACA,EAAA,EAAA,aACA,EAAA,EAAA,MACA,EAAA,EAAA,gBACA,EAAA,EAAA,OACA,EAAA,EAAA,KACA,EAAA,EAAA,SAGA,GADA,GAAA,SACA,GAAA,UACA,EAAA,GAAA,SACA,EAAA,GAAA,SACA,EAAA,GAAA,SACA,EAAA,GAAA,SACA,EAAA,GAAA,SACA,EAAA,GAAA,SACA,EAAA,GAAA,SACA,EAAA,GAAA,SACA,EAAA,GAAA,SACA,EAAA,GAAA,QAoUA,GAAA,WACA,OAAA,SAAA,GACA,MAAA,MAAA,UAAA,EAAA,SAAA,KAAA,OAAA,EAAA,MACA,KAAA,UAAA,EAAA,SAEA,GAAA,WACA,MAAA,QAAA,KAAA,SAEA,OAAA,WACA,KAAA,QAAA,MAIA,IAAA,IAAA,OAAA,KACA,IAAA,UAAA,mBACA,aAAA,EAGA,aAAA,GAmBA,EAAA,WACA,GAAA,UACA,MAAA,GAAA,IAAA,OAEA,GAAA,iBACA,MAAA,GAAA,IAAA,OAEA,GAAA,cACA,MAAA,GAAA,IAAA,OAEA,GAAA,QACA,GAAA,GAAA,GAAA,GAAA,SACA,EAAA,EAAA,IAAA,KACA,IAAA,EAAA,CAKA,IAAA,GAJA,GAAA,EACA,EAAA,EAAA,OAAA,EACA,EAAA,EAAA,EAAA,IAAA,OAEA,EAAA,EAAA,GAAA,EAAA,IAAA,CACA,GAAA,GAAA,EAAA,GAAA,cACA,EAAA,EAAA,EACA,GAAA,SAAA,KAEA,IAAA,GAAA,YAAA,GAAA,QACA,EAAA,KAAA,GAGA,EAAA,OAAA,EAEA,MAAA,IAEA,gBAAA,WACA,EAAA,IAAA,MAAA,IAEA,yBAAA,WACA,EAAA,IAAA,MAAA,GACA,EAAA,IAAA,MAAA,KAGA,EAAA,GAAA,EAAA,SAAA,YAAA,SAqCA,IAAA,IAAA,EAAA,UAAA,GACA,GAAA,EAAA,cAAA,GAEA,IACA,GAAA,iBACA,GAAA,GAAA,EAAA,IAAA,KAEA,OAAA,UAAA,EACA,EACA,EAAA,EAAA,MAAA,iBAYA,GAAA,GACA,eAAA,EAAA,iBAAA,KACA,IAEA,GAAA,GACA,eAAA,EAAA,iBAAA,IACA,IAEA,GAAA,EAAA,aAAA,GAAA,IACA,GAAA,EAAA,aAAA,GAAA,IAKA,GAAA,OAAA,OAAA,MAEA,GAAA,WACA,IACA,GAAA,QAAA,WAAA,SACA,MAAA,GACA,OAAA,EAEA,OAAA,IAyBA,KAAA,GAAA,CACA,GAAA,IAAA,SAAA,EAAA,EAAA,GACA,GAAA,EAAA,CACA,GAAA,GAAA,GAAA,EACA,GAAA,EAAA,KAAA,GAAA,GAGA,GAAA,GAAA,EAKA,IAAA,SAAA,SAAA,EAAA,YAAA,IACA,GAAA,eAAA,OAAA,MAAA,SACA,GAAA,WAAA,KAAA,KAAA,OAAA,GAAA,SACA,GAAA,cACA,QAAA,EACA,QAAA,EACA,QAAA,EACA,QAAA,EACA,SAAA,EACA,QAAA,EACA,UAAA,EACA,SAAA,EACA,OAAA,EACA,cAAA,MACA,WACA,GAAA,cAAA,cAAA,MAAA,WAKA,GAAA,IAAA,OAAA,iBAKA,GAAA,UAAA,OAAA,OAAA,EAAA,WACA,EAAA,EAAA,WACA,GAAA,eACA,MAAA,MAAA,KAAA,aAEA,GAAA,aAAA,GACA,KAAA,KAAA,YAAA,KAIA,IACA,EAAA,GAAA,EAwBA,IAAA,IAAA,OAAA,YAaA,IACA,mBACA,sBACA,kBAGA,KAAA,QAAA,QAAA,SAAA,GACA,GAAA,GAAA,EAAA,SACA,IAAA,QAAA,SAAA,GACA,OAAA,eAAA,EAAA,EAAA,KAAA,MAAA,EAAA,SAUA,EAAA,WACA,iBAAA,SAAA,EAAA,EAAA,GACA,GAAA,EAAA,KAAA,EAAA,GAAA,CAGA,GAAA,GAAA,GAAA,GAAA,EAAA,EAAA,GACA,EAAA,EAAA,IAAA,KACA,IAAA,GAKA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IACA,GAAA,EAAA,OAAA,EAAA,IACA,WANA,MACA,EAAA,IAAA,KAAA,EASA,GAAA,KAAA,EAEA,IAAA,GAAA,EAAA,KACA,GAAA,kBAAA,EAAA,GAAA,KAEA,oBAAA,SAAA,EAAA,EAAA,GACA,EAAA,QAAA,EACA,IAAA,GAAA,EAAA,IAAA,KACA,IAAA,EAAA,CAGA,IAAA,GADA,GAAA,EAAA,GAAA,EACA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,GAAA,OAAA,GAAA,EAAA,GAAA,UAAA,IACA,IACA,EAAA,GAAA,UAAA,IACA,GAAA,EACA,EAAA,GAAA,UAKA,IAAA,GAAA,IAAA,EAAA,CACA,GAAA,GAAA,EAAA,KACA,GAAA,qBAAA,EAAA,GAAA,MAGA,cAAA,SAAA,GAWA,GAAA,GAAA,EAAA,GACA,EAAA,EAAA,IAKA,GAAA,IAAA,GAAA,GAIA,EAAA,kBAEA,IAAA,EACA,GAAA,KAAA,KACA,EAAA,aACA,KAAA,iBAAA,EAAA,GAAA,GAGA,KACA,MAAA,GAAA,MAAA,eAAA,GACA,QACA,GACA,KAAA,oBAAA,EAAA,GAAA,MAwBA,IACA,EAAA,GAAA,EAMA,IAAA,IAAA,SAAA,gBAkEA,GAAA,oBAAA,EACA,EAAA,iBAAA,EACA,EAAA,sBAAA,EACA,EAAA,sBAAA,EACA,EAAA,uBAAA,EACA,EAAA,SAAA,kBAAA,EACA,EAAA,SAAA,YAAA,GACA,EAAA,SAAA,MAAA,EACA,EAAA,SAAA,YAAA,EACA,EAAA,SAAA,WAAA,GACA,EAAA,SAAA,WAAA,GACA,EAAA,SAAA,QAAA,IAEA,OAAA,mBClzBA,SAAA,GACA,YAIA,SAAA,GAAA,EAAA,GACA,OAAA,eAAA,EAAA,GAAA,YAAA,IAGA,QAAA,KACA,KAAA,OAAA,EACA,EAAA,KAAA,UASA,QAAA,GAAA,GACA,GAAA,MAAA,EACA,MAAA,EAEA,KAAA,GADA,GAAA,GAAA,GACA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,IACA,EAAA,GAAA,EAAA,EAAA,GAGA,OADA,GAAA,OAAA,EACA,EAGA,QAAA,GAAA,EAAA,GACA,EAAA,UAAA,GAAA,WACA,MAAA,GAAA,KAAA,KAAA,GAAA,MAAA,KAAA,KAAA,aA9BA,GAAA,GAAA,EAAA,IAUA,GAAA,WACA,KAAA,SAAA,GACA,MAAA,MAAA,KAGA,EAAA,EAAA,UAAA,QAmBA,EAAA,SAAA,SAAA,EACA,EAAA,sBAAA,EACA,EAAA,aAAA,GAEA,OAAA,mBCvCA,SAAA,GACA,YAIA,GAAA,mBAAA,EAAA,aACA,EAAA,SAAA,eAAA,EAAA,SAAA,UAEA,OAAA,mBCRA,SAAA,GACA,YAoBA,SAAA,GAAA,GACA,EAAA,YAAA,IAGA,QAAA,GAAA,GACA,GAAA,GAAA,GAAA,EAGA,OAFA,GAAA,GAAA,EACA,EAAA,OAAA,EACA,EAYA,QAAA,GAAA,EAAA,EAAA,GACA,EAAA,EAAA,aACA,aAAA,EACA,gBAAA,EAAA,gBACA,YAAA,EAAA,cAIA,QAAA,GAAA,EAAA,GACA,EAAA,EAAA,aACA,aAAA,IAUA,QAAA,GAAA,EAAA,EAAA,EAAA,GACA,GAAA,YAAA,kBAAA,CACA,GAAA,GAAA,EAAA,EAGA,IAAA,CACA,KAAA,GAAA,GAAA,EAAA,OAAA,EAAA,GAAA,EAAA,IACA,EAAA,YAAA,EAAA,IACA,EAAA,GAAA,YAAA,CAEA,IAAA,CAEA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,GAAA,iBAAA,EAAA,EAAA,IAAA,EACA,EAAA,GAAA,aAAA,EAAA,EAAA,IAAA,CAQA,OALA,KACA,EAAA,aAAA,EAAA,IACA,IACA,EAAA,iBAAA,EAAA,EAAA,OAAA,IAEA,EAGA,GAAA,GAAA,EAAA,GACA,EAAA,EAAA,UAcA,OAbA,IAEA,EAAA,YAAA,GAGA,EAAA,YAAA,EACA,EAAA,iBAAA,EACA,EAAA,aAAA,EACA,IACA,EAAA,aAAA,GACA,IACA,EAAA,iBAAA,GAEA,EAGA,QAAA,GAAA,GACA,GAAA,YAAA,kBACA,MAAA,GAAA,EAEA,IAAA,GAAA,EAAA,GACA,EAAA,EAAA,UAGA,OAFA,IACA,EAAA,EAAA,EAAA,GACA,EAGA,QAAA,GAAA,GAGA,IAAA,GAFA,GAAA,GAAA,GACA,EAAA,EACA,EAAA,EAAA,WAAA,EAAA,EAAA,EAAA,YACA,EAAA,KAAA,CAIA,OAFA,GAAA,OAAA,EACA,EAAA,EAAA,GACA,EAGA,QAAA,GAAA,GAEA,MAAA,GAIA,QAAA,GAAA,EAAA,GACA,EAAA,EAAA,GACA,EAAA,kBAGA,QAAA,GAAA,EAAA,GAEA,IAAA,GADA,GAAA,EAAA,GACA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,EAAA,GAAA,GAKA,QAAA,GAAA,GACA,EAAA,EAAA,GAAA,GAAA,EAAA,OAGA,QAAA,GAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,EAAA,IAIA,QAAA,GAAA,EAAA,GACA,GAAA,GAAA,EAAA,WAAA,EAAA,cACA,EAAA,EAAA,aACA,KAAA,EAAA,eACA,EAAA,UAAA,GAGA,QAAA,GAAA,EAAA,GACA,GAAA,EAAA,OAAA,CAGA,GAAA,GAAA,EAAA,aAGA,IAAA,IAAA,EAAA,GAAA,cAGA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,kBAAA,EAAA,GAAA,IAIA,QAAA,GAAA,EAAA,GACA,EAAA,EAAA,EACA,IAAA,GAAA,EAAA,MAEA,IAAA,IAAA,EACA,MAAA,GAAA,EAAA,GAGA,KAAA,GADA,GAAA,EAAA,EAAA,cAAA,0BACA,EAAA,EAAA,EAAA,EAAA,IACA,EAAA,YAAA,EAAA,EAAA,IAEA,OAAA,GAGA,QAAA,GAAA,GACA,GAAA,SAAA,EAAA,YAEA,IADA,GAAA,GAAA,EAAA,YACA,GAAA,CACA,GAAA,GAAA,CACA,GAAA,EAAA,aACA,EAAA,YAAA,EAAA,iBAAA,EAAA,aAAA,OAGA,EAAA,YAAA,EAAA,WAAA,OAGA,QAAA,GAAA,GACA,GAAA,EAAA,2BAAA,CAEA,IADA,GAAA,GAAA,EAAA,WACA,GAAA,CACA,EAAA,EAAA,aAAA,EACA,IAAA,GAAA,EAAA,YACA,EAAA,EAAA,GACA,EAAA,EAAA,UACA,IACA,EAAA,KAAA,EAAA,GACA,EAAA,iBAAA,EAAA,aACA,EAAA,YAAA,KACA,EAAA,EAEA,EAAA,YAAA,EAAA,WAAA,SAKA,KAHA,GAEA,GAFA,EAAA,EAAA,GACA,EAAA,EAAA,WAEA,GACA,EAAA,EAAA,YACA,EAAA,KAAA,EAAA,GACA,EAAA,EAKA,QAAA,GAAA,GACA,GAAA,GAAA,EAAA,UACA,OAAA,IAAA,EAAA,2BAGA,QAAA,GAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,EAAA,GACA,EAAA,WAAA,YAAA,GAOA,QAAA,GAAA,EAAA,EAAA,GACA,GAAA,EAMA,IAJA,EAAA,EADA,EACA,EAAA,KAAA,EAAA,EAAA,MAAA,GAEA,EAAA,KAAA,EAAA,MAAA,IAEA,EAAA,CACA,IAAA,GAAA,GAAA,EAAA,WAAA,EAAA,EAAA,EAAA,YACA,EAAA,YAAA,EAAA,GAAA,EAAA,GAGA,IAAA,YAAA,GAAA,oBAEA,IAAA,GADA,GAAA,EAAA,QACA,EAAA,EAAA,QAAA,WACA,EACA,EAAA,EAAA,YACA,EAAA,YAAA,EAAA,GAAA,EAAA,IAKA,MAAA,GAGA,QAAA,GAAA,EAAA,GACA,IAAA,GAAA,EAAA,KAAA,EAAA,GACA,OAAA,CAEA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,WACA,GAAA,IAAA,EACA,OAAA,CAEA,QAAA,EAWA,QAAA,GAAA,GACA,EAAA,YAAA,IAEA,EAAA,KAAA,KAAA,GAUA,KAAA,YAAA,OAMA,KAAA,YAAA,OAMA,KAAA,WAAA,OAMA,KAAA,aAAA,OAMA,KAAA,iBAAA,OAEA,KAAA,WAAA,OArUA,GAAA,GAAA,EAAA,SAAA,YACA,EAAA,EAAA,SAAA,SACA,EAAA,EAAA,UACA,EAAA,EAAA,OACA,EAAA,EAAA,iBACA,EAAA,EAAA,gBACA,EAAA,EAAA,aACA,EAAA,EAAA,UACA,EAAA,EAAA,MACA,EAAA,EAAA,2BACA,EAAA,EAAA,gBACA,EAAA,EAAA,aACA,EAAA,EAAA,OACA,EAAA,EAAA,eACA,EAAA,EAAA,KACA,EAAA,EAAA,aACA,EAAA,EAAA,SAaA,GAAA,EAkNA,EAAA,SAAA,WACA,EAAA,OAAA,KAAA,UAAA,UAsCA,EAAA,OAAA,KAkDA,EAAA,OAAA,iBAEA,GADA,EAAA,UAAA,YAEA,EAAA,UAAA,yBACA,EAAA,EAAA,UAAA,aACA,EAAA,EAAA,UAAA,YACA,EAAA,EAAA,UAAA,aAEA,EAAA,UAAA,KAAA,UAAA,WAEA,EAAA,EACA,SAAA,EAAA,GACA,IACA,EAAA,KAAA,EAAA,GACA,MAAA,GACA,KAAA,YAAA,IACA,KAAA,KAGA,SAAA,EAAA,GACA,EAAA,KAAA,EAAA,GAGA,GAAA,UAAA,OAAA,OAAA,EAAA,WACA,EAAA,EAAA,WACA,YAAA,SAAA,GACA,MAAA,MAAA,aAAA,EAAA,OAGA,aAAA,SAAA,EAAA,GACA,EAAA,EAEA,IAAA,EACA,GACA,EAAA,GACA,EAAA,EAAA,IAEA,EAAA,EACA,EAAA,EAAA,KAGA,EAAA,KACA,EAAA,MAGA,GAAA,EAAA,EAAA,aAAA,KAEA,IAAA,GACA,EACA,EAAA,EAAA,gBAAA,KAAA,UAEA,GAAA,KAAA,6BACA,EAAA,EAOA,IAJA,EADA,EACA,EAAA,GAEA,EAAA,EAAA,KAAA,EAAA,GAEA,EACA,EAAA,KAAA,GACA,EAAA,MACA,EAAA,KAAA,KAAA,KAAA,EAAA,GAAA,OACA,CACA,IACA,KAAA,YAAA,EAAA,IACA,IACA,KAAA,WAAA,EAAA,EAAA,OAAA,GAEA,IAAA,GAAA,EAAA,EAAA,WAAA,KAAA,IAGA,GACA,EAAA,KAAA,EACA,EAAA,KAAA,GAAA,GAEA,EAAA,KAAA,GAYA,MARA,GAAA,KAAA,aACA,WAAA,EACA,YAAA,EACA,gBAAA,IAGA,EAAA,EAAA,MAEA,GAGA,YAAA,SAAA,GAEA,GADA,EAAA,GACA,EAAA,aAAA,KAAA,CAIA,IAAA,GAFA,IAAA,EAEA,GADA,KAAA,WACA,KAAA,YAAA,EACA,EAAA,EAAA,YACA,GAAA,IAAA,EAAA,CACA,GAAA,CACA,OAGA,IAAA,EAEA,KAAA,IAAA,OAAA,iBAIA,GAAA,GAAA,EAAA,GACA,EAAA,EAAA,YACA,EAAA,EAAA,eAEA,IAAA,KAAA,2BAAA,CAIA,GAAA,GAAA,KAAA,WACA,EAAA,KAAA,UAEA,EAAA,EAAA,UACA,IACA,EAAA,EAAA,GAEA,IAAA,IACA,KAAA,YAAA,GACA,IAAA,IACA,KAAA,WAAA,GACA,IACA,EAAA,aAAA,GACA,IACA,EAAA,iBACA,GAGA,EAAA,iBAAA,EAAA,aACA,EAAA,YAAA,WAEA,GAAA,MACA,EAAA,KAAA,KAAA,EAaA,OAVA,IACA,EAAA,KAAA,aACA,aAAA,EAAA,GACA,YAAA,EACA,gBAAA,IAIA,EAAA,KAAA,GAEA,GAGA,aAAA,SAAA,EAAA,GACA,EAAA,EAEA,IAAA,EAQA,IAPA,EAAA,GACA,EAAA,EAAA,IAEA,EAAA,EACA,EAAA,EAAA,IAGA,EAAA,aAAA,KAEA,KAAA,IAAA,OAAA,gBAGA,IAEA,GAFA,EAAA,EAAA,YACA,EAAA,EAAA,gBAGA,GAAA,KAAA,6BACA,EAAA,EA2CA,OAzCA,GACA,EAAA,EAAA,IAEA,IAAA,IACA,EAAA,EAAA,aACA,EAAA,EAAA,EAAA,KAAA,EAAA,IAGA,GAiBA,EAAA,KAAA,GACA,EAAA,MACA,EAAA,KAAA,KAAA,KAAA,EAAA,GACA,KAnBA,KAAA,aAAA,IACA,KAAA,YAAA,EAAA,IACA,KAAA,YAAA,IACA,KAAA,WAAA,EAAA,EAAA,OAAA,IAEA,EAAA,iBAAA,EAAA,aACA,EAAA,YAAA,OAGA,EAAA,YACA,EAAA,KACA,EAAA,WACA,EAAA,KAAA,GACA,IASA,EAAA,KAAA,aACA,WAAA,EACA,aAAA,EAAA,GACA,YAAA,EACA,gBAAA,IAGA,EAAA,GACA,EAAA,EAAA,MAEA,GAQA,gBAAA,WACA,IAAA,GAAA,GAAA,KAAA,WAAA,EAAA,EAAA,EAAA,YACA,EAAA,mBAIA,cAAA,WACA,MAAA,QAAA,KAAA,YAIA,GAAA,cAEA,MAAA,UAAA,KAAA,YACA,KAAA,YAAA,EAAA,KAAA,KAAA,aAIA,GAAA,cACA,MAAA,UAAA,KAAA,YACA,KAAA,YAAA,EAAA,KAAA,KAAA,aAIA,GAAA,aACA,MAAA,UAAA,KAAA,WACA,KAAA,WAAA,EAAA,KAAA,KAAA,YAIA,GAAA,eACA,MAAA,UAAA,KAAA,aACA,KAAA,aAAA,EAAA,KAAA,KAAA,cAIA,GAAA,mBACA,MAAA,UAAA,KAAA,iBACA,KAAA,iBAAA,EAAA,KAAA,KAAA,kBAGA,GAAA,iBAEA,IADA,GAAA,GAAA,KAAA,WACA,GAAA,EAAA,WAAA,EAAA,cACA,EAAA,EAAA,UAEA,OAAA,IAGA,GAAA,eAIA,IAAA,GADA,GAAA,GACA,EAAA,KAAA,WAAA,EAAA,EAAA,EAAA,YACA,EAAA,UAAA,EAAA,eACA,GAAA,EAAA,YAGA,OAAA,IAEA,GAAA,aAAA,GACA,GAAA,GAAA,EAAA,KAAA,WAEA,IAAA,KAAA,4BAEA,GADA,EAAA,MACA,KAAA,EAAA,CACA,GAAA,GAAA,KAAA,KAAA,cAAA,eAAA,EACA,MAAA,YAAA,QAGA,GAAA,MACA,KAAA,KAAA,YAAA,CAGA,IAAA,GAAA,EAAA,KAAA,WAEA,GAAA,KAAA,aACA,WAAA,EACA,aAAA,IAGA,EAAA,GACA,EAAA,EAAA,OAGA,GAAA,cAGA,IAAA,GAFA,GAAA,GAAA,GACA,EAAA,EACA,EAAA,KAAA,WAAA,EAAA,EAAA,EAAA,YACA,EAAA,KAAA,CAGA,OADA,GAAA,OAAA,EACA,GAGA,UAAA,SAAA,GACA,MAAA,GAAA,KAAA,IAGA,SAAA,SAAA,GACA,MAAA,GAAA,KAAA,EAAA,KAGA,wBAAA,SAAA,GAGA,MAAA,GAAA,KAAA,KAAA,KACA,EAAA,KAGA,UAAA,WAMA,IAAA,GAFA,GAEA,EALA,EAAA,EAAA,KAAA,YACA,KACA,EAAA,GAGA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,EAAA,GACA,EAAA,WAAA,EAAA,UACA,GAAA,EAAA,KAAA,OAEA,GAGA,GAAA,EAAA,KACA,EAAA,KAAA,IAHA,EAAA,EAFA,KAAA,WAAA,IAQA,GAAA,EAAA,SACA,EAAA,MAAA,EACA,aAAA,IAEA,KACA,EAAA,GACA,EAAA,KACA,EAAA,WAAA,QACA,EAAA,YAKA,IAAA,EAAA,SACA,EAAA,MAAA,EACA,EAAA,OAKA,EAAA,EAAA,iBAKA,EAAA,EAAA,EAAA,SAAA,gCACA,GAAA,UAAA,oBACA,GAAA,UAAA,iBACA,EAAA,UAAA,EAAA,OAAA,OAAA,EAAA,WAAA,EAAA,WAEA,EAAA,UAAA,EACA,EAAA,aAAA,EACA,EAAA,eAAA,EACA,EAAA,eAAA,EACA,EAAA,iBAAA,EACA,EAAA,iBAAA,EACA,EAAA,SAAA,KAAA,GAEA,OAAA,mBCvtBA,SAAA,GACA,YAEA,SAAA,GAAA,EAAA,GAEA,IADA,GAAA,GAAA,EAAA,EAAA,kBACA,GAAA,CACA,GAAA,EAAA,QAAA,GACA,MAAA,EAEA,IADA,EAAA,EAAA,EAAA,GAEA,MAAA,EACA,GAAA,EAAA,mBAEA,MAAA,MAGA,QAAA,GAAA,EAAA,EAAA,GAEA,IADA,GAAA,GAAA,EAAA,kBACA,GACA,EAAA,QAAA,KACA,EAAA,EAAA,UAAA,GACA,EAAA,EAAA,EAAA,GACA,EAAA,EAAA,kBAEA,OAAA,GAOA,GAAA,IACA,cAAA,SAAA,GACA,MAAA,GAAA,KAAA,IAEA,iBAAA,SAAA,GACA,MAAA,GAAA,KAAA,EAAA,GAAA,aAIA,GACA,qBAAA,SAAA,GAEA,MAAA,MAAA,iBAAA,IAEA,uBAAA,SAAA,GAEA,MAAA,MAAA,iBAAA,IAAA,IAEA,uBAAA,SAAA,EAAA,GACA,GAAA,MAAA,EACA,MAAA,MAAA,qBAAA,EAKA,KAAA,GAFA,GAAA,GAAA,UACA,EAAA,KAAA,qBAAA,GACA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,GAAA,eAAA,IACA,EAAA,KAAA,EAAA,GAGA,OADA,GAAA,OAAA,EACA,GAIA,GAAA,uBAAA,EACA,EAAA,mBAAA,GAEA,OAAA,mBCpEA,SAAA,GACA,YAIA,SAAA,GAAA,GACA,KAAA,GAAA,EAAA,WAAA,KAAA,cACA,EAAA,EAAA,WAEA,OAAA,GAGA,QAAA,GAAA,GACA,KAAA,GAAA,EAAA,WAAA,KAAA,cACA,EAAA,EAAA,eAEA,OAAA,GAbA,GAAA,GAAA,EAAA,SAAA,SAgBA,GACA,GAAA,qBACA,MAAA,GAAA,KAAA,aAGA,GAAA,oBACA,MAAA,GAAA,KAAA,YAGA,GAAA,qBAEA,IAAA,GADA,GAAA,EACA,EAAA,KAAA,kBACA,EACA,EAAA,EAAA,mBACA,GAEA,OAAA,IAGA,GAAA,YAGA,IAAA,GAFA,GAAA,GAAA,GACA,EAAA,EACA,EAAA,KAAA,kBACA,EACA,EAAA,EAAA,mBACA,EAAA,KAAA,CAGA,OADA,GAAA,OAAA,EACA,GAGA,OAAA,WACA,GAAA,GAAA,KAAA,UACA,IACA,EAAA,YAAA,QAIA,GACA,GAAA,sBACA,MAAA,GAAA,KAAA,cAGA,GAAA,0BACA,MAAA,GAAA,KAAA,kBAIA,GAAA,mBAAA,EACA,EAAA,oBAAA,GAEA,OAAA,mBCtEA,SAAA,GACA,YAUA,SAAA,GAAA,GACA,EAAA,KAAA,KAAA,GATA,GAAA,GAAA,EAAA,mBACA,EAAA,EAAA,SAAA,KACA,EAAA,EAAA,gBACA,EAAA,EAAA,MACA,EAAA,EAAA,gBAEA,EAAA,OAAA,aAKA,GAAA,UAAA,OAAA,OAAA,EAAA,WACA,EAAA,EAAA,WACA,GAAA,eACA,MAAA,MAAA,MAEA,GAAA,aAAA,GACA,KAAA,KAAA,GAEA,GAAA,QACA,MAAA,MAAA,KAAA,MAEA,GAAA,MAAA,GACA,GAAA,GAAA,KAAA,KAAA,IACA,GAAA,KAAA,iBACA,SAAA,IAEA,KAAA,KAAA,KAAA,KAIA,EAAA,EAAA,UAAA,GAEA,EAAA,EAAA,EACA,SAAA,eAAA,KAEA,EAAA,SAAA,cAAA,GACA,OAAA,mBCxCA,SAAA,GACA,YAOA,SAAA,GAAA,GACA,MAAA,KAAA,EAKA,QAAA,GAAA,GACA,EAAA,KAAA,KAAA,GAZA,GAAA,GAAA,EAAA,SAAA,cAEA,GADA,EAAA,gBACA,EAAA,OACA,EAAA,EAAA,gBAMA,EAAA,OAAA,IAKA,GAAA,UAAA,OAAA,OAAA,EAAA,WACA,EAAA,EAAA,WACA,UAAA,SAAA,GACA,EAAA,EAAA,EACA,IAAA,GAAA,KAAA,IACA,IAAA,EAAA,EAAA,OACA,KAAA,IAAA,OAAA,iBACA,IAAA,GAAA,EAAA,MAAA,EAAA,GACA,EAAA,EAAA,MAAA,EACA,MAAA,KAAA,CACA,IAAA,GAAA,KAAA,cAAA,eAAA,EAGA,OAFA,MAAA,YACA,KAAA,WAAA,aAAA,EAAA,KAAA,aACA,KAIA,EAAA,EAAA,EAAA,SAAA,eAAA,KAEA,EAAA,SAAA,KAAA,GACA,OAAA,mBCrCA,SAAA,GACA,YA6BA,SAAA,GAAA,EAAA,GAEA,GAAA,GAAA,EAAA,UACA,IAAA,GAAA,EAAA,WAAA,CAGA,GAAA,GAAA,EAAA,mBAAA,EACA,GAAA,mBAAA,IACA,EAAA,cAGA,QAAA,GAAA,EAAA,EAAA,GAIA,EAAA,EAAA,cACA,KAAA,EACA,UAAA,KACA,SAAA,IAIA,QAAA,GAAA,GACA,EAAA,KAAA,KAAA,GAsDA,QAAA,GAAA,EAAA,EAAA,GACA,GAAA,GAAA,GAAA,CACA,QAAA,eAAA,EAAA,GACA,IAAA,WACA,MAAA,MAAA,KAAA,IAEA,IAAA,SAAA,GACA,KAAA,KAAA,GAAA,EACA,EAAA,KAAA,IAEA,cAAA,EACA,YAAA,IAnHA,GAAA,GAAA,EAAA,mBACA,EAAA,EAAA,uBACA,EAAA,EAAA,SAAA,KACA,EAAA,EAAA,oBACA,EAAA,EAAA,mBAEA,GADA,EAAA,sBACA,EAAA,iBACA,EAAA,EAAA,MAEA,GADA,EAAA,MACA,EAAA,iBACA,EAAA,EAAA,SAEA,EAAA,OAAA,QAEA,GACA,UACA,qBACA,oBACA,yBACA,OAAA,SAAA,GACA,MAAA,GAAA,UAAA,KAGA,EAAA,EAAA,GAEA,EAAA,EAAA,UAAA,EA2BA,GAAA,UAAA,OAAA,OAAA,EAAA,WACA,EAAA,EAAA,WACA,iBAAA,WACA,GAAA,GAAA,GAAA,GAAA,WAAA,KACA,MAAA,KAAA,mBAAA,CAEA,IAAA,GAAA,EAAA,mBAAA,KAGA,OAFA,GAAA,aAEA,GAGA,GAAA,cACA,MAAA,MAAA,KAAA,oBAAA,MAGA,aAAA,SAAA,EAAA,GACA,GAAA,GAAA,KAAA,KAAA,aAAA,EACA,MAAA,KAAA,aAAA,EAAA,GACA,EAAA,KAAA,EAAA,GACA,EAAA,KAAA,IAGA,gBAAA,SAAA,GACA,GAAA,GAAA,KAAA,KAAA,aAAA,EACA,MAAA,KAAA,gBAAA,GACA,EAAA,KAAA,EAAA,GACA,EAAA,KAAA,IAGA,QAAA,SAAA,GACA,MAAA,GAAA,KAAA,KAAA,KAAA,MAIA,EAAA,QAAA,SAAA,GACA,YAAA,IACA,EAAA,UAAA,GAAA,SAAA,GACA,MAAA,MAAA,QAAA,OAKA,EAAA,UAAA,yBACA,EAAA,UAAA,uBACA,EAAA,UAAA,kBAsBA,EAAA,EAAA,UAAA,MACA,EAAA,EAAA,UAAA,YAAA,SAEA,EAAA,EAAA,UAAA,GACA,EAAA,EAAA,UAAA,GACA,EAAA,EAAA,UAAA,GACA,EAAA,EAAA,UAAA,GAEA,EAAA,EAAA,EACA,SAAA,gBAAA,KAAA,MAIA,EAAA,aAAA,EACA,EAAA,SAAA,QAAA,GACA,OAAA,mBCzIA,SAAA,GACA,YAqBA,SAAA,GAAA,GACA,OAAA,GACA,IAAA,IACA,MAAA,OACA,KAAA,IACA,MAAA,MACA,KAAA,IACA,MAAA,MACA,KAAA,IACA,MAAA,QACA,KAAA,IACA,MAAA,UAIA,QAAA,GAAA,GACA,MAAA,GAAA,QAAA,EAAA,GAGA,QAAA,GAAA,GACA,MAAA,GAAA,QAAA,EAAA,GAGA,QAAA,GAAA,GAEA,IAAA,GADA,MACA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,EAAA,KAAA,CAEA,OAAA,GAkCA,QAAA,GAAA,EAAA,GACA,OAAA,EAAA,UACA,IAAA,MAAA,aAIA,IAAA,GAAA,GAHA,EAAA,EAAA,QAAA,cACA,EAAA,IAAA,EACA,EAAA,EAAA,WACA,EAAA,EAAA,EAAA,EAAA,GAAA,IACA,GAAA,IAAA,EAAA,KAAA,KAAA,EAAA,EAAA,OAAA,GAGA,OADA,IAAA,IACA,EAAA,GACA,EAEA,EAAA,EAAA,GAAA,KAAA,EAAA,GAEA,KAAA,MAAA,UACA,GAAA,GAAA,EAAA,IACA,OAAA,IAAA,EAAA,EAAA,WACA,EACA,EAAA,EAEA,KAAA,MAAA,aACA,MAAA,OAAA,EAAA,KAAA,KAEA,SAEA,KADA,SAAA,MAAA,GACA,GAAA,OAAA,oBAIA,QAAA,GAAA,GACA,YAAA,GAAA,sBACA,EAAA,EAAA,QAGA,KAAA,GADA,GAAA,GACA,EAAA,EAAA,WAAA,EAAA,EAAA,EAAA,YACA,GAAA,EAAA,EAAA,EAEA,OAAA,GAGA,QAAA,GAAA,EAAA,EAAA,GACA,GAAA,GAAA,GAAA,KACA,GAAA,YAAA,EACA,IAAA,GAAA,EAAA,EAAA,cAAA,cAAA,GACA,GAAA,UAAA,CAEA,KADA,GAAA,GACA,EAAA,EAAA,YACA,EAAA,YAAA,EAAA,IAUA,QAAA,GAAA,GACA,EAAA,KAAA,KAAA,GAwFA,QAAA,GAAA,EAAA,GAEA,GAAA,GAAA,EAAA,EAAA,WAAA,GACA,GAAA,UAAA,CAGA,KAFA,GACA,GADA,EAAA,EAAA,SAAA,0BAEA,EAAA,EAAA,YACA,EAAA,YAAA,EAEA,OAAA,GAAA,GAGA,QAAA,GAAA,GACA,MAAA,YAEA,MADA,GAAA,mBACA,KAAA,KAAA,IAIA,QAAA,GAAA,GACA,EAAA,EAAA,EAAA,EAAA,IAgBA,QAAA,GAAA,GACA,OAAA,eAAA,EAAA,UAAA,GACA,IAAA,EAAA,GACA,IAAA,SAAA,GACA,EAAA,mBACA,KAAA,KAAA,GAAA,GAEA,cAAA,EACA,YAAA,IASA,QAAA,GAAA,GACA,OAAA,eAAA,EAAA,UAAA,GACA,MAAA,WAEA,MADA,GAAA,mBACA,KAAA,KAAA,GAAA,MAAA,KAAA,KAAA,YAEA,cAAA,EACA,YAAA,IAhSA,GAAA,GAAA,EAAA,SAAA,QACA,EAAA,EAAA,aACA,EAAA,EAAA,gBACA,EAAA,EAAA,MACA,EAAA,EAAA,eACA,EAAA,EAAA,iBACA,EAAA,EAAA,gBACA,EAAA,EAAA,iBACA,EAAA,EAAA,OACA,EAAA,EAAA,KACA,EAAA,EAAA,SAMA,EAAA,cACA,EAAA,eAkCA,EAAA,GACA,OACA,OACA,KACA,MACA,UACA,QACA,KACA,MACA,QACA,SACA,OACA,OACA,QACA,SACA,QACA,QAGA,EAAA,GACA,QACA,SACA,MACA,SACA,UACA,WACA,YACA,aAwDA,EAAA,OAAA,KAAA,UAAA,WAEA,EAAA,OAAA,YACA,EAAA,OAAA,mBAKA,GAAA,UAAA,OAAA,OAAA,EAAA,WACA,EAAA,EAAA,WACA,GAAA,aACA,MAAA,GAAA,OAEA,GAAA,WAAA,GAOA,GAAA,GAAA,EAAA,KAAA,WAEA,YADA,KAAA,YAAA,EAIA,IAAA,GAAA,EAAA,KAAA,WAEA,MAAA,2BACA,eAAA,GAAA,oBACA,EAAA,KAAA,QAAA,GAEA,EAAA,KAAA,EAAA,KAAA,UAKA,GACA,eAAA,GAAA,oBACA,EAAA,KAAA,QAAA,GAEA,KAAA,KAAA,UAAA,CAGA,IAAA,GAAA,EAAA,KAAA,WAEA,GAAA,KAAA,aACA,WAAA,EACA,aAAA,IAGA,EAAA,GACA,EAAA,EAAA,OAGA,GAAA,aACA,MAAA,GAAA,KAAA,KAAA,aAEA,GAAA,WAAA,GACA,GAAA,GAAA,KAAA,UACA,IAAA,EAAA,CACA,EAAA,0BACA,IAAA,GAAA,EAAA,EAAA,EACA,GAAA,aAAA,EAAA,QAIA,mBAAA,SAAA,EAAA,GACA,GAAA,GAAA,CACA,QAAA,OAAA,GAAA,eACA,IAAA,cACA,EAAA,KAAA,WACA,EAAA,IACA,MACA,KAAA,WACA,EAAA,KAAA,WACA,EAAA,KAAA,WACA,MACA,KAAA,aACA,EAAA,KACA,EAAA,KAAA,UACA,MACA,KAAA,YACA,EAAA,KACA,EAAA,IACA,MACA,SACA,OAGA,GAAA,GAAA,EAAA,EAAA,EACA,GAAA,aAAA,EAAA,OA4BA,eACA,aACA,YACA,cACA,eACA,aACA,YACA,cACA,eACA,eACA,QAAA,IAeA,aACA,aACA,QAAA,IAcA,wBACA,iBACA,kBACA,QAAA,GAGA,EAAA,EAAA,EACA,SAAA,cAAA,MAEA,EAAA,SAAA,YAAA,EAGA,EAAA,aAAA,EACA,EAAA,aAAA,GACA,OAAA,mBCtTA,SAAA,GACA,YASA,SAAA,GAAA,GACA,EAAA,KAAA,KAAA,GARA,GAAA,GAAA,EAAA,SAAA,YACA,EAAA,EAAA,MACA,EAAA,EAAA,gBACA,EAAA,EAAA,KAEA,EAAA,OAAA,iBAKA,GAAA,UAAA,OAAA,OAAA,EAAA,WAEA,EAAA,EAAA,WACA,WAAA,WACA,GAAA,GAAA,KAAA,KAAA,WAAA,MAAA,KAAA,KAAA,UACA,OAAA,IAAA,EAAA,MAIA,EAAA,EAAA,EACA,SAAA,cAAA,WAEA,EAAA,SAAA,kBAAA,GACA,OAAA,mBC1BA,SAAA,GACA,YAQA,SAAA,GAAA,GACA,EAAA,KAAA,KAAA,GAPA,GAAA,GAAA,EAAA,SAAA,YACA,EAAA,EAAA,MACA,EAAA,EAAA,gBAEA,EAAA,OAAA,kBAKA,GAAA,UAAA,OAAA,OAAA,EAAA,WACA,EAAA,EAAA,WACA,GAAA,UACA,MAAA,MAAA,aAAA,WAEA,GAAA,QAAA,GACA,KAAA,aAAA,SAAA,IAGA,aAAA,SAAA,EAAA,GACA,EAAA,UAAA,aAAA,KAAA,KAAA,EAAA,GACA,WAAA,OAAA,GAAA,eACA,KAAA,0BAAA,MAQA,GACA,EAAA,EAAA,GAEA,EAAA,SAAA,mBAAA,GACA,OAAA,mBCpCA,SAAA,GACA,YASA,SAAA,GAAA,GACA,EAAA,KAAA,KAAA,GAOA,QAAA,GAAA,EAAA,GACA,KAAA,eAAA,IACA,KAAA,IAAA,WACA,yDAGA,IAAA,GAAA,EAAA,SAAA,cAAA,OACA,GAAA,KAAA,KAAA,GACA,EAAA,EAAA,MAEA,SAAA,IACA,EAAA,MAAA,GACA,SAAA,IACA,EAAA,OAAA,GA5BA,GAAA,GAAA,EAAA,SAAA,YACA,EAAA,EAAA,gBACA,EAAA,EAAA,OACA,EAAA,EAAA,OAEA,EAAA,OAAA,gBAKA,GAAA,UAAA,OAAA,OAAA,EAAA,WAEA,EAAA,EAAA,EACA,SAAA,cAAA,QAkBA,EAAA,UAAA,EAAA,UAEA,EAAA,SAAA,iBAAA,EACA,EAAA,SAAA,MAAA,GACA,OAAA,mBCtCA,SAAA,GACA,YAQA,SAAA,GAAA,GACA,EAAA,KAAA,KAAA,GAPA,GAAA,GAAA,EAAA,SAAA,YACA,EAAA,EAAA,MACA,EAAA,EAAA,gBAEA,EAAA,OAAA,iBAKA,GAAA,UAAA,OAAA,OAAA,EAAA,WACA,EAAA,EAAA,cAIA,GACA,EAAA,EAAA,GAEA,EAAA,SAAA,kBAAA,GACA,OAAA,mBCrBA,SAAA,GACA,YAYA,SAAA,GAAA,GACA,IAAA,EAAA,YACA,MAAA,EACA,IAAA,GAAA,EAAA,IAAA,EACA,KAAA,EAAA,CAIA,IADA,EAAA,EAAA,eAAA,mBAAA,IACA,EAAA,WACA,EAAA,YAAA,EAAA,UAEA,GAAA,IAAA,EAAA,GAEA,MAAA,GAGA,QAAA,GAAA,GAKA,IAHA,GAEA,GAFA,EAAA,EAAA,EAAA,eACA,EAAA,EAAA,EAAA,0BAEA,EAAA,EAAA,YACA,EAAA,YAAA,EAEA,OAAA,GAKA,QAAA,GAAA,GAEA,GADA,EAAA,KAAA,KAAA,IACA,EAAA,CACA,GAAA,GAAA,EAAA,EACA,GAAA,IAAA,KAAA,EAAA,KA3CA,GAAA,GAAA,EAAA,SAAA,YACA,EAAA,EAAA,MACA,EAAA,EAAA,gBACA,EAAA,EAAA,OACA,EAAA,EAAA,KAEA,EAAA,GAAA,SACA,EAAA,GAAA,SA8BA,EAAA,OAAA,mBASA,GAAA,UAAA,OAAA,OAAA,EAAA,WAEA,EAAA,EAAA,WACA,GAAA,WACA,MAAA,GACA,EAAA,KAAA,KAAA,SACA,EAAA,IAAA,SAOA,GACA,EAAA,EAAA,GAEA,EAAA,SAAA,oBAAA,GACA,OAAA,mBClEA,SAAA,GACA,YAOA,SAAA,GAAA,GACA,EAAA,KAAA,KAAA,GANA,GAAA,GAAA,EAAA,SAAA,YACA,EAAA,EAAA,gBAEA,EAAA,OAAA,gBAKA,GAAA,UAAA,OAAA,OAAA,EAAA,WAEA,EAAA,EAAA,EACA,SAAA,cAAA,UAEA,EAAA,SAAA,iBAAA,GACA,OAAA,mBCjBA,SAAA,GACA,YASA,SAAA,GAAA,GACA,EAAA,KAAA,KAAA,GAOA,QAAA,GAAA,GACA,KAAA,eAAA,IACA,KAAA,IAAA,WACA,yDAGA,IAAA,GAAA,EAAA,SAAA,cAAA,SACA,GAAA,KAAA,KAAA,GACA,EAAA,EAAA,MAEA,EAAA,aAAA,UAAA,QACA,SAAA,GACA,EAAA,aAAA,MAAA,GA3BA,GAAA,GAAA,EAAA,SAAA,iBACA,EAAA,EAAA,gBACA,EAAA,EAAA,OACA,EAAA,EAAA,OAEA,EAAA,OAAA,gBAKA,GAAA,UAAA,OAAA,OAAA,EAAA,WAEA,EAAA,EAAA,EACA,SAAA,cAAA,UAiBA,EAAA,UAAA,EAAA,UAEA,EAAA,SAAA,iBAAA,EACA,EAAA,SAAA,MAAA,GACA,OAAA,mBCrCA,SAAA,GACA,YAWA,SAAA,GAAA,GACA,MAAA,GAAA,QAAA,OAAA,KAAA,OAGA,QAAA,GAAA,GACA,EAAA,KAAA,KAAA,GAkBA,QAAA,GAAA,EAAA,EAAA,EAAA,GACA,KAAA,eAAA,IACA,KAAA,IAAA,WACA,yDAGA,IAAA,GAAA,EAAA,SAAA,cAAA,UACA,GAAA,KAAA,KAAA,GACA,EAAA,EAAA,MAEA,SAAA,IACA,EAAA,KAAA,GACA,SAAA,GACA,EAAA,aAAA,QAAA,GACA,KAAA,GACA,EAAA,aAAA,WAAA,IACA,EAAA,SAAA,KAAA,EAhDA,GAAA,GAAA,EAAA,SAAA,YACA,EAAA,EAAA,MACA,EAAA,EAAA,gBACA,EAAA,EAAA,OACA,EAAA,EAAA,OACA,EAAA,EAAA,KAEA,EAAA,OAAA,iBASA,GAAA,UAAA,OAAA,OAAA,EAAA,WACA,EAAA,EAAA,WACA,GAAA,QACA,MAAA,GAAA,KAAA,cAEA,GAAA,MAAA,GACA,KAAA,YAAA,EAAA,OAAA,KAEA,GAAA,QACA,MAAA,GAAA,EAAA,MAAA,SAIA,EAAA,EAAA,EACA,SAAA,cAAA,WAqBA,EAAA,UAAA,EAAA,UAEA,EAAA,SAAA,kBAAA,EACA,EAAA,SAAA,OAAA,GACA,OAAA,mBC1DA,SAAA,GACA,YAUA,SAAA,GAAA,GACA,EAAA,KAAA,KAAA,GATA,GAAA,GAAA,EAAA,SAAA,YACA,EAAA,EAAA,MACA,EAAA,EAAA,gBACA,EAAA,EAAA,OACA,EAAA,EAAA,KAEA,EAAA,OAAA,iBAKA,GAAA,UAAA,OAAA,OAAA,EAAA,WACA,EAAA,EAAA,WACA,IAAA,SAAA,EAAA,GACA,gBAAA,KACA,EAAA,EAAA,IACA,EAAA,MAAA,IAAA,EAAA,GAAA,IAGA,OAAA,SAAA,GAGA,MAAA,UAAA,MACA,GAAA,UAAA,OAAA,KAAA,OAIA,gBAAA,KACA,EAAA,EAAA,QAEA,GAAA,MAAA,OAAA,KAGA,GAAA,QACA,MAAA,GAAA,EAAA,MAAA,SAIA,EAAA,EAAA,EACA,SAAA,cAAA,WAEA,EAAA,SAAA,kBAAA,GACA,OAAA,mBC3CA,SAAA,GACA,YAWA,SAAA,GAAA,GACA,EAAA,KAAA,KAAA,GAVA,GAAA,GAAA,EAAA,SAAA,YACA,EAAA,EAAA,MACA,EAAA,EAAA,gBACA,EAAA,EAAA,OACA,EAAA,EAAA,KACA,EAAA,EAAA,mBAEA,EAAA,OAAA,gBAKA,GAAA,UAAA,OAAA,OAAA,EAAA,WACA,EAAA,EAAA,WACA,GAAA,WACA,MAAA,GAAA,EAAA,MAAA,UAEA,cAAA,WACA,MAAA,GAAA,EAAA,MAAA,kBAGA,GAAA,SACA,MAAA,GAAA,EAAA,MAAA,QAEA,YAAA,WACA,MAAA,GAAA,EAAA,MAAA,gBAGA,YAAA,WACA,MAAA,GAAA,EAAA,MAAA,gBAEA,GAAA,SACA,MAAA,GAAA,EAAA,MAAA,QAGA,GAAA,WACA,MAAA,GAAA,EAAA,MAAA,UAEA,YAAA,WACA,MAAA,GAAA,EAAA,MAAA,gBAGA,GAAA,QACA,MAAA,GAAA,EAAA,MAAA,OAEA,UAAA,SAAA,GACA,MAAA,GAAA,EAAA,MAAA,UAAA,OAIA,EAAA,EAAA,EACA,SAAA,cAAA,UAEA,EAAA,SAAA,iBAAA,GACA,OAAA,mBCzDA,SAAA,GACA,YAWA,SAAA,GAAA,GACA,EAAA,KAAA,KAAA,GAVA,GAAA,GAAA,EAAA,SAAA,YACA,EAAA,EAAA,MACA,EAAA,EAAA,gBACA,EAAA,EAAA,mBACA,EAAA,EAAA,OACA,EAAA,EAAA,KAEA,EAAA,OAAA,uBAKA,GAAA,UAAA,OAAA,OAAA,EAAA,WACA,EAAA,EAAA,WACA,GAAA,QACA,MAAA,GAAA,EAAA,MAAA,OAEA,UAAA,SAAA,GACA,MAAA,GAAA,EAAA,MAAA,UAAA,OAIA,EAAA,EAAA,EACA,SAAA,cAAA,UAEA,EAAA,SAAA,wBAAA,GACA,OAAA,mBC7BA,SAAA,GACA,YAWA,SAAA,GAAA,GACA,EAAA,KAAA,KAAA,GAVA,GAAA,GAAA,EAAA,SAAA,YACA,EAAA,EAAA,MACA,EAAA,EAAA,gBACA,EAAA,EAAA,mBACA,EAAA,EAAA,OACA,EAAA,EAAA,KAEA,EAAA,OAAA,mBAKA,GAAA,UAAA,OAAA,OAAA,EAAA,WACA,EAAA,EAAA,WACA,GAAA,SACA,MAAA,GAAA,EAAA,MAAA,QAGA,WAAA,SAAA,GACA,MAAA,GAAA,EAAA,MAAA,WAAA,OAIA,EAAA,EAAA,EACA,SAAA,cAAA,OAEA,EAAA,SAAA,oBAAA,GACA,OAAA,mBChCA,SAAA,GACA,YAWA,SAAA,GAAA,GACA,OAAA,EAAA,WACA,IAAA,UACA,MAAA,IAAA,GAAA,EACA,KAAA,SACA,MAAA,IAAA,GAAA,EACA,KAAA,WACA,MAAA,IAAA,GAAA,GAEA,EAAA,KAAA,KAAA,GAlBA,GAAA,GAAA,EAAA,SAAA,mBACA,EAAA,EAAA,SAAA,YACA,EAAA,EAAA,SAAA,kBACA,EAAA,EAAA,SAAA,oBAEA,GADA,EAAA,MACA,EAAA,iBAEA,EAAA,OAAA,kBAaA,GAAA,UAAA,OAAA,OAAA,EAAA,WACA,EAAA,EAAA,GACA,EAAA,SAAA,mBAAA,GACA,OAAA,mBC1BA,SAAA,GACA,YAEA,IAAA,GAAA,EAAA,eAEA,EAAA,6BACA,EAAA,SAAA,gBAAA,EAAA,SACA,EAAA,EAAA,GACA,EAAA,OAAA,eAAA,EAAA,WAAA,WAEA,GAAA,SAAA,WAAA,GACA,OAAA,mBCXA,SAAA,GACA,YAmBA,SAAA,GAAA,GACA,EAAA,KAAA,KAAA,GAlBA,GAAA,GAAA,EAAA,MACA,EAAA,EAAA,gBACA,EAAA,EAAA,OACA,EAAA,EAAA,KAEA,EAAA,OAAA,cAKA,EAAA,6BACA,EAAA,EAAA,SAAA,gBAAA,EAAA,MACA,EAAA,SAAA,gBAAA,EAAA,OACA,EAAA,EAAA,YACA,EAAA,OAAA,eAAA,EAAA,WACA,EAAA,EAAA,WAMA,GAAA,UAAA,OAAA,OAAA,GAGA,gBAAA,IACA,EAAA,EAAA,WACA,GAAA,gBACA,MAAA,GAAA,EAAA,MAAA,eAEA,GAAA,wBACA,MAAA,GAAA,EAAA,MAAA,yBAKA,EAAA,EAAA,EAAA,GAEA,EAAA,SAAA,cAAA,GACA,OAAA,mBCzCA,SAAA,GACA,YAWA,SAAA,GAAA,GACA,EAAA,KAAA,KAAA,GAVA,GAAA,GAAA,EAAA,SAAA,YACA,EAAA,EAAA,MACA,EAAA,EAAA,gBACA,EAAA,EAAA,KAEA,EAAA,OAAA,kBACA,KAOA,EAAA,UAAA,OAAA,OAAA,EAAA,WACA,EAAA,EAAA,WAEA,GAAA,wBACA,MAAA,GAAA,KAAA,KAAA,uBAIA,GAAA,2BACA,MAAA,GAAA,KAAA,KAAA,0BAIA,GAAA,cACA,MAAA,GAAA,KAAA,KAAA,aAIA,GAAA,cACA,KAAA,IAAA,OAAA,oBAIA,GAAA,cACA,MAAA,GAAA,KAAA,KAAA,aAIA,GAAA,aACA,MAAA,GAAA,KAAA,KAAA,YAIA,GAAA,mBACA,MAAA,GAAA,KAAA,KAAA,kBAIA,GAAA,eACA,MAAA,GAAA,KAAA,KAAA,gBAIA,EAAA,EAAA,GAEA,EAAA,SAAA,mBAAA,IACA,OAAA,mBC9DA,SAAA,GACA,YAUA,SAAA,GAAA,GACA,KAAA,KAAA,EATA,GAAA,GAAA,EAAA,MACA,EAAA,EAAA,gBACA,EAAA,EAAA,OACA,EAAA,EAAA,eACA,EAAA,EAAA,KAEA,EAAA,OAAA,wBAMA,GAAA,EAAA,WACA,GAAA,UACA,MAAA,GAAA,KAAA,KAAA,SAGA,UAAA,WACA,UAAA,GAAA,EAAA,UAAA,IACA,KAAA,KAAA,UAAA,MAAA,KAAA,KAAA,YAGA,cAAA,WAEA,MADA,WAAA,GAAA,EAAA,UAAA,IACA,KAAA,KAAA,cAAA,MAAA,KAAA,KAAA,cAIA,EAAA,EAAA,EACA,SAAA,cAAA,UAAA,WAAA,OAEA,EAAA,SAAA,yBAAA,GACA,OAAA,mBCnCA,SAAA,GACA,YAaA,SAAA,GAAA,GACA,KAAA,KAAA,EAZA,GAAA,GAAA,EAAA,MACA,EAAA,EAAA,gBACA,EAAA,EAAA,eACA,EAAA,EAAA,KAEA,EAAA,OAAA,qBAGA,IAAA,EAAA,CAOA,EAAA,EAAA,WACA,GAAA,UACA,MAAA,GAAA,KAAA,KAAA,SAGA,WAAA,WACA,UAAA,GAAA,EAAA,UAAA,IACA,KAAA,KAAA,WAAA,MAAA,KAAA,KAAA,YAGA,cAAA,WACA,UAAA,GAAA,EAAA,UAAA,IACA,KAAA,KAAA,cAAA,MAAA,KAAA,KAAA,aAQA,IAAA,GAAA,SAAA,KAAA,UAAA,YACA,oBAAA,KAAA,mBAAA,QAEA,GAAA,EAAA,EACA,GAEA,EAAA,SAAA,sBAAA,IACA,OAAA,mBC7CA,SAAA,GACA,YASA,SAAA,GAAA,GACA,KAAA,KAAA,EARA,GAAA,GAAA,EAAA,gBACA,EAAA,EAAA,OACA,EAAA,EAAA,eACA,EAAA,EAAA,KAEA,EAAA,OAAA,KAKA,GAAA,WACA,GAAA,kBACA,MAAA,GAAA,KAAA,KAAA,iBAEA,GAAA,gBACA,MAAA,GAAA,KAAA,KAAA,eAEA,GAAA,2BACA,MAAA,GAAA,KAAA,KAAA,0BAEA,SAAA,SAAA,EAAA,GACA,KAAA,KAAA,SAAA,EAAA,GAAA,IAEA,OAAA,SAAA,EAAA,GACA,KAAA,KAAA,OAAA,EAAA,GAAA,IAEA,eAAA,SAAA,GACA,KAAA,KAAA,eAAA,EAAA,KAEA,cAAA,SAAA,GACA,KAAA,KAAA,cAAA,EAAA,KAEA,aAAA,SAAA,GACA,KAAA,KAAA,aAAA,EAAA,KAEA,YAAA,SAAA,GACA,KAAA,KAAA,YAAA,EAAA,KAEA,WAAA,SAAA,GACA,KAAA,KAAA,WAAA,EAAA,KAEA,mBAAA,SAAA,GACA,KAAA,KAAA,mBAAA,EAAA,KAEA,sBAAA,SAAA,EAAA,GACA,MAAA,MAAA,KAAA,sBAAA,EAAA,EAAA,KAEA,gBAAA,WACA,MAAA,GAAA,KAAA,KAAA,oBAEA,cAAA,WACA,MAAA,GAAA,KAAA,KAAA,kBAEA,WAAA,SAAA,GACA,KAAA,KAAA,WAAA,EAAA,KAEA,iBAAA,SAAA,GACA,KAAA,KAAA,iBAAA,EAAA,KAEA,WAAA,WACA,MAAA,GAAA,KAAA,KAAA,eAEA,eAAA,SAAA,EAAA,GACA,MAAA,MAAA,KAAA,eAAA,EAAA,GAAA,IAEA,aAAA,SAAA,EAAA,GACA,MAAA,MAAA,KAAA,aAAA,EAAA,GAAA,IAEA,eAAA,SAAA,GACA,MAAA,MAAA,KAAA,eAAA,EAAA,KAEA,SAAA,WACA,MAAA,MAAA,KAAA,aAKA,EAAA,UAAA,2BACA,EAAA,UAAA,yBAAA,SAAA,GACA,MAAA,GAAA,KAAA,KAAA,yBAAA;GAIA,EAAA,OAAA,MAAA,EAAA,SAAA,eAEA,EAAA,SAAA,MAAA,GAEA,OAAA,mBC1FA,SAAA,GACA,YAEA,IAAA,GAAA,EAAA,uBACA,EAAA,EAAA,oBACA,EAAA,EAAA,mBACA,EAAA,EAAA,MACA,EAAA,EAAA,eAEA,EAAA,EAAA,SAAA,yBACA,GAAA,EAAA,UAAA,GACA,EAAA,EAAA,UAAA,GACA,EAAA,EAAA,UAAA,EAEA,IAAA,GAAA,EAAA,SAAA,cAAA,IAEA,GAAA,SAAA,QAAA,EACA,EAAA,SAAA,iBAAA,GAEA,OAAA,mBCnBA,SAAA,GACA,YAiBA,SAAA,GAAA,GACA,GAAA,GAAA,EAAA,EAAA,KAAA,cAAA,yBACA,GAAA,KAAA,KAAA,GAIA,EAAA,EAAA,MAEA,KAAA,WAAA,GAAA,GAAA,KAAA,EAAA,GAEA,IAAA,GAAA,EAAA,UACA,GAAA,IAAA,KAAA,GAEA,EAAA,IAAA,KAAA,GA5BA,GAAA,GAAA,EAAA,SAAA,iBACA,EAAA,EAAA,UACA,EAAA,EAAA,iBACA,EAAA,EAAA,aACA,EAAA,EAAA,aACA,EAAA,EAAA,MACA,EAAA,EAAA,OACA,EAAA,EAAA,aACA,EAAA,EAAA,OAEA,EAAA,GAAA,SACA,EAAA,GAAA,SAEA,EAAA,aAiBA,GAAA,UAAA,OAAA,OAAA,EAAA,WACA,EAAA,EAAA,WACA,GAAA,aACA,MAAA,GAAA,OAEA,GAAA,WAAA,GACA,EAAA,KAAA,GACA,KAAA,4BAGA,GAAA,mBACA,MAAA,GAAA,IAAA,OAAA,MAGA,GAAA,QACA,MAAA,GAAA,IAAA,OAAA,MAGA,yBAAA,WACA,MAAA,GAAA,IAAA,MAAA,4BAGA,iBAAA,SAAA,EAAA,GACA,MAAA,GAAA,KAAA,KAAA,cAAA,EAAA,IAGA,eAAA,SAAA,GACA,MAAA,GAAA,KAAA,GACA,KACA,KAAA,cAAA,QAAA,EAAA,SAIA,EAAA,SAAA,WAAA,GAEA,OAAA,mBCpEA,SAAA,GACA,YAoBA,SAAA,GAAA,GACA,EAAA,iBAAA,EAAA,gBACA,EAAA,aAAA,EAAA,YACA,EAAA,YAAA,EAAA,WAuBA,QAAA,GAAA,EAAA,EAAA,GACA,GAAA,GAAA,EAAA,GACA,EAAA,EAAA,GACA,EAAA,EAAA,EAAA,GAAA,IAKA,IAHA,EAAA,GACA,EAAA,GAEA,EASA,EAAA,aAAA,IACA,EAAA,YAAA,GAEA,EAAA,iBAAA,EAAA,oBAZA,CACA,EAAA,WAAA,EAAA,UACA,EAAA,YAAA,EAAA,aACA,EAAA,YAAA,EAAA,WAEA,IAAA,GAAA,EAAA,EAAA,UACA,KACA,EAAA,aAAA,EAAA,aAQA,EAAA,aAAA,EAAA,GAGA,QAAA,GAAA,GACA,GAAA,GAAA,EAAA,GACA,EAAA,EAAA,UACA,IAAA,EAAA,CAGA,GAAA,GAAA,EAAA,EACA,GAAA,GAEA,EAAA,kBACA,EAAA,gBAAA,aAAA,GACA,EAAA,cACA,EAAA,YAAA,iBAAA,GAEA,EAAA,YAAA,IACA,EAAA,WAAA,GACA,EAAA,aAAA,IACA,EAAA,YAAA,GAEA,EAAA,YAAA,IAQA,QAAA,GAAA,EAAA,GACA,EAAA,GAAA,KAAA,GACA,EAAA,EAAA,EAEA,IAAA,GAAA,EAAA,IAAA,EACA,IACA,EAAA,IAAA,EAAA,MACA,EAAA,KAAA,GAGA,QAAA,GAAA,GACA,EAAA,IAAA,MAGA,QAAA,GAAA,GACA,GAAA,GAAA,EAAA,IAAA,EAGA,OAFA,IACA,EAAA,IAAA,EAAA,MACA,EAGA,QAAA,GAAA,GAEA,IAAA,GADA,MAAA,EAAA,EACA,EAAA,EAAA,WAAA,EAAA,EAAA,EAAA,YACA,EAAA,KAAA,CAEA,OAAA,GAUA,QAAA,GAAA,EAAA,EAAA,GAEA,IAAA,GAAA,GAAA,EAAA,WAAA,EAAA,EAAA,EAAA,YACA,GAAA,EAAA,IACA,GAAA,EAAA,MAAA,EACA,WAEA,GAAA,EAAA,EAAA,GAoCA,QAAA,GAAA,EAAA,GACA,GAAA,GAAA,EAAA,aAAA,SACA,KAAA,EACA,OAAA,CAIA,IADA,EAAA,EAAA,QACA,EACA,OAAA,CAEA,MAAA,YAAA,IACA,OAAA,CAMA,IAAA,MAAA,GAAA,IAAA,EAAA,UACA,OAAA,CAGA,KAAA,EAAA,KAAA,GACA,OAAA,CAGA,IAAA,MAAA,EAAA,KAAA,EAAA,KAAA,GACA,OAAA,CAEA,KACA,MAAA,GAAA,QAAA,GACA,MAAA,GAEA,OAAA,GAcA,QAAA,KAGA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,GACA,EAAA,EAAA,cACA,IAAA,EAAA,OAEA,EAAA,SAGA,KAGA,QAAA,KACA,EAAA,KACA,IAQA,QAAA,GAAA,GACA,GAAA,GAAA,EAAA,IAAA,EAKA,OAJA,KACA,EAAA,GAAA,GAAA,GACA,EAAA,IAAA,EAAA,IAEA,EAGA,QAAA,GAAA,GACA,GAAA,GAAA,EAAA,GAAA,IACA,OAAA,aAAA,GACA,EACA,KAGA,QAAA,GAAA,GACA,MAAA,GAAA,EAAA,MAaA,QAAA,GAAA,GACA,KAAA,MAAA,EACA,KAAA,KAAA,EACA,KAAA,cA8DA,QAAA,GAAA,GACA,KAAA,KAAA,EACA,KAAA,OAAA,EACA,KAAA,uBACA,KAAA,cAAA,GAoOA,QAAA,GAAA,GAEA,MAAA,aAAA,GAGA,QAAA,GAAA,GAEA,MAAA,aAAA,GAGA,QAAA,GAAA,GACA,MAAA,aAAA,GAGA,QAAA,GAAA,GAEA,MAAA,aAAA,GAGA,QAAA,GAAA,GACA,MAAA,GAAA,WAGA,QAAA,GAAA,GAGA,IAAA,GAFA,MAEA,EAAA,EAAA,WAAA,EAAA,EAAA,EAAA,gBACA,EAAA,KAAA,EAEA,OAAA,GAGA,QAAA,GAAA,EAAA,GACA,EAAA,IAAA,EAAA,GA9lBA,GA4NA,GA5NA,EAAA,EAAA,SAAA,QACA,EAAA,EAAA,SAAA,mBACA,EAAA,EAAA,SAAA,kBACA,EAAA,EAAA,SAAA,KACA,EAAA,EAAA,SAAA,WAEA,GADA,EAAA,OACA,EAAA,cAEA,GADA,EAAA,MACA,EAAA,OACA,EAAA,EAAA,OACA,EAAA,EAAA,KAkFA,EAAA,GAAA,SACA,EAAA,GAAA,SACA,EAAA,GAAA,SACA,EAAA,GAAA,SAsDA,EAAA,mBAEA,EAAA,GAAA,QAAA,OACA,OACA,UACA,SACA,UACA,WACA,UACA,gBACA,YACA,iBACA,cACA,mBACA,cACA,aACA,gBACA,eACA,gBACA,KAAA,KAAA,KA4CA,EAAA,EAAA,QACA,wBACA,2BACA,8BACA,eAGA,KA+CA,EAAA,GAAA,YACA,GAAA,OAAA,SAAA,EAAA,GACA,MAAA,GAAA,EAAA,QAAA,GAcA,EAAA,WACA,OAAA,SAAA,GACA,GAAA,GAAA,GAAA,GAAA,EAEA,OADA,MAAA,WAAA,KAAA,GACA,GAGA,KAAA,SAAA,GACA,IAAA,KAAA,KAAA,CAcA,IAAA,GAXA,GAAA,KAAA,KAEA,EAAA,KAAA,WAEA,EAAA,EAAA,EAAA,IACA,EAAA,GAAA,GAAA,SAEA,EAAA,EAAA,iBAAA,EAAA,GAEA,EAAA,EAAA,EAAA,EACA,EAAA,EACA,EAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CAEA,IADA,GAAA,GAAA,EAAA,GACA,EAAA,EAAA,MAAA,IACA,IACA,EAAA,KAAA,KAAA,EAIA,KAAA,GADA,GAAA,EAAA,QAAA,OACA,EAAA,EAAA,EAAA,EAAA,IAAA,CACA,GAAA,GAAA,EAAA,EAAA,KACA,GAAA,IAAA,IACA,EAAA,GAKA,IAAA,GAFA,GAAA,EAAA,WACA,EAAA,EAAA,IAAA,EAAA,EAAA,IACA,EAAA,EAAA,EAAA,EAAA,IAAA,CACA,GAAA,GAAA,EAAA,KACA,EAAA,EAAA,IACA,GAAA,EAAA,EAAA,GAIA,EAAA,IAAA,GAAA,GAEA,EAAA,KAAA,GAGA,GAAA,EAGA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,GAAA,KAAA,MAYA,EAAA,WAGA,OAAA,SAAA,GACA,GAAA,KAAA,MAAA,CAGA,KAAA,uBACA,KAAA,iBAEA,IAAA,GAAA,KAAA,KACA,EAAA,EAAA,UAEA,MAAA,cAAA,EAIA,KAAA,GAHA,IAAA,EACA,EAAA,GAAA,GAAA,GAAA,GAEA,EAAA,EAAA,WAAA,EAAA,EAAA,EAAA,YACA,KAAA,WAAA,EAAA,EAAA,GAAA,EAGA,IACA,EAAA,OAEA,KAAA,OAAA,IAGA,GAAA,kBACA,MAAA,GAAA,KAAA,MAAA,UAGA,WAAA,WACA,IAAA,KAAA,MAAA,CAGA,GAFA,KAAA,OAAA,EACA,EAAA,KAAA,MACA,EACA,MACA,GAAA,OAAA,GAAA,EAAA,KAIA,WAAA,SAAA,EAAA,EAAA,EAAA,GACA,GAAA,EAAA,GAAA,CACA,EAAA,EAAA,OAAA,EACA,IAAA,GAAA,EAAA,EACA,GAAA,OAAA,EACA,EAAA,OAAA,OACA,GAAA,GACA,KAAA,qBAAA,EAAA,EAAA,EAAA,GACA,EAAA,GACA,KAAA,2BAAA,EAAA,EAAA,GAEA,KAAA,mBAAA,EAAA,EAAA,EAAA,IAIA,mBAAA,SAAA,EAAA,EAAA,EAAA,GAGA,GAFA,EAAA,EAAA,OAAA,GAEA,EAAA,GAAA,CACA,GAAA,GAAA,EAAA,EACA,GAAA,MAAA,EAAA,MACA,EAAA,OAAA,OAEA,KAAA,GAAA,GAAA,EAAA,WAAA,EAAA,EAAA,EAAA,YACA,KAAA,WAAA,EAAA,EAAA,EAAA,IAKA,qBAAA,SAAA,EAAA,EAAA,EACA,GACA,GAAA,GAAA,EAAA,EACA,IAAA,EAAA,OAAA,CACA,KAAA,cAAA,EAEA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,EACA,GAAA,IAAA,EACA,KAAA,qBAAA,EAAA,EAAA,EAAA,GAEA,KAAA,mBAAA,EAAA,EAAA,EAAA,QAGA,MAAA,sBAAA,EAAA,EAAA,EAEA,MAAA,cAAA,EAAA,aAGA,2BAAA,SAAA,EAAA,EACA,GACA,GAAA,GAAA,EAAA,eACA,IAAA,EAAA,CACA,EAAA,EAAA,GACA,KAAA,cAAA,EAAA,WACA,KAAA,GAAA,GAAA,EAAA,WACA,EACA,EAAA,EAAA,YACA,KAAA,WAAA,EAAA,EAAA,GAAA,OAGA,MAAA,sBAAA,EAAA,EACA,IAIA,sBAAA,SAAA,EAAA,EAAA,GACA,KAAA,cAAA,GACA,KAAA,cAAA,EAAA,WACA,KAAA,GAAA,GAAA,EAAA,WAAA,EAAA,EAAA,EAAA,YACA,KAAA,mBAAA,EAAA,EAAA,GAAA,IAQA,qBAAA,WACA,KAAA,WAAA,OAAA,OAAA,OAQA,0BAAA,SAAA,GACA,GAAA,EAAA,CAGA,GAAA,GAAA,KAAA,UAGA,SAAA,KAAA,KACA,EAAA,UAAA,GAGA,OAAA,KAAA,KACA,EAAA,IAAA,GAEA,EAAA,QAAA,uBAAA,SAAA,EAAA,GACA,EAAA,IAAA,MAMA,mBAAA,SAAA,GACA,MAAA,MAAA,WAAA,IAIA,WAAA,SAAA,EAAA,GACA,GAAA,GAAA,IAEA,GAAA,EAAA,EACA,SAAA,GACA,EAAA,GACA,EAAA,0BACA,EAAA,aAAA,UAEA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,EACA,UAAA,GAEA,EAAA,EAAA,KACA,EAAA,EAAA,GACA,EAAA,GAAA,YAOA,gBAAA,WAKA,IAAA,GAJA,GAAA,KAAA,KACA,EAAA,EAAA,WACA,KAEA,EAAA,EAAA,WACA,EACA,EAAA,EAAA,YACA,GAAA,EAAA,GAAA,CACA,GAAA,GAAA,EAAA,EAEA,IAAA,EAAA,SACA,EAAA,EAAA,IACA,EAAA,KAAA,MAAA,EAAA,OAEA,GAAA,KAAA,EAKA,KADA,GAAA,GAAA,EACA,GAAA,CAUA,GARA,EAAA,OACA,EAAA,EAAA,EAAA,SAAA,GAEA,MADA,GAAA,GACA,IAEA,EAAA,EAEA,KAAA,WAAA,EAAA,GACA,EAAA,CACA,GAAA,GAAA,EAAA,eACA,IAAA,EAEA,CACA,EAAA,EACA,EAAA,EAAA,EACA,UAJA,MAOA,QAKA,cAAA,SAAA,GACA,EAAA,KAAA,uBAAA,OA0DA,EAAA,UAAA,yBAAA,WACA,GAAA,GAAA,KAAA,KAAA,sBACA,OAAA,IACA,EAAA,cACA,IAGA,GAGA,EAAA,UAAA,oBAAA,WAIA,MADA,KACA,EAAA,OAGA,EAAA,UAAA,gBACA,EAAA,UAAA,gBAAA,WAEA,KAAA,0BAEA,IACA,GADA,EAAA,EAAA,KAEA,KACA,EAAA,EAAA,IACA,KAAA,KAAA,uBAAA,EACA,GACA,EAAA,cAGA,EAAA,kBAAA,EACA,EAAA,mBAAA,EACA,EAAA,eAAA,EACA,EAAA,qBAAA,EACA,EAAA,iBAAA,EAGA,EAAA,QACA,aAAA,EACA,OAAA,IAGA,OAAA,mBCjqBA,SAAA,GACA,YAuBA,SAAA,GAAA,GACA,GAAA,OAAA,GAAA,CAIA,GAAA,EAAA,SAAA,GAEA,IAAA,GAAA,SAAA,GAEA,EAAA,KAAA,KAAA,GAEA,GAAA,UAAA,OAAA,OAAA,EAAA,WACA,EAAA,EAAA,WACA,GAAA,QACA,MAAA,GAAA,EAAA,MAAA,SAIA,EAAA,OAAA,GAAA,EACA,SAAA,cAAA,EAAA,MAAA,EAAA,MACA,EAAA,SAAA,GAAA,GAzCA,GAAA,GAAA,EAAA,SAAA,YACA,EAAA,EAAA,OACA,EAAA,EAAA,MACA,EAAA,EAAA,gBACA,EAAA,EAAA,OACA,EAAA,EAAA,KAEA,GACA,oBACA,sBACA,mBACA,oBACA,mBACA,oBACA,oBAEA,oBAEA,sBA0BA,GAAA,QAAA,IAEA,OAAA,mBCjDA,SAAA,GACA,YASA,SAAA,GAAA,GACA,KAAA,KAAA,EARA,CAAA,GAAA,GAAA,EAAA,gBACA,EAAA,EAAA,OACA,EAAA,EAAA,eACA,EAAA,EAAA,IAEA,QAAA,UAKA,EAAA,WACA,GAAA,cACA,MAAA,GAAA,KAAA,KAAA,aAEA,GAAA,aACA,MAAA,GAAA,KAAA,KAAA,YAEA,SAAA,SAAA,GACA,KAAA,KAAA,SAAA,EAAA,KAEA,SAAA,SAAA,EAAA,GACA,KAAA,KAAA,SAAA,EAAA,GAAA,IAEA,aAAA,SAAA,EAAA,GACA,MAAA,MAAA,KAAA,aAAA,EAAA,GAAA,IAEA,OAAA,SAAA,EAAA,GACA,KAAA,KAAA,OAAA,EAAA,GAAA,IAEA,WAAA,SAAA,GACA,MAAA,GAAA,KAAA,KAAA,WAAA,KAEA,YAAA,SAAA,GACA,KAAA,KAAA,YAAA,EAAA,KAEA,kBAAA,SAAA,GACA,KAAA,KAAA,kBAAA,EAAA,KAEA,SAAA,WACA,MAAA,MAAA,KAAA,aAgBA,EAAA,OAAA,UAAA,EAAA,OAAA,gBAEA,EAAA,SAAA,UAAA,GAEA,OAAA,mBC9DA,SAAA,GACA,YAyBA,SAAA,GAAA,GACA,EAAA,KAAA,KAAA,GACA,KAAA,WAAA,GAAA,GAAA,KAAA,MAcA,QAAA,GAAA,GACA,GAAA,GAAA,SAAA,EACA,GAAA,UAAA,GAAA,WACA,MAAA,GAAA,EAAA,MAAA,KAAA,KAAA,aAkBA,QAAA,GAAA,EAAA,GACA,EAAA,KAAA,EAAA,KAAA,EAAA,IACA,EAAA,EAAA,GAGA,QAAA,GAAA,EAAA,GACA,EAAA,YACA,EAAA,UAAA,EAAA,YACA,YAAA,IACA,EAAA,EAAA,EACA,KAAA,GAAA,GAAA,EAAA,WAAA,EAAA,EAAA,EAAA,YACA,EAAA,EAAA,GAIA,QAAA,GAAA,EAAA,GACA,GAAA,GAAA,EAAA,eACA,IACA,EAAA,UAAA,GAsMA,QAAA,GAAA,GACA,KAAA,KAAA,EAGA,QAAA,GAAA,EAAA,GACA,GAAA,GAAA,SAAA,eAAA,EACA,GAAA,UAAA,GAAA,WACA,MAAA,GAAA,EAAA,MAAA,KAAA,KAAA,aAIA,QAAA,GAAA,EAAA,GACA,GAAA,GAAA,SAAA,eAAA,EACA,GAAA,UAAA,GAAA,WACA,MAAA,GAAA,MAAA,KAAA,KAAA,YAlSA,GAAA,GAAA,EAAA,uBACA,EAAA,EAAA,SAAA,KACA,EAAA,EAAA,oBACA,EAAA,EAAA,SAAA,UACA,EAAA,EAAA,mBACA,EAAA,EAAA,SAAA,WACA,EAAA,EAAA,UACA,EAAA,EAAA,UACA,EAAA,EAAA,iBACA,EAAA,EAAA,iBACA,EAAA,EAAA,wBACA,EAAA,EAAA,aACA,EAAA,EAAA,MACA,EAAA,EAAA,gBACA,EAAA,EAAA,iBACA,EAAA,EAAA,OACA,EAAA,EAAA,OACA,EAAA,EAAA,KACA,EAAA,EAAA,uBAGA,GAFA,EAAA,aAEA,GAAA,SAMA,GAAA,UAAA,OAAA,OAAA,EAAA,WAEA,EAAA,EAAA,mBAIA,EAAA,EAAA,QACA,EAAA,EAAA,SAaA,gBACA,yBACA,gBACA,kBACA,cACA,gBACA,cACA,iBACA,kBACA,QAAA,EAEA,IAAA,GAAA,SAAA,UAuBA,EAAA,SAAA,YAqBA,IAnBA,EAAA,EAAA,WACA,UAAA,SAAA,GAIA,MAHA,GAAA,YACA,EAAA,WAAA,YAAA,GACA,EAAA,EAAA,MACA,GAEA,iBAAA,SAAA,EAAA,GACA,MAAA,GAAA,KAAA,KAAA,EAAA,IAEA,WAAA,SAAA,EAAA,GACA,MAAA,GAAA,EAAA,EAAA,KAAA,OAEA,aAAA,WAEA,MADA,KACA,GAAA,GAAA,EAAA,KAAA,EAAA,WAIA,SAAA,gBAAA,CACA,GAAA,GAAA,SAAA,eACA,GAAA,UAAA,gBAAA,SAAA,EAAA,GAyEA,QAAA,GAAA,GACA,MAAA,QAOA,KAAA,KAAA,GANA,EACA,SAAA,cAAA,EAAA,GAEA,SAAA,cAAA,GA7EA,GAAA,GAAA,CAYA,IAXA,SAAA,IACA,EAAA,EAAA,UACA,EAAA,EAAA,SAGA,IACA,EAAA,OAAA,OAAA,YAAA,YAKA,EAAA,qBAAA,IAAA,GAEA,KAAA,IAAA,OAAA,oBASA,KAHA,GACA,GADA,EAAA,OAAA,eAAA,GAEA,KACA,KACA,EAAA,EAAA,qBAAA,IAAA,KAGA,EAAA,KAAA,GACA,EAAA,OAAA,eAAA,EAGA,KAAA,EAEA,KAAA,IAAA,OAAA,oBAQA,KAAA,GADA,GAAA,OAAA,OAAA,GACA,EAAA,EAAA,OAAA,EAAA,GAAA,EAAA,IACA,EAAA,OAAA,OAAA,IAQA,kBACA,mBACA,mBACA,4BACA,QAAA,SAAA,GACA,GAAA,GAAA,EAAA,EACA,KAEA,EAAA,GAAA,WAGA,EAAA,eAAA,IACA,EAAA,MAEA,EAAA,MAAA,EAAA,MAAA,cAIA,IAAA,IAAA,UAAA,EACA,KACA,EAAA,QAAA,GAYA,EAAA,UAAA,EACA,EAAA,UAAA,YAAA,EAEA,EAAA,iBAAA,IAAA,EAAA,GACA,EAAA,qBAAA,IAAA,EAAA,EAGA,GAAA,KAAA,EAAA,MACA,EAAA,EACA,OAAA,IAGA,GACA,OAAA,cAAA,OAAA,WAEA,oBAMA,GACA,OAAA,gBACA,OAAA,cAAA,OAAA,SACA,OAAA,gBACA,OAAA,kBAEA,cACA,0BACA,WACA,yBACA,uBACA,yBACA,eACA,gBACA,mBACA,cACA,gBACA,OAAA,IAEA,GACA,OAAA,cAAA,OAAA,WAEA,YACA,aACA,WACA,gBACA,yBACA,gBACA,kBACA,cACA,gBACA,cACA,iBACA,mBACA,iBACA,iBAGA,EAAA,EAAA,UAAA,GACA,EAAA,EAAA,UAAA,GACA,EAAA,EAAA,UAAA,GAEA,EAAA,EAAA,WACA,GAAA,kBACA,GAAA,GAAA,EAAA,IAAA,KACA,OAAA,GACA,GACA,EACA,GAAA,GAAA,EAAA,MAAA,gBACA,EAAA,IAAA,KAAA,GACA,MAIA,EAAA,OAAA,SAAA,EACA,SAAA,eAAA,mBAAA,KAIA,OAAA,cACA,EAAA,OAAA,aAAA,GAEA,GACA,OAAA,gBACA,OAAA,cAAA,OAAA,SACA,OAAA,kBAqBA,EAAA,EAAA,sBACA,EAAA,EAAA,kBACA,EAAA,EAAA,sBACA,EAAA,EAAA,cAEA,EAAA,OAAA,kBAAA,GAEA,GACA,OAAA,oBAEA,qBACA,iBACA,qBACA,eAGA,EAAA,kBAAA,EACA,EAAA,SAAA,kBAAA,EACA,EAAA,SAAA,SAAA,GAEA,OAAA,mBC7TA,SAAA,GACA,YAeA,SAAA,GAAA,GACA,EAAA,KAAA,KAAA,GAdA,GAAA,GAAA,EAAA,SAAA,YACA,EAAA,EAAA,SAAA,UACA,EAAA,EAAA,MACA,EAAA,EAAA,gBACA,EAAA,EAAA,iBACA,EAAA,EAAA,OACA,EAAA,EAAA,eACA,EAAA,EAAA,KAEA,EAAA,OAAA,OACA,EAAA,OAAA,iBACA,EAAA,OAAA,YAKA,GAAA,UAAA,OAAA,OAAA,EAAA,WAEA,EAAA,UAAA,iBAAA,SAAA,EAAA,GACA,MAAA,GAAA,MAAA,QAAA,iBAAA,EAAA,GAAA,IAGA,EAAA,UAAA,aAAA,WACA,MAAA,GAAA,MAAA,QAAA,sBAIA,QAAA,uBACA,QAAA,cAEA,mBAAA,sBAAA,iBAAA,QACA,SAAA,GACA,EAAA,UAAA,GAAA,WACA,GAAA,GAAA,EAAA,MAAA,OACA,OAAA,GAAA,GAAA,MAAA,EAAA,kBAIA,QAAA,KAGA,EAAA,EAAA,WACA,iBAAA,SAAA,EAAA,GAEA,MADA,KACA,EAAA,KAAA,EAAA,MAAA,EAAA,GACA,IAEA,aAAA,WAEA,MADA,KACA,GAAA,GAAA,EAAA,KAAA,EAAA,WAIA,EAAA,EAAA,GAEA,EAAA,SAAA,OAAA,GAEA,OAAA,mBC1DA,SAAA,GACA,YAEA,IAAA,GAAA,EAAA,OAMA,EAAA,OAAA,cAAA,OAAA,UACA,EACA,EAAA,UAAA,YAEA,GAAA,UAAA,aAAA,SAAA,EAAA,EAAA,GACA,EAAA,KAAA,KAAA,EAAA,GAAA,EAAA,KAGA,OAAA,mBCnBA,SAAA,GACA,YAsFA,SAAA,GAAA,GACA,GAAA,GAAA,EAAA,GACA,EAAA,OAAA,EACA,IAAA,EAAA,CAEA,GAAA,GAAA,SAAA,cAAA,GACA,EAAA,EAAA,WACA,QAAA,GAAA,GA3FA,GAIA,IAJA,EAAA,cAKA,EAAA,oBAKA,KAAA,kBACA,MAAA,mBACA,KAAA,kBACA,KAAA,kBACA,GAAA,gBACA,OAAA,oBACA,OAAA,oBACA,QAAA,0BACA,IAAA,sBAEA,QAAA,qBACA,KAAA,kBACA,SAAA,sBACA,IAAA,iBACA,IAAA,uBACA,IAAA,iBACA,GAAA,mBACA,MAAA,mBACA,SAAA,sBACA,KAAA,kBACA,KAAA,kBACA,MAAA,mBACA,SAAA,sBACA,GAAA,qBACA,KAAA,kBACA,GAAA,gBACA,KAAA,kBACA,OAAA,oBACA,IAAA,mBACA,MAAA,mBACA,OAAA,oBACA,MAAA,mBACA,OAAA,oBACA,GAAA,gBACA,KAAA,kBACA,IAAA,iBACA,QAAA,qBACA,KAAA,kBACA,SAAA,sBACA,KAAA,kBACA,MAAA,mBACA,OAAA,oBACA,GAAA,mBACA,SAAA,sBACA,OAAA,oBACA,OAAA,oBACA,EAAA,uBACA,MAAA,mBACA,IAAA,iBACA,SAAA,sBACA,EAAA,mBACA,OAAA,oBACA,OAAA,oBACA,OAAA,oBACA,OAAA,oBACA,KAAA,kBACA,MAAA,mBACA,MAAA,mBACA,MAAA,0BAKA,SAAA,sBACA,SAAA,sBACA,MAAA,0BACA,KAAA,kBACA,MAAA,mBACA,GAAA,sBACA,MAAA,mBACA,GAAA,mBACA,MAAA,oBAaA,QAAA,KAAA,GAAA,QAAA,GAEA,OAAA,oBAAA,EAAA,UAAA,QAAA,SAAA,GACA,OAAA,GAAA,EAAA,SAAA,MAGA,OAAA,mBCtGA,WAGA,OAAA,KAAA,kBAAA,aACA,OAAA,OAAA,kBAAA,eAkBA,OAAA,eAAA,QAAA,UAAA,mBACA,OAAA,yBAAA,QAAA,UAAA,cAEA,IAAA,GAAA,QAAA,UAAA,gBACA,SAAA,UAAA,iBAAA,WACA,GAAA,GAAA,EAAA,KAAA,KAEA,OADA,gBAAA,YAAA,MACA,GAGA,QAAA,UAAA,uBAAA,QAAA,UAAA,oBCmFA,SAAA,GA0aA,QAAA,GAAA,EAAA,GACA,GAAA,GAAA,EAQA,OAPA,OAAA,UAAA,QAAA,KAAA,EAAA,SAAA,GACA,GAAA,EAAA,YAAA,SAGA,IACA,EAAA,EAAA,QAAA,EAAA,KAEA,EAGA,QAAA,GAAA,GACA,GAAA,GAAA,SAAA,cAAA,QAEA,OADA,GAAA,YAAA,EACA,EAGA,QAAA,GAAA,GACA,GAAA,GAAA,EAAA,EACA,UAAA,KAAA,YAAA,EACA,IAAA,KACA,IAAA,EAAA,MAIA,IACA,EAAA,EAAA,MAAA,SACA,MAAA,QAIA,SAAA,KAAA,kBAAA,EAGA,OADA,GAAA,WAAA,YAAA,GACA,EAMA,QAAA,KACA,EAAA,aAAA,EACA,SAAA,KAAA,YAAA,EACA,IAAA,GAAA,EAAA,gBACA,EAAA,EAAA,cAAA,OACA,GAAA,KAAA,SAAA,QACA,EAAA,KAAA,YAAA,GAGA,QAAA,GAAA,GACA,EAAA,aACA,IAEA,SAAA,KAAA,YAAA,GACA,EAAA,EAAA,iBACA,SAAA,KAAA,YAAA,GAMA,QAAA,GAAA,EAAA,GACA,GAAA,EAAA,CAGA,GAAA,EACA,IAAA,EAAA,MAAA,YAAA,EAAA,CACA,GAAA,GAAA,EAAA,EACA,GAAA,SAAA,GACA,EAAA,KAAA,YAAA,EAAA,MACA,EAAA,EAAA,MAAA,SACA,EAAA,SAGA,GAAA,EAAA,GACA,EAAA,IAWA,QAAA,GAAA,GACA,GACA,IAAA,YAAA,SAAA,eAAA,IAIA,QAAA,GAAA,EAAA,GACA,GAAA,GAAA,EAAA,EACA,GAAA,aAAA,EAAA,IACA,EAAA,aAAA,EAAA,IACA,SAAA,KAAA,YAAA,GAQA,QAAA,KAMA,MALA,KACA,EAAA,SAAA,cAAA,SACA,EAAA,aAAA,EAAA,IACA,EAAA,IAAA,GAEA,EAvhBA,GAAA,IACA,eAAA,EACA,YAMA,YAAA,SAAA,EAAA,EAAA,GACA,GAAA,GAAA,KAAA,YAAA,EAAA,EAAA,GACA,EAAA,KAAA,gBAAA,GACA,EAAA,KAAA,kBAAA,EAAA,GAGA,EAAA,EAAA,GAAA,EACA,GAAA,KAAA,aAAA,EAAA,GAEA,IACA,EAAA,aAAA,GAGA,KAAA,iBAAA,EAAA,IAMA,UAAA,SAAA,EAAA,GACA,MAAA,MAAA,YAAA,EAAA,YAAA,IAMA,YAAA,SAAA,EAAA,GAEA,MADA,GAAA,KAAA,iBAAA,GACA,KAAA,aAAA,EAAA,IAEA,kBAAA,SAAA,EAAA,GACA,MAAA,GACA,EAAA,OAAA,EAAA,IAAA,EAEA,IAEA,gBAAA,SAAA,GACA,MAAA,IAAA,EAAA,QAAA,KAAA,GAEA,YAAA,SAAA,EAAA,EAAA,GACA,GAAA,GAAA,KAAA,aAAA,EAAA,EAAA,EAQA,OAPA,MAAA,oBAAA,EAAA,WAAA,KAAA,kBAEA,KAAA,aAAA,EAAA,EAAA,YAEA,KAAA,eACA,KAAA,oBAAA,EAAA,GAEA,EAAA,aAEA,aAAA,SAAA,EAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,IAAA,EAAA,EAAA,IAAA,IACA,EAAA,WAAA,YAAA,IAGA,aAAA,SAAA,EAAA,EAAA,GACA,GAAA,GAAA,KAAA,SAAA,IACA,KAAA,EACA,KAAA,EACA,YAAA,GAEA,EAAA,KAAA,WAAA,EACA,GAAA,WAAA,EACA,EAAA,YAAA,EAAA,UACA,IAAA,GAAA,KAAA,SAAA,EAAA,YAIA,OAHA,KACA,EAAA,YAAA,EAAA,YAAA,OAAA,EAAA,cAEA,GAEA,WAAA,SAAA,GACA,IAAA,EACA,QAEA,IAAA,GAAA,EAAA,iBAAA,QACA,OAAA,OAAA,UAAA,OAAA,KAAA,EAAA,SAAA,GACA,OAAA,EAAA,aAAA,MAGA,oBAAA,SAAA,EAAA,GACA,IAEA,MAAA,UAAA,QAAA,KAAA,EAAA,iBAAA,KACA,SAAA,GACA,EAAA,aAAA,EAAA,MAGA,MAAA,UAAA,QAAA,KAAA,EAAA,iBAAA,YACA,SAAA,GACA,KAAA,oBAAA,EAAA,QAAA,IAEA,QAGA,iBAAA,SAAA,GAEA,MADA,GAAA,KAAA,kCAAA,GACA,KAAA,6BAAA,IAgBA,kCAAA,SAAA,GAMA,MAJA,GAAA,EAAA,QAAA,EAAA,SAAA,EAAA,GAEA,MAAA,GAAA,MAAA,EAAA,IAAA,MAEA,EAAA,QAAA,EAAA,SAAA,EAAA,GACA,MAAA,GAAA,QAkBA,6BAAA,SAAA,GAMA,MAJA,GAAA,EAAA,QAAA,EAAA,SAAA,EAAA,GAEA,MAAA,GAAA,MAAA,EAAA,MAEA,EAAA,QAAA,EAAA,SAAA,EAAA,EAAA,EAAA,GACA,GAAA,GAAA,EAAA,QAAA,EAAA,IAAA,QAAA,EAAA,GACA,OAAA,GAAA,KAWA,aAAA,SAAA,EAAA,GACA,GAAA,GAAA,KAAA,gCAAA,EAKA,IAJA,EAAA,KAAA,4BAAA,GACA,EAAA,KAAA,iBAAA,GACA,EAAA,KAAA,wBAAA,GACA,EAAA,KAAA,mBAAA,GACA,EAAA,CACA,GAAA,GAAA,EAAA,IACA,GAAA,EAAA,SAAA,GACA,EAAA,EAAA,WAAA,EAAA,KAKA,MADA,GAAA,EAAA,KAAA,EACA,EAAA,QAgBA,gCAAA,SAAA,GAGA,IADA,GAAA,GAAA,EAAA,GACA,EAAA,EAAA,KAAA,IACA,GAAA,EAAA,GAAA,MAAA,EAAA,IAAA,MAEA,MAAA,EAAA,EAAA,KAAA,IACA,GAAA,EAAA,GAAA,QAAA,EAAA,GAAA,IAAA,QAAA,EAAA,GAAA,EAAA,IAAA,MAEA,OAAA,IASA,iBAAA,SAAA,GACA,MAAA,MAAA,iBAAA,EAAA,eACA,KAAA,wBAiBA,wBAAA,SAAA,GACA,MAAA,MAAA,iBAAA,EAAA,sBACA,KAAA,+BAEA,iBAAA,SAAA,EAAA,EAAA,GAEA,MAAA,GAAA,QAAA,EAAA,SAAA,EAAA,EAAA,EAAA,GAEA,GADA,EAAA,yBACA,EAAA,CAEA,IAAA,GAAA,GADA,EAAA,EAAA,MAAA,KAAA,KACA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,IAAA,EAAA,EAAA,IAAA,IACA,EAAA,EAAA,OACA,EAAA,KAAA,EAAA,EAAA,EAAA,GAEA,OAAA,GAAA,KAAA,KAEA,MAAA,GAAA,KAIA,6BAAA,SAAA,EAAA,EAAA,GACA,MAAA,GAAA,MAAA,GACA,KAAA,sBAAA,EAAA,EAAA,GAEA,EAAA,EAAA,EAAA,KAAA,EAAA,IAAA,EAAA,GAGA,sBAAA,SAAA,EAAA,EAAA,GACA,MAAA,GAAA,EAAA,QAAA,EAAA,IAAA,GAKA,mBAAA,SAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,cAAA,OAAA,IACA,EAAA,EAAA,QAAA,cAAA,GAAA,IAEA,OAAA,IAGA,WAAA,SAAA,EAAA,GACA,GAAA,GAAA,EAgBA,OAfA,IACA,MAAA,UAAA,QAAA,KAAA,EAAA,SAAA,GACA,EAAA,cAAA,EAAA,OAAA,EAAA,MAAA,SACA,GAAA,KAAA,cAAA,EAAA,aAAA,EACA,KAAA,eAAA,QACA,GAAA,KAAA,mBAAA,GAAA,WACA,EAAA,OAAA,QAAA,YACA,GAAA,UAAA,EAAA,MAAA,UAAA,OACA,GAAA,KAAA,WAAA,EAAA,SAAA,GACA,GAAA,WACA,EAAA,UACA,GAAA,EAAA,QAAA,SAEA,MAEA,GAEA,cAAA,SAAA,EAAA,EAAA,GACA,GAAA,MAAA,EAAA,EAAA,MAAA,IAUA,OATA,GAAA,QAAA,SAAA,GACA,EAAA,EAAA,OACA,KAAA,qBAAA,EAAA,KACA,EAAA,IAAA,EAAA,MAAA,0BACA,KAAA,yBAAA,EAAA,GACA,KAAA,yBAAA,EAAA,IAEA,EAAA,KAAA,IACA,MACA,EAAA,KAAA,OAEA,qBAAA,SAAA,EAAA,GACA,GAAA,GAAA,KAAA,iBAAA,EACA,QAAA,EAAA,MAAA,IAEA,iBAAA,SAAA,GAEA,MADA,GAAA,EAAA,QAAA,MAAA,OAAA,QAAA,MAAA,OACA,GAAA,QAAA,KAAA,EAAA,IAAA,iBAAA,MAGA,yBAAA,SAAA,EAAA,GACA,MAAA,GAAA,MAAA,iBACA,EAAA,EAAA,QAAA,yBAAA,GACA,EAAA,QAAA,eAAA,EAAA,MAEA,EAAA,IAAA,GAKA,yBAAA,SAAA,EAAA,GACA,EAAA,EAAA,QAAA,mBAAA,KACA,IAAA,IAAA,IAAA,IAAA,IAAA,KACA,EAAA,EACA,EAAA,IAAA,EAAA,GAYA,OAXA,GAAA,QAAA,SAAA,GACA,GAAA,GAAA,EAAA,MAAA,EACA,GAAA,EAAA,IAAA,SAAA,GAEA,GAAA,GAAA,EAAA,OAAA,QAAA,eAAA,GAIA,OAHA,IAAA,EAAA,QAAA,GAAA,GAAA,EAAA,QAAA,GAAA,IACA,EAAA,EAAA,QAAA,kBAAA,KAAA,EAAA,SAEA,IACA,KAAA,KAEA,GAEA,4BAAA,SAAA,GACA,MAAA,GAAA,QAAA,mBAAA,GAAA,QACA,YAAA,IAEA,mBAAA,SAAA,GACA,GAAA,GAAA,EAAA,MAAA,OAIA,GAAA,MAAA,UAAA,EAAA,MAAA,QAAA,MAAA,gBACA,EAAA,EAAA,QAAA,kBAAA,aACA,EAAA,MAAA,QAAA,MAQA,IAAA,GAAA,EAAA,KACA,KAAA,GAAA,KAAA,GACA,YAAA,EAAA,KACA,GAAA,EAAA,cAGA,OAAA,IAEA,oBAAA,SAAA,EAAA,GACA,GAAA,IACA,YAAA,SACA,GAAA,IAEA,MAAA,UAAA,QAAA,KAAA,EAAA,SAAA,GACA,EAAA,YAAA,EAAA,KAAA,KAAA,EAAA,cACA,QAGA,iBAAA,SAAA,EAAA,GACA,EAAA,MAAA,WACA,EAAA,EAAA,GAEA,EAAA,KAMA,EAAA,oCAEA,EAAA,4DACA,EAAA,uEAEA,EAAA,sDACA,EAAA,+DAEA,EAAA,+DACA,EAAA,wEAIA,EAAA,iBAEA,EAAA,oBACA,EAAA,iDAGA,gBAAA,GAAA,QAAA,IAAA,EAAA,EAAA,OACA,sBAAA,GAAA,QAAA,IAAA,EAAA,EAAA,OACA,iBAAA,6BACA,YAAA,YACA,mBAAA,oBAEA,yBAAA,EAAA,iBACA,eAAA,GAAA,QAAA,EAAA,OACA,sBAAA,GAAA,QAAA,EAAA,OACA,eACA,QACA,MACA,cACA,mBACA,YACA,YAyCA,IAAA,GAAA,SAAA,cAAA,SACA,GAAA,MAAA,QAAA,MAsBA,IA2CA,GA3CA,EAAA,UAAA,UAAA,MAAA,UAuCA,EAAA,iBACA,EAAA,qBACA,EAAA,SAaA,IAAA,OAAA,kBAAA,CACA,EAAA,wCACA,IAAA,GAAA,KAAA,UACA,EAAA,EAAA,cAAA,OACA,GAAA,aAAA,IAAA,EAAA,WAAA,IAIA,SAAA,iBAAA,mBAAA,WACA,GAAA,GAAA,EAAA,WAEA,IAAA,OAAA,cAAA,YAAA,UAAA,CACA,GAAA,GAAA,wBACA,EAAA,IACA,EAAA,SAAA,EAAA,GACA,aAAA,SAAA,0BAAA,IAAA,EACA,YAAA,SAAA,yBAAA,IAAA,EAEA,YAAA,OAAA,mBACA,YAAA,OAAA,kBACA,EACA,GACA,KAAA,IAEA,IAAA,GAAA,YAAA,OAAA,YAEA,aAAA,OAAA,aAAA,SAAA,GACA,IAAA,EAAA,GAAA,CAGA,GAAA,GAAA,EAAA,iBAAA,CACA,KAAA,EAAA,aAAA,GAEA,WADA,GAAA,KAAA,KAAA,EAGA,GAAA,YACA,EAAA,EAAA,cAAA,cAAA,SACA,EAAA,YAAA,EAAA,eACA,EAAA,WAAA,EAAA,OAEA,EAAA,aAAA,GAEA,EAAA,YAAA,EAAA,UAAA,GACA,EAAA,gBAAA,EAAA,IACA,EAAA,aAAA,EAAA,IACA,EAAA,IAAA,EAEA,EAAA,aAAA,IAEA,EAAA,aAAA,EACA,EAAA,aAAA,EAAA,GAEA,EAAA,YAAA,IAGA,EAAA,gBAAA,EACA,KAAA,oBAAA,IAGA,IAAA,GAAA,YAAA,OAAA,WACA,aAAA,OAAA,YAAA,SAAA,GACA,MAAA,SAAA,EAAA,WAAA,eAAA,EAAA,KACA,EAAA,aAAA,GACA,EAAA,WAEA,EAAA,KAAA,KAAA,OASA,EAAA,UAAA,GAEA,OAAA,YC5tBA,WAGA,OAAA,gBAAA,OAAA,iBAAA,SAAA,GACA,MAAA,GAAA,SAKA,OAAA,KAAA,OAAA,OAAA,SAAA,GACA,MAAA,IAGA,iBAAA,mBAAA,WACA,GAAA,eAAA,aAAA,EAAA,CACA,GAAA,GAAA,QAAA,UAAA,gBACA,SAAA,UAAA,iBAAA,WACA,GAAA,GAAA,EAAA,KAAA,KAEA,OADA,gBAAA,YAAA,MACA,MAKA,OAAA,gBAAA,SAAA,GAOA,GALA,OAAA,qBAAA,oBAAA,WACA,oBAAA,UAAA,IAIA,EAAA,UAAA,EAAA,SAAA,CAEA,IADA,GAAA,GAAA,SAAA,yBACA,EAAA,YACA,EAAA,YAAA,EAAA,WAEA,GAAA,SAAA,EAEA,MAAA,GAAA,SAAA,EAAA,aCxCA,SAAA,GACA,YA6BA,SAAA,GAAA,GACA,MAAA,UAAA,EAAA,GAGA,QAAA,KACA,EAAA,KAAA,MACA,KAAA,YAAA,EAGA,QAAA,GAAA,GAKA,MAJA,IAAA,GACA,EAAA,KAAA,MAGA,EAAA,cAGA,QAAA,GAAA,GACA,GAAA,GAAA,EAAA,WAAA,EACA,OAAA,GAAA,IACA,IAAA,GAEA,KAAA,GAAA,GAAA,GAAA,GAAA,GAAA,IAAA,QAAA,GAEA,EAEA,mBAAA,GAGA,QAAA,GAAA,GAIA,GAAA,GAAA,EAAA,WAAA,EACA,OAAA,GAAA,IACA,IAAA,GAEA,KAAA,GAAA,GAAA,GAAA,GAAA,IAAA,QAAA,GAEA,EAEA,mBAAA,GAOA,QAAA,GAAA,EAAA,EAAA,GACA,QAAA,GAAA,GACA,EAAA,KAAA,GAGA,GAAA,GAAA,GAAA,eACA,EAAA,EACA,EAAA,GACA,GAAA,EACA,GAAA,EACA,IAEA,GAAA,MAAA,EAAA,EAAA,IAAA,GAAA,GAAA,KAAA,KAAA,YAAA,CACA,GAAA,GAAA,EAAA,EACA,QAAA,GACA,IAAA,eACA,IAAA,IAAA,EAAA,KAAA,GAGA,CAAA,GAAA,EAIA,CACA,EAAA,kBACA,MAAA,GALA,EAAA,GACA,EAAA,WACA,UALA,GAAA,EAAA,cACA,EAAA,QASA,MAEA,KAAA,SACA,GAAA,GAAA,EAAA,KAAA,GACA,GAAA,EAAA,kBACA,CAAA,GAAA,KAAA,EAkBA,CAAA,GAAA,EAKA,CAAA,GAAA,GAAA,EACA,KAAA,EAEA,GAAA,qCAAA,EACA,MAAA,GARA,EAAA,GACA,EAAA,EACA,EAAA,WACA,UAnBA,GAFA,KAAA,QAAA,EACA,EAAA,GACA,EACA,KAAA,EAEA,GAAA,KAAA,WACA,KAAA,aAAA,GAGA,EADA,QAAA,KAAA,QACA,WACA,KAAA,aAAA,GAAA,EAAA,SAAA,KAAA,QACA,wBACA,KAAA,YACA,wBAEA,cAaA,KAEA,KAAA,cACA,KAAA,GACA,MAAA,IACA,EAAA,SACA,KAAA,GACA,KAAA,UAAA,IACA,EAAA,YAGA,GAAA,GAAA,KAAA,GAAA,MAAA,GAAA,MAAA,IACA,KAAA,aAAA,EAAA,GAGA,MAEA,KAAA,YACA,GAAA,GAAA,EAAA,EAAA,SAGA,CACA,EAAA,UACA,UAJA,EAAA,mBACA,EAAA,KAAA,KAKA,MAEA,KAAA,wBACA,GAAA,KAAA,GAAA,KAAA,EAAA,EAAA,GAEA,CACA,EAAA,oBAAA,GACA,EAAA,UACA,UAJA,EAAA,0BAMA,MAEA,KAAA,WAIA,GAHA,KAAA,aAAA,EACA,QAAA,KAAA,UACA,KAAA,QAAA,EAAA,SACA,GAAA,EAAA,CACA,KAAA,MAAA,EAAA,MACA,KAAA,MAAA,EAAA,MACA,KAAA,MAAA,EAAA,MAAA,QACA,KAAA,OAAA,EAAA,MACA,MAAA,GACA,GAAA,KAAA,GAAA,MAAA,EACA,MAAA,GACA,EAAA,gCACA,EAAA,qBACA,IAAA,KAAA,EACA,KAAA,MAAA,EAAA,MACA,KAAA,MAAA,EAAA,MACA,KAAA,MAAA,EAAA,MAAA,QACA,KAAA,OAAA,IACA,EAAA,YACA,CAAA,GAAA,KAAA,EAOA,CACA,GAAA,GAAA,EAAA,EAAA,GACA,EAAA,EAAA,EAAA,IAEA,QAAA,KAAA,UAAA,EAAA,KAAA,IACA,KAAA,GAAA,KAAA,GACA,GAAA,GAAA,KAAA,GAAA,MAAA,GAAA,KAAA,GAAA,KAAA,KACA,KAAA,MAAA,EAAA,MACA,KAAA,MAAA,EAAA,MACA,KAAA,MAAA,EAAA,MAAA,QACA,KAAA,MAAA,OAEA,EAAA,eACA,UAnBA,KAAA,MAAA,EAAA,MACA,KAAA,MAAA,EAAA,MACA,KAAA,MAAA,EAAA,MAAA,QACA,KAAA,OAAA,EAAA,OACA,KAAA,UAAA,IACA,EAAA,WAgBA,KAEA,KAAA,iBACA,GAAA,KAAA,GAAA,MAAA,EASA,CACA,QAAA,KAAA,UACA,KAAA,MAAA,EAAA,MACA,KAAA,MAAA,EAAA,OAEA,EAAA,eACA,UAdA,MAAA,GACA,EAAA,gCAGA,EADA,QAAA,KAAA,QACA,YAEA,0BAUA,MAEA,KAAA,wBACA,GAAA,KAAA,EAEA,CACA,EAAA,sBAAA,GACA,EAAA,0BACA,UAJA,EAAA,wBAMA,MAEA,KAAA,yBAEA,GADA,EAAA,2BACA,KAAA,EAAA,CACA,EAAA,sBAAA,EACA,UAEA,KAEA,KAAA,2BACA,GAAA,KAAA,GAAA,MAAA,EAAA,CACA,EAAA,WACA,UAEA,EAAA,4BAAA,EAEA,MAEA,KAAA,YACA,GAAA,KAAA,EAAA,CACA,IACA,EAAA,mBACA,GAAA,OAEA,GAAA,CACA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,EACA,IAAA,KAAA,GAAA,MAAA,GAAA,MAAA,EAKA,GAAA,KAAA,GAAA,OAAA,KAAA,UAAA,CAIA,GAAA,GAAA,EAAA,EACA,QAAA,KAAA,UAAA,KAAA,WAAA,EAAA,KAAA,WAAA,MAJA,MAAA,UAAA,OALA,GAAA,oCAWA,EAAA,OACA,CAAA,GAAA,GAAA,GAAA,KAAA,GAAA,MAAA,GAAA,KAAA,GAAA,KAAA,EAAA,CACA,GAAA,EAAA,OACA,EAAA,GACA,EAAA,MACA,UAEA,GAAA,EAEA,KAEA,KAAA,YACA,GAAA,GAAA,GAAA,KAAA,GAAA,MAAA,GAAA,KAAA,GAAA,KAAA,EAAA,CACA,GAAA,EAAA,SAAA,EAAA,KAAA,EAAA,KAAA,KAAA,EAAA,IAAA,KAAA,EAAA,GAEA,GAAA,EAAA,OACA,EAAA,uBAEA,KAAA,MAAA,EAAA,KAAA,KAAA,GACA,EAAA,GACA,EAAA,uBANA,EAAA,eAQA,UACA,KAAA,GAAA,MAAA,GAAA,MAAA,EACA,EAAA,oCAEA,GAAA,CAEA,MAEA,KAAA,OACA,IAAA,WACA,GAAA,KAAA,GAAA,EAQA,CAAA,GAAA,GAAA,GAAA,KAAA,GAAA,MAAA,GAAA,KAAA,GAAA,KAAA,EAAA,CAIA,GAHA,KAAA,MAAA,EAAA,KAAA,KAAA,GACA,EAAA,GACA,EAAA,sBACA,EACA,KAAA,EAEA,UACA,KAAA,GAAA,MAAA,GAAA,MAAA,GACA,KAAA,EACA,GAAA,EACA,KAAA,IACA,GAAA,GAEA,GAAA,GAEA,EAAA,wCAAA,OAnBA,IAHA,KAAA,MAAA,EAAA,KAAA,KAAA,GACA,EAAA,GACA,EAAA,OACA,YAAA,EACA,KAAA,EAoBA,MAEA,KAAA,OACA,GAAA,QAAA,KAAA,GACA,GAAA,MACA,CAAA,GAAA,GAAA,GAAA,KAAA,GAAA,MAAA,GAAA,KAAA,GAAA,KAAA,GAAA,EAAA,CACA,GAAA,IAAA,EAAA,CACA,GAAA,GAAA,SAAA,EAAA,GACA,IAAA,EAAA,KAAA,WACA,KAAA,MAAA,EAAA,IAEA,EAAA,GAEA,GAAA,EACA,KAAA,EAEA,GAAA,qBACA,UACA,KAAA,GAAA,MAAA,GAAA,MAAA,EACA,EAAA,+BAAA,GAEA,EAAA,KAAA,MAEA,KAEA,KAAA,sBAIA,GAHA,MAAA,GACA,EAAA,6BACA,EAAA,gBACA,KAAA,GAAA,MAAA,EACA,QAEA,MAEA,KAAA,gBACA,GAAA,GAAA,GAAA,KAAA,GAAA,MAAA,IAAA,GAAA,KAAA,GAAA,KAAA,GA6BA,KAAA,GAAA,MAAA,GAAA,MAAA,IACA,GAAA,EAAA,QA9BA,CACA,MAAA,GACA,EAAA,mCAEA,IAAA,IACA,EAAA,EAAA,EAAA,kBACA,EAAA,GAEA,MAAA,GACA,KAAA,MAAA,MACA,KAAA,GAAA,MAAA,GACA,KAAA,MAAA,KAAA,KAEA,KAAA,GAAA,KAAA,GAAA,MAAA,EACA,KAAA,MAAA,KAAA,IACA,KAAA,IACA,QAAA,KAAA,SAAA,GAAA,KAAA,MAAA,QAAA,GAAA,EAAA,QAAA,EAAA,KAAA,EAAA,KAAA,KAAA,EAAA,KACA,EAAA,EAAA,GAAA,KAEA,KAAA,MAAA,KAAA,IAEA,EAAA,GACA,KAAA,GACA,KAAA,OAAA,IACA,EAAA,SACA,KAAA,IACA,KAAA,UAAA,IACA,EAAA,YAKA,KAEA,KAAA,QACA,GAAA,KAAA,EAGA,GAAA,GAAA,KAAA,GAAA,MAAA,GAAA,MAAA,IACA,KAAA,QAAA,EAAA,KAHA,KAAA,UAAA,IACA,EAAA,WAIA,MAEA,KAAA,WACA,GAAA,GAAA,KAAA,GAAA,MAAA,GAAA,MAAA,IACA,KAAA,WAAA,GAKA,KAIA,QAAA,KACA,KAAA,QAAA,GACA,KAAA,YAAA,GACA,KAAA,UAAA,GACA,KAAA,UAAA,KACA,KAAA,MAAA,GACA,KAAA,MAAA,GACA,KAAA,SACA,KAAA,OAAA,GACA,KAAA,UAAA,GACA,KAAA,YAAA,EACA,KAAA,aAAA,EAKA,QAAA,GAAA,EAAA,GACA,SAAA,GAAA,YAAA,KACA,EAAA,GAAA,GAAA,OAAA,KAEA,KAAA,KAAA,EACA,EAAA,KAAA,KAEA,IAAA,GAAA,EAAA,QAAA,+BAAA,GAGA,GAAA,KAAA,KAAA,EAAA,KAAA,GAzcA,GAAA,IAAA,CACA,KAAA,EAAA,UACA,IACA,GAAA,GAAA,GAAA,KAAA,IAAA,WACA,GAAA,eAAA,EAAA,KACA,MAAA,IAGA,IAAA,EAAA,CAGA,GAAA,GAAA,OAAA,OAAA,KACA,GAAA,IAAA,GACA,EAAA,KAAA,EACA,EAAA,OAAA,GACA,EAAA,KAAA,GACA,EAAA,MAAA,IACA,EAAA,GAAA,GACA,EAAA,IAAA,GAEA,IAAA,GAAA,OAAA,OAAA,KACA,GAAA,OAAA,IACA,EAAA,QAAA,KACA,EAAA,QAAA,KACA,EAAA,UAAA,IA8CA,IAAA,GAAA,OACA,EAAA,WACA,EAAA,mBAoYA,GAAA,WACA,GAAA,QACA,GAAA,KAAA,WACA,MAAA,MAAA,IAEA,IAAA,GAAA,EAMA,QALA,IAAA,KAAA,WAAA,MAAA,KAAA,aACA,EAAA,KAAA,WACA,MAAA,KAAA,UAAA,IAAA,KAAA,UAAA,IAAA,KAGA,KAAA,UACA,KAAA,YAAA,KAAA,EAAA,KAAA,KAAA,IACA,KAAA,SAAA,KAAA,OAAA,KAAA,WAEA,GAAA,MAAA,GACA,EAAA,KAAA,MACA,EAAA,KAAA,KAAA,IAGA,GAAA,YACA,MAAA,MAAA,QAAA,KAEA,GAAA,UAAA,GACA,KAAA,YAEA,EAAA,KAAA,KAAA,EAAA,IAAA,iBAGA,GAAA,QACA,MAAA,MAAA,WAAA,GAAA,KAAA,MACA,KAAA,MAAA,IAAA,KAAA,MAAA,KAAA,OAEA,GAAA,MAAA,IACA,KAAA,YAAA,KAAA,aAEA,EAAA,KAAA,KAAA,EAAA,SAGA,GAAA,YACA,MAAA,MAAA,OAEA,GAAA,UAAA,IACA,KAAA,YAAA,KAAA,aAEA,EAAA,KAAA,KAAA,EAAA,aAGA,GAAA,QACA,MAAA,MAAA,OAEA,GAAA,MAAA,IACA,KAAA,YAAA,KAAA,aAEA,EAAA,KAAA,KAAA,EAAA,SAGA,GAAA,YACA,MAAA,MAAA,WAAA,GAAA,KAAA,YACA,IAAA,KAAA,MAAA,KAAA,KAAA,KAAA,aAEA,GAAA,UAAA,IACA,KAAA,YAAA,KAAA,cAEA,KAAA,SACA,EAAA,KAAA,KAAA,EAAA;EAGA,GAAA,UACA,MAAA,MAAA,aAAA,KAAA,QAAA,KAAA,KAAA,OACA,GAAA,KAAA,QAEA,GAAA,QAAA,IACA,KAAA,YAAA,KAAA,cAEA,KAAA,OAAA,IACA,KAAA,EAAA,KACA,EAAA,EAAA,MAAA,IACA,EAAA,KAAA,KAAA,EAAA,WAGA,GAAA,QACA,MAAA,MAAA,aAAA,KAAA,WAAA,KAAA,KAAA,UACA,GAAA,KAAA,WAEA,GAAA,MAAA,GACA,KAAA,aAEA,KAAA,UAAA,IACA,KAAA,EAAA,KACA,EAAA,EAAA,MAAA,IACA,EAAA,KAAA,KAAA,EAAA,eAIA,EAAA,IAAA,IAEA,QC9iBA,SAAA,GAmBA,QAAA,GAAA,GAEA,IAAA,GADA,GAAA,MACA,EAAA,EAAA,EAAA,UAAA,OAAA,IAAA,CACA,GAAA,GAAA,UAAA,EACA,KACA,IAAA,GAAA,KAAA,GACA,EAAA,EAAA,EAAA,GAEA,MAAA,KAGA,MAAA,GAIA,QAAA,GAAA,EAAA,EAAA,GACA,GAAA,GAAA,EAAA,EAAA,EACA,QAAA,eAAA,EAAA,EAAA,GAKA,QAAA,GAAA,EAAA,GACA,GAAA,EAAA,CACA,GAAA,GAAA,OAAA,yBAAA,EAAA,EACA,OAAA,IAAA,EAAA,OAAA,eAAA,GAAA,IAxCA,SAAA,UAAA,OACA,SAAA,UAAA,KAAA,SAAA,GACA,GAAA,GAAA,KACA,EAAA,MAAA,UAAA,MAAA,KAAA,UAAA,EACA,OAAA,YACA,GAAA,GAAA,EAAA,OAEA,OADA,GAAA,KAAA,MAAA,EAAA,WACA,EAAA,MAAA,EAAA,MAuCA,EAAA,MAAA,GAEA,OAAA,UC5CA,SAAA,GAEA,YAiFA,SAAA,GAAA,EAAA,EAAA,GACA,GAAA,GAAA,gBAAA,GACA,SAAA,cAAA,GAAA,EAAA,WAAA,EAEA,IADA,EAAA,UAAA,EACA,EACA,IAAA,GAAA,KAAA,GACA,EAAA,aAAA,EAAA,EAAA,GAGA,OAAA,GAnFA,GAAA,GAAA,aAAA,UAAA,IACA,EAAA,aAAA,UAAA,MACA,cAAA,UAAA,IAAA,WACA,IAAA,GAAA,GAAA,EAAA,EAAA,UAAA,OAAA,IACA,EAAA,KAAA,KAAA,UAAA,KAGA,aAAA,UAAA,OAAA,WACA,IAAA,GAAA,GAAA,EAAA,EAAA,UAAA,OAAA,IACA,EAAA,KAAA,KAAA,UAAA,KAGA,aAAA,UAAA,OAAA,SAAA,EAAA,GACA,GAAA,UAAA,SACA,GAAA,KAAA,SAAA,IAEA,EAAA,KAAA,IAAA,GAAA,KAAA,OAAA,IAEA,aAAA,UAAA,OAAA,SAAA,EAAA,GACA,GAAA,KAAA,OAAA,GACA,GAAA,KAAA,IAAA,GAKA,IAAA,GAAA,WACA,MAAA,OAAA,UAAA,MAAA,KAAA,OAGA,EAAA,OAAA,cAAA,OAAA,mBAQA,IANA,SAAA,UAAA,MAAA,EACA,EAAA,UAAA,MAAA,EACA,eAAA,UAAA,MAAA,GAIA,OAAA,YAAA,CACA,GAAA,GAAA,KAAA,KAEA,QAAA,aAAA,IAAA,WAAA,MAAA,MAAA,MAAA,IAKA,OAAA,wBACA,OAAA,sBAAA,WACA,GAAA,GAAA,OAAA,6BACA,OAAA,wBAEA,OAAA,GACA,SAAA,GACA,MAAA,GAAA,WACA,EAAA,YAAA,UAGA,SAAA,GACA,MAAA,QAAA,WAAA,EAAA,IAAA,SAKA,OAAA,uBACA,OAAA,qBAAA,WACA,MAAA,QAAA,4BACA,OAAA,yBACA,SAAA,GACA,aAAA,OAwBA,IAAA,MAEA,EAAA,WACA,EAAA,KAAA,WAEA,QAAA,QAAA,EAGA,EAAA,oBAAA,WAIA,MAHA,GAAA,oBAAA,WACA,KAAA,0CAEA,GAMA,OAAA,iBAAA,mBAAA,WACA,OAAA,UAAA,IACA,OAAA,QAAA,WACA,QAAA,MAAA,sIAQA,EAAA,UAAA,GAEA,OAAA,UC1IA,OAAA,gBAAA,OAAA,iBAAA,SAAA,GACA,MAAA,GAAA,SCRA,SAAA,GAEA,EAAA,IAAA,OAAA,aAEA,IAAA,EAEA,QAAA,SAAA,SAAA,EAAA,GACA,IACA,EAAA,OAAA,KAAA,GAAA,sBAAA,MAAA,GACA,EAAA,SAAA,MAAA,GAEA,EAAA,KACA,UAAA,YAGA,EAAA,GAAA,KAAA,SAAA,MAAA,GAGA,IAAA,IACA,kBACA,SACA,WACA,yCACA,cACA,eACA,UACA,cACA,8CACA,8BACA,UACA,cACA,yBACA,UACA,aACA,sBACA,uBACA,6BACA,UACA,aACA,kCACA,sCACA,6BACA,+BACA,8BACA,UACA,eACA,YACA,WACA,uBACA,YACA,4BACA,YACA,WACA,KAAA,MAEA,KAEA,EAAA,WAEA,GAAA,GAAA,EAAA,SAEA,EAAA,EAAA,cAAA,UAEA,GAAA,YAAA,EAEA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,GAAA,IAAA,CACA,GAAA,GAAA,EAAA,cAAA,IACA,GAAA,KAAA,IACA,EAAA,YAAA,EAAA,UACA,EAAA,IAAA,EACA,EAAA,QAAA,SAAA,GAEA,IADA,GAAA,GACA,EAAA,OAAA,KAAA,KACA,EAAA,EAAA,KAEA,GAAA,EAAA,QAAA,EAAA,GACA,EAAA,kBAEA,EAAA,YAAA,EAAA,cAAA,OAAA,YAAA,KAIA,EAAA,SAAA,EAAA,GAEA,GAAA,GAAA,EAAA,QAEA,KAEA,IAAA,GAAA,GAAA,CACA,GAAA,KAAA,GAEA,IAEA,EAAA,KAAA,cAAA,SAAA,UACA,QAAA,EAAA,EAAA,EAAA,YAAA,UAGA,EAAA,MAAA,UAAA,QAAA,KAAA,KAAA,MAAA,UAAA,SAEA,GAAA,MAAA,EAAA,OAAA,EAAA,WAAA,EAAA,SAAA,GACA,EAAA,SAAA,GACA,MAAA,GAAA,EAAA,WAGA,EAAA,SAAA,EAAA,EAAA,GACA,GAAA,EAAA,GACA,MAAA,EAEA,IAAA,GAAA,GAAA,EACA,IAAA,EAAA,WAAA,IAAA,EAAA,SAAA,CACA,GAAA,GAAA,EAAA,WAAA,cAEA,EAAA,EAAA,EAAA,EAOA,YAAA,IACA,EAAA,EAAA,uBAEA,GAAA,OACA,IAAA,GAAA,EAAA,cACA,GAAA,EAAA,SAAA,GACA,GAAA,EAAA,EAAA,EAAA,WAAA,KAEA,GAAA,GAEA,GAAA,GAAA,KACA,GAAA,aAAA,EAAA,aACA,GAAA,aAEA,CACA,GAAA,GAAA,EAAA,YAAA,MACA,GAAA,EAAA,EAAA,IAAA,EAAA,SAAA,GAEA,MAAA,IAWA,KAEA,EAAA,SAAA,GACA,GAAA,GAAA,YACA,EAAA,EAAA,WAAA,aAcA,OAbA,GAAA,kBAAA,EAAA,YACA,GAAA,iBAAA,EAAA,OACA,wCAAA,EAAA,YACA,EAAA,KAAA,IAEA,GAAA,GAAA,cAEA,EAAA,YACA,EAAA,EAAA,WAAA,SAAA,GACA,GAAA,IAAA,EAAA,MAAA,EAAA,MAAA,KAAA,EAAA,MAAA,IAAA,MAGA,GAAA,aAMA,WAAA,WACA,GAAA,GAAA,OAAA,KAAA,WAAA,IAAA,OAEA,EAAA,EAAA,EACA,GACA,EAAA,EAAA,kBAAA,EAAA,WAAA,IAEA,QAAA,IAAA,sBACA,QAAA,IAAA,QAMA,EAAA,OAAA,GAEA,OAAA,WCtLA,WASA,GAAA,GAAA,SAAA,cAAA,QACA,GAAA,YAAA,kHAQA,IAAA,GAAA,SAAA,cAAA,OACA,GAAA,aAAA,EAAA,EAAA,aAEA,UC1BA,SAAA,GAEA,QAAA,GAAA,EAAA,GAKA,MAJA,GAAA,MACA,EAAA,MACA,GAAA,IAEA,EAAA,MAAA,KAAA,EAAA,IAAA,IAGA,QAAA,GAAA,EAAA,EAAA,GACA,GAAA,EACA,QAAA,UAAA,QACA,IAAA,GACA,MACA,KAAA,GACA,EAAA,IACA,MACA,KAAA,GACA,EAAA,EAAA,MAAA,KACA,MACA,SACA,EAAA,EAAA,EAAA,GAGA,EAAA,GAAA,EAGA,QAAA,GAAA,GACA,MAAA,GAAA,GAKA,QAAA,GAAA,EAAA,GACA,YAAA,iBAAA,WACA,EAAA,EAAA,KAJA,GAAA,KAUA,GAAA,QAAA,EACA,EAAA,OAAA,EACA,EAAA,MAAA,GAEA,QCzCA,SAAA,GAMA,QAAA,GAAA,GACA,EAAA,YAAA,IACA,EAAA,KAAA,GAGA,QAAA,KACA,KAAA,EAAA,QACA,EAAA,UAXA,GAAA,GAAA,EACA,KACA,EAAA,SAAA,eAAA,GAaA,KAAA,OAAA,kBAAA,oBAAA,GACA,QAAA,GAAA,eAAA,IAKA,EAAA,eAAA,GAEA,UCxBA,SAAA,GAmEA,QAAA,GAAA,EAAA,EAAA,GACA,MAAA,GAAA,QAAA,EAAA,SAAA,EAAA,EAAA,EAAA,GACA,GAAA,GAAA,EAAA,QAAA,QAAA,GAEA,OADA,GAAA,EAAA,EAAA,GACA,EAAA,IAAA,EAAA,IAAA,IAIA,QAAA,GAAA,EAAA,GACA,GAAA,GAAA,GAAA,KAAA,EAAA,EACA,OAAA,GAAA,EAAA,MAGA,QAAA,GAAA,GACA,GAAA,GAAA,SAAA,QACA,EAAA,GAAA,KAAA,EAAA,EACA,OAAA,GAAA,OAAA,EAAA,MAAA,EAAA,OAAA,EAAA,MACA,EAAA,WAAA,EAAA,SACA,EAAA,EAAA,SAAA,EAAA,UAEA,EAKA,QAAA,GAAA,EAAA,GAGA,IAFA,GAAA,GAAA,EAAA,MAAA,KACA,EAAA,EAAA,MAAA,KACA,EAAA,QAAA,EAAA,KAAA,EAAA,IACA,EAAA,QACA,EAAA,OAEA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,EAAA,IACA,EAAA,QAAA,KAEA,OAAA,GAAA,KAAA,KApGA,GAAA,IACA,WAAA,SAAA,EAAA,GACA,EAAA,GAAA,EAAA,cAAA,QACA,KAAA,kBAAA,EAAA,GACA,KAAA,cAAA,EAAA,EAEA,IAAA,GAAA,EAAA,iBAAA,WACA,IAAA,EACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,IAAA,EAAA,EAAA,IAAA,IACA,EAAA,SACA,KAAA,WAAA,EAAA,QAAA,IAKA,gBAAA,SAAA,GACA,KAAA,WAAA,EAAA,QAAA,EAAA,cAAA,UAEA,cAAA,SAAA,EAAA,GACA,GAAA,GAAA,EAAA,iBAAA,QACA,IAAA,EACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,IAAA,EAAA,EAAA,IAAA,IACA,KAAA,aAAA,EAAA,IAIA,aAAA,SAAA,EAAA,GACA,EAAA,GAAA,EAAA,cAAA,QACA,EAAA,YAAA,KAAA,eAAA,EAAA,YAAA,IAEA,eAAA,SAAA,EAAA,GAEA,MADA,GAAA,EAAA,EAAA,EAAA,GACA,EAAA,EAAA,EAAA,IAEA,kBAAA,SAAA,EAAA,GACA,EAAA,eAAA,EAAA,iBACA,KAAA,yBAAA,EAAA,EAGA,IAAA,GAAA,GAAA,EAAA,iBAAA,EACA,IAAA,EACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,IAAA,EAAA,EAAA,IAAA,IACA,KAAA,yBAAA,EAAA,IAIA,yBAAA,SAAA,EAAA,GACA,EAAA,GAAA,EAAA,cAAA,QACA,EAAA,QAAA,SAAA,GACA,GAAA,GAAA,EAAA,WAAA,EACA,IAAA,GAAA,EAAA,OACA,EAAA,MAAA,OAAA,GAAA,EAAA,CACA,GAAA,GAAA,EAAA,EAAA,EAAA,MACA,GAAA,MAAA,OAMA,EAAA,sBACA,EAAA,qCACA,GAAA,OAAA,MAAA,UACA,EAAA,IAAA,EAAA,KAAA,OAAA,IACA,EAAA,QAyCA,GAAA,YAAA,GAEA,UC5GA,SAAA,GAoCA,QAAA,GAAA,GACA,EAAA,KAAA,GACA,IACA,GAAA,EACA,EAAA,IAIA,QAAA,GAAA,GACA,MAAA,QAAA,mBACA,OAAA,kBAAA,aAAA,IACA,EAGA,QAAA,KAGA,GAAA,CAEA,IAAA,GAAA,CACA,MAEA,EAAA,KAAA,SAAA,EAAA,GACA,MAAA,GAAA,KAAA,EAAA,MAGA,IAAA,IAAA,CACA,GAAA,QAAA,SAAA,GAGA,GAAA,GAAA,EAAA,aAEA,GAAA,GAGA,EAAA,SACA,EAAA,UAAA,EAAA,GACA,GAAA,KAKA,GACA,IAGA,QAAA,GAAA,GACA,EAAA,OAAA,QAAA,SAAA,GACA,GAAA,GAAA,EAAA,IAAA,EACA,IAEA,EAAA,QAAA,SAAA,GACA,EAAA,WAAA,GACA,EAAA,+BAiBA,QAAA,GAAA,EAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,WAAA,CACA,GAAA,GAAA,EAAA,IAAA,EAEA,IAAA,EACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,GACA,EAAA,EAAA,OAGA,IAAA,IAAA,GAAA,EAAA,QAAA,CAGA,GAAA,GAAA,EAAA,EACA,IACA,EAAA,QAAA,MAaA,QAAA,GAAA,GACA,KAAA,UAAA,EACA,KAAA,UACA,KAAA,YACA,KAAA,OAAA,EAoFA,QAAA,GAAA,EAAA,GACA,KAAA,KAAA,EACA,KAAA,OAAA,EACA,KAAA,cACA,KAAA,gBACA,KAAA,gBAAA,KACA,KAAA,YAAA,KACA,KAAA,cAAA,KACA,KAAA,mBAAA,KACA,KAAA,SAAA,KAGA,QAAA,GAAA,GACA,GAAA,GAAA,GAAA,GAAA,EAAA,KAAA,EAAA,OAQA,OAPA,GAAA,WAAA,EAAA,WAAA,QACA,EAAA,aAAA,EAAA,aAAA,QACA,EAAA,gBAAA,EAAA,gBACA,EAAA,YAAA,EAAA,YACA,EAAA,cAAA,EAAA,cACA,EAAA,mBAAA,EAAA,mBACA,EAAA,SAAA,EAAA,SACA,EAYA,QAAA,GAAA,EAAA,GACA,MAAA,GAAA,GAAA,GAAA,EAAA,GAQA,QAAA,GAAA,GACA,MAAA,GACA,GACA,EAAA,EAAA,GACA,EAAA,SAAA,EACA,GAGA,QAAA,KACA,EAAA,EAAA,OAQA,QAAA,GAAA,GACA,MAAA,KAAA,GAAA,IAAA,EAWA,QAAA,GAAA,EAAA,GACA,MAAA,KAAA,EACA,EAIA,GAAA,EAAA,GACA,EAEA,KAUA,QAAA,GAAA,EAAA,EAAA,GACA,KAAA,SAAA,EACA,KAAA,OAAA,EACA,KAAA,QAAA,EACA,KAAA,0BA1TA,GAAA,GAAA,GAAA,SAGA,EAAA,OAAA,cAGA,KAAA,EAAA,CACA,GAAA,MACA,EAAA,OAAA,KAAA,SACA,QAAA,iBAAA,UAAA,SAAA,GACA,GAAA,EAAA,OAAA,EAAA,CACA,GAAA,GAAA,CACA,MACA,EAAA,QAAA,SAAA,GACA,SAIA,EAAA,SAAA,GACA,EAAA,KAAA,GACA,OAAA,YAAA,EAAA,MAKA,GAAA,IAAA,EAGA,KAiGA,EAAA,CAcA,GAAA,WACA,QAAA,SAAA,EAAA,GAIA,GAHA,EAAA,EAAA,IAGA,EAAA,YAAA,EAAA,aAAA,EAAA,eAGA,EAAA,oBAAA,EAAA,YAGA,EAAA,iBAAA,EAAA,gBAAA,SACA,EAAA,YAGA,EAAA,wBAAA,EAAA,cAEA,KAAA,IAAA,YAGA,IAAA,GAAA,EAAA,IAAA,EACA,IACA,EAAA,IAAA,EAAA,KAOA,KAAA,GADA,GACA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,GAAA,EAAA,GAAA,WAAA,KAAA,CACA,EAAA,EAAA,GACA,EAAA,kBACA,EAAA,QAAA,CACA,OASA,IACA,EAAA,GAAA,GAAA,KAAA,EAAA,GACA,EAAA,KAAA,GACA,KAAA,OAAA,KAAA,IAGA,EAAA,gBAGA,WAAA,WACA,KAAA,OAAA,QAAA,SAAA,GAEA,IAAA,GADA,GAAA,EAAA,IAAA,GACA,EAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,EACA,IAAA,EAAA,WAAA,KAAA,CACA,EAAA,kBACA,EAAA,OAAA,EAAA,EAGA,UAGA,MACA,KAAA,aAGA,YAAA,WACA,GAAA,GAAA,KAAA,QAEA,OADA,MAAA,YACA,GAkCA,IAAA,GAAA,CAwEA,GAAA,WACA,QAAA,SAAA,GACA,GAAA,GAAA,KAAA,SAAA,SACA,EAAA,EAAA,MAMA,IAAA,EAAA,OAAA,EAAA,CACA,GAAA,GAAA,EAAA,EAAA,GACA,EAAA,EAAA,EAAA,EACA,IAAA,EAEA,YADA,EAAA,EAAA,GAAA,OAIA,GAAA,KAAA,SAGA,GAAA,GAAA,GAGA,aAAA,WACA,KAAA,cAAA,KAAA,SAGA,cAAA,SAAA,GACA,GAAA,GAAA,KAAA,OACA,GAAA,YACA,EAAA,iBAAA,kBAAA,MAAA,GAEA,EAAA,eACA,EAAA,iBAAA,2BAAA,MAAA,GAEA,EAAA,WACA,EAAA,iBAAA,kBAAA,MAAA,IAEA,EAAA,WAAA,EAAA,UACA,EAAA,iBAAA,iBAAA,MAAA,IAGA,gBAAA,WACA,KAAA,iBAAA,KAAA,SAGA,iBAAA,SAAA,GACA,GAAA,GAAA,KAAA,OACA,GAAA,YACA,EAAA,oBAAA,kBAAA,MAAA,GAEA,EAAA,eACA,EAAA,oBAAA,2BAAA,MAAA,GAEA,EAAA,WACA,EAAA,oBAAA,kBAAA,MAAA,IAEA,EAAA,WAAA,EAAA,UACA,EAAA,oBAAA,iBAAA,MAAA,IAQA,qBAAA,SAAA,GAGA,GAAA,IAAA,KAAA,OAAA,CAGA,KAAA,cAAA,GACA,KAAA,uBAAA,KAAA,EACA,IAAA,GAAA,EAAA,IAAA,EACA,IACA,EAAA,IAAA,EAAA,MAIA,EAAA,KAAA,QAGA,yBAAA,WACA,GAAA,GAAA,KAAA,sBACA,MAAA,0BAEA,EAAA,QAAA,SAAA,GAEA,KAAA,iBAAA,EAGA,KAAA,GADA,GAAA,EAAA,IAAA,GACA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,GAAA,EAAA,KAAA,KAAA,CACA,EAAA,OAAA,EAAA,EAGA,SAGA,OAGA,YAAA,SAAA,GAMA,OAFA,EAAA,2BAEA,EAAA,MACA,IAAA,kBAGA,GAAA,GAAA,EAAA,SACA,EAAA,EAAA,YAAA,aACA,EAAA,EAAA,OAGA,EAAA,GAAA,GAAA,aAAA,EACA,GAAA,cAAA,EACA,EAAA,mBAAA,CAGA,IAAA,GACA,EAAA,aAAA,cAAA,SAAA,KAAA,EAAA,SAEA,GAAA,EAAA,SAAA,GAEA,OAAA,EAAA,YAIA,EAAA,iBAAA,EAAA,gBAAA,QACA,KAAA,EAAA,gBAAA,QAAA,IACA,KAAA,EAAA,gBAAA,QAAA,GANA,OAUA,EAAA,kBACA,EAAA,GAGA,GAGA,MAEA,KAAA,2BAEA,GAAA,GAAA,EAAA,OAGA,EAAA,EAAA,gBAAA,GAGA,EAAA,EAAA,SAGA,GAAA,EAAA,SAAA,GAEA,MAAA,GAAA,cAIA,EAAA,sBACA,EAAA,GAGA,EARA,QAWA,MAEA,KAAA,iBACA,KAAA,qBAAA,EAAA,OAEA,KAAA,kBAEA,GAEA,GAAA,EAFA,EAAA,EAAA,YACA,EAAA,EAAA,MAEA,qBAAA,EAAA,MACA,GAAA,GACA,OAGA,KACA,GAAA,GAEA,IAAA,GAAA,EAAA,gBACA,EAAA,EAAA,YAGA,EAAA,EAAA,YAAA,EACA,GAAA,WAAA,EACA,EAAA,aAAA,EACA,EAAA,gBAAA,EACA,EAAA,YAAA,EAEA,EAAA,EAAA,SAAA,GAEA,MAAA,GAAA,UAIA,EAJA,SASA,MAIA,EAAA,mBAAA,EAEA,EAAA,mBACA,EAAA,iBAAA,IAGA,MC5hBA,OAAA,YAAA,OAAA,cAAA,UCCA,SAAA,GAGA,GACA,IADA,EAAA,KACA,EAAA,KACA,EAAA,EAAA,MAMA,EAAA,SAAA,EAAA,GACA,KAAA,SACA,KAAA,OAAA,EACA,KAAA,WAAA,EACA,KAAA,SAAA,EACA,KAAA,WAGA,GAAA,WACA,SAAA,SAAA,GAEA,KAAA,UAAA,EAAA,MAEA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,IAAA,EAAA,EAAA,IAAA,IACA,KAAA,QAAA,EAGA,MAAA,aAEA,QAAA,SAAA,GAEA,KAAA,WAEA,KAAA,QAAA,GAEA,KAAA,aAEA,QAAA,SAAA,GACA,GAAA,GAAA,EAAA,KAAA,EAAA,IAIA,GAAA,UAAA,EAEA,KAAA,OAAA,EAAA,IAEA,KAAA,MAAA,EAAA,IAGA,OAAA,SAAA,EAAA,GACA,GAAA,KAAA,QAAA,GAIA,MAFA,MAAA,QAAA,GAAA,KAAA,IAEA,CAGA,OAAA,MAAA,MAAA,IACA,KAAA,OAAA,EAAA,EAAA,KAAA,MAAA,IAEA,KAAA,QAEA,IAGA,KAAA,QAAA,IAAA,IAEA,IAEA,MAAA,SAAA,EAAA,GAEA,GADA,EAAA,MAAA,QAAA,IAAA,QAAA,EAAA,GACA,EAAA,MAAA,UAAA,CAEA,GAAA,GAAA,EAAA,MAAA,KACA,EAAA,EAAA,GACA,EAAA,EAAA,EAEA,GADA,EAAA,QAAA,WAAA,GACA,KAAA,GAEA,mBAAA,GAEA,WAAA,WACA,KAAA,QAAA,EAAA,EAAA,KAAA,IACA,KAAA,MAAA,OACA,CACA,GAAA,GAAA,SAAA,EAAA,GACA,KAAA,QAAA,EAAA,EAAA,EAAA,IACA,KAAA,KACA,GAAA,KAAA,EAAA,KAgBA,QAAA,SAAA,EAAA,EAAA,EAAA,GACA,KAAA,MAAA,GAAA,CAEA,KAAA,GAAA,GADA,EAAA,KAAA,QAAA,GACA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,IAAA,EAAA,EAAA,IAAA,IAEA,KAAA,OAAA,EAAA,EAAA,GAEA,KAAA,MAEA,MAAA,QAAA,GAAA,MAEA,KAAA,aACA,KAAA,SACA,KAAA,aAEA,UAAA,WACA,KAAA,UACA,KAAA,eAKA,EAAA,IACA,OAAA,EACA,GAAA,SAAA,GACA,MAAA,GAAA,QAAA,KAAA,EAAA,OAAA,KACA,MAAA,EAAA,QACA,IAAA,EAAA,QAEA,KAAA,SAAA,EAAA,EAAA,GACA,GAAA,GAAA,GAAA,eAYA,QAXA,EAAA,MAAA,OAAA,EAAA,MAAA,QACA,GAAA,IAAA,KAAA,UAEA,EAAA,KAAA,MAAA,EAAA,EAAA,OACA,EAAA,iBAAA,mBAAA,WACA,IAAA,EAAA,YACA,EAAA,KAAA,GAAA,EAAA,GAAA,IAAA,EACA,EAAA,UAAA,EAAA,aAAA,KAGA,EAAA,OACA,GAEA,aAAA,SAAA,EAAA,EAAA,GACA,KAAA,KAAA,EAAA,EAAA,GAAA,aAAA,aAKA,EAAA,IAAA,EACA,EAAA,OAAA,GAEA,OAAA,aC9JA,SAAA,GA4MA,QAAA,GAAA,GACA,MAAA,SAAA,EAAA,WAAA,EAAA,MAAA,EAGA,QAAA,GAAA,GACA,GAAA,GAAA,EAAA,EAAA,EACA,KACA,EAAA,KAAA,GACA,MAAA,GACA,EAAA,KAAA,SAAA,mBAAA,KACA,QAAA,KAAA,iGACA,GAEA,MAAA,+BAAA,EAGA,QAAA,GAAA,GACA,MAAA,GAAA,YAAA,EAAA,GAIA,QAAA,GAAA,GACA,GAAA,GAAA,EAAA,SACA,KAAA,EAAA,CACA,EAAA,EAAA,cAAA,OAEA,IAAA,GAAA,IAAA,KAAA,MAAA,KAAA,KAAA,SAAA,IAAA,IAGA,EAAA,EAAA,YAAA,MAAA,wBACA,GAAA,GAAA,EAAA,IAAA,EAEA,GAAA,IAAA,EAAA,MAEA,MAAA,mBAAA,EAAA,KAOA,QAAA,GAAA,GACA,GAAA,GAAA,EAAA,cAAA,cAAA,QAGA,OAFA,GAAA,YAAA,EAAA,YACA,EAAA,mBAAA,GACA,EAvPA,GAAA,GAAA,SACA,EAAA,EAAA,MACA,EAAA,UAAA,KAAA,UAAA,WAEA,EAAA,OAAA,kBACA,OAAA,kBAAA,aAAA,UAAA,SAUA,GAEA,kBAAA,YAAA,EAAA,IAEA,kBACA,YAAA,EAAA,IACA,uBACA,QACA,qBACA,kCACA,KAAA,KACA,KACA,KAAA,YACA,OAAA,cACA,MAAA,cAGA,UAAA,WACA,GAAA,GAAA,KAAA,aACA,IACA,KAAA,MAAA,IAGA,MAAA,SAAA,GACA,GAAA,KAAA,SAAA,GAEA,YADA,EAAA,OAAA,QAAA,IAAA,yBAAA,EAAA,WAGA,IAAA,GAAA,KAAA,KAAA,IAAA,EAAA,WACA,KACA,KAAA,YAAA,GACA,EAAA,KAAA,KAAA,KAMA,YAAA,SAAA,GACA,EAAA,OAAA,QAAA,IAAA,UAAA,GACA,KAAA,eAAA,GAEA,oBAAA,SAAA,GACA,EAAA,gBAAA,EACA,EAAA,kBACA,EAAA,gBAAA,gBAAA,GAEA,KAAA,eAAA,KACA,EAAA,OAAA,QAAA,IAAA,YAAA,GACA,KAAA,aAEA,YAAA,SAAA,GAgBA,GAfA,EAAA,OAAA,gBAAA,EAIA,YAAA,sBACA,YAAA,qBAAA,GAIA,EAAA,cADA,EAAA,WACA,GAAA,aAAA,QAAA,SAAA,IAEA,GAAA,aAAA,SAAA,SAAA,KAIA,EAAA,UAEA,IADA,GAAA,GACA,EAAA,UAAA,QACA,EAAA,EAAA,UAAA,QACA,GACA,GAAA,OAAA,GAIA,MAAA,oBAAA,IAEA,UAAA,SAAA,GACA,EAAA,GACA,KAAA,YAAA,IAGA,EAAA,KAAA,EAAA,KACA,KAAA,aAAA,KAGA,WAAA,SAAA,GAEA,GAAA,GAAA,CACA,GAAA,EAAA,GACA,EAAA,gBAAA,EACA,KAAA,aAAA,IAEA,aAAA,SAAA,GACA,KAAA,aAAA,GACA,SAAA,KAAA,YAAA,IAGA,aAAA,SAAA,EAAA,GACA,GAAA,GAAA,KACA,EAAA,SAAA,GACA,GACA,EAAA,GAEA,EAAA,oBAAA,GAOA,IALA,EAAA,iBAAA,OAAA,GACA,EAAA,iBAAA,QAAA,GAIA,GAAA,UAAA,EAAA,UAAA,CACA,GAAA,IAAA,CAEA,IAAA,IAAA,EAAA,YAAA,QAAA,WACA,GAAA,MAEA,IAAA,EAAA,MAAA,CACA,GAAA,CAIA,KAAA,GAAA,GAHA,EAAA,EAAA,MAAA,SACA,EAAA,EAAA,EAAA,OAAA,EAEA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,IAAA,IACA,EAAA,OAAA,QAAA,cAEA,EAAA,GAAA,QAAA,EAAA,aAKA,GACA,EAAA,cAAA,GAAA,aAAA,QAAA,SAAA,OAUA,YAAA,SAAA,GACA,GAAA,GAAA,SAAA,cAAA,SACA,GAAA,gBAAA,EACA,EAAA,IAAA,EAAA,IAAA,EAAA,IACA,EAAA,GACA,EAAA,cAAA,EACA,KAAA,aAAA,EAAA,WACA,EAAA,WAAA,YAAA,GACA,EAAA,cAAA,OAEA,SAAA,KAAA,YAAA,IAGA,YAAA,WACA,OAAA,KAAA,gBAAA,KAAA,iBAAA,IAEA,iBAAA,SAAA,EAAA,GAEA,IAAA,GAAA,GADA,EAAA,EAAA,iBAAA,KAAA,sBAAA,IACA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,IAAA,EAAA,EAAA,IAAA,IACA,IAAA,KAAA,SAAA,GACA,MAAA,MAAA,YAAA,GACA,EAAA,GAAA,KAAA,iBAAA,EAAA,OAAA,GAAA,EAEA,MAKA,OAAA,IAGA,sBAAA,SAAA,GACA,GAAA,GAAA,EAAA,eAAA,CACA,OAAA,KAAA,EAAA,KAAA,kBAAA,KAAA,kBAEA,SAAA,SAAA,GACA,MAAA,GAAA,gBAEA,YAAA,SAAA,GACA,MAAA,GAAA,KAAA,EAAA,QACA,GAEA,IAsDA,EAAA,sBACA,EAAA,qCAEA,GACA,mBAAA,SAAA,GACA,GAAA,GAAA,EAAA,cACA,EAAA,EAAA,cAAA,IAEA,OADA,GAAA,YAAA,KAAA,qBAAA,EAAA,YAAA,GACA,GAEA,qBAAA,SAAA,EAAA,GACA,GAAA,GAAA,KAAA,YAAA,EAAA,EAAA,EAEA,OADA,GAAA,KAAA,YAAA,EAAA,EAAA,IAGA,YAAA,SAAA,EAAA,EAAA,GACA,MAAA,GAAA,QAAA,EAAA,SAAA,EAAA,EAAA,EAAA,GACA,GAAA,GAAA,EAAA,QAAA,QAAA,GAGA,OAFA,GAAA,KAAA,EACA,EAAA,EAAA,KACA,EAAA,IAAA,EAAA,IAAA,KAMA,GAAA,OAAA,EACA,EAAA,KAAA,EACA,EAAA,KAAA,GAEA,aC5RA,SAAA,GA0FA,QAAA,GAAA,GACA,MAAA,GAAA,EAAA,GAGA,QAAA,GAAA,EAAA,GACA,MAAA,SAAA,EAAA,WAAA,EAAA,aAAA,SAAA,EAOA,QAAA,GAAA,EAAA,GAEA,GAAA,GAAA,CACA,aAAA,YACA,EAAA,SAAA,eAAA,mBAAA,IAGA,EAAA,KAAA,CAEA,IAAA,GAAA,EAAA,cAAA,OACA,GAAA,aAAA,OAAA,GAEA,EAAA,UACA,EAAA,QAAA,EAGA,IAAA,GAAA,EAAA,cAAA,OAmBA,OAlBA,GAAA,aAAA,UAAA,SAEA,EAAA,KAAA,YAAA,GACA,EAAA,KAAA,YAAA,GAMA,YAAA,YAEA,EAAA,KAAA,UAAA,GAIA,OAAA,qBAAA,oBAAA,WACA,oBAAA,UAAA,GAEA,EAsCA,QAAA,GAAA,EAAA,GACA,EAAA,GAAA,EAEA,EAAA,WACA,EAAA,EAAA,IACA,GAMA,QAAA,GAAA,GACA,MAAA,aAAA,EAAA,YACA,EAAA,aAAA,EAIA,QAAA,GAAA,EAAA,GACA,GAAA,EAAA,GASA,GACA,QAVA,CACA,GAAA,GAAA,YACA,aAAA,EAAA,YACA,EAAA,aAAA,KACA,EAAA,oBAAA,EAAA,GACA,EAAA,EAAA,IAGA,GAAA,iBAAA,EAAA,IAOA,QAAA,GAAA,EAAA,GAGA,QAAA,KACA,GAAA,GAEA,sBAAA,GAGA,QAAA,KACA,IACA,IAVA,GAAA,GAAA,EAAA,iBAAA,oBACA,EAAA,EAAA,EAAA,EAAA,MAWA,IAAA,EACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,IAAA,IACA,EAAA,GACA,EAAA,KAAA,IAEA,EAAA,iBAAA,OAAA,GACA,EAAA,iBAAA,QAAA,QAIA,KAIA,QAAA,GAAA,GACA,MAAA,GAAA,EAAA,QAAA,YAAA,EAAA,OAAA,WACA,EAAA,eA3OA,GAAA,GAAA,UAAA,UAAA,cAAA,QACA,EAAA,EACA,EAAA,EAAA,MACA,EAAA,SAGA,EAAA,OAAA,kBACA,kBAAA,aAAA,UAAA,QAEA,IAAA,EAkIA,GAAA,UA/HA,IACA,IADA,EAAA,IACA,EAAA,QACA,EAAA,EAAA,OAQA,GACA,aAEA,yBAAA,YAAA,EAAA,IAEA,yBACA,YAAA,EAAA,KACA,KAAA,KACA,SAAA,SAAA,GACA,EAAA,QAAA,IAGA,YAAA,SAAA,GACA,GAAA,GAAA,KAAA,aAAA,EAEA,GAAA,SAAA,IAEA,aAAA,SAAA,GAEA,MAAA,GAAA,iBAAA,KAAA,qBAAA,KAGA,qBAAA,SAAA,GACA,GAAA,GAAA,EAAA,eAAA,CACA,OAAA,KAAA,EAAA,KAAA,yBACA,KAAA,yBAEA,OAAA,SAAA,EAAA,EAAA,GAMA,GALA,EAAA,MAAA,QAAA,IAAA,SAAA,EAAA,GAIA,EAAA,WAAA,EACA,EAAA,GAAA,CACA,GAAA,GAAA,KAAA,UAAA,EAEA,KAEA,EAAA,EAAA,EAAA,GACA,EAAA,aAAA,EAGA,KAAA,aAAA,GAEA,KAAA,UAAA,GAAA,GAIA,EAAA,OAAA,EAEA,EAAA,aAEA,aAAA,SAAA,GACA,KAAA,YAAA,GACA,KAAA,QAAA,GACA,EAAA,aAEA,UAAA,WACA,EAAA,cAKA,EAAA,GAAA,GAAA,EAAA,OAAA,KAAA,GACA,EAAA,UAAA,KAAA,GA4DA,IAAA,IACA,IAAA,WACA,MAAA,aAAA,eAAA,SAAA,eAEA,cAAA,EAOA,IAJA,OAAA,eAAA,SAAA,iBAAA,GACA,OAAA,eAAA,EAAA,iBAAA,IAGA,SAAA,QAAA,CACA,GAAA,IACA,IAAA,WACA,MAAA,QAAA,SAAA,MAEA,cAAA,EAGA,QAAA,eAAA,SAAA,UAAA,GACA,OAAA,eAAA,EAAA,UAAA,GAgBA,GAAA,GAAA,YAAA,KAAA,WAAA,cACA,EAAA,kBAwDA,GAAA,UAAA,EACA,EAAA,UAAA,EACA,EAAA,SAAA,EACA,EAAA,iBAAA,EACA,EAAA,iBAAA,EACA,EAAA,eAAA,EACA,EAAA,aAAA,GAEA,OAAA,aCzPA,SAAA,GAOA,QAAA,GAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,IAAA,EAAA,EAAA,IAAA,IACA,cAAA,EAAA,MAAA,EAAA,WAAA,QACA,EAAA,EAAA,YAMA,QAAA,GAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,IAAA,EAAA,EAAA,IAAA,IACA,EAAA,IACA,EAAA,SAAA,GAEA,EAAA,UAAA,EAAA,SAAA,QACA,EAAA,EAAA,UAKA,QAAA,GAAA,GACA,MAAA,KAAA,EAAA,UAAA,EAAA,KAAA,EACA,EAAA,qBAAA,IAaA,QAAA,GAAA,GACA,EAAA,QAAA,GAAA,WAAA,EAAA,SAAA,IAzCA,GAEA,IAFA,EAAA,iBAEA,EAAA,UA6BA,EAAA,YAAA,UAAA,SACA,YAAA,UAAA,iBACA,YAAA,UAAA,uBACA,YAAA,UAAA,oBACA,YAAA,UAAA,kBAEA,EAAA,GAAA,kBAAA,EASA,GAAA,QAAA,EACA,EAAA,QAAA,GAEA,aCpDA,WAmCA,QAAA,KACA,YAAA,SAAA,aAAA,GA/BA,kBAAA,QAAA,cACA,OAAA,YAAA,SAAA,EAAA,GACA,GAAA,GAAA,SAAA,YAAA,aAKA,OAJA,GAAA,UAAA,EACA,EAAA,WAAA,GAAA,GAAA,EACA,EAAA,cAAA,GAAA,GAAA,EACA,EAAA,QACA,GAKA,IAAA,GAAA,OAAA,kBACA,OAAA,kBAAA,aAAA,UAAA,QAMA,aAAA,iBAAA,WACA,YAAA,OAAA,EACA,YAAA,WAAA,GAAA,OAAA,UACA,EAAA,cACA,GAAA,aAAA,qBAAA,SAAA,OAMA,YAAA,YAQA,aAAA,SAAA,YACA,gBAAA,SAAA,aAAA,OAAA,YACA,IAEA,SAAA,iBAAA,mBAAA,OC9CA,OAAA,eAAA,OAAA,iBAAA,UCCA,SAAA,GAQA,QAAA,GAAA,EAAA,EAAA,GACA,GAAA,GAAA,EAAA,iBACA,KAAA,EAEA,IADA,EAAA,EAAA,WACA,GAAA,EAAA,WAAA,KAAA,cACA,EAAA,EAAA,WAGA,MAAA,GACA,EAAA,EAAA,MAAA,GACA,EAAA,EAAA,EAAA,GAEA,EAAA,EAAA,kBAEA,OAAA,MAIA,QAAA,GAAA,EAAA,GAEA,IADA,GAAA,GAAA,EAAA,WACA,GACA,EAAA,EAAA,GACA,EAAA,EAAA,gBAMA,QAAA,GAAA,EAAA,GAEA,EAAA,EAAA,SAAA,GACA,MAAA,GAAA,IACA,MAEA,GAAA,EAAA,KAEA,EAAA,EAAA,GAKA,QAAA,GAAA,GACA,MAAA,GAAA,IACA,EAAA,IACA,OAEA,GAAA,GAIA,QAAA,GAAA,GACA,EAAA,EAAA,SAAA,GACA,MAAA,GAAA,IACA,EADA,SAOA,QAAA,GAAA,GACA,MAAA,GAAA,IAAA,EAAA,GAIA,QAAA,GAAA,GACA,IAAA,EAAA,cAAA,EAAA,WAAA,KAAA,aAAA,CACA,GAAA,GAAA,EAAA,aAAA,OAAA,EAAA,UACA,EAAA,EAAA,SAAA,EACA,IAAA,EAIA,MAHA,GAAA,KAAA,QAAA,MAAA,WAAA,EAAA,WACA,EAAA,QAAA,GACA,EAAA,KAAA,QAAA,YACA,GAKA,QAAA,GAAA,GACA,EAAA,GACA,EAAA,IACA,EAAA,EAAA,SAAA,GACA,EAAA,KAiBA,QAAA,GAAA,GAEA,GADA,EAAA,KAAA,IACA,EAAA,CACA,GAAA,CACA,IAAA,GAAA,OAAA,UAAA,OAAA,SAAA,gBACA,UACA,GAAA,IAIA,QAAA,KACA,GAAA,CAEA,KAAA,GAAA,GADA,EAAA,EACA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,IAAA,EAAA,EAAA,IAAA,IACA,GAEA,MAGA,QAAA,GAAA,GACA,EACA,EAAA,WACA,EAAA,KAGA,EAAA,GAKA,QAAA,GAAA,IAWA,EAAA,kBAAA,EAAA,kBAAA,EAAA,cAAA,EAAA,OACA,EAAA,KAAA,QAAA,MAAA,YAAA,EAAA,WACA,EAAA,KACA,EAAA,YAAA,EAAA,YAAA,GAAA,EAEA,EAAA,WAAA,IACA,EAAA,WAAA,GAGA,EAAA,WAAA,EACA,EAAA,KAAA,QAAA,KAAA,YAAA,EAAA,UACA,uBAAA,EAAA,YACA,EAAA,mBACA,EAAA,KAAA,QAAA,IAAA,YAAA,EAAA,WACA,EAAA,qBAGA,EAAA,KAAA,QAAA,YAIA,QAAA,GAAA,GACA,EAAA,GACA,EAAA,EAAA,SAAA,GACA,EAAA,KAIA,QAAA,GAAA,GACA,EACA,EAAA,WACA,EAAA,KAGA,EAAA,GAIA,QAAA,GAAA,IAGA,EAAA,kBAAA,EAAA,kBAAA,EAAA,cAAA,EAAA,OACA,EAAA,KAAA,QAAA,MAAA,WAAA,EAAA,WACA,EAAA,KACA,EAAA,YAAA,EAAA,YAAA,GAAA,EAEA,EAAA,WAAA,IACA,EAAA,WAAA,GAGA,EAAA,WAAA,EACA,EAAA,KAAA,QAAA,KAAA,WAAA,EAAA,UACA,uBAAA,EAAA,YACA,EAAA,kBACA,EAAA,oBAGA,EAAA,KAAA,QAAA,YAMA,QAAA,GAAA,GACA,MAAA,QAAA,kBAAA,kBAAA,aAAA,GACA,EAGA,QAAA,GAAA,GAGA,IAFA,GAAA,GAAA,EACA,EAAA,EAAA,UACA,GAAA,CACA,GAAA,GAAA,EACA,OAAA,CAEA,GAAA,EAAA,YAAA,EAAA,MAIA,QAAA,GAAA,GACA,GAAA,EAAA,aAAA,EAAA,WAAA,UAAA,CACA,EAAA,KAAA,QAAA,IAAA,6BAAA,EAAA,UAGA,KADA,GAAA,GAAA,EAAA,WACA,GACA,EAAA,GACA,EAAA,EAAA,iBAKA,QAAA,GAAA,GACA,EAAA,YACA,EAAA,GACA,EAAA,WAAA,GAIA,QAAA,GAAA,GAEA,GAAA,EAAA,IAAA,CACA,GAAA,GAAA,EAAA,EACA,IAAA,GAAA,cAAA,EAAA,MAAA,EAAA,YACA,EAAA,WAAA,CAEA,IADA,GAAA,GAAA,EAAA,WAAA,GACA,GAAA,IAAA,WAAA,EAAA,MACA,EAAA,EAAA,UAEA,IAAA,GAAA,IAAA,EAAA,KAAA,EAAA,MAAA,EAAA,MAAA,EAAA,KAAA,YAAA,EACA,GAAA,EAAA,MAAA,MAAA,QAAA,MAAA,KAAA,MAGA,QAAA,MAAA,sBAAA,EAAA,OAAA,GAAA,IAGA,EAAA,QAAA,SAAA,GAEA,cAAA,EAAA,OACA,EAAA,EAAA,WAAA,SAAA,GAEA,EAAA,WAIA,EAAA,KAGA,EAAA,EAAA,aAAA,SAAA,GAEA,EAAA,WAGA,EAAA,QAKA,EAAA,KAAA,QAAA,WAKA,QAAA,KAEA,EAAA,EAAA,eACA,IAKA,QAAA,GAAA,GACA,EAAA,QAAA,GAAA,WAAA,EAAA,SAAA,IAGA,QAAA,GAAA,GACA,EAAA,GAGA,QAAA,GAAA,GACA,EAAA,KAAA,QAAA,MAAA,oBAAA,EAAA,QAAA,MAAA,KAAA,OACA,EAAA,GACA,EAAA,KAAA,QAAA,WAGA,QAAA,GAAA,GACA,EAAA,EAAA,EAIA,KAAA,GAAA,GADA,EAAA,EAAA,iBAAA,YAAA,EAAA,KACA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,IAAA,EAAA,EAAA,IAAA,IACA,EAAA,QAAA,EAAA,OAAA,UACA,EAAA,EAAA,OAGA,GAAA,GA/TA,GAAA,GAAA,OAAA,aACA,EAAA,OAAA,YAAA,YAAA,iBAAA,OAiGA,GAAA,OAAA,kBACA,OAAA,mBAAA,OAAA,kBACA,GAAA,qBAAA,CAEA,IAAA,IAAA,EACA,KAsLA,EAAA,GAAA,kBAAA,GAQA,EAAA,MAAA,UAAA,QAAA,KAAA,KAAA,MAAA,UAAA,QA8BA,GAAA,iBAAA,EACA,EAAA,YAAA,EACA,EAAA,oBAAA,EACA,EAAA,WAAA,EACA,EAAA,eAAA,EACA,EAAA,aAAA,EAEA,EAAA,gBAAA,EACA,EAAA,gBAAA,EAEA,EAAA,YAAA,GAEA,OAAA,gBCvUA,SAAA,GA8EA,QAAA,GAAA,EAAA,GAIA,GAAA,GAAA,KACA,KAAA,EAGA,KAAA,IAAA,OAAA,oEAEA,IAAA,EAAA,QAAA,KAAA,EAGA,KAAA,IAAA,OAAA,uGAAA,OAAA,GAAA,KAGA,IAAA,EAAA,GACA,KAAA,IAAA,OAAA,oFAAA,OAAA,GAAA,+BAGA,IAAA,EAAA,GACA,KAAA,IAAA,OAAA,+CAAA,OAAA,GAAA,0BAIA,KAAA,EAAA,UAGA,KAAA,IAAA,OAAA,8CA+BA,OA5BA,GAAA,OAAA,EAAA,cAEA,EAAA,UAAA,EAAA,cAIA,EAAA,SAAA,EAAA,EAAA,SAGA,EAAA,GAGA,EAAA,GAEA,EAAA,EAAA,WAEA,EAAA,EAAA,OAAA,GAGA,EAAA,KAAA,EAAA,GACA,EAAA,KAAA,UAAA,EAAA,UAEA,EAAA,UAAA,YAAA,EAAA,KAEA,EAAA,OAEA,EAAA,oBAAA,UAEA,EAAA,KAGA,QAAA,GAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IACA,GAAA,IAAA,EAAA,GACA,OAAA,EAUA,QAAA,GAAA,GACA,GAAA,GAAA,EAAA,EACA,OAAA,GACA,EAAA,EAAA,SAAA,QAAA,OAKA,QAAA,GAAA,GAMA,IAAA,GAAA,GAHA,EAAA,EAAA,QAGA,EAAA,EAAA,EAAA,EAAA,SAAA,GAAA,IACA,EAAA,EAAA,IAAA,EAAA,GAGA,GAAA,IAAA,GAAA,EAAA,OACA,IAEA,EAAA,GAAA,EAAA,QAIA,QAAA,GAAA,GAGA,IAAA,OAAA,UAAA,CAEA,GAAA,GAAA,YAAA,SAEA,IAAA,EAAA,GAAA,CACA,GAAA,GAAA,SAAA,cAAA,EAAA,IACA,GAAA,OAAA,eAAA,GAQA,IADA,GAAA,GAAA,EAAA,EAAA,UACA,GAAA,IAAA,GAAA,CACA,GAAA,GAAA,OAAA,eAAA,EACA,GAAA,UAAA,EACA,EAAA,GAIA,EAAA,OAAA,EAKA,QAAA,GAAA,GAOA,MAAA,GAAA,EAAA,EAAA,KAAA,GAGA,QAAA,GAAA,EAAA,GAkBA,MAhBA,GAAA,IACA,EAAA,aAAA,KAAA,EAAA,IAGA,EAAA,gBAAA,cAEA,EAAA,EAAA,GAEA,EAAA,cAAA,EAEA,EAAA,GAEA,EAAA,aAAA,GAEA,EAAA,eAAA,GAEA,EAGA,QAAA,GAAA,EAAA,GAEA,OAAA,UACA,EAAA,UAAA,EAAA,WAKA,EAAA,EAAA,EAAA,UAAA,EAAA,QACA,EAAA,UAAA,EAAA,WAIA,QAAA,GAAA,EAAA,EAAA,GASA,IALA,GAAA,MAEA,EAAA,EAGA,IAAA,GAAA,IAAA,YAAA,WAAA,CAEA,IAAA,GAAA,GADA,EAAA,OAAA,oBAAA,GACA,EAAA,EAAA,EAAA,EAAA,GAAA,IACA,EAAA,KACA,OAAA,eAAA,EAAA,EACA,OAAA,yBAAA,EAAA,IACA,EAAA,GAAA,EAGA,GAAA,OAAA,eAAA,IAIA,QAAA,GAAA,GAEA,EAAA,iBACA,EAAA,kBAMA,QAAA,GAAA,GAIA,IAAA,EAAA,aAAA,YAAA,CAGA,GAAA,GAAA,EAAA,YACA,GAAA,aAAA,SAAA,EAAA,GACA,EAAA,KAAA,KAAA,EAAA,EAAA,GAEA,IAAA,GAAA,EAAA,eACA,GAAA,gBAAA,SAAA,GACA,EAAA,KAAA,KAAA,EAAA,KAAA,IAEA,EAAA,aAAA,aAAA,GAKA,QAAA,GAAA,EAAA,EAAA,GACA,GAAA,GAAA,KAAA,aAAA,EACA,GAAA,MAAA,KAAA,UACA,IAAA,GAAA,KAAA,aAAA,EACA,MAAA,0BACA,IAAA,GACA,KAAA,yBAAA,EAAA,EAAA,GAQA,QAAA,GAAA,GACA,MAAA,GACA,EAAA,EAAA,eADA,OAKA,QAAA,GAAA,EAAA,GACA,EAAA,GAAA,EAGA,QAAA,GAAA,GACA,MAAA,YACA,MAAA,GAAA,IAKA,QAAA,GAAA,EAAA,EAAA,GAGA,MAAA,KAAA,EACA,EAAA,EAAA,GAEA,EAAA,EAAA,GAIA,QAAA,GAAA,EAAA,GAGA,GAAA,GAAA,EAAA,GAAA,EACA,IAAA,EAAA,CACA,GAAA,GAAA,EAAA,KAAA,GAAA,EAAA,GACA,MAAA,IAAA,GAAA,IAGA,KAAA,IAAA,EAAA,GACA,MAAA,IAAA,GAAA,KAIA,GAAA,EAAA,CACA,GAAA,GAAA,EAAA,EAEA,OADA,GAAA,aAAA,KAAA,GACA,EAEA,GAAA,GAAA,EAAA,EAKA,OAHA,GAAA,QAAA,MAAA,GACA,EAAA,EAAA,aAEA,EAGA,QAAA,GAAA,GACA,IAAA,EAAA,cAAA,EAAA,WAAA,KAAA,aAAA,CACA,GAAA,GAAA,EAAA,aAAA,MACA,EAAA,EAAA,GAAA,EAAA,UACA,IAAA,EAAA,CACA,GAAA,GAAA,EAAA,KAAA,EAAA,UACA,MAAA,GAAA,EAAA,EACA,KAAA,IAAA,EAAA,QACA,MAAA,GAAA,EAAA,KAMA,QAAA,GAAA,GAEA,GAAA,GAAA,EAAA,KAAA,KAAA,EAIA,OAFA,GAAA,WAAA,GAEA,EAlYA,IACA,EAAA,OAAA,gBAAA,UAEA,IAAA,GAAA,EAAA,MAIA,EAAA,QAAA,SAAA,iBAMA,GAAA,EAAA,UAAA,IAAA,OAAA,iBAEA,IAAA,EAAA,CAGA,GAAA,GAAA,YAGA,GAAA,YACA,EAAA,eAAA,EAEA,EAAA,YAAA,EACA,EAAA,QAAA,EACA,EAAA,WAAA,EACA,EAAA,eAAA,EACA,EAAA,gBAAA,EACA,EAAA,gBAAA,EACA,EAAA,oBAAA,EACA,EAAA,YAAA,EACA,EAAA,uBAEA,CA8GA,GAAA,IACA,iBAAA,gBAAA,YAAA,gBACA,gBAAA,mBAAA,iBAAA,iBAoKA,KAkBA,EAAA,+BA8DA,EAAA,SAAA,cAAA,KAAA,UACA,EAAA,SAAA,gBAAA,KAAA,UAIA,EAAA,KAAA,UAAA,SAIA,UAAA,gBAAA,EACA,SAAA,cAAA,EACA,SAAA,gBAAA,EACA,KAAA,UAAA,UAAA,EAEA,EAAA,SAAA,EAaA,EAAA,QAAA,EAKA,GAAA,EAgBA,GAfA,OAAA,WAAA,EAeA,SAAA,EAAA,GACA,MAAA,aAAA,IAfA,SAAA,EAAA,GAEA,IADA,GAAA,GAAA,EACA,GAAA,CAIA,GAAA,IAAA,EAAA,UACA,OAAA,CAEA,GAAA,EAAA,UAEA,OAAA,GASA,EAAA,WAAA,EACA,EAAA,gBAAA,EAGA,SAAA,SAAA,SAAA,gBAEA,EAAA,UAAA,EACA,EAAA,UAAA,GAEA,OAAA,gBCndA,SAAA,GA6CA,QAAA,GAAA,GACA,MAAA,SAAA,EAAA,WACA,EAAA,aAAA,SAAA,EA3CA,GAAA,GAAA,EAAA,iBAIA,GACA,WACA,YAAA,EAAA,KAEA,KACA,KAAA,aAEA,MAAA,SAAA,GACA,IAAA,EAAA,SAAA,CAEA,EAAA,UAAA,CAEA,IAAA,GAAA,EAAA,iBAAA,EAAA,UAEA,GAAA,EAAA,SAAA,GACA,EAAA,EAAA,IAAA,EAAA,YAAA,KAIA,eAAA,gBAAA,GAEA,eAAA,gBAAA,KAGA,UAAA,SAAA,GAEA,EAAA,IACA,KAAA,YAAA,IAGA,YAAA,SAAA,GACA,EAAA,QACA,EAAA,MAAA,EAAA,UAUA,EAAA,MAAA,UAAA,QAAA,KAAA,KAAA,MAAA,UAAA,QAIA,GAAA,OAAA,EACA,EAAA,iBAAA,GAEA,OAAA,gBC1DA,SAAA,GAGA,QAAA,KAEA,eAAA,OAAA,MAAA,UAEA,eAAA,gBAAA,SAEA,IAAA,GAAA,OAAA,UAAA,SAAA,eACA,SAAA,eACA,UACA,GAAA,WAGA,eAAA,OAAA,EAEA,eAAA,UAAA,KAAA,MACA,OAAA,cACA,eAAA,QAAA,eAAA,UAAA,YAAA,WAGA,SAAA,cACA,GAAA,aAAA,sBAAA,SAAA,KAIA,OAAA,cACA,YAAA,qBAAA,SAAA,GACA,eAAA,OAAA,MAAA,EAAA,YAkBA,GAXA,kBAAA,QAAA,cACA,OAAA,YAAA,SAAA,GACA,GAAA,GAAA,SAAA,YAAA,aAEA,OADA,GAAA,UAAA,GAAA,GAAA,GACA,IAOA,aAAA,SAAA,YAAA,EAAA,MAAA,MACA,QAGA,IAAA,gBAAA,SAAA,YAAA,OAAA,aACA,OAAA,cAAA,OAAA,YAAA,MAIA,CACA,GAAA,GAAA,OAAA,cAAA,YAAA,MACA,oBAAA,kBACA,QAAA,iBAAA,EAAA,OANA,MASA,OAAA,gBC9DA,WAEA,GAAA,OAAA,kBAAA,CAGA,GAAA,IAAA,aAAA,iBAAA,kBACA,mBAGA,IACA,GAAA,QAAA,SAAA,GACA,EAAA,GAAA,eAAA,KAIA,EAAA,QAAA,SAAA,GACA,eAAA,GAAA,SAAA,GACA,MAAA,GAAA,GAAA,KAAA,WCjBA,SAAA,GAIA,QAAA,GAAA,GACA,KAAA,MAAA,EAJA,GAAA,GAAA,EAAA,cAMA,GAAA,WAGA,YAAA,SAAA,EAAA,GAGA,IAFA,GACA,GAAA,EADA,KAEA,EAAA,KAAA,MAAA,KAAA,IACA,EAAA,GAAA,KAAA,EAAA,GAAA,GACA,EAAA,MAAA,QAAA,EAAA,GAAA,IAAA,EAAA,MAEA,OAAA,IAIA,QAAA,SAAA,EAAA,EAAA,GACA,GAAA,GAAA,KAAA,YAAA,EAAA,EACA,MAAA,MAAA,KAAA,IAGA,MAAA,SAAA,EAAA,EAAA,GACA,GAAA,GAAA,EAAA,MAGA,KAAA,EACA,MAAA,GAAA,EAwBA,KAAA,GADA,GAAA,EAAA,EApBA,EAAA,WACA,MAAA,GACA,EAAA,IAKA,EAAA,SAAA,EAAA,GACA,GAAA,GAAA,EAAA,MACA,EAAA,EAAA,GAEA,IAAA,EAEA,MADA,GAAA,GAAA,GACA,GAEA;GAAA,GAAA,EAAA,UAAA,EAAA,YACA,GAAA,GAAA,EACA,KAAA,MAAA,KAAA,YAAA,EAAA,GAAA,EAAA,IAIA,EAAA,EAAA,EAAA,EAAA,IACA,EAAA,EAAA,GACA,EAAA,EAAA,IAEA,EAAA,GAEA,EAAA,IAGA,EAAA,KAAA,IAAA,EAAA,EAAA,MACA,EAAA,MAAA,EAEA,EAAA,GAAA,IAGA,IAAA,SAAA,EAAA,EAAA,GACA,GAAA,GAAA,GAAA,eASA,OARA,GAAA,KAAA,MAAA,GAAA,GACA,EAAA,OACA,EAAA,OAAA,WACA,EAAA,KAAA,EAAA,KAAA,IAEA,EAAA,QAAA,WACA,EAAA,KAAA,EAAA,KAAA,IAEA,IAIA,EAAA,OAAA,GACA,OAAA,UCrFA,SAAA,GAKA,QAAA,KACA,KAAA,OAAA,GAAA,GAAA,KAAA,OAJA,GAAA,GAAA,EAAA,YACA,EAAA,EAAA,MAKA,GAAA,WACA,MAAA,+CAEA,QAAA,SAAA,EAAA,EAAA,GACA,GAAA,GAAA,SAAA,GACA,EAAA,KAAA,QAAA,EAAA,EAAA,KACA,KAAA,KACA,MAAA,OAAA,QAAA,EAAA,EAAA,IAGA,YAAA,SAAA,EAAA,GACA,GAAA,GAAA,EAAA,YACA,EAAA,EAAA,cAAA,QACA,EAAA,SAAA,GACA,EAAA,YAAA,EACA,EAAA,GAEA,MAAA,QAAA,EAAA,EAAA,IAGA,QAAA,SAAA,EAAA,EAAA,GAGA,IAAA,GADA,GAAA,EAAA,EADA,EAAA,KAAA,OAAA,YAAA,EAAA,GAEA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,EAAA,GACA,EAAA,EAAA,IAEA,EAAA,EAAA,eAAA,EAAA,GAAA,GAEA,EAAA,KAAA,QAAA,EAAA,EAAA,GACA,EAAA,EAAA,QAAA,EAAA,QAAA,EAEA,OAAA,IAEA,WAAA,SAAA,EAAA,GAGA,QAAA,KACA,IACA,IAAA,GAAA,GACA,IAGA,IAAA,GAAA,GARA,EAAA,EAAA,EAAA,EAAA,OAQA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,IAAA,IACA,KAAA,YAAA,EAAA,IAKA,IAAA,GAAA,GAAA,EAGA,GAAA,cAAA,GAEA,OAAA,UC7DA,SAAA,GACA,EAAA,MACA,EAAA,SAAA,EAAA,YACA,IAAA,IACA,OAAA,SAAA,GACA,MAAA,GACA,EAAA,YAAA,EAAA,iBADA,QAIA,UAAA,SAAA,GACA,MAAA,IAAA,QAAA,EAAA,mBAEA,gBAAA,SAAA,GACA,GAAA,GAAA,KAAA,OAAA,EACA,OAAA,MAAA,UAAA,GACA,EADA,QAIA,YAAA,SAAA,GACA,GAAA,GAAA,EAAA,eACA,KAAA,EAAA,CACA,GAAA,GAAA,EAAA,cAAA,SACA,KACA,EAAA,EAAA,iBAGA,MAAA,IAEA,WAAA,SAAA,GAEA,IADA,GAAA,MAAA,EAAA,KAAA,OAAA,GACA,GACA,EAAA,KAAA,GACA,EAAA,KAAA,YAAA,EAEA,OAAA,IAEA,WAAA,SAAA,EAAA,EAAA,GACA,GAAA,EAAA,CACA,GACA,GAAA,EADA,EAAA,EAAA,iBAAA,EAAA,EAIA,KADA,EAAA,KAAA,gBAAA,GACA,GAAA,CAGA,GADA,EAAA,EAAA,iBAAA,EAAA,GAIA,CAEA,GAAA,GAAA,KAAA,gBAAA,EACA,OAAA,MAAA,WAAA,EAAA,EAAA,IAAA,EAJA,EAAA,KAAA,YAAA,GAQA,MAAA,KAGA,MAAA,SAAA,GAGA,IAFA,GAAA,GAAA,EAEA,EAAA,YACA,EAAA,EAAA,UAMA,OAHA,GAAA,UAAA,KAAA,eAAA,EAAA,UAAA,KAAA,yBACA,EAAA,UAEA,GAEA,WAAA,SAAA,GACA,GAAA,GAAA,EAAA,QAAA,EAAA,EAAA,QAEA,EAAA,KAAA,MAAA,EAAA,OAKA,OAHA,GAAA,iBAAA,EAAA,KACA,EAAA,UAEA,KAAA,WAAA,EAAA,EAAA,IAGA,GAAA,cAAA,EACA,EAAA,WAAA,EAAA,WAAA,KAAA,GAEA,OAAA,sBAAA,GACA,OAAA,uBCtFA,WACA,QAAA,GAAA,GACA,MAAA,sBAAA,EAAA,GAEA,QAAA,GAAA,GACA,MAAA,kBAAA,EAAA,KAEA,QAAA,GAAA,GACA,MAAA,uBAAA,EAAA,mBAAA,EAAA,gCAEA,GAAA,IACA,OACA,OACA,QACA,SAEA,KAAA,cACA,WACA,cACA,iBAIA,EAAA,GAGA,GADA,SAAA,KACA,OAAA,cAAA,OAAA,gBAEA,GAAA,OAAA,mBAAA,SAAA,KAAA,gBAEA,IAAA,EAAA,CACA,EAAA,QAAA,SAAA,GACA,OAAA,KAAA,GACA,GAAA,EAAA,GAAA,EAAA,GAAA,KACA,IACA,GAAA,EAAA,GAAA,EAAA,GAAA,QAGA,GAAA,EAAA,UAAA,IAAA,GAAA,EAAA,EAAA,MAAA,KACA,IACA,GAAA,EAAA,UAAA,IAAA,GAAA,EAAA,EAAA,MAAA,QAKA,IAAA,GAAA,SAAA,cAAA,QACA,GAAA,YAAA,EACA,SAAA,KAAA,YAAA,OChCA,SAAA,GAwCA,QAAA,GAAA,EAAA,GACA,EAAA,GAAA,OAAA,OAAA,KAEA,IAAA,GAAA,SAAA,YAAA,QACA,GAAA,UAAA,EAAA,EAAA,UAAA,EAAA,EAAA,aAAA,EAGA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,EAAA,GACA,EAAA,GAAA,EAAA,IAAA,EAAA,EAEA,GAAA,QAAA,EAAA,SAAA,CAIA,IAAA,GAAA,CAqBA,OAnBA,GADA,EAAA,SACA,EAAA,SAEA,EAAA,QAAA,GAAA,EAIA,EAAA,EAAA,EAAA,QACA,EAAA,EAAA,EAAA,QAGA,EAAA,UAAA,EAAA,WAAA,EACA,EAAA,MAAA,EAAA,OAAA,EACA,EAAA,OAAA,EAAA,QAAA,EACA,EAAA,SAAA,EACA,EAAA,MAAA,EAAA,OAAA,EACA,EAAA,MAAA,EAAA,OAAA,EACA,EAAA,YAAA,EAAA,aAAA,GACA,EAAA,YAAA,EAAA,aAAA,EACA,EAAA,UAAA,EAAA,YAAA,EACA,EA1EA,GAAA,IACA,UACA,aACA,OACA,SACA,UACA,UACA,UACA,UACA,UACA,SACA,WACA,UACA,SACA,gBACA,QACA,SAGA,IACA,GACA,EACA,KACA,KACA,EACA,EACA,EACA,GACA,GACA,GACA,GACA,EACA,EACA,KACA,EACA,EA2CA,GAAA,eACA,EAAA,aAAA,IAEA,QC9FA,SAAA,GAGA,QAAA,KACA,GAAA,EAAA,CACA,GAAA,GAAA,GAAA,IAEA,OADA,GAAA,SAAA,EACA,EAEA,KAAA,QACA,KAAA,UATA,GAAA,GAAA,OAAA,KAAA,OAAA,IAAA,UAAA,QACA,EAAA,WAAA,MAAA,MAAA,KAYA,GAAA,WACA,IAAA,SAAA,EAAA,GACA,GAAA,GAAA,KAAA,KAAA,QAAA,EACA,GAAA,GACA,KAAA,OAAA,GAAA,GAEA,KAAA,KAAA,KAAA,GACA,KAAA,OAAA,KAAA,KAGA,IAAA,SAAA,GACA,MAAA,MAAA,KAAA,QAAA,GAAA,IAEA,SAAA,SAAA,GACA,GAAA,GAAA,KAAA,KAAA,QAAA,EACA,GAAA,KACA,KAAA,KAAA,OAAA,EAAA,GACA,KAAA,OAAA,OAAA,EAAA,KAGA,IAAA,SAAA,GACA,GAAA,GAAA,KAAA,KAAA,QAAA,EACA,OAAA,MAAA,OAAA,IAEA,MAAA,WACA,KAAA,KAAA,OAAA,EACA,KAAA,OAAA,OAAA,GAGA,QAAA,SAAA,EAAA,GACA,KAAA,OAAA,QAAA,SAAA,EAAA,GACA,EAAA,KAAA,EAAA,EAAA,KAAA,KAAA,GAAA,OACA,OAEA,SAAA,WACA,MAAA,MAAA,KAAA,SAIA,EAAA,WAAA,GACA,OAAA,uBCzDA,SAAA,GACA,GAAA,IAEA,UACA,aACA,OACA,SACA,UACA,UACA,UACA,UACA,UACA,SACA,WACA,UACA,SACA,gBAEA,UAEA,YACA,QACA,SACA,WACA,QACA,QACA,cACA,cACA,YAEA,OACA,SACA,gBACA,QACA,QACA,SAGA,IAEA,GACA,EACA,KACA,KACA,EACA,EACA,EACA,GACA,GACA,GACA,GACA,EACA,EACA,KAEA,EAEA,EACA,EACA,EACA,EACA,EACA,EACA,GACA,GACA,EAEA,GACA,KACA,KACA,EACA,EACA,GAGA,EAAA,mBAAA,oBAcA,GACA,WAAA,GAAA,GAAA,WACA,SAAA,OAAA,OAAA,MACA,YAAA,OAAA,OAAA,MAGA,aAAA,OAAA,OAAA,MACA,mBASA,eAAA,SAAA,EAAA,GACA,GAAA,GAAA,EACA,EAAA,EAAA,MACA,KACA,EAAA,QAAA,SAAA,GACA,EAAA,KACA,KAAA,SAAA,GAAA,EAAA,GAAA,KAAA,KAEA,MACA,KAAA,aAAA,GAAA,EACA,KAAA,gBAAA,KAAA,KAGA,SAAA,SAAA,GAEA,IAAA,GAAA,GADA,EAAA,KAAA,gBAAA,OACA,EAAA,EAAA,EAAA,IAAA,EAAA,KAAA,gBAAA,IAAA,IAEA,EAAA,SAAA,KAAA,EAAA,IAGA,WAAA,SAAA,GAEA,IAAA,GAAA,GADA,EAAA,KAAA,gBAAA,OACA,EAAA,EAAA,EAAA,IAAA,EAAA,KAAA,gBAAA,IAAA,IAEA,EAAA,WAAA,KAAA,EAAA,IAGA,SAAA,EAAA,SAAA,UAAA,SAAA,EAAA,GACA,MAAA,GAAA,SAAA,IAGA,KAAA,SAAA,GACA,EAAA,SAAA,EACA,KAAA,UAAA,cAAA,IAEA,KAAA,SAAA,GACA,EAAA,SAAA,EACA,KAAA,UAAA,cAAA,IAEA,GAAA,SAAA,GACA,EAAA,SAAA,EACA,KAAA,UAAA,YAAA,IAEA,MAAA,SAAA,GACA,EAAA,SAAA,EACA,KAAA,UAAA,eAAA,IAEA,MAAA,SAAA,GACA,EAAA,SAAA,EACA,KAAA,UAAA,eAAA,IAEA,KAAA,SAAA,GACA,EAAA,SAAA,EACA,KAAA,UAAA,cAAA,IAEA,IAAA,SAAA,GACA,EAAA,SAAA,EACA,KAAA,UAAA,aAAA,IAEA,OAAA,SAAA,GACA,EAAA,SAAA,EACA,KAAA,UAAA,gBAAA,IAEA,SAAA,SAAA,GACA,KAAA,IAAA,GACA,KAAA,SAAA,EAAA,OAAA,EAAA,gBACA,KAAA,MAAA,IAGA,UAAA,SAAA,GACA,KAAA,KAAA,GACA,KAAA,SAAA,EAAA,OAAA,EAAA,gBACA,KAAA,MAAA,IAIA,aAAA,SAAA,GAIA,IAAA,EAAA,aAAA,CAGA,GAAA,GAAA,EAAA,KACA,EAAA,KAAA,UAAA,KAAA,SAAA,EACA,IACA,EAAA,GAEA,EAAA,cAAA,IAGA,OAAA,SAAA,EAAA,GACA,EAAA,QAAA,SAAA,GACA,KAAA,SAAA,EAAA,IACA,OAGA,SAAA,SAAA,EAAA,GACA,EAAA,QAAA,SAAA,GACA,KAAA,YAAA,EAAA,IACA,OAEA,SAAA,EAAA,SAAA,UAAA,SAAA,EAAA,GACA,EAAA,iBAAA,EAAA,KAAA,eAEA,YAAA,EAAA,SAAA,aAAA,SAAA,EAAA,GACA,EAAA,oBAAA,EAAA,KAAA,eAWA,UAAA,SAAA,EAAA,GAEA,KAAA,YAAA,EAAA,aACA,EAAA,cAAA,KAEA,IAAA,GAAA,GAAA,cAAA,EAAA,EAKA,OAJA,GAAA,iBACA,EAAA,eAAA,EAAA,gBAEA,EAAA,QAAA,EAAA,SAAA,EAAA,OACA,GAGA,UAAA,SAAA,EAAA,GACA,GAAA,GAAA,KAAA,UAAA,EAAA,EACA,OAAA,MAAA,cAAA,IASA,WAAA,SAAA,GAEA,IAAA,GADA,GAAA,EAAA,OAAA,OAAA,MACA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,EAAA,GACA,EAAA,GAAA,EAAA,IAAA,EAAA,IAIA,GAAA,WAAA,GAAA,kBAAA,GACA,EAAA,YAAA,sBACA,EAAA,GAAA,EAAA,GAAA,wBAUA,OALA,GAAA,iBACA,EAAA,eAAA,WACA,EAAA,mBAGA,GAEA,UAAA,SAAA,GAGA,MAAA,MAAA,YAAA,EAAA,YAAA,EAAA,SAEA,WAAA,SAAA,EAAA,GACA,KAAA,YAAA,IACA,KAAA,eAAA,GAEA,KAAA,YAAA,GAAA,CACA,IAAA,GAAA,SAAA,YAAA,QACA,GAAA,UAAA,qBAAA,GAAA,GACA,EAAA,UAAA,EACA,KAAA,gBAAA,KAAA,eAAA,KAAA,KAAA,GACA,SAAA,iBAAA,YAAA,KAAA,iBACA,SAAA,iBAAA,gBAAA,KAAA,iBACA,EAAA,QAAA,EACA,KAAA,mBAAA,IAEA,eAAA,SAAA,GACA,GAAA,GAAA,KAAA,YAAA,EACA,IAAA,EAAA,CACA,GAAA,GAAA,SAAA,YAAA,QACA,GAAA,UAAA,sBAAA,GAAA,GACA,EAAA,UAAA,EACA,KAAA,YAAA,GAAA,OACA,SAAA,oBAAA,YAAA,KAAA,iBACA,SAAA,oBAAA,gBAAA,KAAA,iBACA,EAAA,QAAA,EACA,KAAA,mBAAA,KASA,cAAA,EAAA,SAAA,eAAA,SAAA,GACA,GAAA,GAAA,KAAA,UAAA,EACA,OAAA,GACA,EAAA,cAAA,GADA,QAIA,mBAAA,SAAA,GACA,sBAAA,KAAA,cAAA,KAAA,KAAA,KAGA,GAAA,aAAA,EAAA,aAAA,KAAA,GACA,EAAA,WAAA,EACA,EAAA,SAAA,EAAA,SAAA,KAAA,GACA,EAAA,WAAA,EAAA,WAAA,KAAA,IACA,OAAA,uBCzTA,SAAA,GAeA,QAAA,GAAA,EAAA,EAAA,EAAA,GACA,KAAA,YAAA,EAAA,KAAA,GACA,KAAA,eAAA,EAAA,KAAA,GACA,KAAA,gBAAA,EAAA,KAAA,GACA,IACA,KAAA,SAAA,GAAA,GAAA,KAAA,gBAAA,KAAA,QAnBA,GAAA,GAAA,MAAA,UAAA,QAAA,KAAA,KAAA,MAAA,UAAA,SACA,EAAA,MAAA,UAAA,IAAA,KAAA,KAAA,MAAA,UAAA,KACA,EAAA,MAAA,UAAA,MAAA,KAAA,KAAA,MAAA,UAAA,OACA,EAAA,MAAA,UAAA,OAAA,KAAA,KAAA,MAAA,UAAA,QACA,EAAA,OAAA,kBAAA,OAAA,uBACA,EAAA,iBACA,GACA,SAAA,EACA,WAAA,EACA,YAAA,EACA,mBAAA,EACA,iBAAA,gBAYA,GAAA,WACA,aAAA,SAAA,GAQA,EAAA,cAAA,UAAA,IACA,KAAA,SAAA,QAAA,EAAA,IAGA,gBAAA,SAAA,GACA,KAAA,aAAA,GACA,IAAA,UAAA,aAAA,SAAA,WACA,KAAA,gBAEA,KAAA,kBAAA,IAGA,kBAAA,SAAA,GACA,EAAA,KAAA,aAAA,GAAA,KAAA,WAAA,OAEA,aAAA,SAAA,GACA,MAAA,GAAA,iBACA,EAAA,iBAAA,OAIA,cAAA,SAAA,GACA,KAAA,eAAA,IAEA,WAAA,SAAA,GACA,KAAA,YAAA,IAEA,eAAA,SAAA,EAAA,GACA,KAAA,gBAAA,EAAA,IAEA,YAAA,SAAA,EAAA,GACA,MAAA,GAAA,OAAA,EAAA,KAGA,cAAA,WACA,SAAA,iBAAA,mBAAA,WACA,aAAA,SAAA,YACA,KAAA,kBAAA,WAEA,KAAA,QAEA,UAAA,SAAA,GACA,MAAA,GAAA,WAAA,KAAA,cAEA,oBAAA,SAAA,GAEA,GAAA,GAAA,EAAA,EAAA,KAAA,aAAA,KAIA,OAFA,GAAA,KAAA,EAAA,EAAA,KAAA,YAEA,EAAA,OAAA,KAAA,iBAEA,gBAAA,SAAA,GACA,EAAA,QAAA,KAAA,gBAAA,OAEA,gBAAA,SAAA,GACA,GAAA,cAAA,EAAA,KAAA,CACA,GAAA,GAAA,KAAA,oBAAA,EAAA,WACA,GAAA,QAAA,KAAA,WAAA,KACA,IAAA,GAAA,KAAA,oBAAA,EAAA,aACA,GAAA,QAAA,KAAA,cAAA,UACA,eAAA,EAAA,MACA,KAAA,eAAA,EAAA,OAAA,EAAA,YAKA,IACA,EAAA,UAAA,aAAA,WACA,QAAA,KAAA,uGAIA,EAAA,UAAA,GACA,OAAA,uBClHA,SAAA,GACA,GAAA,GAAA,EAAA,WACA,EAAA,EAAA,WAEA,EAAA,GAEA,GAAA,EAAA,EAAA,EAAA,GAEA,GAAA,CACA,KACA,EAAA,IAAA,GAAA,YAAA,QAAA,QAAA,IAAA,QACA,MAAA,IAGA,GAAA,IACA,WAAA,EACA,aAAA,QACA,QACA,YACA,YACA,UACA,YACA,YAEA,SAAA,SAAA,GACA,EAAA,OAAA,EAAA,KAAA,SAEA,WAAA,SAAA,GACA,EAAA,SAAA,EAAA,KAAA,SAEA,eAEA,0BAAA,SAAA,GAGA,IAAA,GAAA,GAFA,EAAA,KAAA,YACA,EAAA,EAAA,QAAA,EAAA,EAAA,QACA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,IAAA,EAAA,EAAA,IAAA,IAAA,CAEA,GAAA,GAAA,KAAA,IAAA,EAAA,EAAA,GAAA,EAAA,KAAA,IAAA,EAAA,EAAA,EACA,IAAA,GAAA,GAAA,GAAA,EACA,OAAA,IAIA,aAAA,SAAA,GACA,GAAA,GAAA,EAAA,WAAA,GAEA,EAAA,EAAA,cAWA,OAVA,GAAA,eAAA,WACA,EAAA,iBACA,KAEA,EAAA,UAAA,KAAA,WACA,EAAA,WAAA,EACA,EAAA,YAAA,KAAA,aACA,IACA,EAAA,QAAA,EAAA,EAAA,QAAA,GAEA,GAEA,UAAA,SAAA,GACA,IAAA,KAAA,0BAAA,GAAA,CACA,GAAA,GAAA,EAAA,IAAA,KAAA,WAGA,IACA,KAAA,OAAA,EAEA,IAAA,GAAA,KAAA,aAAA,EACA,GAAA,IAAA,KAAA,WAAA,GACA,EAAA,KAAA,KAGA,UAAA,SAAA,GACA,IAAA,KAAA,0BAAA,GAAA,CACA,GAAA,GAAA,KAAA,aAAA,EACA,GAAA,KAAA,KAGA,QAAA,SAAA,GACA,IAAA,KAAA,0BAAA,GAAA,CACA,GAAA,GAAA,EAAA,IAAA,KAAA,WACA,IAAA,GAAA,EAAA,SAAA,EAAA,OAAA,CACA,GAAA,GAAA,KAAA,aAAA,EACA,GAAA,GAAA,GACA,KAAA,kBAIA,UAAA,SAAA,GACA,IAAA,KAAA,0BAAA,GAAA,CACA,GAAA,GAAA,KAAA,aAAA,EACA,GAAA,UAAA,KAGA,SAAA,SAAA,GACA,IAAA,KAAA,0BAAA,GAAA,CACA,GAAA,GAAA,KAAA,aAAA,EACA,GAAA,SAAA,KAGA,OAAA,SAAA,GACA,GAAA,GAAA,KAAA,aAAA,EACA,GAAA,OAAA,GACA,KAAA,gBAEA,aAAA,WACA,EAAA,UAAA,KAAA,aAIA,GAAA,YAAA,GACA,OAAA,uBC/GA,SAAA,GACA,GAUA,GAVA,EAAA,EAAA,WACA,EAAA,EAAA,YACA,EAAA,EAAA,WACA,EAAA,EAAA,cAAA,WAAA,KAAA,EAAA,eACA,EAAA,EAAA,WAGA,GAFA,MAAA,UAAA,IAAA,KAAA,KAAA,MAAA,UAAA,KAEA,MACA,EAAA,IACA,EAAA,eAOA,GAAA,EAGA,GACA,QACA,aACA,YACA,WACA,eAEA,SAAA,SAAA,GACA,EACA,EAAA,OAAA,EAAA,KAAA,QAEA,EAAA,gBAAA,IAGA,WAAA,SAAA,GACA,GACA,EAAA,SAAA,EAAA,KAAA,SAKA,aAAA,SAAA,GACA,GAAA,GAAA,EAAA,aAAA,GACA,EAAA,KAAA,wBAAA,EACA,KACA,EAAA,YAAA,EACA,EAAA,OAAA,EAAA,KAAA,QAEA,EAAA,GAAA,QAAA,SAAA,GACA,EAAA,YAAA,EACA,EAAA,OAAA,EAAA,KAAA,SACA,QAGA,eAAA,SAAA,GACA,EAAA,YAAA,OACA,EAAA,SAAA,EAAA,KAAA,QAEA,EAAA,GAAA,QAAA,SAAA,GACA,EAAA,YAAA,OACA,EAAA,SAAA,EAAA,KAAA,SACA,OAEA,eAAA,SAAA,EAAA,GACA,GAAA,GAAA,EAAA,aAAA,GACA,EAAA,KAAA,wBAAA,GACA,EAAA,KAAA,wBAAA,EAEA,IAAA,GACA,EAAA,YAAA,EACA,EAAA,GAAA,QAAA,SAAA,GACA,EAAA,YAAA,GACA,OACA,EACA,KAAA,eAAA,GACA,GACA,KAAA,aAAA,IAGA,aACA,QAAA,OACA,UAAA,QACA,UAAA,QACA,SAAA,0CAEA,wBAAA,SAAA,GACA,GAAA,GAAA,EACA,EAAA,KAAA,WACA,OAAA,SAAA,EACA,OACA,IAAA,EAAA,UACA,IACA,IAAA,EAAA,UACA,IACA,EAAA,SAAA,KAAA,GACA,KADA,QAIA,aAAA,QACA,WAAA,KACA,eAAA,SAAA,GACA,MAAA,MAAA,aAAA,EAAA,YAEA,gBAAA,SAAA,IAEA,IAAA,EAAA,YAAA,IAAA,EAAA,YAAA,EAAA,IAAA,MACA,KAAA,WAAA,EAAA,WACA,KAAA,SAAA,EAAA,EAAA,QAAA,EAAA,EAAA,SACA,KAAA,WAAA,EACA,KAAA,0BAGA,qBAAA,SAAA,GACA,EAAA,YACA,KAAA,WAAA,KACA,KAAA,QAAA,KACA,KAAA,oBAGA,WAAA,EACA,QAAA,KACA,gBAAA,WACA,GAAA,GAAA,WACA,KAAA,WAAA,EACA,KAAA,QAAA,MACA,KAAA,KACA,MAAA,QAAA,WAAA,EAAA,IAEA,sBAAA,WACA,KAAA,SACA,aAAA,KAAA,UAGA,cAAA,SAAA,GACA,GAAA,GAAA,CAIA,QAHA,eAAA,GAAA,cAAA,KACA,EAAA,GAEA,GAEA,eAAA,SAAA,GACA,GAAA,GAAA,KAAA,kBACA,EAAA,EAAA,WAAA,GAIA,EAAA,EAAA,UAAA,EAAA,WAAA,CACA,GAAA,OAAA,EAAA,IAAA,EAAA,GACA,EAAA,SAAA,EACA,EAAA,YAAA,EACA,EAAA,OAAA,KAAA,WACA,EAAA,OAAA,EACA,EAAA,QAAA,KAAA,cAAA,EAAA,MACA,EAAA,MAAA,EAAA,eAAA,EAAA,SAAA,EACA,EAAA,OAAA,EAAA,eAAA,EAAA,SAAA,EACA,EAAA,SAAA,EAAA,aAAA,EAAA,OAAA,GACA,EAAA,UAAA,KAAA,eAAA,GACA,EAAA,YAAA,KAAA,YAEA,IAAA,GAAA,IAMA,OALA,GAAA,eAAA,WACA,EAAA,WAAA,EACA,EAAA,QAAA,KACA,EAAA,kBAEA,GAEA,eAAA,SAAA,EAAA,GACA,GAAA,GAAA,EAAA,cACA,MAAA,kBAAA,CACA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,EAAA,GACA,EAAA,KAAA,KAAA,KAAA,eAAA,KAKA,aAAA,SAAA,GACA,GAAA,KAAA,QAAA,CACA,GAAA,GACA,EAAA,EAAA,cAAA,WACA,IAAA,SAAA,EAEA,GAAA,MACA,IAAA,OAAA,EAEA,GAAA,MACA,CACA,GAAA,GAAA,EAAA,eAAA,GAEA,EAAA,EACA,EAAA,MAAA,EAAA,IAAA,IACA,EAAA,KAAA,IAAA,EAAA,SAAA,GAAA,KAAA,QAAA,IACA,EAAA,KAAA,IAAA,EAAA,SAAA,GAAA,KAAA,QAAA,GAGA,GAAA,GAAA,EAGA,MADA,MAAA,QAAA,KACA,IAGA,UAAA,SAAA,EAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,IAAA,EAAA,EAAA,IAAA,IACA,GAAA,EAAA,aAAA,EACA,OAAA,GAUA,cAAA,SAAA,GACA,GAAA,GAAA,EAAA,OAGA,IAAA,EAAA,YAAA,EAAA,OAAA,CACA,GAAA,KACA,GAAA,QAAA,SAAA,EAAA,GAIA,GAAA,IAAA,IAAA,KAAA,UAAA,EAAA,EAAA,GAAA,CACA,GAAA,GAAA,EAAA,GACA,GAAA,KAAA,KAEA,MACA,EAAA,QAAA,KAAA,UAAA,QAGA,WAAA,SAAA,GACA,KAAA,cAAA,GACA,KAAA,gBAAA,EAAA,eAAA,IACA,KAAA,gBAAA,GACA,KAAA,YACA,KAAA,aACA,KAAA,eAAA,EAAA,KAAA,YAGA,SAAA,SAAA,GACA,EAAA,IAAA,EAAA,WACA,OAAA,EAAA,OACA,IAAA,EACA,UAAA,EAAA,QAEA,GAAA,KAAA,GACA,EAAA,MAAA,GACA,EAAA,KAAA,IAEA,UAAA,SAAA,GACA,KAAA,YACA,KAAA,aAAA,IACA,KAAA,WAAA,EACA,KAAA,YAAA,KAEA,EAAA,iBACA,KAAA,eAAA,EAAA,KAAA,gBAIA,YAAA,SAAA,GACA,GAAA,GAAA,EACA,EAAA,EAAA,IAAA,EAAA,UAEA,IAAA,EAAA,CAGA,GAAA,GAAA,EAAA,IACA,EAAA,EAAA,SACA,GAAA,KAAA,GACA,GAAA,IAAA,EAAA,SACA,EAAA,cAAA,EAAA,OACA,EAAA,cAAA,EAEA,EAAA,OAAA,EACA,EAAA,QACA,EAAA,SAAA,GACA,EAAA,UAAA,KAGA,EAAA,OAAA,EACA,EAAA,cAAA,KACA,KAAA,UAAA,KAGA,EAAA,IAAA,EACA,EAAA,UAAA,EAAA,SAEA,SAAA,SAAA,GACA,KAAA,gBAAA,GACA,KAAA,eAAA,EAAA,KAAA,QAEA,MAAA,SAAA,GACA,KAAA,YACA,EAAA,GAAA,GACA,EAAA,IAAA,GACA,EAAA,MAAA,IAEA,KAAA,eAAA,IAEA,YAAA,SAAA,GACA,KAAA,eAAA,EAAA,KAAA,YAEA,UAAA,SAAA,GACA,EAAA,OAAA,GACA,EAAA,IAAA,GACA,EAAA,MAAA,GACA,KAAA,eAAA,IAEA,eAAA,SAAA,GACA,EAAA,UAAA,EAAA,WACA,KAAA,qBAAA,IAGA,gBAAA,SAAA,GACA,GAAA,GAAA,EAAA,YAAA,YACA,EAAA,EAAA,eAAA,EAEA,IAAA,KAAA,eAAA,GAAA,CAEA,GAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,QACA,GAAA,KAAA,EACA,IAAA,GAAA,SAAA,EAAA,GACA,GAAA,GAAA,EAAA,QAAA,EACA,GAAA,IACA,EAAA,OAAA,EAAA,IAEA,KAAA,KAAA,EAAA,EACA,YAAA,EAAA,KAKA,KACA,EAAA,GAAA,GAAA,UAAA,EAAA,aAAA,EAAA,eAAA,EAAA,eAAA,IAGA,EAAA,YAAA,GACA,OAAA,uBCrVA,SAAA,GACA,GAAA,GAAA,EAAA,WACA,EAAA,EAAA,WACA,EAAA,OAAA,gBAAA,gBAAA,QAAA,eAAA,qBACA,GACA,QACA,gBACA,gBACA,cACA,eACA,gBACA,kBACA,sBACA,wBAEA,SAAA,SAAA,GACA,EAAA,OAAA,EAAA,KAAA,SAEA,WAAA,SAAA,GACA,EAAA,SAAA,EAAA,KAAA,SAEA,eACA,GACA,cACA,QACA,MACA,SAEA,aAAA,SAAA,GACA,GAAA,GAAA,CAKA,OAJA,KACA,EAAA,EAAA,WAAA,GACA,EAAA,YAAA,KAAA,cAAA,EAAA,cAEA,GAEA,QAAA,SAAA,GACA,EAAA,UAAA,IAEA,cAAA,SAAA,GACA,EAAA,IAAA,EAAA,UAAA,EACA,IAAA,GAAA,KAAA,aAAA,EACA,GAAA,KAAA,IAEA,cAAA,SAAA,GACA,GAAA,GAAA,KAAA,aAAA,EACA,GAAA,KAAA,IAEA,YAAA,SAAA,GACA,GAAA,GAAA,KAAA,aAAA,EACA,GAAA,GAAA,GACA,KAAA,QAAA,EAAA,YAEA,aAAA,SAAA,GACA,GAAA,GAAA,KAAA,aAAA,EACA,GAAA,SAAA,IAEA,cAAA,SAAA,GACA,GAAA,GAAA,KAAA,aAAA,EACA,GAAA,UAAA,IAEA,gBAAA,SAAA,GACA,GAAA,GAAA,KAAA,aAAA,EACA,GAAA,OAAA,GACA,KAAA,QAAA,EAAA,YAEA,qBAAA,SAAA,GACA,GAAA,GAAA,EAAA,UAAA,qBAAA,EACA,GAAA,cAAA,IAEA,oBAAA,SAAA,GACA,GAAA,GAAA,EAAA,UAAA,oBAAA,EACA,GAAA,cAAA,IAIA,GAAA,SAAA,GACA,OAAA,uBCxEA,SAAA,GACA,GAAA,GAAA,EAAA,UAGA,IAAA,OAAA,eAAA,EAAA,aAAA,CAEA,GAAA,OAAA,UAAA,iBAAA,CACA,GAAA,GAAA,OAAA,UAAA,gBACA,QAAA,eAAA,OAAA,UAAA,kBACA,MAAA,EACA,YAAA,IAEA,EAAA,eAAA,KAAA,EAAA,cAEA,GAAA,eAAA,QAAA,EAAA,aACA,SAAA,OAAA,cACA,EAAA,eAAA,QAAA,EAAA,YAIA,GAAA,SAAA,YAEA,OAAA,uBC3BA,SAAA,GAIA,QAAA,GAAA,GACA,IAAA,EAAA,WAAA,IAAA,GACA,KAAA,IAAA,OAAA,oBALA,GAEA,GAAA,EAFA,EAAA,EAAA,WACA,EAAA,OAAA,SAOA,GAAA,kBACA,EAAA,SAAA,GACA,EAAA,GACA,KAAA,oBAAA,IAEA,EAAA,SAAA,GACA,EAAA,GACA,KAAA,wBAAA,MAGA,EAAA,SAAA,GACA,EAAA,GACA,EAAA,WAAA,EAAA,OAEA,EAAA,SAAA,GACA,EAAA,GACA,EAAA,eAAA,EAAA,QAGA,OAAA,UAAA,QAAA,UAAA,mBACA,OAAA,iBAAA,QAAA,WACA,mBACA,MAAA,GAEA,uBACA,MAAA,MAIA,OAAA,uBnFDA,oBAAA,UAAA,WAAA,WACA,KAAA,cAAA,GoFtCA,SAAA,GAQA,EAAA,MACA,EAAA,OACA,KAEA,KAAA,SAAA,EAAA,GACA,GAAA,IAAA,EACA,MAAA,EAGA,IAAA,EAAA,SAAA,CACA,GAAA,EAAA,SAAA,GACA,MAAA,EAEA,IAAA,EAAA,SAAA,GACA,MAAA,GAGA,GAAA,GAAA,KAAA,MAAA,GACA,EAAA,KAAA,MAAA,GACA,EAAA,EAAA,CAMA,KALA,EAAA,EACA,EAAA,KAAA,KAAA,EAAA,GAEA,EAAA,KAAA,KAAA,GAAA,GAEA,GAAA,GAAA,IAAA,GACA,EAAA,KAAA,KAAA,EAAA,GACA,EAAA,KAAA,KAAA,EAAA,EAEA,OAAA,IAEA,KAAA,SAAA,EAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,IACA,EAAA,EAAA,UAEA,OAAA,IAEA,MAAA,SAAA,GAEA,IADA,GAAA,GAAA,EACA,GACA,IACA,EAAA,EAAA,UAEA,OAAA,MAIA,EAAA,QAAA,SAAA,EAAA,GACA,MAAA,GAAA,MAAA,IAAA,KAAA,EAAA,IAEA,OAAA,gBAAA,GACA,OAAA,iBCxDA,SAAA,GAGA,QAAA,KACA,GAAA,EAAA,CACA,GAAA,GAAA,GAAA,IAEA,OADA,GAAA,SAAA,EACA,EAEA,KAAA,QACA,KAAA,UATA,GAAA,GAAA,OAAA,KAAA,OAAA,IAAA,UAAA,QACA,EAAA,WAAA,MAAA,MAAA,KAYA,GAAA,WACA,IAAA,SAAA,EAAA,GACA,GAAA,GAAA,KAAA,KAAA,QAAA,EACA,GAAA,GACA,KAAA,OAAA,GAAA,GAEA,KAAA,KAAA,KAAA,GACA,KAAA,OAAA,KAAA,KAGA,IAAA,SAAA,GACA,MAAA,MAAA,KAAA,QAAA,GAAA,IAEA,SAAA,SAAA,GACA,GAAA,GAAA,KAAA,KAAA,QAAA,EACA,GAAA,KACA,KAAA,KAAA,OAAA,EAAA,GACA,KAAA,OAAA,OAAA,EAAA,KAGA,IAAA,SAAA,GACA,GAAA,GAAA,KAAA,KAAA,QAAA,EACA,OAAA,MAAA,OAAA,IAEA,MAAA,WACA,KAAA,KAAA,OAAA,EACA,KAAA,OAAA,OAAA,GAGA,QAAA,SAAA,EAAA,GACA,KAAA,OAAA,QAAA,SAAA,EAAA,GACA,EAAA,KAAA,EAAA,EAAA,KAAA,KAAA,GAAA,OACA,OAEA,SAAA,WACA,MAAA,MAAA,KAAA,SAIA,EAAA,WAAA,GACA,OAAA,iBCzDA,SAAA,GACA,GAAA,IAEA,UACA,aACA,OACA,SACA,UACA,UACA,UACA,UACA,UACA,SACA,WACA,UACA,SACA,gBAEA,UAEA,YACA,QACA,SACA,WACA,QACA,QACA,cACA,cACA,YAEA,OACA,SACA,gBACA,UACA,UACA,QACA,QACA,gBAGA,IAEA,GACA,EACA,KACA,KACA,EACA,EACA,EACA,GACA,GACA,GACA,GACA,EACA,EACA,KAEA,EAEA,EACA,EACA,EACA,EACA,EACA,EACA,GACA,GACA,EAEA,GACA,KACA,KACA,EACA,EACA,EACA,GAGA,GACA,cAAA,GAAA,SACA,QAAA,GAAA,SACA,YACA,eACA,UAGA,mBAAA,SAAA,EAAA,GACA,GAAA,GAAA,CACA,MAAA,YAAA,GAAA,EACA,EAAA,OAAA,QAAA,SAAA,GACA,GAAA,EAAA,GAAA,CACA,KAAA,OAAA,IAAA,CACA,IAAA,GAAA,EAAA,GAAA,KAAA,EACA,MAAA,WAAA,EAAA,KAEA,OAEA,WAAA,SAAA,EAAA,GACA,GAAA,GAAA,CACA,MAAA,SAAA,KACA,KAAA,SAAA,OAEA,KAAA,SAAA,GAAA,KAAA,IAGA,eAAA,SAAA,GACA,KAAA,OAAA,OAAA,KAAA,KAAA,QAAA,IAGA,iBAAA,SAAA,GACA,KAAA,SAAA,OAAA,KAAA,KAAA,QAAA,IAGA,aAAA,SAAA,GACA,IAAA,KAAA,cAAA,IAAA,GAAA,CAGA,GAAA,GAAA,EAAA,KAAA,EAAA,KAAA,SAAA,EACA,IACA,KAAA,UAAA,EAAA,GAEA,KAAA,cAAA,IAAA,GAAA,KAGA,UAAA,SAAA,EAAA,GAGA,GAAA,GAAA,KAAA,WAAA,EACA,uBAAA,KAAA,SAAA,KAAA,KAAA,EAAA,KAGA,SAAA,SAAA,EAAA,GACA,KAAA,iBAAA,EAAA,SACA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,IAAA,EAAA,EAAA,IAAA,IACA,EAAA,EAEA,MAAA,iBAAA,GAGA,OAAA,SAAA,EAAA,GACA,EAAA,QAAA,SAAA,GACA,KAAA,SAAA,EAAA,KAAA,cAAA,EAAA,IACA,OAGA,SAAA,SAAA,GACA,EAAA,QAAA,SAAA,GACA,KAAA,YAAA,EAAA,KAAA,cAAA,EAAA,WACA,OAEA,SAAA,SAAA,EAAA,EAAA,EAAA,GACA,EAAA,iBAAA,EAAA,EAAA,IAEA,YAAA,SAAA,EAAA,EAAA,EAAA,GACA,EAAA,oBAAA,EAAA,EAAA,IAKA,UAAA,SAAA,EAAA,GACA,MAAA,IAAA,qBAAA,EAAA,IAUA,WAAA,SAAA,GAEA,IAAA,GADA,GAAA,KACA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,EAAA,GACA,EAAA,GAAA,EAAA,IAAA,EAAA,EAEA,OAAA,IAGA,cAAA,SAAA,EAAA,GACA,GAAA,GAAA,GAAA,KAAA,QAAA,IAAA,EACA,KACA,EAAA,cAAA,GACA,EAAA,cACA,KAAA,WAAA,KAAA,oBAIA,mBAAA,SAAA,EAAA,GACA,sBAAA,KAAA,cAAA,KAAA,KAAA,EAAA,KAEA,WAAA,SAAA,GACA,GAAA,GAAA,KAAA,YAAA,GACA,IACA,EAAA,WAAA,IAIA,GAAA,aAAA,EAAA,aAAA,KAAA,GAGA,EAAA,iBACA,EAAA,mBAAA,EACA,EAAA,WAAA,EAUA,EAAA,SAAA,SAAA,GACA,GAAA,EAAA,kBAAA,CACA,GAAA,GAAA,OAAA,qBACA,IACA,EAAA,SAAA,GAEA,EAAA,WAAA,eAAA,OAEA,GAAA,cAAA,KAAA,IAGA,EAAA,SAAA,WACA,OAAA,iBCrLA,SAAA,GACA,GAAA,GAAA,EAAA,WACA,GAEA,WAAA,IAEA,iBAAA,GACA,QACA,cACA,cACA,YACA,iBAEA,YAAA,KACA,QAAA,KACA,MAAA,WACA,GAAA,GAAA,KAAA,MAAA,KAAA,YAAA,UACA,EAAA,KAAA,KAAA,YAAA,MACA,MAAA,SAAA,EAAA,GACA,KAAA,MAAA,GAEA,OAAA,WACA,cAAA,KAAA,SACA,KAAA,MACA,KAAA,SAAA,WAEA,KAAA,MAAA,EACA,KAAA,YAAA,KACA,KAAA,OAAA,KACA,KAAA,QAAA,MAEA,YAAA,SAAA,GACA,EAAA,YAAA,KAAA,cACA,KAAA,YAAA,EACA,KAAA,OAAA,EAAA,OACA,KAAA,QAAA,YAAA,KAAA,MAAA,KAAA,MAAA,KAAA,cAGA,UAAA,SAAA,GACA,KAAA,aAAA,KAAA,YAAA,YAAA,EAAA,WACA,KAAA,UAGA,cAAA,WACA,KAAA,UAEA,YAAA,SAAA,GACA,GAAA,KAAA,aAAA,KAAA,YAAA,YAAA,EAAA,UAAA,CACA,GAAA,GAAA,EAAA,QAAA,KAAA,YAAA,QACA,EAAA,EAAA,QAAA,KAAA,YAAA,OACA,GAAA,EAAA,EAAA,EAAA,KAAA,kBACA,KAAA,WAIA,SAAA,SAAA,EAAA,GACA,GAAA,IACA,YAAA,KAAA,YAAA,YACA,QAAA,KAAA,YAAA,QACA,QAAA,KAAA,YAAA,QAEA,KACA,EAAA,SAAA,EAEA,IAAA,GAAA,EAAA,UAAA,EAAA,EACA,GAAA,cAAA,EAAA,KAAA,QACA,EAAA,cACA,EAAA,WAAA,KAAA,YAAA,YAIA,GAAA,mBAAA,OAAA,IACA,OAAA,iBCpBA,SAAA,GACA,GAAA,GAAA,EAAA,WACA,EAAA,GAAA,GAAA,WACA,GACA,QACA,cACA,cACA,YACA,iBAEA,iBAAA,EACA,SAAA,SAAA,GACA,MAAA,GAAA,EAAA,EAAA,IAEA,kBAAA,SAAA,EAAA,GACA,GAAA,GAAA,EAAA,EAAA,CAKA,OAJA,IAAA,IACA,EAAA,EAAA,MAAA,EAAA,MACA,EAAA,EAAA,MAAA,EAAA,QAEA,EAAA,EAAA,EAAA,IAEA,UAAA,SAAA,EAAA,EAAA,GACA,GAAA,GAAA,EACA,EAAA,KAAA,kBAAA,EAAA,UAAA,GACA,EAAA,KAAA,kBAAA,EAAA,cAAA,EACA,GAAA,IACA,EAAA,WAAA,KAAA,SAAA,EAAA,IAEA,EAAA,IACA,EAAA,WAAA,KAAA,SAAA,EAAA,GAEA,IAAA,IACA,GAAA,EAAA,EACA,GAAA,EAAA,EACA,IAAA,EAAA,EACA,IAAA,EAAA,EACA,QAAA,EAAA,QACA,QAAA,EAAA,QACA,MAAA,EAAA,MACA,MAAA,EAAA,MACA,QAAA,EAAA,QACA,QAAA,EAAA,QACA,WAAA,EAAA,WACA,WAAA,EAAA,WACA,UAAA,EAAA,UACA,cAAA,EAAA,OACA,YAAA,EAAA,aAEA,EAAA,EAAA,UAAA,EAAA,EACA,GAAA,cAAA,EACA,EAAA,cAAA,EAAA,EAAA,aAEA,YAAA,SAAA,GACA,GAAA,EAAA,YAAA,UAAA,EAAA,YAAA,IAAA,EAAA,SAAA,GAAA,CACA,GAAA,IACA,UAAA,EACA,WAAA,EAAA,OACA,aACA,cAAA,KACA,WAAA,EACA,WAAA,EACA,UAAA,EAEA,GAAA,IAAA,EAAA,UAAA,KAGA,YAAA,SAAA,GACA,GAAA,GAAA,EAAA,IAAA,EAAA,UACA,IAAA,EACA,GAAA,EAAA,SAUA,KAAA,UAAA,QAAA,EAAA,OAVA,CACA,GAAA,GAAA,KAAA,kBAAA,EAAA,UAAA,GACA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,CAEA,GAAA,KAAA,mBACA,EAAA,UAAA,EACA,KAAA,UAAA,aAAA,EAAA,UAAA,GACA,KAAA,UAAA,QAAA,EAAA,MAOA,UAAA,SAAA,GACA,GAAA,GAAA,EAAA,IAAA,EAAA,UACA,KACA,EAAA,UACA,KAAA,UAAA,WAAA,EAAA,GAEA,EAAA,OAAA,EAAA,aAGA,cAAA,SAAA,GACA,KAAA,UAAA,IAGA,GAAA,mBAAA,QAAA,IACA,OAAA,iBCxJA,SAAA,GACA,GAAA,GAAA,EAAA,WACA,GAGA,aAAA,GACA,UAAA,EACA,aACA,OAAA,KACA,UAAA,KACA,QACA,cACA,cACA,YACA,iBAEA,YAAA,SAAA,GACA,EAAA,YAAA,KAAA,YACA,KAAA,UAAA,EAAA,UACA,KAAA,OAAA,EAAA,OACA,KAAA,QAAA,KAGA,YAAA,SAAA,GACA,EAAA,YAAA,KAAA,WACA,KAAA,QAAA,IAGA,UAAA,SAAA,GACA,EAAA,YAAA,KAAA,WACA,KAAA,UAAA,GAEA,KAAA,WAEA,cAAA,WACA,KAAA,WAEA,QAAA,WACA,KAAA,aACA,KAAA,OAAA,KACA,KAAA,UAAA,MAEA,QAAA,SAAA,GACA,KAAA,UAAA,QAAA,KAAA,WACA,KAAA,UAAA,QAEA,KAAA,UAAA,KAAA,IAEA,UAAA,SAAA,GAKA,IAAA,GAFA,GAAA,EAAA,EAAA,EAAA,EAAA,EAEA,EAJA,EAAA,EACA,EAAA,KAAA,UAAA,OACA,EAAA,EAAA,EAAA,EAAA,EAAA,EAEA,EAAA,EAAA,EAAA,IAAA,EAAA,KAAA,UAAA,IAAA,IACA,EAAA,EAAA,UAAA,EAAA,UACA,EAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,QACA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,EAAA,GACA,EAAA,IACA,EAAA,EAAA,EAAA,EAAA,EAAA,EAGA,IAAA,GAAA,KAAA,IAAA,GAAA,KAAA,IAAA,GAAA,IAAA,IACA,EAAA,KAAA,UAAA,EAAA,EACA,IAAA,KAAA,IAAA,IAAA,KAAA,aAAA,CACA,GAAA,GAAA,EAAA,UAAA,SACA,UAAA,EACA,UAAA,EACA,SAAA,EACA,MAAA,EACA,UAAA,EACA,YAAA,EAAA,aAEA,GAAA,cAAA,EAAA,KAAA,UAGA,UAAA,SAAA,EAAA,GACA,MAAA,KAAA,KAAA,MAAA,EAAA,GAAA,KAAA,IAGA,GAAA,mBAAA,QAAA,IACA,OAAA,iBC5EA,SAAA,GACA,GAAA,GAAA,EAAA,WACA,EAAA,GAAA,GAAA,WACA,EAAA,IAAA,KAAA,GACA,GACA,QACA,cACA,cACA,YACA,iBAEA,aACA,YAAA,SAAA,GAEA,GADA,EAAA,IAAA,EAAA,UAAA,GACA,GAAA,EAAA,WAAA,CACA,GAAA,GAAA,KAAA,YACA,EAAA,KAAA,UAAA,EACA,MAAA,WACA,MAAA,EACA,SAAA,EAAA,SACA,OAAA,EAAA,QAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WAIA,UAAA,SAAA,GACA,EAAA,OAAA,EAAA,YAEA,YAAA,SAAA,GACA,EAAA,IAAA,EAAA,aACA,EAAA,IAAA,EAAA,UAAA,GACA,EAAA,WAAA,GACA,KAAA,oBAIA,cAAA,SAAA,GACA,KAAA,UAAA,IAEA,cAAA,SAAA,EAAA,GACA,GAAA,GAAA,EAAA,KAAA,UAAA,SACA,EAAA,EAAA,UAAA,SACA,MAAA,EACA,QAAA,EAAA,OAAA,EACA,QAAA,EAAA,OAAA,GAEA,GAAA,cAAA,EAAA,KAAA,UAAA,SAEA,eAAA,SAAA,EAAA,GACA,GAAA,GAAA,KAAA,OAAA,EAAA,KAAA,UAAA,OAAA,KACA,EAAA,EAAA,UAAA,UACA,MAAA,EACA,QAAA,EAAA,OAAA,EACA,QAAA,EAAA,OAAA,GAEA,GAAA,cAAA,EAAA,KAAA,UAAA,SAEA,gBAAA,WACA,GAAA,GAAA,KAAA,YACA,EAAA,EAAA,SACA,EAAA,KAAA,UAAA,EACA,IAAA,KAAA,UAAA,UACA,KAAA,cAAA,EAAA,GAEA,GAAA,KAAA,UAAA,OACA,KAAA,eAAA,EAAA,IAGA,UAAA,WACA,GAAA,KACA,GAAA,QAAA,SAAA,GACA,EAAA,KAAA,IAMA,KAAA,GADA,GAAA,EAAA,EAHA,EAAA,EAEA,GAAA,EAAA,EAAA,GAAA,EAAA,EAAA,IAEA,EAAA,EAAA,EAAA,EAAA,OAAA,IAEA,IAAA,GADA,GAAA,EAAA,GACA,EAAA,EAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,EACA,GAAA,KAAA,IAAA,EAAA,QAAA,EAAA,SACA,EAAA,KAAA,IAAA,EAAA,QAAA,EAAA,SACA,EAAA,EAAA,EACA,EAAA,IACA,EAAA,EACA,GAAA,EAAA,EAAA,EAAA,IAQA,MAJA,GAAA,KAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,SAAA,EACA,EAAA,KAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,SAAA,EACA,EAAA,QAAA,EAAA,EAAA,EAAA,GACA,EAAA,SAAA,EACA,GAEA,UAAA,SAAA,GACA,GAAA,GAAA,EAAA,EAAA,QAAA,EAAA,EAAA,QACA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,OACA,QAAA,IAAA,KAAA,MAAA,EAAA,GAAA,GAAA,KAGA,GAAA,mBAAA,QAAA,IACA,OAAA,iBCvHA,SAAA,GACA,GAAA,GAAA,EAAA,WACA,EAAA,GAAA,GAAA,WACA,GACA,QACA,cACA,cACA,YACA,gBACA,SAEA,YAAA,SAAA,GACA,EAAA,YAAA,EAAA,cACA,EAAA,IAAA,EAAA,WACA,OAAA,EAAA,OACA,QAAA,EAAA,QACA,EAAA,EAAA,QACA,EAAA,EAAA,WAIA,YAAA,SAAA,GACA,GAAA,EAAA,UAAA,CACA,GAAA,GAAA,EAAA,IAAA,EAAA,UACA,IACA,EAAA,cACA,EAAA,OAAA,EAAA,aAKA,UAAA,SAAA,EAAA,GACA,MAAA,GAAA,aAAA,OACA,UAAA,EAAA,YAEA,IAAA,EAAA,SAEA,GAIA,UAAA,SAAA,GACA,GAAA,GAAA,EAAA,IAAA,EAAA,UACA,IAAA,GAAA,KAAA,UAAA,EAAA,GAAA,CACA,GAAA,GAAA,EAAA,QAAA,EAAA,OAAA,EAAA,OACA,IAAA,EAAA,CACA,GAAA,GAAA,EAAA,UAAA,OACA,EAAA,EAAA,QACA,EAAA,EAAA,QACA,OAAA,EAAA,OACA,YAAA,EAAA,aAEA,GAAA,cAAA,EAAA,IAGA,EAAA,OAAA,EAAA,YAEA,cAAA,SAAA,GACA,EAAA,OAAA,EAAA,YAEA,MAAA,SAAA,GACA,GAAA,GAAA,EAAA,OAEA,IAAA,KAAA,EAAA,CACA,GAAA,GAAA,EAAA,MACA,aAAA,mBAAA,YAAA,sBACA,EAAA,cAAA,EAAA,UAAA,OACA,EAAA,EACA,EAAA,EACA,OAAA,EACA,YAAA,gBACA,KAIA,WAAA,SAAA,GACA,EAAA,OAAA,IAGA,GAAA,mBAAA,MAAA,IACA,OAAA,iBCzGA,SAAA,GAEA,QAAA,KACA,EAAA,mBAAA,CACA,IAAA,GAAA,EAAA,aACA,GAAA,QAAA,EAAA,UACA,EAAA,OAAA,EALA,GAAA,GAAA,EAAA,UAOA,cAAA,SAAA,WACA,IAIA,SAAA,iBAAA,mBAAA,WACA,aAAA,SAAA,YACA,OAIA,OAAA,iBCtBA,WACA,YAIA,SAAA,GAAA,GACA,KAAA,EAAA,YACA,EAAA,EAAA,UAGA,OAAA,kBAAA,GAAA,eAAA,EAAA,KAOA,QAAA,GAAA,EAAA,EAAA,GACA,GAAA,GAAA,EAAA,SAOA,OANA,KACA,EAAA,EAAA,cAEA,EAAA,IACA,EAAA,GAAA,QAEA,EAAA,GAAA,EAGA,QAAA,GAAA,EAAA,EAAA,GACA,MAAA,GAGA,QAAA,GAAA,GACA,MAAA,OAAA,EAAA,GAAA,EAGA,QAAA,GAAA,EAAA,GACA,EAAA,KAAA,EAAA,GAGA,QAAA,GAAA,GACA,MAAA,UAAA,GACA,MAAA,GAAA,EAAA,IA6BA,QAAA,GAAA,EAAA,EAAA,EAAA,GACA,MAAA,QACA,EACA,EAAA,aAAA,EAAA,IAEA,EAAA,gBAAA,QAIA,GAAA,aAAA,EAAA,EAAA,IAGA,QAAA,GAAA,EAAA,EAAA,GACA,MAAA,UAAA,GACA,EAAA,EAAA,EAAA,EAAA,IAiDA,QAAA,GAAA,GACA,OAAA,EAAA,MACA,IAAA,WACA,MAAA,EACA,KAAA,QACA,IAAA,kBACA,IAAA,aACA,MAAA,QACA,KAAA,QACA,GAAA,eAAA,KAAA,UAAA,WACA,MAAA,QACA,SACA,MAAA,SAIA,QAAA,GAAA,EAAA,EAAA,EAAA,GACA,EAAA,IAAA,GAAA,GAAA,GAGA,QAAA,GAAA,EAAA,EAAA,GACA,MAAA,UAAA,GACA,MAAA,GAAA,EAAA,EAAA,EAAA,IAIA,QAAA,MAEA,QAAA,GAAA,EAAA,EAAA,EAAA,GAGA,QAAA,KACA,EAAA,SAAA,EAAA,IACA,EAAA,kBACA,GAAA,GAAA,GACA,SAAA,6BANA,GAAA,GAAA,EAAA,EAUA,OAFA,GAAA,iBAAA,EAAA,IAGA,MAAA,WACA,EAAA,oBAAA,EAAA,GACA,EAAA,SAGA,YAAA,GAIA,QAAA,GAAA,GACA,MAAA,SAAA,GAYA,QAAA,GAAA,GACA,GAAA,EAAA,KACA,MAAA,GAAA,EAAA,KAAA,SAAA,SAAA,GACA,MAAA,IAAA,GACA,SAAA,EAAA,SACA,SAAA,EAAA,MACA,EAAA,MAAA,EAAA,MAGA,IAAA,GAAA,EAAA,EACA,KAAA,EACA,QACA,IAAA,GAAA,EAAA,iBACA,6BAAA,EAAA,KAAA,KACA,OAAA,GAAA,EAAA,SAAA,GACA,MAAA,IAAA,IAAA,EAAA,OAKA,QAAA,GAAA,GAIA,UAAA,EAAA,SACA,UAAA,EAAA,MACA,EAAA,GAAA,QAAA,SAAA,GACA,GAAA,GAAA,EAAA,UAAA,OACA,IAEA,EAAA,YAAA,UAAA,KA4CA,QAAA,GAAA,EAAA,GACA,GACA,GACA,EACA,EAHA,EAAA,EAAA,UAIA,aAAA,oBACA,EAAA,WACA,EAAA,UAAA,QACA,EAAA,EACA,EAAA,EAAA,UAAA,MACA,EAAA,EAAA,OAGA,EAAA,MAAA,EAAA,GAEA,GAAA,EAAA,OAAA,IACA,EAAA,YAAA,SAAA,EAAA,OACA,EAAA,YAAA,iBACA,SAAA,8BAIA,QAAA,GAAA,GACA,MAAA,UAAA,GACA,EAAA,EAAA,IAnSA,GAAA,GAAA,MAAA,UAAA,OAAA,KAAA,KAAA,MAAA,UAAA,OAUA,MAAA,UAAA,KAAA,SAAA,EAAA,GACA,QAAA,MAAA,8BAAA,KAAA,EAAA,GAgCA,IAAA,GAAA,CAEA,QAAA,eAAA,SAAA,4BACA,IAAA,WACA,MAAA,KAAA,GAEA,IAAA,SAAA,GAEA,MADA,GAAA,EAAA,EAAA,EACA,GAEA,cAAA,IAGA,KAAA,UAAA,KAAA,SAAA,EAAA,EAAA,GACA,GAAA,gBAAA,EACA,MAAA,MAAA,UAAA,KAAA,KAAA,KAAA,EAAA,EAAA,EAEA,IAAA,EACA,MAAA,GAAA,KAAA,EAEA;GAAA,GAAA,CAEA,OADA,GAAA,KAAA,EAAA,KAAA,EAAA,QACA,EAAA,KAAA,EAAA,IAqBA,QAAA,UAAA,KAAA,SAAA,EAAA,EAAA,GACA,GAAA,GAAA,KAAA,EAAA,EAAA,OAAA,EAMA,IALA,IACA,KAAA,gBAAA,GACA,EAAA,EAAA,MAAA,EAAA,KAGA,EACA,MAAA,GAAA,KAAA,EAAA,EAAA,EAGA,IAAA,GAAA,CAIA,OAHA,GAAA,KAAA,EAAA,EACA,EAAA,KAAA,EAAA,KAAA,EAAA,KAEA,EAAA,KAAA,EAAA,GAGA,IAAA,IACA,WAGA,GAAA,GAAA,SAAA,cAAA,OACA,EAAA,EAAA,YAAA,SAAA,cAAA,SACA,GAAA,aAAA,OAAA,WACA,IAAA,GACA,EAAA,CACA,GAAA,iBAAA,QAAA,WACA,IACA,EAAA,GAAA,UAEA,EAAA,iBAAA,SAAA,WACA,IACA,EAAA,GAAA,UAGA,IAAA,GAAA,SAAA,YAAA,aACA,GAAA,eAAA,SAAA,GAAA,EAAA,OAAA,EAAA,EAAA,EAAA,EAAA,GAAA,GACA,GAAA,GAAA,EAAA,EAAA,MACA,EAAA,cAAA,GAGA,EAAA,GAAA,EAAA,SAAA,KAqGA,iBAAA,UAAA,KAAA,SAAA,EAAA,EAAA,GACA,GAAA,UAAA,GAAA,YAAA,EACA,MAAA,aAAA,UAAA,KAAA,KAAA,KAAA,EAAA,EAAA,EAEA,MAAA,gBAAA,EACA,IAAA,GAAA,WAAA,EAAA,EAAA,EACA,EAAA,WAAA,EAAA,EAAA,CAEA,IAAA,EACA,MAAA,GAAA,KAAA,EAAA,EAAA,EAGA,IAAA,GAAA,EACA,EAAA,EAAA,KAAA,EAAA,EAAA,EAMA,OALA,GAAA,KAAA,EACA,EAAA,KAAA,EAAA,KAAA,EAAA,IACA,GAGA,EAAA,KAAA,EAAA,IAGA,oBAAA,UAAA,KAAA,SAAA,EAAA,EAAA,GACA,GAAA,UAAA,EACA,MAAA,aAAA,UAAA,KAAA,KAAA,KAAA,EAAA,EAAA,EAIA,IAFA,KAAA,gBAAA,SAEA,EACA,MAAA,GAAA,KAAA,QAAA,EAEA,IAAA,GAAA,EACA,EAAA,EAAA,KAAA,QAAA,EAGA,OAFA,GAAA,KAAA,QACA,EAAA,KAAA,EAAA,KAAA,QAAA,KACA,EAAA,KAAA,EAAA,IA+BA,kBAAA,UAAA,KAAA,SAAA,EAAA,EAAA,GACA,GAAA,UAAA,EACA,MAAA,aAAA,UAAA,KAAA,KAAA,KAAA,EAAA,EAAA,EAIA,IAFA,KAAA,gBAAA,SAEA,EACA,MAAA,GAAA,KAAA,EAEA,IAAA,GAAA,EACA,EAAA,EAAA,KAAA,QAAA,EAEA,OADA,GAAA,KAAA,EAAA,KAAA,EAAA,QACA,EAAA,KAAA,EAAA,IAGA,kBAAA,UAAA,KAAA,SAAA,EAAA,EAAA,GAIA,GAHA,kBAAA,IACA,EAAA,iBAEA,kBAAA,GAAA,UAAA,EACA,MAAA,aAAA,UAAA,KAAA,KAAA,KAAA,EAAA,EAAA,EAIA,IAFA,KAAA,gBAAA,GAEA,EACA,MAAA,GAAA,KAAA,EAAA,EAEA,IAAA,GAAA,EACA,EAAA,EAAA,KAAA,EAAA,EAKA,OAJA,GAAA,KAAA,EACA,EAAA,KAAA,EAAA,KAAA,KAGA,EAAA,KAAA,EAAA,KAEA,MC7UA,SAAA,GACA,YAEA,SAAA,GAAA,GACA,IAAA,EACA,KAAA,IAAA,OAAA,oBAKA,QAAA,GAAA,GAEA,IADA,GAAA,GACA,EAAA,EAAA,YACA,EAAA,CAGA,OAAA,GAGA,QAAA,GAAA,EAAA,GACA,GAAA,EAAA,CAKA,IAFA,GAAA,GACA,EAAA,IAAA,GACA,IACA,EAAA,EAAA,GAEA,EAAA,cACA,EAAA,EAAA,cAAA,cAAA,GACA,EAAA,iBACA,EAAA,EAAA,eAAA,KAEA,GAAA,EAAA,mBAGA,EAAA,EAAA,gBAGA,OAAA,IAiIA,QAAA,GAAA,GACA,MAAA,YAAA,EAAA,SACA,8BAAA,EAAA,aAGA,QAAA,GAAA,GACA,MAAA,YAAA,EAAA,SACA,gCAAA,EAAA,aAGA,QAAA,GAAA,GACA,MAAA,SAAA,EAAA,EAAA,UACA,EAAA,aAAA,aAGA,QAAA,GAAA,GAIA,MAHA,UAAA,EAAA,cACA,EAAA,YAAA,YAAA,EAAA,SAAA,EAAA,IAEA,EAAA,YAYA,QAAA,GAAA,EAAA,GACA,GAAA,GAAA,EAAA,iBAAA,EAEA,GAAA,IACA,EAAA,GACA,EAAA,EAAA,GAGA,QAAA,GAAA,GACA,QAAA,GAAA,GACA,oBAAA,SAAA,IACA,EAAA,EAAA,SAGA,EAAA,EAAA,GAgBA,QAAA,GAAA,EAAA,GACA,OAAA,oBAAA,GAAA,QAAA,SAAA,GACA,OAAA,eAAA,EAAA,EACA,OAAA,yBAAA,EAAA,MAKA,QAAA,GAAA,GACA,GAAA,GAAA,EAAA,aACA,KAAA,EAAA,YACA,MAAA,EACA,IAAA,GAAA,EAAA,sBACA,KAAA,EAAA,CAIA,IADA,EAAA,EAAA,eAAA,mBAAA,IACA,EAAA,WACA,EAAA,YAAA,EAAA,UAEA,GAAA,uBAAA,EAEA,MAAA,GAGA,QAAA,GAAA,GACA,IAAA,EAAA,iBAAA,CACA,GAAA,GAAA,EAAA,aACA,KAAA,EAAA,iBAAA,CACA,EAAA,iBAAA,EAAA,eAAA,mBAAA,GAKA,IAAA,GAAA,EAAA,iBAAA,cAAA,OACA,GAAA,KAAA,SAAA,QACA,EAAA,iBAAA,KAAA,YAAA,GAEA,EAAA,iBAAA,iBAAA,EAAA,iBAGA,EAAA,iBAAA,EAAA,iBAGA,MAAA,GAAA,iBAgBA,QAAA,GAAA,GACA,GAAA,GAAA,EAAA,cAAA,cAAA,WACA,GAAA,WAAA,aAAA,EAAA,EAIA,KAFA,GAAA,GAAA,EAAA,WACA,EAAA,EAAA,OACA,IAAA,GAAA,CACA,GAAA,GAAA,EAAA,EACA,GAAA,EAAA,QACA,aAAA,EAAA,MACA,EAAA,aAAA,EAAA,KAAA,EAAA,OACA,EAAA,gBAAA,EAAA,OAIA,MAAA,GAGA,QAAA,GAAA,GACA,GAAA,GAAA,EAAA,cAAA,cAAA,WACA,GAAA,WAAA,aAAA,EAAA,EAIA,KAFA,GAAA,GAAA,EAAA,WACA,EAAA,EAAA,OACA,IAAA,GAAA,CACA,GAAA,GAAA,EAAA,EACA,GAAA,aAAA,EAAA,KAAA,EAAA,OACA,EAAA,gBAAA,EAAA,MAIA,MADA,GAAA,WAAA,YAAA,GACA,EAGA,QAAA,GAAA,EAAA,EAAA,GACA,GAAA,GAAA,EAAA,OACA,IAAA,EAEA,WADA,GAAA,YAAA,EAKA,KADA,GAAA,GACA,EAAA,EAAA,YACA,EAAA,YAAA,GA4FA,QAAA,GAAA,GACA,EACA,EAAA,UAAA,oBAAA,UAEA,EAAA,EAAA,oBAAA,WAGA,QAAA,GAAA,GACA,EAAA,cACA,EAAA,YAAA,WACA,EAAA,sBAAA,CACA,IAAA,GAAA,EAAA,EACA,EAAA,WAAA,EAAA,UAAA,eACA,GAAA,EAAA,EAAA,EAAA,UAIA,EAAA,uBACA,EAAA,sBAAA,EACA,SAAA,QAAA,EAAA,cAkNA,QAAA,GAAA,EAAA,EAAA,EAAA,GACA,GAAA,GAAA,EAAA,OAAA,CAOA,IAJA,GAAA,GACA,EAAA,EAAA,OACA,EAAA,EAAA,EAAA,EAAA,EAAA,EACA,GAAA,EACA,EAAA,GAAA,CACA,GAAA,GAAA,EAAA,QAAA,KAAA,GACA,EAAA,EAAA,QAAA,KAAA,GACA,GAAA,EACA,EAAA,IAWA,IATA,GAAA,IACA,EAAA,GAAA,EAAA,KACA,EAAA,EACA,GAAA,EACA,EAAA,MAGA,EAAA,EAAA,EAAA,GAAA,EAAA,QAAA,EAAA,EAAA,GAEA,EAAA,EAAA,CACA,IAAA,EACA,MAEA,GAAA,KAAA,EAAA,MAAA,GACA,OAGA,EAAA,MACA,EAAA,KAAA,EAAA,MAAA,EAAA,GACA,IAAA,GAAA,EAAA,MAAA,EAAA,EAAA,GAAA,MACA,GAAA,KAAA,GACA,EAAA,GAAA,CACA,IAAA,GAAA,GACA,EAAA,EAAA,EAAA,EAGA,GAAA,KADA,MAAA,EACA,KAAA,IAAA,GAEA,MAEA,EAAA,KAAA,GACA,EAAA,EAAA,EAyBA,MAtBA,KAAA,GACA,EAAA,KAAA,IAEA,EAAA,WAAA,IAAA,EAAA,OACA,EAAA,aAAA,EAAA,YACA,IAAA,EAAA,IACA,IAAA,EAAA,GACA,EAAA,YAAA,EAEA,EAAA,WAAA,SAAA,GAGA,IAAA,GAFA,GAAA,EAAA,GAEA,EAAA,EAAA,EAAA,EAAA,OAAA,GAAA,EAAA,CACA,GAAA,GAAA,EAAA,WAAA,EAAA,GAAA,EAAA,GAAA,EACA,UAAA,IACA,GAAA,GACA,GAAA,EAAA,EAAA,GAGA,MAAA,IAGA,GAGA,QAAA,GAAA,EAAA,EAAA,EAAA,GACA,GAAA,EAAA,WAAA,CACA,GAAA,GAAA,EAAA,GACA,EAAA,EAAA,EAAA,EAAA,GAAA,GACA,EAAA,GAAA,aAAA,EACA,OAAA,GAAA,aAAA,EAAA,EAAA,WAAA,GAIA,IAAA,GADA,MACA,EAAA,EAAA,EAAA,EAAA,OAAA,GAAA,EAAA,CACA,GAAA,GAAA,EAAA,EAAA,EACA,IAAA,EAAA,GAAA,GAAA,EAAA,EAAA,EAAA,GACA,EAAA,EAAA,GAAA,aAAA,GAGA,MAAA,GAAA,WAAA,GAGA,QAAA,GAAA,EAAA,EAAA,EAAA,GACA,GAAA,GAAA,EAAA,GACA,EAAA,EAAA,EAAA,EAAA,GAAA,GACA,GAAA,cAAA,EAAA,EAAA,GAEA,OAAA,GAAA,aAAA,EACA,GAAA,mBAAA,EAAA,EAAA,YAGA,QAAA,GAAA,EAAA,EAAA,EAAA,GACA,GAAA,EAAA,YACA,MAAA,GAAA,EAAA,EAAA,EAAA,EAEA,IAAA,EAAA,WACA,MAAA,GAAA,EAAA,EAAA,EAAA,EAIA,KAAA,GAFA,GAAA,GAAA,kBAEA,EAAA,EAAA,EAAA,EAAA,OAAA,GAAA,EAAA,CACA,GAAA,GAAA,EAAA,GACA,EAAA,EAAA,EAAA,EAEA,IAAA,EAAA,CACA,GAAA,GAAA,EAAA,EAAA,EAAA,EACA,GACA,EAAA,QAAA,GAEA,EAAA,YAAA,OALA,CASA,GAAA,GAAA,EAAA,EAAA,EACA,GACA,EAAA,QAAA,EAAA,aAAA,IAEA,EAAA,QAAA,EAAA,IAGA,MAAA,IAAA,mBAAA,EAAA,EAAA,YAGA,QAAA,GAAA,EAAA,EAAA,EAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,GAAA,EAAA,CACA,GAAA,GAAA,EAAA,GACA,EAAA,EAAA,EAAA,GACA,EAAA,EAAA,EAAA,EAAA,EAAA,GACA,EAAA,EAAA,KAAA,EAAA,EAAA,EAAA,YACA,IAAA,GACA,EAAA,KAAA,GAGA,GAAA,EAAA,WAAA,CAGA,EAAA,OAAA,CACA,IAAA,GAAA,EAAA,0BAAA,EACA,IAAA,GACA,EAAA,KAAA,IAGA,QAAA,GAAA,EAAA,EAAA,GACA,GAAA,GAAA,EAAA,aAAA,EACA,OAAA,GAAA,IAAA,EAAA,OAAA,EAAA,EAAA,EAAA,GAGA,QAAA,GAAA,EAAA,GACA,EAAA,EAMA,KAAA,GAJA,MAIA,EAAA,EAAA,EAAA,EAAA,WAAA,OAAA,IAAA,CAUA,IATA,GAAA,GAAA,EAAA,WAAA,GACA,EAAA,EAAA,KACA,EAAA,EAAA,MAOA,MAAA,EAAA,IACA,EAAA,EAAA,UAAA,EAGA,KAAA,EAAA,IACA,IAAA,GAAA,IAAA,GAAA,IAAA,EADA,CAKA,GAAA,GAAA,EAAA,EAAA,EAAA,EACA,EACA,IAGA,EAAA,KAAA,EAAA,IAaA,MAVA,GAAA,KACA,EAAA,YAAA,EACA,EAAA,GAAA,EAAA,EAAA,EAAA,GACA,EAAA,KAAA,EAAA,EAAA,EAAA,GACA,EAAA,OAAA,EAAA,EAAA,EAAA,IAEA,EAAA,IAAA,EAAA,MAAA,EAAA,SACA,EAAA,KAAA,EAAA,OAAA,EAAA,EAAA,KAGA,EAGA,QAAA,GAAA,EAAA,GACA,GAAA,EAAA,WAAA,KAAA,aACA,MAAA,GAAA,EAAA,EAEA,IAAA,EAAA,WAAA,KAAA,UAAA,CACA,GAAA,GAAA,EAAA,EAAA,KAAA,cAAA,EACA,EACA,IAAA,EACA,OAAA,cAAA,GAGA,SAGA,QAAA,GAAA,EAAA,EAAA,EAAA,EAAA,EACA,EACA,GAKA,IAAA,GAHA,GAAA,EAAA,YAAA,EAAA,WAAA,GAAA,IAEA,EAAA,EACA,EAAA,EAAA,WAAA,EAAA,EAAA,EAAA,YACA,EAAA,EAAA,EAAA,EACA,EAAA,SAAA,KACA,EACA,EACA,EAUA,OAPA,GAAA,aACA,oBAAA,SAAA,EAAA,GACA,GACA,EAAA,aAAA,IAGA,EAAA,EAAA,EAAA,EAAA,GACA,EAGA,QAAA,GAAA,EAAA,GACA,GAAA,GAAA,EAAA,EAAA,EACA,GAAA,WAEA,KAAA,GADA,GAAA,EACA,EAAA,EAAA,WAAA,EAAA,EAAA,EAAA,YACA,EAAA,SAAA,KAAA,EAAA,EAAA,EAGA,OAAA,GAeA,QAAA,GAAA,GACA,KAAA,QAAA,EACA,KAAA,iBAAA,EACA,KAAA,aACA,KAAA,KAAA,OACA,KAAA,iBACA,KAAA,aAAA,OACA,KAAA,cAAA,OAr5BA,GAyCA,GAzCA,EAAA,MAAA,UAAA,QAAA,KAAA,KAAA,MAAA,UAAA,QA0CA,GAAA,KAAA,kBAAA,GAAA,IAAA,UAAA,QACA,EAAA,EAAA,KAEA,EAAA,WACA,KAAA,QACA,KAAA,WAGA,EAAA,WACA,IAAA,SAAA,EAAA,GACA,GAAA,GAAA,KAAA,KAAA,QAAA,EACA,GAAA,GACA,KAAA,KAAA,KAAA,GACA,KAAA,OAAA,KAAA,IAEA,KAAA,OAAA,GAAA,GAIA,IAAA,SAAA,GACA,GAAA,GAAA,KAAA,KAAA,QAAA,EACA,MAAA,EAAA,GAGA,MAAA,MAAA,OAAA,IAGA,SAAA,SAAA,GACA,GAAA,GAAA,KAAA,KAAA,QAAA,EACA,OAAA,GAAA,GACA,GAEA,KAAA,KAAA,OAAA,EAAA,GACA,KAAA,OAAA,OAAA,EAAA,IACA,IAGA,QAAA,SAAA,EAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,KAAA,KAAA,OAAA,IACA,EAAA,KAAA,GAAA,KAAA,KAAA,OAAA,GAAA,KAAA,KAAA,GAAA,QAyBA,mBAAA,UAAA,WACA,SAAA,UAAA,SAAA,SAAA,GACA,MAAA,KAAA,MAAA,EAAA,aAAA,MACA,EACA,KAAA,gBAAA,SAAA,IAIA,IAAA,GAAA,OACA,EAAA,SACA,EAAA,KAEA,GACA,UAAA,EACA,QAAA,EACA,MAAA,EACA,KAAA,GAGA,GACA,OAAA,EACA,OAAA,EACA,OAAA,EACA,IAAA,EACA,IAAA,EACA,IAAA,EACA,UAAA,EACA,KAAA,EACA,SAAA,EACA,QAAA,EACA,UAAA,GAGA,EAAA,mBAAA,oBACA,KAIA,WACA,GAAA,GAAA,SAAA,cAAA,YACA,EAAA,EAAA,QAAA,cACA,EAAA,EAAA,YAAA,EAAA,cAAA,SACA,EAAA,EAAA,YAAA,EAAA,cAAA,SACA,EAAA,EAAA,cAAA,OACA,GAAA,KAAA,SAAA,QACA,EAAA,YAAA,KAIA,IAAA,GAAA,aACA,OAAA,KAAA,GAAA,IAAA,SAAA,GACA,MAAA,GAAA,cAAA,eACA,KAAA,KA2BA,UAAA,iBAAA,mBAAA,WACA,EAAA,UAEA,SAAA,+BACA,GAmBA,IAMA,EAAA,oBAAA,WACA,KAAA,WAAA,wBAIA,IA6GA,GA7GA,EAAA,eA8GA,mBAAA,oBACA,EAAA,GAAA,kBAAA,SAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,GAAA,OAAA,iBAWA,oBAAA,SAAA,SAAA,EAAA,GACA,GAAA,EAAA,qBACA,OAAA,CAEA,IAAA,GAAA,CACA,GAAA,sBAAA,CAEA,IAAA,GAAA,EAAA,IACA,EACA,EAAA,EACA,GAAA,EACA,GAAA,CAgBA,IAdA,IACA,EAAA,IACA,GAAA,GACA,EAAA,EAAA,GACA,EAAA,sBAAA,EACA,EAAA,EACA,GAAA,GACA,EAAA,KACA,EAAA,EAAA,GACA,EAAA,sBAAA,EACA,EAAA,KAIA,EAAA,CACA,EAAA,EACA,IAAA,GAAA,EAAA,EACA,GAAA,SAAA,EAAA,yBAeA,MAZA,GAGA,EAAA,aAAA,EACA,EACA,EAAA,EACA,EACA,GACA,GACA,EAAA,EAAA,UAGA,GAOA,oBAAA,UAAA,CAEA,IAAA,GAAA,EAAA,oBAAA,YAEA,GACA,IAAA,WACA,MAAA,MAAA,UAEA,YAAA,EACA,cAAA,EAGA,KAGA,oBAAA,UAAA,OAAA,OAAA,EAAA,WAEA,OAAA,eAAA,oBAAA,UAAA,UACA,IA0BA,EAAA,oBAAA,WACA,KAAA,SAAA,EAAA,EAAA,GACA,GAAA,OAAA,EACA,MAAA,SAAA,UAAA,KAAA,KAAA,KAAA,EAAA,EAAA,EAEA,IAAA,GAAA,KACA,EAAA,EAAA,EAAA,EAAA,KAAA,SAAA,GACA,EAAA,aAAA,MAAA,GACA,EAAA,eAKA,OAFA,MAAA,aAAA,MAAA,GACA,KAAA,cACA,EAAA,QAGA,KAAA,UAGA,KAAA,UAAA,IAAA,EAFA,KAAA,WAAA,IAAA,GAKA,IAGA,0BAAA,SAAA,GAIA,MAHA,MAAA,WACA,KAAA,UAAA,YAEA,EAAA,IAAA,EAAA,MAAA,EAAA,QASA,KAAA,YACA,KAAA,UAAA,GAAA,GAAA,OAGA,KAAA,UAAA,mBAAA,EAAA,KAAA,QAEA,GACA,EAAA,QAAA,MAAA,YAAA,EACA,iBAAA,SAGA,KAAA,gBAnBA,KAAA,YACA,KAAA,UAAA,QACA,KAAA,UAAA,UAoBA,eAAA,SAAA,EAAA,EAAA,GACA,IACA,EAAA,KAAA,aAAA,IAEA,KAAA,cACA,KAAA,YAAA,KAAA,KAAA,QACA,IAAA,GAAA,KAAA,WACA,IAAA,OAAA,EAAA,WACA,MAAA,EAEA,IAAA,GAAA,KAAA,WACA,IAAA,EAAA,UAAA,IAGA,EAAA,EAAA,EACA,GAAA,EAAA,oBACA,EAAA,QAAA,EACA,KAAA,YAAA,EAGA,IAAA,GAAA,EAAA,MACA,EAAA,EAAA,wBACA,GAAA,iBAAA,KACA,EAAA,cAAA,EACA,EAAA,aACA,EAAA,YAAA,IASA,KAAA,GARA,GAAA,EAAA,mBACA,UAAA,KACA,SAAA,KACA,MAAA,GAGA,EAAA,EACA,GAAA,EACA,EAAA,EAAA,WAAA,EAAA,EAAA,EAAA,YAAA,CAKA,OAAA,EAAA,cACA,GAAA,EAEA,IAAA,GAAA,EAAA,EAAA,EAAA,EACA,EAAA,SAAA,KACA,EACA,EACA,EAAA,UACA,GAAA,kBAAA,EACA,IACA,EAAA,YAAA,GAOA,MAJA,GAAA,UAAA,EAAA,WACA,EAAA,SAAA,EAAA,UACA,EAAA,iBAAA,OACA,EAAA,cAAA,OACA,GAGA,GAAA,SACA,MAAA,MAAA,QAGA,GAAA,OAAA,GACA,KAAA,OAAA,EACA,EAAA,OAGA,GAAA,mBACA,MAAA,MAAA,WAAA,KAAA,UAAA,KAGA,YAAA,WACA,KAAA,WAAA,KAAA,cAAA,KAAA,KAAA,UAGA,KAAA,YAAA,OACA,KAAA,UAAA,eACA,KAAA,UAAA,wBAGA,MAAA,WACA,KAAA,OAAA,OACA,KAAA,UAAA,OACA,KAAA,WAAA,KAAA,UAAA,KACA,KAAA,UAAA,IAAA,QACA,KAAA,YAAA,OACA,KAAA,YAEA,KAAA,UAAA,eACA,KAAA,UAAA,QACA,KAAA,UAAA,SAGA,aAAA,SAAA,GACA,KAAA,UAAA,EACA,KAAA,YAAA,OACA,KAAA,YACA,KAAA,UAAA,2BAAA,OACA,KAAA,UAAA,iBAAA,SAIA,aAAA,SAAA,GAIA,QAAA,GAAA,GACA,GAAA,GAAA,GAAA,EAAA,EACA,IAAA,kBAAA,GAGA,MAAA,YACA,MAAA,GAAA,MAAA,EAAA,YATA,MAAA,IAcA,IAAA,EACA,eAAA,EAAA,kBACA,qBAAA,EAAA,wBACA,+BACA,EAAA,uCAOA,GAAA,iBAAA,GACA,GAAA,KAAA,UACA,KAAA,OAAA,wEAIA,MAAA,aAAA,KAAA,aAAA,KAGA,GAAA,QACA,GAAA,GAAA,EAAA,KAAA,KAAA,aAAA,OAIA,IAHA,IACA,EAAA,KAAA,eAEA,EACA,MAAA,KAEA,IAAA,GAAA,EAAA,IACA,OAAA,GAAA,EAAA,KAoQA,OAAA,eAAA,KAAA,UAAA,oBACA,IAAA,WACA,GAAA,GAAA,KAAA,iBACA,OAAA,GAAA,EACA,KAAA,WAAA,KAAA,WAAA,iBAAA,SAIA,IAAA,GAAA,SAAA,wBACA,GAAA,aACA,EAAA,YAAA,KAYA,EAAA,WACA,UAAA,WACA,GAAA,GAAA,KAAA,IACA,KACA,EAAA,aAAA,GACA,EAAA,QAAA,QACA,EAAA,WAAA,GACA,EAAA,MAAA,UAIA,mBAAA,SAAA,EAAA,GACA,KAAA,WAEA,IAAA,GAAA,KAAA,QACA,EAAA,KAAA,gBAEA,IAAA,EAAA,GAAA,CAMA,GALA,EAAA,OAAA,EACA,EAAA,UAAA,EAAA,GAAA,YACA,EAAA,QAAA,EAAA,EAAA,EAAA,GAAA,EAAA,GAGA,EAAA,YAAA,EAAA,QAEA,WADA,MAAA,qBAIA,GAAA,WACA,EAAA,QAAA,KAAA,KAAA,oBAAA,MAGA,EAAA,QACA,EAAA,QAAA,EACA,EAAA,QAAA,EAAA,OAAA,YACA,EAAA,MAAA,EAAA,EAAA,EAAA,OAAA,EAAA,KAEA,EAAA,QAAA,EACA,EAAA,QAAA,EAAA,KAAA,YACA,EAAA,MAAA,EAAA,EAAA,EAAA,KAAA,EAAA,IAGA,EAAA,SACA,EAAA,MAAA,KAAA,KAAA,oBAAA,MAEA,KAAA,uBAGA,oBAAA,WACA,GAAA,KAAA,KAAA,MAAA,CACA,GAAA,GAAA,KAAA,KAAA,OAGA,IAFA,KAAA,KAAA,YACA,EAAA,EAAA,mBACA,EAEA,WADA,MAAA,eAKA,GAAA,GAAA,KAAA,KAAA,KACA,MAAA,KAAA,UACA,EAAA,EAAA,kBACA,KAAA,KAAA,SACA,GAAA,GACA,IAAA,GAAA,KAAA,KAAA,SACA,KAAA,KAAA,SACA,MAAA,QAAA,EACA,MAAA,aAAA,EAAA,IAGA,aAAA,SAAA,EAAA,GACA,MAAA,QAAA,KACA,MAEA,IAAA,KAAA,gBAGA,KAAA,YACA,KAAA,aAAA,EACA,IACA,KAAA,cAAA,GAAA,eAAA,KAAA,cACA,KAAA,cAAA,KAAA,KAAA,cAAA,OAGA,KAAA,cAAA,cAAA,iBAAA,KAAA,aACA,KAAA,kBAGA,oBAAA,SAAA,GACA,GAAA,IAAA,EACA,MAAA,MAAA,gBACA,IAAA,GAAA,KAAA,UAAA,GACA,EAAA,EAAA,WACA,KAAA,EACA,MAAA,MAAA,oBAAA,EAAA,EAEA,IAAA,EAAA,WAAA,KAAA,cACA,KAAA,mBAAA,EACA,MAAA,EAGA,IAAA,GAAA,EAAA,SACA,OAAA,GAGA,EAAA,sBAFA,GAKA,oBAAA,WACA,MAAA,MAAA,oBAAA,KAAA,UAAA,OAAA,IAGA,iBAAA,SAAA,EAAA,GACA,GAAA,GAAA,KAAA,oBAAA,EAAA,GACA,EAAA,KAAA,iBAAA,UACA,MAAA,UAAA,OAAA,EAAA,EAAA,GAEA,EAAA,aAAA,EAAA,EAAA,cAGA,kBAAA,SAAA,GAMA,IALA,GAAA,GAAA,KAAA,oBAAA,EAAA,GACA,EAAA,KAAA,oBAAA,GACA,EAAA,KAAA,iBAAA,WACA,EAAA,KAAA,UAAA,OAAA,EAAA,GAAA,GAEA,IAAA,GAAA,CACA,GAAA,GAAA,EAAA,WACA,IAAA,IACA,EAAA,GAEA,EAAA,YAAA,EAAA,YAAA,IAGA,MAAA,IAGA,cAAA,SAAA,GAEA,MADA,GAAA,GAAA,EAAA,KAAA,kBACA,kBAAA,GAAA,EAAA,MAGA,cAAA,SAAA,GACA,IAAA,KAAA,QAAA,EAAA,OAAA,CAGA,GAAA,GAAA,KAAA,gBAEA,KAAA,EAAA,WAEA,WADA,MAAA,OAIA,eAAA,aAAA,KAAA,cAAA,KAAA,aACA,EAEA,IAAA,GAAA,EAAA,SACA,UAAA,KAAA,mBACA,KAAA,iBACA,KAAA,cAAA,GAAA,EAAA,uBAGA,SAAA,KAAA,6BACA,KAAA,2BACA,KAAA,cAAA,GACA,EAAA,gCAMA,KAAA,GAFA,GAAA,GAAA,GACA,EAAA,EACA,EAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CAGA,IAAA,GAFA,GAAA,EAAA,GACA,EAAA,EAAA,QACA,EAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,GACA,EAAA,KAAA,kBAAA,EAAA,MAAA,EACA,KAAA,GACA,EAAA,IAAA,EAAA,GAIA,GAAA,EAAA,WAIA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IAGA,IAFA,GAAA,GAAA,EAAA,GACA,EAAA,EAAA,MACA,EAAA,EAAA,MAAA,EAAA,WAAA,IAAA,CACA,GAAA,GAAA,KAAA,cAAA,GACA,EAAA,EAAA,IAAA,EACA,GACA,EAAA,OAAA,IAEA,KAAA,mBACA,EAAA,KAAA,iBAAA,IAIA,EADA,SAAA,EACA,EAEA,EAAA,eAAA,EAAA,OAAA,IAIA,KAAA,iBAAA,EAAA,GAIA,EAAA,QAAA,SAAA,GACA,KAAA,sBAAA,IACA,MAEA,KAAA,4BACA,KAAA,qBAAA,KAGA,oBAAA,SAAA,GACA,GAAA,GAAA,KAAA,UAAA,EACA,KAAA,GAGA,KAAA,2BAAA,EAAA,kBAAA,IAGA,qBAAA,SAAA,GAGA,IAAA,GAFA,GAAA,EACA,EAAA,EACA,EAAA,EAAA,EAAA,EAAA,OAAA,IAAA,CACA,GAAA,GAAA,EAAA,EACA,IAAA,GAAA,EACA,KAAA,EAAA,EAAA,OACA,KAAA,oBAAA,GACA,QAGA,GAAA,EAAA,KAGA,MAAA,EAAA,EAAA,MAAA,EAAA,YACA,KAAA,oBAAA,GACA,GAGA,IAAA,EAAA,WAAA,EAAA,QAAA,OAGA,GAAA,GAAA,EAIA,IADA,GAAA,GAAA,KAAA,UAAA,OACA,EAAA,GACA,KAAA,oBAAA,GACA,KAIA,sBAAA,SAAA,GAEA,IAAA,GADA,GAAA,EAAA,UACA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,GAAA,SAIA,UAAA,WACA,KAAA,gBAGA,KAAA,cAAA,QACA,KAAA,cAAA,SAGA,MAAA,WACA,IAAA,KAAA,OAAA,CAEA,KAAA,WACA,KAAA,GAAA,GAAA,EAAA,EAAA,KAAA,UAAA,OAAA,IACA,KAAA,sBAAA,KAAA,UAAA,GAGA,MAAA,UAAA,OAAA,EACA,KAAA,YACA,KAAA,iBAAA,UAAA,OACA,KAAA,QAAA,KAKA,oBAAA,qBAAA,GACA,MCzqCA,SAAA,GACA,YAiEA,SAAA,GAAA,EAAA,GACA,IAAA,EACA,KAAA,IAAA,OAAA,WAAA,GAIA,QAAA,GAAA,GACA,MAAA,IAAA,IAAA,IAAA,EAMA,QAAA,GAAA,GACA,MAAA,MAAA,GACA,IAAA,GACA,KAAA,GACA,KAAA,GACA,MAAA,GACA,GAAA,MAAA,oBAAA,QAAA,OAAA,aAAA,IAAA,EAKA,QAAA,GAAA,GACA,MAAA,MAAA,GAAA,KAAA,GAAA,OAAA,GAAA,OAAA,EAKA,QAAA,GAAA,GACA,MAAA,MAAA,GAAA,KAAA,GACA,GAAA,IAAA,IAAA,GACA,GAAA,IAAA,KAAA,EAGA,QAAA,GAAA,GACA,MAAA,MAAA,GAAA,KAAA,GACA,GAAA,IAAA,IAAA,GACA,GAAA,IAAA,KAAA,GACA,GAAA,IAAA,IAAA,EAKA,QAAA,GAAA,GACA,MAAA,SAAA,EAKA,QAAA,KACA,KAAA,EAAA,GAAA,EAAA,EAAA,WAAA,OACA,EAIA,QAAA,KACA,GAAA,GAAA,CAGA,KADA,EAAA,IACA,EAAA,IACA,EAAA,EAAA,WAAA,GACA,EAAA,OACA,CAMA,OAAA,GAAA,MAAA,EAAA,GAGA,QAAA,KACA,GAAA,GAAA,EAAA,CAoBA,OAlBA,GAAA,EAEA,EAAA,IAKA,EADA,IAAA,EAAA,OACA,EAAA,WACA,EAAA,GACA,EAAA,QACA,SAAA,EACA,EAAA,YACA,SAAA,GAAA,UAAA,EACA,EAAA,eAEA,EAAA,YAIA,KAAA,EACA,MAAA,EACA,OAAA,EAAA,IAOA,QAAA,KACA,GAEA,GAEA,EAJA,EAAA,EACA,EAAA,EAAA,WAAA,GAEA,EAAA,EAAA,EAGA,QAAA,GAGA,IAAA,IACA,IAAA,IACA,IAAA,IACA,IAAA,IACA,IAAA,IACA,IAAA,KACA,IAAA,KACA,IAAA,IACA,IAAA,IACA,IAAA,IACA,IAAA,IAEA,QADA,GAEA,KAAA,EAAA,WACA,MAAA,OAAA,aAAA,GACA,OAAA,EAAA,GAGA,SAIA,GAHA,EAAA,EAAA,WAAA,EAAA,GAGA,KAAA,EACA,OAAA,GACA,IAAA,IACA,IAAA,IACA,IAAA,IACA,IAAA,IACA,IAAA,IACA,IAAA,IACA,IAAA,IACA,IAAA,IACA,IAAA,KAEA,MADA,IAAA,GAEA,KAAA,EAAA,WACA,MAAA,OAAA,aAAA,GAAA,OAAA,aAAA,GACA,OAAA,EAAA,GAGA,KAAA,IACA,IAAA,IAOA,MANA,IAAA,EAGA,KAAA,EAAA,WAAA,MACA,GAGA,KAAA,EAAA,WACA,MAAA,EAAA,MAAA,EAAA,GACA,OAAA,EAAA,KAeA,MAJA,GAAA,EAAA,EAAA,GAIA,IAAA,GAAA,KAAA,QAAA,IAAA,GACA,GAAA,GAEA,KAAA,EAAA,WACA,MAAA,EAAA,EACA,OAAA,EAAA,KAIA,eAAA,QAAA,IAAA,KACA,GAEA,KAAA,EAAA,WACA,MAAA,EACA,OAAA,EAAA,SAIA,MAAA,EAAA,gBAAA,WAIA,QAAA,KACA,GAAA,GAAA,EAAA,CAQA,IANA,EAAA,EAAA,GACA,EAAA,EAAA,EAAA,WAAA,KAAA,MAAA,EACA,sEAEA,EAAA,EACA,EAAA,GACA,MAAA,EAAA,CAaA,IAZA,EAAA,EAAA,KACA,EAAA,EAAA,GAIA,MAAA,GAEA,GAAA,EAAA,EAAA,WAAA,KACA,KAAA,EAAA,gBAAA,WAIA,EAAA,EAAA,WAAA,KACA,GAAA,EAAA,IAEA,GAAA,EAAA,GAGA,GAAA,MAAA,EAAA,CAEA,IADA,GAAA,EAAA,KACA,EAAA,EAAA,WAAA,KACA,GAAA,EAAA,IAEA,GAAA,EAAA,GAGA,GAAA,MAAA,GAAA,MAAA,EAOA,GANA,GAAA,EAAA,KAEA,EAAA,EAAA,IACA,MAAA,GAAA,MAAA,KACA,GAAA,EAAA,MAEA,EAAA,EAAA,WAAA,IACA,KAAA,EAAA,EAAA,WAAA,KACA,GAAA,EAAA,SAGA,MAAA,EAAA,gBAAA,UAQA,OAJA,GAAA,EAAA,WAAA,KACA,KAAA,EAAA,gBAAA,YAIA,KAAA,EAAA,eACA,MAAA,WAAA,GACA,OAAA,EAAA,IAMA,QAAA,KACA,GAAA,GAAA,EAAA,EAAA,EAAA,GAAA,GAAA,CASA,KAPA,EAAA,EAAA,GACA,EAAA,MAAA,GAAA,MAAA,EACA,2CAEA,EAAA,IACA,EAEA,EAAA,GAAA,CAGA,GAFA,EAAA,EAAA,KAEA,IAAA,EAAA,CACA,EAAA,EACA,OACA,GAAA,OAAA,EAEA,GADA,EAAA,EAAA,KACA,GAAA,EAAA,EAAA,WAAA,IA0BA,OAAA,GAAA,OAAA,EAAA,MACA,MA1BA,QAAA,GACA,IAAA,IACA,GAAA,IACA,MACA,KAAA,IACA,GAAA,IACA,MACA,KAAA,IACA,GAAA,GACA,MACA,KAAA,IACA,GAAA,IACA,MACA,KAAA,IACA,GAAA,IACA,MACA,KAAA,IACA,GAAA,GACA,MAEA,SACA,GAAA,MAQA,CAAA,GAAA,EAAA,EAAA,WAAA,IACA,KAEA,IAAA,GAQA,MAJA,KAAA,GACA,KAAA,EAAA,gBAAA,YAIA,KAAA,EAAA,cACA,MAAA,EACA,MAAA,EACA,OAAA,EAAA,IAIA,QAAA,GAAA,GACA,MAAA,GAAA,OAAA,EAAA,YACA,EAAA,OAAA,EAAA,SACA,EAAA,OAAA,EAAA,gBACA,EAAA,OAAA,EAAA,YAGA,QAAA,KACA,GAAA,EAIA,OAFA,KAEA,GAAA,GAEA,KAAA,EAAA,IACA,OAAA,EAAA,KAIA,EAAA,EAAA,WAAA,GAGA,KAAA,GAAA,KAAA,GAAA,KAAA,EACA,IAIA,KAAA,GAAA,KAAA,EACA,IAGA,EAAA,GACA,IAKA,KAAA,EACA,EAAA,EAAA,WAAA,EAAA,IACA,IAEA,IAGA,EAAA,GACA,IAGA,KAGA,QAAA,KACA,GAAA,EASA,OAPA,GAAA,EACA,EAAA,EAAA,MAAA,GAEA,EAAA,IAEA,EAAA,EAAA,MAAA,GAEA,EAGA,QAAA,KACA,GAAA,EAEA,GAAA,EACA,EAAA,IACA,EAAA,EAKA,QAAA,GAAA,EAAA,GACA,GAAA,GACA,EAAA,MAAA,UAAA,MAAA,KAAA,UAAA,GACA,EAAA,EAAA,QACA,SACA,SAAA,EAAA,GAEA,MADA,GAAA,EAAA,EAAA,OAAA,sCACA,EAAA,IAOA,MAHA,GAAA,GAAA,OAAA,GACA,EAAA,MAAA,EACA,EAAA,YAAA,EACA,EAKA,QAAA,GAAA,GACA,EAAA,EAAA,EAAA,gBAAA,EAAA,OAMA,QAAA,GAAA,GACA,GAAA,GAAA,KACA,EAAA,OAAA,EAAA,YAAA,EAAA,QAAA,IACA,EAAA,GAMA,QAAA,GAAA,GACA,MAAA,GAAA,OAAA,EAAA,YAAA,EAAA,QAAA,EAKA,QAAA,GAAA,GACA,MAAA,GAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAwBA,QAAA,KACA,GAAA,KAIA,KAFA,EAAA,MAEA,EAAA,MACA,EAAA,MACA,IACA,EAAA,KAAA,QAEA,EAAA,KAAA,MAEA,EAAA,MACA,EAAA,KAOA,OAFA,GAAA,KAEA,EAAA,sBAAA,GAKA,QAAA,KACA,GAAA,EAOA,OALA,KACA,EAAA,IAIA,EAAA,OAAA,EAAA,eAAA,EAAA,OAAA,EAAA,eACA,EAAA,cAAA,GAGA,EAAA,iBAAA,EAAA,OAGA,QAAA,KACA,GAAA,GAAA,CAWA,OATA,GAAA,EACA,KAEA,EAAA,OAAA,EAAA,KAAA,EAAA,OAAA,EAAA,aACA,EAAA,GAGA,EAAA,IACA,EAAA,KACA,EAAA,eAAA,OAAA,EAAA,MAGA,QAAA,KACA,GAAA,KAIA,KAFA,EAAA,MAEA,EAAA,MACA,EAAA,KAAA,KAEA,EAAA,MACA,EAAA,IAMA,OAFA,GAAA,KAEA,EAAA,uBAAA,GAKA,QAAA,KACA,GAAA,EAQA,OANA,GAAA,KAEA,EAAA,KAEA,EAAA,KAEA,EAMA,QAAA,KACA,GAAA,GAAA,EAAA,CAEA,OAAA,GAAA,KACA,KAGA,EAAA,EAAA,KAEA,IAAA,EAAA,WACA,EAAA,EAAA,iBAAA,IAAA,OACA,IAAA,EAAA,eAAA,IAAA,EAAA,eACA,EAAA,EAAA,cAAA,KACA,IAAA,EAAA,QACA,EAAA,UACA,IACA,EAAA,EAAA,wBAEA,IAAA,EAAA,gBACA,EAAA,IACA,EAAA,MAAA,SAAA,EAAA,MACA,EAAA,EAAA,cAAA,IACA,IAAA,EAAA,aACA,EAAA,IACA,EAAA,MAAA,KACA,EAAA,EAAA,cAAA,IACA,EAAA,KACA,EAAA,IACA,EAAA,OACA,EAAA,KAGA,EACA,MAGA,GAAA,MAKA,QAAA,KACA,GAAA,KAIA,IAFA,EAAA,MAEA,EAAA,KACA,KAAA,EAAA,IACA,EAAA,KAAA,OACA,EAAA,OAGA,EAAA,IAMA,OAFA,GAAA,KAEA,EAGA,QAAA,KACA,GAAA,EAQA,OANA,GAAA,IAEA,EAAA,IACA,EAAA,GAGA,EAAA,iBAAA,EAAA,OAGA,QAAA,KAGA,MAFA,GAAA,KAEA,IAGA,QAAA,KACA,GAAA,EAQA,OANA,GAAA,KAEA,EAAA,KAEA,EAAA,KAEA,EAGA,QAAA,KACA,GAAA,GAAA,CAIA,KAFA,EAAA,IAEA,EAAA,MAAA,EAAA,MACA,EAAA,MACA,EAAA,IACA,EAAA,EAAA,uBAAA,IAAA,EAAA,KAEA,EAAA,IACA,EAAA,EAAA,uBAAA,IAAA,EAAA,GAIA,OAAA,GASA,QAAA,KACA,GAAA,GAAA,CAcA,OAZA,GAAA,OAAA,EAAA,YAAA,EAAA,OAAA,EAAA,QACA,EAAA,KACA,EAAA,MAAA,EAAA,MAAA,EAAA,MACA,EAAA,IACA,EAAA,IACA,EAAA,EAAA,sBAAA,EAAA,MAAA,IACA,EAAA,WAAA,EAAA,SAAA,EAAA,UACA,KAAA,EAAA,iBAEA,EAAA,KAGA,EAGA,QAAA,GAAA,GACA,GAAA,GAAA,CAEA,IAAA,EAAA,OAAA,EAAA,YAAA,EAAA,OAAA,EAAA,QACA,MAAA,EAGA,QAAA,EAAA,OACA,IAAA,KACA,EAAA,CACA,MAEA,KAAA,KACA,EAAA,CACA,MAEA,KAAA,KACA,IAAA,KACA,IAAA,MACA,IAAA,MACA,EAAA,CACA,MAEA,KAAA,IACA,IAAA,IACA,IAAA,KACA,IAAA,KACA,IAAA,aACA,EAAA,CACA,MAEA,KAAA,KACA,EAAA,CACA,MAEA,KAAA,IACA,IAAA,IACA,EAAA,CACA,MAEA,KAAA,IACA,IAAA,IACA,IAAA,IACA,EAAA,GAOA,MAAA,GAWA,QAAA,KACA,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,CAMA,IAJA,EAAA,IAEA,EAAA,EACA,EAAA,EAAA,GACA,IAAA,EACA,MAAA,EASA,KAPA,EAAA,KAAA,EACA,IAEA,EAAA,IAEA,GAAA,EAAA,EAAA,IAEA,EAAA,EAAA,IAAA,GAAA,CAGA,KAAA,EAAA,OAAA,GAAA,GAAA,EAAA,EAAA,OAAA,GAAA,MACA,EAAA,EAAA,MACA,EAAA,EAAA,MAAA,MACA,EAAA,EAAA,MACA,EAAA,EAAA,uBAAA,EAAA,EAAA,GACA,EAAA,KAAA,EAIA,GAAA,IACA,EAAA,KAAA,EACA,EAAA,KAAA,GACA,EAAA,IACA,EAAA,KAAA,GAMA,IAFA,EAAA,EAAA,OAAA,EACA,EAAA,EAAA,GACA,EAAA,GACA,EAAA,EAAA,uBAAA,EAAA,EAAA,GAAA,MAAA,EAAA,EAAA,GAAA,GACA,GAAA,CAGA,OAAA,GAMA,QAAA,KACA,GAAA,GAAA,EAAA,CAaA,OAXA,GAAA,IAEA,EAAA,OACA,IACA,EAAA,IACA,EAAA,KACA,EAAA,IAEA,EAAA,EAAA,4BAAA,EAAA,EAAA,IAGA,EAaA,QAAA,KACA,GAAA,GAAA,CAUA,OARA,GAAA,IAEA,EAAA,OAAA,EAAA,YACA,EAAA,GAGA,EAAA,EAAA,KAAA,OAEA,EAAA,aAAA,EAAA,MAAA,GAOA,QAAA,KACA,KAAA,EAAA,MACA,IACA,IAqBA,QAAA,KACA,IACA,GAEA,IAAA,GAAA,IACA,KACA,MAAA,EAAA,OAAA,MAAA,EAAA,OACA,EAAA,OAAA,EAAA,WACA,EAAA,IAEA,IACA,OAAA,EAAA,MACA,EAAA,GAEA,EAAA,eAAA,KAKA,EAAA,OAAA,EAAA,KACA,EAAA,GAIA,QAAA,GAAA,GACA,GACA,IAAA,GAAA,IAAA,KACA,GAAA,mBAAA,EAAA,GAGA,QAAA,GAAA,GACA,GAAA,EACA,OAAA,EAAA,QACA,IACA,EAAA,OAAA,EAAA,YACA,EAAA,GACA,EAAA,IAAA,OAGA,GACA,IAAA,GAAA,IACA,KACA,EAAA,mBAAA,EAAA,KAAA,EAAA,GAGA,QAAA,GAAA,EAAA,GAUA,MATA,GAAA,EACA,EAAA,EACA,EAAA,EACA,EAAA,EAAA,OACA,EAAA,KACA,GACA,aAGA,IAn+BA,GAAA,GACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,CAEA,IACA,eAAA,EACA,IAAA,EACA,WAAA,EACA,QAAA,EACA,YAAA,EACA,eAAA,EACA,WAAA,EACA,cAAA,GAGA,KACA,EAAA,EAAA,gBAAA,UACA,EAAA,EAAA,KAAA,QACA,EAAA,EAAA,YAAA,aACA,EAAA,EAAA,SAAA,UACA,EAAA,EAAA,aAAA,OACA,EAAA,EAAA,gBAAA,UACA,EAAA,EAAA,YAAA,aACA,EAAA,EAAA,eAAA,SAEA,GACA,gBAAA,kBACA,iBAAA,mBACA,eAAA,iBACA,sBAAA,wBACA,eAAA,iBACA,oBAAA,sBACA,WAAA,aACA,QAAA,UACA,iBAAA,mBACA,kBAAA,oBACA,iBAAA,mBACA,iBAAA,mBACA,QAAA,UACA,SAAA,WACA,eAAA,iBACA,gBAAA,mBAIA,GACA,gBAAA,sBACA,aAAA,uBACA,cAAA,oCA2qBA,IAAA,IAAA,EAuJA,GAAA,CA6GA,GAAA,SACA,MAAA,IAEA,MCrgCA,SAAA,GACA,YAqBA,SAAA,GAAA,EAAA,EAAA,EAAA,GACA,GAAA,EACA,KAEA,GADA,EAAA,EAAA,GACA,EAAA,aACA,EAAA,WAAA,KAAA,cACA,aAAA,EAAA,SACA,SAAA,GAAA,WAAA,GACA,KAAA,OAAA,4DAEA,MAAA,GAEA,WADA,SAAA,MAAA,8BAAA,EAAA,GAIA,MAAA,UAAA,EAAA,EAAA,GACA,GAAA,GAAA,EAAA,WAAA,EAAA,EAAA,EAOA,OANA,GAAA,YAAA,IACA,EAAA,6BAAA,EAAA,WACA,EAAA,aACA,EAAA,6BAAA,EAAA,aAGA,GAOA,QAAA,GAAA,GACA,GAAA,GAAA,EAAA,EACA,KAAA,EAAA,CACA,GAAA,GAAA,GAAA,EACA,SAAA,MAAA,EAAA,GACA,EAAA,GAAA,GAAA,GACA,EAAA,GAAA,EAEA,MAAA,GAGA,QAAA,GAAA,GACA,KAAA,MAAA,EACA,KAAA,SAAA,OAgBA,QAAA,GAAA,GACA,KAAA,KAAA,EACA,KAAA,KAAA,KAAA,IAAA,GA2BA,QAAA,GAAA,EAAA,EAAA,GAGA,KAAA,GACA,YAAA,IACA,KAAA,IAAA,EAAA,OAAA,QACA,EAAA,IACA,EAAA,GAAA,GAAA,EAAA,QAGA,KAAA,YAAA,kBAAA,IAAA,EAAA,QAEA,KAAA,QAAA,kBAAA,IACA,EAAA,SACA,KAAA,EAEA,KAAA,YACA,KAAA,UACA,KAAA,aACA,YAAA,KACA,YAAA,IAAA,YAAA,IAEA,KAAA,OAAA,KAAA,WAAA,EAAA,EAAA,GACA,KAAA,SAAA,KAAA,EAAA,EAAA,EAAA,GAoEA,QAAA,GAAA,EAAA,GACA,KAAA,KAAA,EACA,KAAA,OACA,KAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IACA,KAAA,KAAA,GAAA,EAAA,EAAA,IA2CA,QAAA,KAAA,KAAA,OAAA,mBA0BA,QAAA,GAAA,GACA,MAAA,kBAAA,GAAA,EAAA,EAAA,UAGA,QAAA,KACA,KAAA,WAAA,KACA,KAAA,WACA,KAAA,QACA,KAAA,YAAA,OACA,KAAA,WAAA,OACA,KAAA,WAAA,OACA,KAAA,aAAA,EA6GA,QAAA,GAAA,GACA,KAAA,OAAA,EAUA,QAAA,GAAA,GAIA,GAHA,KAAA,WAAA,EAAA,WACA,KAAA,WAAA,EAAA,YAEA,EAAA,WACA,KAAA,OAAA,uBAEA,MAAA,WAAA,EAAA,WACA,EAAA,KAAA,YAEA,KAAA,QAAA,EAAA,QACA,KAAA,YAAA,EAAA,YAmEA,QAAA,GAAA,GACA,MAAA,QAAA,GAAA,QAAA,SAAA,SAAA,GACA,MAAA,IAAA,EAAA,gBAIA,QAAA,GAAA,GACA,MAAA,MAAA,EAAA,IACA,MAAA,EAAA,IACA,MAAA,EAAA,GAoBA,QAAA,GAAA,EAAA,GACA,KAAA,EAAA,KACA,OAAA,UAAA,eAAA,KAAA,EAAA,IACA,EAAA,EAAA,EAGA,OAAA,GAGA,QAAA,GAAA,EAAA,GACA,GAAA,GAAA,EAAA,OACA,MAAA,OAEA,IAAA,GAAA,EAAA,OACA,MAAA,GAAA,EAAA,EAAA,GAEA,KAAA,GAAA,GAAA,EAAA,MAAA,GAAA,EAAA,EAAA,OAAA,EAAA,IACA,EAAA,EAAA,EAAA,GAGA,OAAA,GAGA,QAAA,GAAA,EAAA,EAAA,GACA,GAAA,GAAA,EAAA,UAAA,EAGA,OAFA,GAAA,EAAA,IAAA,EAEA,SAAA,EAAA,EAAA,GA2BA,QAAA,KACA,MAAA,MAAA,EAAA,MA3BA,GAAA,GAAA,EAAA,CAuBA,OArBA,GADA,kBAAA,GAAA,oBACA,SAAA,GACA,EAAA,GAAA,EAAA,oBAAA,EAAA,EAAA,GACA,EAAA,EAAA,EAAA,OAAA,EAAA,eAEA,UAAA,kBAAA,UAAA,OACA,SAAA,SAGA,SAAA,GACA,EAAA,GAAA,EAAA,aAAA,GACA,EAAA,GAAA,EAAA,EAAA,EAAA,GAEA,EAAA,MAAA,GAAA,EAAA,EAAA,OAAA,EAAA,gBAEA,UAAA,kBAAA,UAAA,OACA,SAAA,SAIA,EAAA,iBAAA,EAAA,GAEA,EAAA,QAQA,KAAA,EACA,eAAA,EACA,MAAA,WACA,EAAA,oBAAA,EAAA,MAMA,QAAA,GAAA,GACA,OAAA,GACA,IAAA,GACA,OAAA,CAEA,KAAA,QACA,IAAA,OACA,IAAA,OACA,OAAA,EAGA,MAAA,OAAA,OAAA,KAGA,GAFA,EAKA,QAAA,MA7kBA,GA0CA,GAAA,OAAA,OAAA,KAkBA,GAAA,WACA,QAAA,WACA,IAAA,KAAA,SAAA,CACA,GAAA,GAAA,KAAA,KACA,MAAA,SAAA,WACA,MAAA,IAIA,MAAA,MAAA,WASA,EAAA,WACA,QAAA,WACA,IAAA,KAAA,SAAA,CACA,GACA,IADA,KAAA,KACA,KAAA,KACA,MAAA,SAAA,SAAA,EAAA,GAIA,MAHA,IACA,EAAA,QAAA,EAAA,GAEA,EAAA,aAAA,IAIA,MAAA,MAAA,UAGA,SAAA,SAAA,EAAA,GAIA,MAHA,IAAA,KAAA,KAAA,OACA,EAAA,EAAA,EAAA,KAAA,KAAA,IAEA,KAAA,KAAA,aAAA,EAAA,KA8BA,EAAA,WACA,GAAA,YACA,IAAA,KAAA,UAAA,CACA,GAAA,GAAA,KAAA,iBAAA,GACA,KAAA,OAAA,KAAA,KAAA,OAAA,QACA,MAAA,UAAA,KAAA,IAAA,EAAA,IAAA,KAAA,SAAA,MAGA,MAAA,MAAA,WAGA,QAAA,WACA,IAAA,KAAA,SAAA,CACA,GAAA,GAAA,KAAA,MAEA,IAAA,KAAA,WAAA,CACA,GAAA,GAAA,KAAA,QAEA,MAAA,SAAA,SAAA,EAAA,GAIA,MAHA,IACA,EAAA,QAAA,EAAA,GAEA,EAAA,aAAA,QAEA,IAAA,KAAA,mBAAA,GAAA,CACA,GAAA,GAAA,KAAA,IAAA,KAAA,SAAA,KAEA,MAAA,SAAA,SAAA,EAAA,GACA,GAAA,GAAA,EAAA,EAAA,EAKA,OAHA,IACA,EAAA,QAAA,EAAA,GAEA,EAAA,aAAA,QAEA,CAEA,GAAA,GAAA,KAAA,QAEA,MAAA,SAAA,SAAA,EAAA,GACA,GAAA,GAAA,EAAA,EAAA,GACA,EAAA,EAAA,EAAA,EAIA,OAHA,IACA,EAAA,QAAA,EAAA,GAEA,EAAA,EAAA,GAAA,SAIA,MAAA,MAAA,UAGA,SAAA,SAAA,EAAA,GACA,GAAA,KAAA,WAEA,MADA,MAAA,SAAA,aAAA,EAAA,GACA,CAGA,IAAA,GAAA,KAAA,OAAA,GACA,EAAA,KAAA,mBAAA,GAAA,KAAA,SAAA,KACA,KAAA,SAAA,EACA,OAAA,GAAA,GAAA,IAYA,EAAA,WACA,UAAA,SAAA,EAAA,EAAA,EAAA,EACA,GACA,GAAA,GAAA,EAAA,KAAA,MACA,EAAA,CACA,IAAA,EACA,EAAA,WAGA,IADA,EAAA,EAAA,KAAA,OACA,EAEA,WADA,SAAA,MAAA,uBAAA,KAAA,KAcA,IANA,EACA,EAAA,EAAA,QACA,kBAAA,GAAA,QACA,EAAA,EAAA,OAGA,kBAAA,GAGA,WAFA,SAAA,MAAA,OAAA,EAAA,UAAA,SACA,YAAA,KAAA,KAKA,KAAA,GADA,IAAA,GACA,EAAA,EAAA,EAAA,KAAA,KAAA,OAAA,IACA,EAAA,EAAA,GAAA,EAAA,KAAA,KAAA,IAAA,EAAA,EAGA,OAAA,GAAA,MAAA,EAAA,IAMA,IAAA,IACA,IAAA,SAAA,GAAA,OAAA,GACA,IAAA,SAAA,GAAA,OAAA,GACA,IAAA,SAAA,GAAA,OAAA,IAGA,GACA,IAAA,SAAA,EAAA,GAAA,MAAA,GAAA,GACA,IAAA,SAAA,EAAA,GAAA,MAAA,GAAA,GACA,IAAA,SAAA,EAAA,GAAA,MAAA,GAAA,GACA,IAAA,SAAA,EAAA,GAAA,MAAA,GAAA,GACA,IAAA,SAAA,EAAA,GAAA,MAAA,GAAA,GACA,IAAA,SAAA,EAAA,GAAA,MAAA,GAAA,GACA,IAAA,SAAA,EAAA,GAAA,MAAA,GAAA,GACA,KAAA,SAAA,EAAA,GAAA,MAAA,IAAA,GACA,KAAA,SAAA,EAAA,GAAA,MAAA,IAAA,GACA,KAAA,SAAA,EAAA,GAAA,MAAA,IAAA,GACA,KAAA,SAAA,EAAA,GAAA,MAAA,IAAA,GACA,MAAA,SAAA,EAAA,GAAA,MAAA,KAAA,GACA,MAAA,SAAA,EAAA,GAAA,MAAA,KAAA,GACA,KAAA,SAAA,EAAA,GAAA,MAAA,IAAA,GACA,KAAA,SAAA,EAAA,GAAA,MAAA,IAAA,GAiBA,GAAA,WACA,sBAAA,SAAA,EAAA,GACA,IAAA,EAAA,GACA,KAAA,OAAA,wBAAA,EAIA,OAFA,GAAA,EAAA,GAEA,SAAA,EAAA,GACA,MAAA,GAAA,GAAA,EAAA,EAAA,MAIA,uBAAA,SAAA,EAAA,EAAA,GACA,IAAA,EAAA,GACA,KAAA,OAAA,wBAAA,EAKA,OAHA,GAAA,EAAA,GACA,EAAA,EAAA,GAEA,SAAA,EAAA,GACA,MAAA,GAAA,GAAA,EAAA,EAAA,GACA,EAAA,EAAA,MAIA,4BAAA,SAAA,EAAA,EAAA,GAKA,MAJA,GAAA,EAAA,GACA,EAAA,EAAA,GACA,EAAA,EAAA,GAEA,SAAA,EAAA,GACA,MAAA,GAAA,EAAA,GACA,EAAA,EAAA,GAAA,EAAA,EAAA,KAIA,iBAAA,SAAA,GACA,GAAA,GAAA,GAAA,GAAA,EAEA,OADA,GAAA,KAAA,aACA,GAGA,uBAAA,SAAA,EAAA,EAAA,GACA,GAAA,GAAA,GAAA,GAAA,EAAA,EAAA,EAGA,OAFA,GAAA,cACA,KAAA,aAAA,GACA,GAGA,cAAA,SAAA,GACA,MAAA,IAAA,GAAA,EAAA,QAGA,sBAAA,SAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,GAAA,EAAA,EAAA,GAEA,OAAA,UAAA,EAAA,GAEA,IAAA,GADA,MACA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,KAAA,EAAA,GAAA,EAAA,GACA,OAAA,KAIA,eAAA,SAAA,EAAA,EAAA,GACA,OACA,IAAA,YAAA,GAAA,EAAA,KAAA,EAAA,MACA,MAAA,IAIA,uBAAA,SAAA,GACA,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,GAAA,MAAA,EAAA,EAAA,GAAA,MAEA,OAAA,UAAA,EAAA,GAEA,IAAA,GADA,MACA,EAAA,EAAA,EAAA,EAAA,OAAA,IACA,EAAA,EAAA,GAAA,KAAA,EAAA,GAAA,MAAA,EAAA,EACA,OAAA,KAIA,aAAA,SAAA,EAAA,GACA,KAAA,QAAA,KAAA,GAAA,GAAA,EAAA,KAGA,mBAAA,SAAA,EAAA,GACA,KAAA,WAAA,EACA,KAAA,WAAA,GAGA,mBAAA,SAAA,EAAA,EAAA,GACA,KAAA,WAAA,EACA,KAAA,WAAA,EACA,KAAA,WAAA,GAGA,eAAA,SAAA,GACA,KAAA,WAAA,GAGA,qBAAA,GAOA,EAAA,WACA,KAAA,WAAA,MAAA,MAAA,QACA,eAAA,WAAA,MAAA,MAAA,QACA,QAAA,aACA,MAAA,cAiBA,EAAA,WACA,WAAA,SAAA,EAAA,EAAA,GAUA,QAAA,KAEA,GAAA,EAEA,MADA,IAAA,EACA,CAGA,GAAA,aACA,EAAA,YAEA,IAAA,GAAA,EAAA,SAAA,EACA,EAAA,YAAA,EAAA,OACA,EAIA,OAHA,GAAA,aACA,EAAA,cAEA,EAGA,QAAA,GAAA,GAEA,MADA,GAAA,SAAA,EAAA,EAAA,GACA,EA9BA,GAAA,EACA,MAAA,MAAA,SAAA,EAAA,OAAA,EAEA,IAAA,GAAA,GAAA,kBAEA,EAAA,KAAA,SAAA,EAAA,EAAA,GACA,GAAA,EACA,EAAA,IA0BA,OAAA,IAAA,mBAAA,EAAA,EAAA,GAAA,IAGA,SAAA,SAAA,EAAA,EAAA,GAEA,IAAA,GADA,GAAA,EAAA,KAAA,YAAA,EAAA,GACA,EAAA,EAAA,EAAA,KAAA,QAAA,OAAA,IACA,EAAA,KAAA,QAAA,GAAA,UAAA,GAAA,EAAA,EAAA,EACA,EAGA,OAAA,IAGA,SAAA,SAAA,EAAA,EAAA,GAEA,IADA,GAAA,GAAA,KAAA,QAAA,KAAA,QAAA,OAAA,EACA,IAAA,GACA,EAAA,KAAA,QAAA,GAAA,UAAA,GAAA,EAAA,EACA,EAGA,OAAA,MAAA,WAAA,SACA,KAAA,WAAA,SAAA,EAAA,GADA,QAqBA,IAAA,OAEA,uBACA,qBACA,sBACA,cACA,aACA,kBACA,QAAA,SAAA,GACA,EAAA,EAAA,eAAA,GAGA,IAAA,GAAA,IAAA,KAAA,SAAA,SAAA,IAAA,MAAA,EA4FA,GAAA,WAEA,YAAA,SAAA,GACA,GAAA,KACA,KAAA,GAAA,KAAA,GACA,EAAA,KAAA,EAAA,GAAA,KAAA,EAAA,GAEA,OAAA,GAAA,KAAA,OAGA,UAAA,SAAA,GACA,GAAA,KACA,KAAA,GAAA,KAAA,GACA,EAAA,IACA,EAAA,KAAA,EAEA,OAAA,GAAA,KAAA,MAIA,+BAAA,SAAA,GACA,GAAA,GAAA,EAAA,4BACA,IAAA,EAGA,MAAA,UAAA,EAAA,GACA,EAAA,MAAA,GAAA,IAIA,eAAA,SAAA,EAAA,EAAA,GACA,GAAA,GAAA,KAAA,IAAA,EACA,IAAA,EAAA,GACA,MAAA,GAAA,MAKA,EAAA,EAAA,EAAA,UAJA,SAAA,MAAA,gDAOA,EAAA,GAAA,EAAA,KAAA,EAAA,MAaA,MAAA,GAAA,EAAA,EAAA,EAAA,KAZA,IAAA,GAAA,EAAA,OACA,MAAA,UAAA,EAAA,EAAA,GACA,GAAA,EACA,MAAA,GAAA,aAAA,EAEA,IAAA,GAAA,EAAA,EAAA,EAAA,GACA,OAAA,IAAA,cAAA,EAAA,MASA,qBAAA,SAAA,GACA,GAAA,GAAA,EAAA,4BACA,IAAA,EAAA,CAGA,GAAA,GAAA,EAAA,iBACA,EAAA,iBAAA,MACA,EAAA,MAEA,EAAA,EAAA,4BAEA,OAAA,UAAA,GACA,GAAA,GAAA,OAAA,OAAA,EAIA,OAHA,GAAA,GAAA,EACA,EAAA,GAAA,OACA,EAAA,GAAA,EACA,MAKA,EAAA,mBAAA,EACA,EAAA,sBACA,EAAA,eAAA,GAEA,EAAA,mBAAA,oBAAA,GACA,MC5qBA,SAAA,GAUA,QAAA,KACA,IACA,GAAA,EACA,EAAA,eAAA,WACA,GAAA,EACA,SAAA,MAAA,QAAA,MAAA,oBACA,EAAA,6BACA,SAAA,MAAA,QAAA;IAdA,GAAA,GAAA,SAAA,cAAA,QACA,GAAA,YAAA,oEACA,IAAA,GAAA,SAAA,cAAA,OACA,GAAA,aAAA,EAAA,EAAA,WAGA,IAAA,EAeA,IAAA,SAAA,iBAQA,EAAA,iBARA,CACA,GAAA,GAAA,GACA,QAAA,iBAAA,qBAAA,WACA,IACA,EAAA,UAAA,YAAA,EAAA,KAOA,GAAA,OAAA,iBAAA,eAAA,UAAA,CACA,GAAA,GAAA,SAAA,UAAA,UACA,UAAA,UAAA,WAAA,SAAA,EAAA,GACA,GAAA,GAAA,EAAA,KAAA,KAAA,EAAA,EAEA,OADA,gBAAA,WAAA,GACA,GAKA,EAAA,MAAA,GAEA,OAAA","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  // 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    var arr = [];\n    Object.observe(test, callback);\n    Array.observe(arr, callback);\n    test.id = 1;\n    test.id = 2;\n    delete test.id;\n    arr.push(1, 2);\n    arr.length = 0;\n\n    Object.deliverChangeRecords(callback);\n    if (records.length !== 5)\n      return false;\n\n    if (records[0].type != 'add' ||\n        records[1].type != 'update' ||\n        records[2].type != 'delete' ||\n        records[3].type != 'splice' ||\n        records[4].type != 'splice') {\n      return false;\n    }\n\n    Object.unobserve(test, callback);\n    Array.unobserve(arr, 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 (!isObject(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 (!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      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 scheduledReset() {\n      resetScheduled = false;\n      if (!resetNeeded)\n        return;\n\n      reset();\n    }\n\n    function scheduleReset() {\n      if (resetScheduled)\n        return;\n\n      resetNeeded = true;\n      resetScheduled = true;\n      runEOM(scheduledReset);\n    }\n\n    function callback() {\n      reset();\n\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\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 = hasObserve && (function() {\n    try {\n      eval('%RunMicrotasks()');\n      return true;\n    } catch (ex) {\n      return false;\n    }\n  })();\n\n  global.Platform = global.Platform || {};\n\n  global.Platform.performMicrotaskCheckpoint = function() {\n    if (runningMicrotaskCheckpoint)\n      return;\n\n    if (hasDebugForceFullDelivery) {\n      eval('%RunMicrotasks()');\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    add: true,\n    update: true,\n    delete: true\n  };\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('update', 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 == 'update')\n        continue;\n\n      if (record.type == 'add') {\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 'splice':\n          mergeSplice(splices, record.index, record.removed.slice(), record.addedCount);\n          break;\n        case 'add':\n        case 'update':\n        case 'delete':\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})(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 ||\r\n      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  if (flags.shadow && document.querySelectorAll('script').length > 1) {\r\n    console.warn('platform.js is not the first script on the page. ' +\r\n        'See http://www.polymer-project.org/docs/start/platform.html#setup ' +\r\n        'for details.');\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    // Set it again. Some VMs optimizes objects that are used as prototypes.\n    wrapperConstructor.prototype = wrapperPrototype;\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    var p = Object.create(superWrapperConstructor.prototype);\n    p.constructor = GeneratedWrapper;\n    GeneratedWrapper.prototype = p;\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","/**\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\n(function(scope) {\n  'use strict';\n\n  /**\n   * A tree scope represents the root of a tree. All nodes in a tree point to\n   * the same TreeScope object. The tree scope of a node get set the first time\n   * it is accessed or when a node is added or remove to a tree.\n   * @constructor\n   */\n  function TreeScope(root, parent) {\n    this.root = root;\n    this.parent = parent;\n  }\n\n  TreeScope.prototype = {\n    get renderer() {\n      if (this.root instanceof scope.wrappers.ShadowRoot) {\n        return scope.getRendererForHost(this.root.host);\n      }\n      return null;\n    },\n\n    contains: function(treeScope) {\n      for (; treeScope; treeScope = treeScope.parent) {\n        if (treeScope === this)\n          return true;\n      }\n      return false;\n    }\n  };\n\n  function setTreeScope(node, treeScope) {\n    if (node.treeScope_ !== treeScope) {\n      node.treeScope_ = treeScope;\n      for (var sr = node.shadowRoot; sr; sr = sr.olderShadowRoot) {\n        sr.treeScope_.parent = treeScope;\n      }\n      for (var child = node.firstChild; child; child = child.nextSibling) {\n        setTreeScope(child, treeScope);\n      }\n    }\n  }\n\n  function getTreeScope(node) {\n    if (node.treeScope_)\n      return node.treeScope_;\n    var parent = node.parentNode;\n    var treeScope;\n    if (parent)\n      treeScope = getTreeScope(parent);\n    else\n      treeScope = new TreeScope(node, null);\n    return node.treeScope_ = treeScope;\n  }\n\n  scope.TreeScope = TreeScope;\n  scope.getTreeScope = getTreeScope;\n  scope.setTreeScope = setTreeScope;\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 getTreeScope = scope.getTreeScope;\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 inSameTree(a, b) {\n    return getTreeScope(a) === getTreeScope(b);\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    dispatchEvent(wrap(originalEvent), wrap(originalEvent.target));\n  }\n\n  function isLoadLikeEvent(event) {\n    switch (event.type) {\n      case 'beforeunload':\n      case 'load':\n      case 'unload':\n        return true;\n    }\n    return false;\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 (eventPath.length === 2 &&\n        eventPath[0].target instanceof wrappers.Document &&\n        isLoadLikeEvent(event)) {\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      var unwrappedRelatedTarget = originalEvent.relatedTarget;\n\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 (unwrappedRelatedTarget) {\n        // In IE we can get objects that are not EventTargets at this point.\n        // Safari does not have an EventTarget interface so revert to checking\n        // for addEventListener as an approximation.\n        if (unwrappedRelatedTarget instanceof Object &&\n            unwrappedRelatedTarget.addEventListener) {\n          var relatedTarget = wrap(unwrappedRelatedTarget);\n\n          var adjusted = adjustRelatedTarget(currentTarget, relatedTarget);\n          if (adjusted === target)\n            return true;\n        } else {\n          adjusted = null;\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      var impl = type;\n      if (!OriginalBeforeUnloadEvent && impl.type === 'beforeunload')\n        return new BeforeUnloadEvent(impl);\n      this.impl = impl;\n    } else {\n      return wrap(constructEvent(OriginalEvent, 'Event', type, options));\n    }\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 = getTreeScope(currentTargetTable.get(this));\n\n        for (var i = 0; i <= lastIndex; i++) {\n          var currentTarget = eventPath[i].currentTarget;\n          var currentRoot = getTreeScope(currentTarget);\n          if (currentRoot.contains(baseRoot) &&\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      var relatedTarget = relatedTargetTable.get(this);\n      // relatedTarget can be null.\n      if (relatedTarget !== undefined)\n        return relatedTarget;\n      return 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  // Safari 7 does not yet have BeforeUnloadEvent.\n  // https://bugs.webkit.org/show_bug.cgi?id=120849\n  var OriginalBeforeUnloadEvent = window.BeforeUnloadEvent;\n\n  function BeforeUnloadEvent(impl) {\n    Event.call(this, impl);\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  if (OriginalBeforeUnloadEvent)\n    registerWrapper(OriginalBeforeUnloadEvent, BeforeUnloadEvent);\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","/*\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\n(function(scope) {\n  'use strict';\n\n  // TODO(arv): Implement.\n\n  scope.wrapHTMLCollection = scope.wrapNodeList;\n  scope.wrappers.HTMLCollection = scope.wrappers.NodeList;\n\n})(window.ShadowDOMPolyfill);\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(scope) {\n  'use strict';\n\n  var EventTarget = scope.wrappers.EventTarget;\n  var NodeList = scope.wrappers.NodeList;\n  var TreeScope = scope.TreeScope;\n  var assert = scope.assert;\n  var defineWrapGetter = scope.defineWrapGetter;\n  var enqueueMutation = scope.enqueueMutation;\n  var getTreeScope = scope.getTreeScope;\n  var isWrapper = scope.isWrapper;\n  var mixin = scope.mixin;\n  var registerTransientObservers = scope.registerTransientObservers;\n  var registerWrapper = scope.registerWrapper;\n  var setTreeScope = scope.setTreeScope;\n  var unwrap = scope.unwrap;\n  var unwrapIfNeeded = scope.unwrapIfNeeded;\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, treeScope) {\n    setTreeScope(node, treeScope);\n    node.nodeIsInserted_();\n  }\n\n  function nodesWereAdded(nodes, parent) {\n    var treeScope = getTreeScope(parent);\n    for (var i = 0; i < nodes.length; i++) {\n      nodeWasAdded(nodes[i], treeScope);\n    }\n  }\n\n  // http://dom.spec.whatwg.org/#node-is-removed\n  function nodeWasRemoved(node) {\n    setTreeScope(node, new TreeScope(node, null));\n  }\n\n  function nodesWereRemoved(nodes) {\n    for (var i = 0; i < nodes.length; i++) {\n      nodeWasRemoved(nodes[i]);\n    }\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  function contains(self, child) {\n    if (!child || getTreeScope(self) !== getTreeScope(child))\n      return false;\n\n    for (var node = child; node; node = node.parentNode) {\n      if (node === self)\n        return true;\n    }\n    return false;\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    this.treeScope_ = 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, this);\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, this);\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, this);\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      return contains(this, wrapIfNeeded(child));\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,\n                                                  unwrapIfNeeded(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.cloneNode = cloneNode;\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\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    remove: function() {\n      var p = this.parentNode;\n      if (p)\n        p.removeChild(this);\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, this);\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 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 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 OriginalHTMLSelectElement = window.HTMLSelectElement;\n\n  function HTMLSelectElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLSelectElement.prototype = Object.create(HTMLElement.prototype);\n  mixin(HTMLSelectElement.prototype, {\n    add: function(element, before) {\n      if (typeof before === 'object')  // also includes null\n        before = unwrap(before);\n      unwrap(this).add(unwrap(element), before);\n    },\n\n    remove: function(indexOrNode) {\n      // Spec only allows index but implementations allow index or node.\n      // remove() is also allowed which is same as remove(undefined)\n      if (indexOrNode === undefined) {\n        HTMLElement.prototype.remove.call(this);\n        return;\n      }\n\n      if (typeof indexOrNode === 'object')\n        indexOrNode = unwrap(indexOrNode);\n\n      unwrap(this).remove(indexOrNode);\n    },\n\n    get form() {\n      return wrap(unwrap(this).form);\n    }\n  });\n\n  registerWrapper(OriginalHTMLSelectElement, HTMLSelectElement,\n                  document.createElement('select'));\n\n  scope.wrappers.HTMLSelectElement = HTMLSelectElement;\n})(window.ShadowDOMPolyfill);\n","/*\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\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  var wrapHTMLCollection = scope.wrapHTMLCollection;\n\n  var OriginalHTMLTableElement = window.HTMLTableElement;\n\n  function HTMLTableElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLTableElement.prototype = Object.create(HTMLElement.prototype);\n  mixin(HTMLTableElement.prototype, {\n    get caption() {\n      return wrap(unwrap(this).caption);\n    },\n    createCaption: function() {\n      return wrap(unwrap(this).createCaption());\n    },\n\n    get tHead() {\n      return wrap(unwrap(this).tHead);\n    },\n    createTHead: function() {\n      return wrap(unwrap(this).createTHead());\n    },\n\n    createTFoot: function() {\n      return wrap(unwrap(this).createTFoot());\n    },\n    get tFoot() {\n      return wrap(unwrap(this).tFoot);\n    },\n\n    get tBodies() {\n      return wrapHTMLCollection(unwrap(this).tBodies);\n    },\n    createTBody: function() {\n      return wrap(unwrap(this).createTBody());\n    },\n\n    get rows() {\n      return wrapHTMLCollection(unwrap(this).rows);\n    },\n    insertRow: function(index) {\n      return wrap(unwrap(this).insertRow(index));\n    }\n  });\n\n  registerWrapper(OriginalHTMLTableElement, HTMLTableElement,\n                  document.createElement('table'));\n\n  scope.wrappers.HTMLTableElement = HTMLTableElement;\n})(window.ShadowDOMPolyfill);\n","/*\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\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 wrapHTMLCollection = scope.wrapHTMLCollection;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n\n  var OriginalHTMLTableSectionElement = window.HTMLTableSectionElement;\n\n  function HTMLTableSectionElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLTableSectionElement.prototype = Object.create(HTMLElement.prototype);\n  mixin(HTMLTableSectionElement.prototype, {\n    get rows() {\n      return wrapHTMLCollection(unwrap(this).rows);\n    },\n    insertRow: function(index) {\n      return wrap(unwrap(this).insertRow(index));\n    }\n  });\n\n  registerWrapper(OriginalHTMLTableSectionElement, HTMLTableSectionElement,\n                  document.createElement('thead'));\n\n  scope.wrappers.HTMLTableSectionElement = HTMLTableSectionElement;\n})(window.ShadowDOMPolyfill);\n","/*\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\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 wrapHTMLCollection = scope.wrapHTMLCollection;\n  var unwrap = scope.unwrap;\n  var wrap = scope.wrap;\n\n  var OriginalHTMLTableRowElement = window.HTMLTableRowElement;\n\n  function HTMLTableRowElement(node) {\n    HTMLElement.call(this, node);\n  }\n  HTMLTableRowElement.prototype = Object.create(HTMLElement.prototype);\n  mixin(HTMLTableRowElement.prototype, {\n    get cells() {\n      return wrapHTMLCollection(unwrap(this).cells);\n    },\n\n    insertCell: function(index) {\n      return wrap(unwrap(this).insertCell(index));\n    }\n  });\n\n  registerWrapper(OriginalHTMLTableRowElement, HTMLTableRowElement,\n                  document.createElement('tr'));\n\n  scope.wrappers.HTMLTableRowElement = HTMLTableRowElement;\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 TreeScope = scope.TreeScope;\n  var elementFromPoint = scope.elementFromPoint;\n  var getInnerHTML = scope.getInnerHTML;\n  var getTreeScope = scope.getTreeScope;\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    this.treeScope_ = new TreeScope(this, getTreeScope(hostWrapper));\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 getTreeScope = scope.getTreeScope;\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    var rv = distributedChildNodesTable.get(insertionPoint);\n    if (!rv)\n      distributedChildNodesTable.set(insertionPoint, rv = []);\n    return rv;\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    // TODO(arv): Order these in document order. That way we do not have to\n    // render something twice.\n    for (var i = 0; i < pendingDirtyRenderers.length; i++) {\n      var renderer = pendingDirtyRenderers[i];\n      var parentRenderer = renderer.parentRenderer;\n      if (parentRenderer && parentRenderer.dirty)\n        continue;\n      renderer.render();\n    }\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    var root = getTreeScope(node).root;\n    if (root instanceof ShadowRoot)\n      return root;\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    get parentRenderer() {\n      return getTreeScope(this.host).renderer;\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 is handled in HTMLSelectElement.js\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 TreeScope = scope.TreeScope;\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    this.treeScope_ = new TreeScope(this, null);\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, extendsOption;\n      if (object !== undefined) {\n        prototype = object.prototype;\n        extendsOption = object.extends;\n      }\n\n      if (!prototype)\n        prototype = Object.create(HTMLElement.prototype);\n\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 (extendsOption)\n        p.extends = extendsOption;\n\n      function CustomElementConstructor(node) {\n        if (!node) {\n          if (extendsOption) {\n            return document.createElement(extendsOption, 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","/**\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\n(function(scope) {\n  'use strict';\n\n  var unwrap = scope.unwrap;\n\n  // DataTransfer (Clipboard in old Blink/WebKit) has a single method that\n  // requires wrapping. Since it is only a method we do not need a real wrapper,\n  // we can just override the method.\n\n  var OriginalDataTransfer = window.DataTransfer || window.Clipboard;\n  var OriginalDataTransferSetDragImage =\n      OriginalDataTransfer.prototype.setDragImage;\n\n  OriginalDataTransfer.prototype.setDragImage = function(image, x, y) {\n    OriginalDataTransferSetDragImage.call(this, unwrap(image), x, y);\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 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    // 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    'area': 'HTMLAreaElement',\n    'audio': 'HTMLAudioElement',\n    'base': 'HTMLBaseElement',\n    'body': 'HTMLBodyElement',\n    'br': 'HTMLBRElement',\n    'button': 'HTMLButtonElement',\n    'canvas': 'HTMLCanvasElement',\n    'caption': 'HTMLTableCaptionElement',\n    'col': 'HTMLTableColElement',\n    // 'command': 'HTMLCommandElement',  // Not fully implemented in Gecko.\n    'content': 'HTMLContentElement',\n    'data': 'HTMLDataElement',\n    'datalist': 'HTMLDataListElement',\n    'del': 'HTMLModElement',\n    'dir': 'HTMLDirectoryElement',\n    'div': 'HTMLDivElement',\n    'dl': 'HTMLDListElement',\n    'embed': 'HTMLEmbedElement',\n    'fieldset': 'HTMLFieldSetElement',\n    'font': 'HTMLFontElement',\n    'form': 'HTMLFormElement',\n    'frame': 'HTMLFrameElement',\n    'frameset': 'HTMLFrameSetElement',\n    'h1': 'HTMLHeadingElement',\n    'head': 'HTMLHeadElement',\n    'hr': 'HTMLHRElement',\n    'html': 'HTMLHtmlElement',\n    'iframe': 'HTMLIFrameElement',\n    'img': 'HTMLImageElement',\n    'input': 'HTMLInputElement',\n    'keygen': 'HTMLKeygenElement',\n    'label': 'HTMLLabelElement',\n    'legend': 'HTMLLegendElement',\n    'li': 'HTMLLIElement',\n    'link': 'HTMLLinkElement',\n    'map': 'HTMLMapElement',\n    'marquee': 'HTMLMarqueeElement',\n    'menu': 'HTMLMenuElement',\n    'menuitem': 'HTMLMenuItemElement',\n    'meta': 'HTMLMetaElement',\n    'meter': 'HTMLMeterElement',\n    'object': 'HTMLObjectElement',\n    'ol': 'HTMLOListElement',\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    'shadow': 'HTMLShadowElement',\n    'source': 'HTMLSourceElement',\n    'span': 'HTMLSpanElement',\n    'style': 'HTMLStyleElement',\n    'table': 'HTMLTableElement',\n    'tbody': 'HTMLTableSectionElement',\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    'template': 'HTMLTemplateElement',\n    'textarea': 'HTMLTextAreaElement',\n    'thead': 'HTMLTableSectionElement',\n    'time': 'HTMLTimeElement',\n    'title': 'HTMLTitleElement',\n    'tr': 'HTMLTableRowElement',\n    'track': 'HTMLTrackElement',\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})(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, :host-context: 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 scopeStyles = this.prepareRoot(root, name, extendsName);\n    var typeExtension = this.isTypeExtension(extendsName);\n    var scopeSelector = this.makeScopeSelector(name, typeExtension);\n    // use caching to make working with styles nodes easier and to facilitate\n    // lookup of extendee\n    var cssText = stylesToCssText(scopeStyles, true);\n    cssText = this.scopeCssText(cssText, scopeSelector);\n    // cache shimmed css on root for user extensibility\n    if (root) {\n      root.shimmedStyle = cssText;\n    }\n    // add style to document\n    this.addCssToDocument(cssText, name);\n  },\n  /*\n  * Shim a style element with the given selector. Returns cssText that can\n  * be included in the document via Platform.ShadowCSS.addCssToDocument(css).\n  */\n  shimStyle: function(style, selector) {\n    return this.shimCssText(style.textContent, selector);\n  },\n  /*\n  * Shim some cssText with the given selector. Returns cssText that can\n  * be included in the document via Platform.ShadowCSS.addCssToDocument(css).\n  */\n  shimCssText: function(cssText, selector) {\n    cssText = this.insertDirectives(cssText);\n    return this.scopeCssText(cssText, selector);\n  },\n  makeScopeSelector: function(name, typeExtension) {\n    if (name) {\n      return typeExtension ? '[is=' + name + ']' : name;\n    }\n    return '';\n  },\n  isTypeExtension: function(extendsName) {\n    return extendsName && extendsName.indexOf('-') < 0;\n  },\n  prepareRoot: function(root, name, extendsName) {\n    var def = this.registerRoot(root, name, extendsName);\n    this.replaceTextInStyles(def.rootStyles, this.insertDirectives);\n    // remove existing style elements\n    this.removeStyles(root, def.rootStyles);\n    // apply strict attr\n    if (this.strictStyling) {\n      this.applyScopeToContent(root, name);\n    }\n    return def.scopeStyles;\n  },\n  removeStyles: function(root, styles) {\n    for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) {\n      s.parentNode.removeChild(s);\n    }\n  },\n  registerRoot: function(root, name, extendsName) {\n    var def = this.registry[name] = {\n      root: root,\n      name: name,\n      extendsName: extendsName\n    }\n    var styles = this.findStyles(root);\n    def.rootStyles = styles;\n    def.scopeStyles = def.rootStyles;\n    var extendee = this.registry[def.extendsName];\n    if (extendee) {\n      def.scopeStyles = extendee.scopeStyles.concat(def.scopeStyles);\n    }\n    return def;\n  },\n  findStyles: function(root) {\n    if (!root) {\n      return [];\n    }\n    var styles = root.querySelectorAll('style');\n    return Array.prototype.filter.call(styles, function(s) {\n      return !s.hasAttribute(NO_SHIM_ATTRIBUTE);\n    });\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  insertDirectives: function(cssText) {\n    cssText = this.insertPolyfillDirectivesInCssText(cssText);\n    return this.insertPolyfillRulesInCssText(cssText);\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 inert rules.\n   * \n   * For example, we convert this rule:\n   * \n   * polyfill-next-selector { content: ':host menu-item'; }\n   * ::content menu-item {\n   * \n   * to this:\n   * \n   * scopeName menu-item {\n   *\n  **/\n  insertPolyfillDirectivesInCssText: function(cssText) {\n    // TODO(sorvell): remove either content or comment\n    cssText = cssText.replace(cssCommentNextSelectorRe, function(match, p1) {\n      // remove end comment delimiter and add block start\n      return p1.slice(0, -2) + '{';\n    });\n    return cssText.replace(cssContentNextSelectorRe, function(match, p1) {\n      return p1 + ' {';\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   * polyfill-rule {\n   *   content: ':host menu-item';\n   * ...\n   * }\n   * \n   * to this:\n   * \n   * scopeName menu-item {...}\n   *\n  **/\n  insertPolyfillRulesInCssText: function(cssText) {\n    // TODO(sorvell): remove either content or comment\n    cssText = cssText.replace(cssCommentRuleRe, function(match, p1) {\n      // remove end comment delimiter\n      return p1.slice(0, -1);\n    });\n    return cssText.replace(cssContentRuleRe, function(match, p1, p2, p3) {\n      var rule = match.replace(p1, '').replace(p2, '');\n      return p3 + rule;\n    });\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  scopeCssText: function(cssText, scopeSelector) {\n    var unscoped = this.extractUnscopedRulesFromCssText(cssText);\n    cssText = this.insertPolyfillHostInCssText(cssText);\n    cssText = this.convertColonHost(cssText);\n    cssText = this.convertColonHostContext(cssText);\n    cssText = this.convertCombinators(cssText);\n    if (scopeSelector) {\n      var self = this, cssText;\n      withCssRules(cssText, function(rules) {\n        cssText = self.scopeRules(rules, scopeSelector);\n      });\n\n    }\n    cssText = cssText + '\\n' + unscoped;\n    return cssText.trim();\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  extractUnscopedRulesFromCssText: function(cssText) {\n    // TODO(sorvell): remove either content or comment\n    var r = '', m;\n    while (m = cssCommentUnscopedRuleRe.exec(cssText)) {\n      r += m[1].slice(0, -1) + '\\n\\n';\n    }\n    while (m = cssContentUnscopedRuleRe.exec(cssText)) {\n      r += m[0].replace(m[2], '').replace(m[1], m[3]) + '\\n\\n';\n    }\n    return r;\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 :host-context(.foo) > .bar { }\n   *\n   * to\n   *\n   * scopeName.foo > .bar, .foo scopeName > .bar { }\n   * \n   * and\n   *\n   * :host-context(.foo:host) .bar { ... }\n   * \n   * to\n   * \n   * scopeName.foo .bar { ... }\n  */\n  convertColonHostContext: function(cssText) {\n    return this.convertColonRule(cssText, cssColonHostContextRe,\n        this.colonHostContextPartReplacer);\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  colonHostContextPartReplacer: 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    for (var i=0; i < combinatorsRe.length; i++) {\n      cssText = cssText.replace(combinatorsRe[i], ' ');\n    }\n    return cssText;\n  },\n  // change a selector like 'div' to 'name div'\n  scopeRules: function(cssRules, scopeSelector) {\n    var cssText = '';\n    if (cssRules) {\n      Array.prototype.forEach.call(cssRules, function(rule) {\n        if (rule.selectorText && (rule.style && rule.style.cssText)) {\n          cssText += this.scopeSelector(rule.selectorText, scopeSelector, \n            this.strictStyling) + ' {\\n\\t';\n          cssText += this.propertiesFromRule(rule) + '\\n}\\n\\n';\n        } else if (rule.type === CSSRule.MEDIA_RULE) {\n          cssText += '@media ' + rule.media.mediaText + ' {\\n';\n          cssText += this.scopeRules(rule.cssRules, scopeSelector);\n          cssText += '\\n}\\n\\n';\n        } else if (rule.cssText) {\n          cssText += rule.cssText + '\\n\\n';\n        }\n      }, this);\n    }\n    return cssText;\n  },\n  scopeSelector: function(selector, scopeSelector, strict) {\n    var r = [], parts = selector.split(',');\n    parts.forEach(function(p) {\n      p = p.trim();\n      if (this.selectorNeedsScoping(p, scopeSelector)) {\n        p = (strict && !p.match(polyfillHostNoCombinator)) ? \n            this.applyStrictSelectorScope(p, scopeSelector) :\n            this.applySimpleSelectorScope(p, scopeSelector);\n      }\n      r.push(p);\n    }, this);\n    return r.join(', ');\n  },\n  selectorNeedsScoping: function(selector, scopeSelector) {\n    var re = this.makeScopeMatcher(scopeSelector);\n    return !selector.match(re);\n  },\n  makeScopeMatcher: function(scopeSelector) {\n    scopeSelector = scopeSelector.replace(/\\[/g, '\\\\[').replace(/\\[/g, '\\\\]');\n    return new RegExp('^(' + scopeSelector + ')' + selectorReSuffix, 'm');\n  },\n  // scope via name and [is=name]\n  applySimpleSelectorScope: function(selector, scopeSelector) {\n    if (selector.match(polyfillHostRe)) {\n      selector = selector.replace(polyfillHostNoCombinator, scopeSelector);\n      return selector.replace(polyfillHostRe, scopeSelector + ' ');\n    } else {\n      return scopeSelector + ' ' + 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, scopeSelector) {\n    scopeSelector = scopeSelector.replace(/\\[is=([^\\]]*)\\]/g, '$1');\n    var splits = [' ', '>', '+', '~'],\n      scoped = selector,\n      attrName = '[' + scopeSelector + ']';\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(colonHostContextRe, polyfillHostContext).replace(\n        colonHostRe, polyfillHost);\n  },\n  propertiesFromRule: function(rule) {\n    var cssText = rule.style.cssText;\n    // TODO(sorvell): Safari cssom incorrectly removes quotes from the content\n    // property. (https://bugs.webkit.org/show_bug.cgi?id=118045)\n    // don't replace attr rules\n    if (rule.style.content && !rule.style.content.match(/['\"]+|attr/)) {\n      cssText = cssText.replace(/content:[^;]*;/g, 'content: \\'' + \n          rule.style.content + '\\';');\n    }\n    // TODO(sorvell): we can workaround this issue here, but we need a list\n    // of troublesome properties to fix https://github.com/Polymer/platform/issues/53\n    //\n    // inherit rules can be omitted from cssText\n    // TODO(sorvell): remove when Blink bug is fixed:\n    // https://code.google.com/p/chromium/issues/detail?id=358273\n    var style = rule.style;\n    for (var i in style) {\n      if (style[i] === 'initial') {\n        cssText += i + ': initial; ';\n      }\n    }\n    return cssText;\n  },\n  replaceTextInStyles: function(styles, action) {\n    if (styles && action) {\n      if (!(styles instanceof Array)) {\n        styles = [styles];\n      }\n      Array.prototype.forEach.call(styles, function(s) {\n        s.textContent = action.call(this, s.textContent);\n      }, this);\n    }\n  },\n  addCssToDocument: function(cssText, name) {\n    if (cssText.match('@import')) {\n      addOwnSheet(cssText, name);\n    } else {\n      addCssToDocument(cssText);\n    }\n  }\n};\n\nvar selectorRe = /([^{]*)({[\\s\\S]*?})/gim,\n    cssCommentRe = /\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\//gim,\n    // TODO(sorvell): remove either content or comment\n    cssCommentNextSelectorRe = /\\/\\*\\s*@polyfill ([^*]*\\*+([^/*][^*]*\\*+)*\\/)([^{]*?){/gim,\n    cssContentNextSelectorRe = /polyfill-next-selector[^}]*content\\:[\\s]*'([^']*)'[^}]*}([^{]*?){/gim,\n    // TODO(sorvell): remove either content or comment\n    cssCommentRuleRe = /\\/\\*\\s@polyfill-rule([^*]*\\*+([^/*][^*]*\\*+)*)\\//gim,\n    cssContentRuleRe = /(polyfill-rule)[^}]*(content\\:[\\s]*'([^']*)'[^;]*;)[^}]*}/gim,\n    // TODO(sorvell): remove either content or comment\n    cssCommentUnscopedRuleRe = /\\/\\*\\s@polyfill-unscoped-rule([^*]*\\*+([^/*][^*]*\\*+)*)\\//gim,\n    cssContentUnscopedRuleRe = /(polyfill-unscoped-rule)[^}]*(content\\:[\\s]*'([^']*)'[^;]*;)[^}]*}/gim,\n    cssPseudoRe = /::(x-[^\\s{,(]*)/gim,\n    cssPartRe = /::part\\(([^)]*)\\)/gim,\n    // note: :host pre-processed to -shadowcsshost.\n    polyfillHost = '-shadowcsshost',\n    // note: :host-context pre-processed to -shadowcsshostcontext.\n    polyfillHostContext = '-shadowcsscontext',\n    parenSuffix = ')(?:\\\\((' +\n        '(?:\\\\([^)(]*\\\\)|[^)(]*)+?' +\n        ')\\\\))?([^,{]*)';\n    cssColonHostRe = new RegExp('(' + polyfillHost + parenSuffix, 'gim'),\n    cssColonHostContextRe = new RegExp('(' + polyfillHostContext + parenSuffix, 'gim'),\n    selectorReSuffix = '([>\\\\s~+\\[.,{:][\\\\s\\\\S]*)?$',\n    colonHostRe = /\\:host/gim,\n    colonHostContextRe = /\\:host-context/gim,\n    /* host name without combinator */\n    polyfillHostNoCombinator = polyfillHost + '-no-combinator',\n    polyfillHostRe = new RegExp(polyfillHost, 'gim'),\n    polyfillHostContextRe = new RegExp(polyfillHostContext, 'gim'),\n    combinatorsRe = [\n      /\\^\\^/g,\n      /\\^/g,\n      /\\/shadow\\//g,\n      /\\/shadow-deep\\//g,\n      /::shadow/g,\n      /\\/deep\\//g\n    ];\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 = [];\n  if (style.sheet) {\n    // TODO(sorvell): Firefox throws when accessing the rules of a stylesheet\n    // with an @import\n    // https://bugzilla.mozilla.org/show_bug.cgi?id=625013\n    try {\n      rules = style.sheet.cssRules;\n    } catch(e) {\n      //\n    }\n  } else {\n    console.warn('sheet not found', style);\n  }\n  style.parentNode.removeChild(style);\n  return rules;\n}\n\nvar frame = document.createElement('iframe');\nframe.style.display = 'none';\n\nfunction initFrame() {\n  frame.initialized = true;\n  document.body.appendChild(frame);\n  var doc = frame.contentDocument;\n  var base = doc.createElement('base');\n  base.href = document.baseURI;\n  doc.head.appendChild(base);\n}\n\nfunction inFrame(fn) {\n  if (!frame.initialized) {\n    initFrame();\n  }\n  document.body.appendChild(frame);\n  fn(frame.contentDocument);\n  document.body.removeChild(frame);\n}\n\n// TODO(sorvell): use an iframe if the cssText contains an @import to workaround\n// https://code.google.com/p/chromium/issues/detail?id=345114\nvar isChrome = navigator.userAgent.match('Chrome');\nfunction withCssRules(cssText, callback) {\n  if (!callback) {\n    return;\n  }\n  var rules;\n  if (cssText.match('@import') && isChrome) {\n    var style = cssTextToStyle(cssText);\n    inFrame(function(doc) {\n      doc.head.appendChild(style.impl);\n      rules = style.sheet.cssRules;\n      callback(rules);\n    });\n  } else {\n    rules = cssToRules(cssText);\n    callback(rules);\n  }\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\nfunction addOwnSheet(cssText, name) {\n  var style = cssTextToStyle(cssText);\n  style.setAttribute(name, '');\n  style.setAttribute(SHIMMED_ATTRIBUTE, '');\n  document.head.appendChild(style);\n}\n\nvar SHIM_ATTRIBUTE = 'shim-shadowdom';\nvar SHIMMED_ATTRIBUTE = 'shim-shadowdom-css';\nvar NO_SHIM_ATTRIBUTE = 'no-shim';\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        style.textContent = ShadowCSS.shimStyle(style);\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  addEventListener('DOMContentLoaded', function() {\n    if (CustomElements.useNative === false) {\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  });\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  // 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 = function() {\n     throw 'Possible attempt to load Polymer twice';\n    };\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  resolveTemplate: function(template) {\n    this.resolveDom(template.content, template.ownerDocument.baseURI);\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      if (url.match(/^data:/)) {\n        // Handle Data URI Scheme\n        var pieces = url.split(',');\n        var header = pieces[0];\n        var body = pieces[1];\n        if(header.indexOf(';base64') > -1) {\n          body = atob(body);\n        } else {\n          body = decodeURIComponent(body);\n        }\n        setTimeout(function() {\n            this.receive(url, elt, null, body);\n        }.bind(this), 0);\n      } else {\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    },\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, callback) {\n    var self = this;\n    var done = function(e) {\n      if (callback) {\n        callback(e);\n      }\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  // NOTE: execute scripts by injecting them and watching for the load/error\n  // event. Inline scripts are handled via dataURL's because browsers tend to\n  // provide correct parsing errors in this case. If this has any compatibility\n  // issues, we can switch to injecting the inline script with textContent.\n  // Scripts with dataURL's do not appear to generate load events and therefore\n  // we assume they execute synchronously.\n  parseScript: function(scriptElt) {\n    var script = document.createElement('script');\n    script.__importElement = scriptElt;\n    script.src = scriptElt.src ? scriptElt.src : \n        generateScriptDataUrl(scriptElt);\n    scope.currentScript = scriptElt;\n    this.trackElement(script, function(e) {\n      script.parentNode.removeChild(script);\n      scope.currentScript = null;  \n    });\n    document.head.appendChild(script);\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    return true;\n  }\n};\n\nfunction nodeIsImport(elt) {\n  return (elt.localName === 'link') && (elt.rel === IMPORT_LINK_TYPE);\n}\n\nfunction generateScriptDataUrl(script) {\n  var scriptContent = generateScriptContent(script), b64;\n  try {\n    b64 = btoa(scriptContent);\n  } catch(e) {\n    b64 = btoa(unescape(encodeURIComponent(scriptContent)));\n    console.warn('Script contained non-latin characters that were forced ' +\n      'to latin. Some characters may be wrong.', script);\n  }\n  return 'data:text/javascript;base64,' + b64;\n}\n\nfunction generateScriptContent(script) {\n  return script.textContent + generateSourceMapHint(script);\n}\n\n// calculate source map hint\nfunction generateSourceMapHint(script) {\n  var moniker = script.__nodeUrl;\n  if (!moniker) {\n    moniker = script.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 = script.textContent.match(/Polymer\\(['\"]([^'\"]*)/);\n    tag = matches && matches[1] || tag;\n    // tag the moniker\n    moniker += '/' + tag + '.js';\n  }\n  return '\\n//# sourceURL=' + moniker + '\\n';\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\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    ].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    // ensure UTF-8 charset\n    var meta = doc.createElement('meta');\n    meta.setAttribute('charset', 'utf-8');\n\n    doc.head.appendChild(meta);\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  //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  upgradeDocument(doc);\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  scope.reservedTagList = [];\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    // prevent registering reserved names\n    if (isReservedTag(name)) {\n      throw new Error('Failed to execute \\'registerElement\\' on \\'Document\\': Registration failed for type \\'' + String(name) + '\\'. The type name is invalid.');\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 isReservedTag(name) {\n    for (var i = 0; i < reservedTagList.length; i++) {\n      if (name === reservedTagList[i]) {\n        return true;\n      }\n    }\n  }\n\n  var reservedTagList = [\n    'annotation-xml', 'color-profile', 'font-face', 'font-face-src',\n    'font-face-uri', 'font-face-format', 'font-face-name', 'missing-glyph'\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    // The default is HTMLElement.prototype, so we add a test to avoid mixing in\n    // native prototypes\n    while (p !== inNative && p !== HTMLElement.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  var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';\n  function createElementNS(namespace, tag, typeExtension) {\n    // NOTE: we do not support non-HTML elements,\n    // just call createElementNS for non HTML Elements\n    if (namespace === HTML_NAMESPACE) {\n      return createElement(tag, typeExtension);\n    } else {\n      return domCreateElementNS(namespace, tag);\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  var domCreateElementNS = document.createElementNS.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  document.createElementNS = createElementNS; // 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// Create a custom 'instanceof'. This is necessary when CustomElements\n// are implemented via a mixin strategy, as for example on IE10.\nvar isInstance;\nif (!Object.__proto__ && !useNative) {\n  isInstance = function(obj, ctor) {\n    var p = obj;\n    while (p) {\n      // NOTE: this is not technically correct since we're not checking if\n      // an object is an instance of a constructor; however, this should\n      // be good enough for the mixin strategy.\n      if (p === ctor.prototype) {\n        return true;\n      }\n      p = p.__proto__;\n    }\n    return false;\n  }\n} else {\n  isInstance = function(obj, base) {\n    return obj instanceof base;\n  }\n}\n\n// exports\nscope.instanceof = isInstance;\nscope.reservedTagList = reservedTagList;\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\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  var endOfMicrotask = scope.endOfMicrotask;\n\n  // Generic url loader\n  function Loader(regex) {\n    this.regex = regex;\n  }\n  Loader.prototype = {\n    // TODO(dfreedm): there may be a better factoring here\n    // extract absolute urls from the text (full of relative urls)\n    extractUrls: function(text, base) {\n      var matches = [];\n      var matched, u;\n      while ((matched = this.regex.exec(text))) {\n        u = new URL(matched[1], base);\n        matches.push({matched: matched[0], url: u.href});\n      }\n      return matches;\n    },\n    // take a text blob, a root url, and a callback and load all the urls found within the text\n    // returns a map of absolute url to text\n    process: function(text, root, callback) {\n      var matches = this.extractUrls(text, root);\n      this.fetch(matches, {}, callback);\n    },\n    // build a mapping of url -> text from matches\n    fetch: function(matches, map, callback) {\n      var inflight = matches.length;\n\n      // return early if there is no fetching to be done\n      if (!inflight) {\n        return callback(map);\n      }\n\n      var done = function() {\n        if (--inflight === 0) {\n          callback(map);\n        }\n      };\n\n      // map url -> responseText\n      var handleXhr = function(err, request) {\n        var match = request.match;\n        var key = match.url;\n        // handle errors with an empty string\n        if (err) {\n          map[key] = '';\n          return done();\n        }\n        var response = request.response || request.responseText;\n        map[key] = response;\n        this.fetch(this.extractUrls(response, key), map, done);\n      };\n\n      var m, req, url;\n      for (var i = 0; i < inflight; i++) {\n        m = matches[i];\n        url = m.url;\n        // if this url has already been requested, skip requesting it again\n        if (map[url]) {\n          // Async call to done to simplify the inflight logic\n          endOfMicrotask(done);\n          continue;\n        }\n        req = this.xhr(url, handleXhr, this);\n        req.match = m;\n        // tag the map with an XHR request to deduplicate at the same level\n        map[url] = req;\n      }\n    },\n    xhr: function(url, callback, scope) {\n      var request = new XMLHttpRequest();\n      request.open('GET', url, true);\n      request.send();\n      request.onload = function() {\n        callback.call(scope, null, request);\n      };\n      request.onerror = function() {\n        callback.call(scope, null, request);\n      };\n      return request;\n    }\n  };\n\n  scope.Loader = Loader;\n})(window.Platform);\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 urlResolver = scope.urlResolver;\nvar Loader = scope.Loader;\n\nfunction StyleResolver() {\n  this.loader = new Loader(this.regex);\n}\nStyleResolver.prototype = {\n  regex: /@import\\s+(?:url)?[\"'\\(]*([^'\"\\)]*)['\"\\)]*;/g,\n  // Recursively replace @imports with the text at that url\n  resolve: function(text, url, callback) {\n    var done = function(map) {\n      callback(this.flatten(text, url, map));\n    }.bind(this);\n    this.loader.process(text, url, done);\n  },\n  // resolve the textContent of a style node\n  resolveNode: function(style, callback) {\n    var text = style.textContent;\n    var url = style.ownerDocument.baseURI;\n    var done = function(text) {\n      style.textContent = text;\n      callback(style);\n    };\n    this.resolve(text, url, done);\n  },\n  // flatten all the @imports to text\n  flatten: function(text, base, map) {\n    var matches = this.loader.extractUrls(text, base);\n    var match, url, intermediate;\n    for (var i = 0; i < matches.length; i++) {\n      match = matches[i];\n      url = match.url;\n      // resolve any css text to be relative to the importer\n      intermediate = urlResolver.resolveCssText(map[url], url);\n      // flatten intermediate @imports\n      intermediate = this.flatten(intermediate, url, map);\n      text = text.replace(match.matched, intermediate);\n    }\n    return text;\n  },\n  loadStyles: function(styles, callback) {\n    var loaded=0, l = styles.length;\n    // called in the context of the style\n    function loadedStyle(style) {\n      loaded++;\n      if (loaded === l && callback) {\n        callback();\n      }\n    }\n    for (var i=0, s; (i<l) && (s=styles[i]); i++) {\n      this.resolveNode(s, loadedStyle);\n    }\n  }\n};\n\nvar styleResolver = new StyleResolver();\n\n// exports\nscope.styleResolver = styleResolver;\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 /shadow-deep/ ' + 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  // only install stylesheet if the browser has touch action support\n  var head = document.head;\n  var hasNativePE = window.PointerEvent || window.MSPointerEvent;\n  // only add shadow selectors if shadowdom is supported\n  var hasShadowRoot = !window.ShadowDOMPolyfill && document.head.createShadowRoot;\n\n  if (hasNativePE) {\n    attrib2css.forEach(function(r) {\n      if (String(r) === r) {\n        styles += selector(r) + rule(r) + '\\n';\n        if (hasShadowRoot) {\n          styles += shadowSelector(r) + rule(r) + '\\n';\n        }\n      } else {\n        styles += r.selectors.map(selector) + rule(r.rule) + '\\n';\n        if (hasShadowRoot) {\n          styles += r.selectors.map(shadowSelector) + rule(r.rule) + '\\n';\n        }\n      }\n    });\n\n    var el = document.createElement('style');\n    el.textContent = styles;\n    document.head.appendChild(el);\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/**\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\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    'pageX',\n    'pageY'\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    0,\n    0\n  ];\n\n  function PointerEvent(inType, inDict) {\n    inDict = inDict || Object.create(null);\n\n    var e = document.createEvent('Event');\n    e.initEvent(inType, inDict.bubbles || false, inDict.cancelable || false);\n\n    // define inherited MouseEvent properties\n    for(var i = 0, p; i < MOUSE_PROPS.length; i++) {\n      p = MOUSE_PROPS[i];\n      e[p] = inDict[p] || MOUSE_DEFAULTS[i];\n    }\n    e.buttons = inDict.buttons || 0;\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 = e.buttons ? 0.5 : 0;\n    }\n\n    // add x/y properties aliased to clientX/Y\n    e.x = e.clientX;\n    e.y = e.clientY;\n\n    // define the properties of the PointerEvent interface\n    e.pointerId = inDict.pointerId || 0;\n    e.width = inDict.width || 0;\n    e.height = inDict.height || 0;\n    e.pressure = pressure;\n    e.tiltX = inDict.tiltX || 0;\n    e.tiltY = inDict.tiltY || 0;\n    e.pointerType = inDict.pointerType || '';\n    e.hwTimestamp = inDict.hwTimestamp || 0;\n    e.isPrimary = inDict.isPrimary || false;\n    return e;\n  }\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    'pageX',\n    'pageY'\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  ];\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    pointermap: new scope.PointerMap(),\n    eventMap: Object.create(null),\n    captureInfo: Object.create(null),\n    // Scope objects for native events.\n    // This exists for ease of testing.\n    eventSources: Object.create(null),\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      inEvent.bubbles = true;\n      this.fireEvent('pointerdown', inEvent);\n    },\n    move: function(inEvent) {\n      inEvent.bubbles = true;\n      this.fireEvent('pointermove', inEvent);\n    },\n    up: function(inEvent) {\n      inEvent.bubbles = true;\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      inEvent.bubbles = true;\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 (inEvent._handledByPE) {\n        return;\n      }\n      var type = inEvent.type;\n      var fn = this.eventMap && this.eventMap[type];\n      if (fn) {\n        fn(inEvent);\n      }\n      inEvent._handledByPE = 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[inEvent.pointerId]) {\n        inEvent.relatedTarget = null;\n      }\n      var e = new PointerEvent(inType, inEvent);\n      if (inEvent.preventDefault) {\n        e.preventDefault = inEvent.preventDefault;\n      }\n      e._target = e._target || 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 = Object.create(null), 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      return this.captureInfo[inEvent.pointerId] || inEvent._target;\n    },\n    setCapture: function(inPointerId, inTarget) {\n      if (this.captureInfo[inPointerId]) {\n        this.releaseCapture(inPointerId);\n      }\n      this.captureInfo[inPointerId] = inTarget;\n      var e = document.createEvent('Event');\n      e.initEvent('gotpointercapture', true, false);\n      e.pointerId = inPointerId;\n      this.implicitRelease = this.releaseCapture.bind(this, inPointerId);\n      document.addEventListener('pointerup', this.implicitRelease);\n      document.addEventListener('pointercancel', this.implicitRelease);\n      e._target = inTarget;\n      this.asyncDispatchEvent(e);\n    },\n    releaseCapture: function(inPointerId) {\n      var t = this.captureInfo[inPointerId];\n      if (t) {\n        var e = document.createEvent('Event');\n        e.initEvent('lostpointercapture', true, false);\n        e.pointerId = inPointerId;\n        this.captureInfo[inPointerId] = undefined;\n        document.removeEventListener('pointerup', this.implicitRelease);\n        document.removeEventListener('pointercancel', this.implicitRelease);\n        e._target = 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      requestAnimationFrame(this.dispatchEvent.bind(this, inEvent));\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('readystatechange', function() {\n        if (document.readyState === 'complete') {\n          this.installNewSubtree(document);\n        }\n      }.bind(this));\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  var WHICH_TO_BUTTONS = [0, 1, 4, 2];\n\n  var HAS_BUTTONS = false;\n  try {\n    HAS_BUTTONS = new MouseEvent('test', {buttons: 1}).buttons === 1;\n  } catch (e) {}\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      if (!HAS_BUTTONS) {\n        e.buttons = WHICH_TO_BUTTONS[e.which] || 0;\n      }\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 captureInfo = dispatcher.captureInfo;\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    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        el._scrollType = st;\n        dispatcher.listen(el, this.events);\n        // set touch-action on shadows as well\n        allShadows(el).forEach(function(s) {\n          s._scrollType = st;\n          dispatcher.listen(s, this.events);\n        }, this);\n      }\n    },\n    elementRemoved: function(el) {\n      el._scrollType = undefined;\n      dispatcher.unlisten(el, this.events);\n      // remove touch-action from shadow\n      allShadows(el).forEach(function(s) {\n        s._scrollType = undefined;\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        el._scrollType = st;\n        allShadows(el).forEach(function(s) {\n          s._scrollType = 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    typeToButtons: function(type) {\n      var ret = 0;\n      if (type === 'touchstart' || type === 'touchmove') {\n        ret = 1;\n      }\n      return ret;\n    },\n    touchToPointer: function(inTouch) {\n      var cte = this.currentTouchEvent;\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      var id = e.pointerId = inTouch.identifier + 2;\n      e.target = captureInfo[id] || findTarget(e);\n      e.bubbles = true;\n      e.cancelable = true;\n      e.detail = this.clickCount;\n      e.button = 0;\n      e.buttons = this.typeToButtons(cte.type);\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      // forward touch preventDefaults\n      var self = this;\n      e.preventDefault = function() {\n        self.scrolling = false;\n        self.firstXY = null;\n        cte.preventDefault();\n      };\n      return e;\n    },\n    processTouches: function(inEvent, inFunction) {\n      var tl = inEvent.changedTouches;\n      this.currentTouchEvent = inEvent;\n      for (var i = 0, t; i < tl.length; i++) {\n        t = tl[i];\n        inFunction.call(this, this.touchToPointer(t));\n      }\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 = inEvent.currentTarget._scrollType;\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(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.PointerEvent !== scope.PointerEvent) {\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      requestAnimationFrame(this.runQueue.bind(this, inHandlerFns, e));\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      requestAnimationFrame(this.dispatchEvent.bind(this, inEvent, inTarget));\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  // recognizers call into the dispatcher and load later\n  // solve the chicken and egg problem by having registerScopes module run last\n  dispatcher.registerQueue = [];\n  dispatcher.immediateRegister = false;\n  scope.dispatcher = dispatcher;\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 (dispatcher.immediateRegister) {\n      var pe = window.PointerEventsPolyfill;\n      if (pe) {\n        pe.register(inScope);\n      }\n      scope.dispatcher.registerTarget(inScope);\n    } else {\n      dispatcher.registerQueue.push(inScope);\n    }\n  };\n  scope.register(document);\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 * Type of pointer that made the holding event.\n * @type String\n * @property pointerType\n */\n/**\n * Screen X axis position of the held pointer\n * @type Number\n * @property clientX\n */\n/**\n * Screen Y axis position of the held pointer\n * @type Number\n * @property clientY\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 * Milliseconds pointer has been held down.\n * @type Number\n * @property holdTime\n */\n/**\n * This event is fired when a held pointer is released or moved.\n *\n * @class released\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        clientX: this.heldPointer.clientX,\n        clientY: this.heldPointer.clientY\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      // start with at least two pointers\n      var points = {a: pointers[0], b: pointers[1]};\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          buttons: inEvent.buttons,\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    shouldTap: function(e, downState) {\n      if (!e.tapPrevented) {\n        if (e.pointerType === 'mouse') {\n          // only allow left click to tap for mouse\n          return downState.buttons === 1;\n        } else {\n          return true;\n        }\n      }\n    },\n    pointerup: function(inEvent) {\n      var start = pointermap.get(inEvent.pointerId);\n      if (start && this.shouldTap(inEvent, start)) {\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","/*\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\n/**\n * Because recognizers are loaded after dispatcher, we have to wait to register\n * scopes until after all the recognizers.\n */\n(function(scope) {\n  var dispatcher = scope.dispatcher;\n  function registerScopes() {\n    dispatcher.immediateRegister = true;\n    var rq = dispatcher.registerQueue;\n    rq.forEach(scope.register);\n    rq.length = 0;\n  }\n  if (document.readyState === 'complete') {\n    registerScopes();\n  } else {\n    // register scopes after a steadystate is reached\n    // less MutationObserver churn\n    document.addEventListener('readystatechange', function() {\n      if (document.readyState === 'complete') {\n        registerScopes();\n      }\n    });\n  }\n})(window.PointerGestures);\n","// Copyright (c) 2014 The Polymer Project Authors. All rights reserved.\n// This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt\n// The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt\n// The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt\n// Code distributed by Google as part of the polymer project is also\n// subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt\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  Node.prototype.bind = function(name, observable) {\n    console.error('Unhandled binding to Node: ', this, name, observable);\n  };\n\n  function updateBindings(node, name, binding) {\n    var bindings = node.bindings_;\n    if (!bindings)\n      bindings = node.bindings_ = {};\n\n    if (bindings[name])\n      binding[name].close();\n\n    return bindings[name] = binding;\n  }\n\n  function returnBinding(node, name, binding) {\n    return binding;\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  var maybeUpdateBindings = returnBinding;\n\n  Object.defineProperty(Platform, 'enableBindingsReflection', {\n    get: function() {\n      return maybeUpdateBindings === updateBindings;\n    },\n    set: function(enable) {\n      maybeUpdateBindings = enable ? updateBindings : returnBinding;\n      return enable;\n    },\n    configurable: true\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    var observable = value;\n    updateText(this, observable.open(textBinding(this)));\n    return maybeUpdateBindings(this, name, observable);\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\n    var observable = value;\n    updateAttribute(this, name, conditional,\n        observable.open(attributeBinding(this, name, conditional)));\n\n    return maybeUpdateBindings(this, name, observable);\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      case 'range':\n        if (/Trident|MSIE/.test(navigator.userAgent))\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    return {\n      close: function() {\n        input.removeEventListener(eventType, eventHandler);\n        observable.close();\n      },\n\n      observable_: observable\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.observable_.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    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\n    var observable = value;\n    var binding = bindInputEvent(this, name, observable, postEventFn);\n    updateInput(this, name,\n                observable.open(inputBinding(this, name, sanitizeFn)),\n                sanitizeFn);\n\n    // Checkboxes may need to update bindings of other checkboxes.\n    return updateBindings(this, name, binding);\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    var observable = value;\n    var binding = bindInputEvent(this, 'value', observable);\n    updateInput(this, 'value',\n                observable.open(inputBinding(this, 'value', sanitizeValue)));\n    return maybeUpdateBindings(this, name, binding);\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.observable_.setValue(select.value);\n      selectBinding.observable_.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    var observable = value;\n    var binding = bindInputEvent(this, 'value', observable);\n    updateOption(this, observable.open(optionBinding(this)));\n    return maybeUpdateBindings(this, name, binding);\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    var observable = value;\n    var binding = bindInputEvent(this, name, observable);\n    updateInput(this, name,\n                observable.open(inputBinding(this, name)));\n\n    // Option update events may need to access select bindings.\n    return updateBindings(this, name, binding);\n  }\n})(this);\n","// Copyright (c) 2014 The Polymer Project Authors. All rights reserved.\n// This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt\n// The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt\n// The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt\n// Code distributed by Google as part of the polymer project is also\n// subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt\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  if (hasTemplateElement) {\n    // TODO(rafaelw): Remove when fix for\n    // https://codereview.chromium.org/164803002/\n    // makes it to Chrome release.\n    (function() {\n      var t = document.createElement('template');\n      var d = t.content.ownerDocument;\n      var html = d.appendChild(d.createElement('html'));\n      var head = html.appendChild(d.createElement('head'));\n      var base = d.createElement('base');\n      base.href = document.baseURI;\n      head.appendChild(base);\n    })();\n  }\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\n        // TODO(rafaelw): Remove when fix for\n        // https://codereview.chromium.org/164803002/\n        // makes it to Chrome release.\n        var base = owner.stagingDocument_.createElement('base');\n        base.href = document.baseURI;\n        owner.stagingDocument_.head.appendChild(base);\n\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      if (!this.bindings_) {\n        this.bindings_ = { ref: value };\n      } else {\n        this.bindings_.ref = value;\n      }\n\n      return 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        }\n\n        return;\n      }\n\n      if (!this.iterator_) {\n        this.iterator_ = new TemplateIterator(this);\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      if (bindingDelegate)\n        delegate_ = this.newDelegate_(bindingDelegate);\n\n      if (!this.refContent_)\n        this.refContent_ = this.ref_.content;\n      var content = this.refContent_;\n      if (content.firstChild === null)\n        return emptyInstance;\n\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      instance.bindings_ = [];\n      instance.terminator_ = null;\n      var instanceRecord = instance.templateInstance_ = {\n        firstNode: null,\n        lastNode: null,\n        model: model\n      };\n\n      var i = 0;\n      var collectTerminator = false;\n      for (var child = content.firstChild; child; child = child.nextSibling) {\n        // The terminator of the instance is the clone of the last child of the\n        // content. If the last child is an active template, it may produce\n        // instances as a result of production, so simply collecting the last\n        // child of the instance after it has finished producing may be wrong.\n        if (child.nextSibling === null)\n          collectTerminator = true;\n\n        var clone = cloneAndBindInstance(child, instance, stagingDocument,\n                                         map.children[i++],\n                                         model,\n                                         delegate_,\n                                         instance.bindings_);\n        clone.templateInstance_ = instanceRecord;\n        if (collectTerminator)\n          instance.terminator_ = clone;\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      if (this.bindings_ && this.bindings_.ref)\n        this.bindings_.ref.close()\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      var delegateFn = prepareBindingFn &&\n                       prepareBindingFn(pathString, name, node);\n      // Don't try to parse the expression if there's a prepareBinding function\n      if (delegateFn == null) {\n        tokens.push(Path.get(pathString)); // PATH\n      } else {\n        tokens.push(null);\n      }\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  var emptyInstance = document.createDocumentFragment();\n  emptyInstance.bindings_ = [];\n  emptyInstance.terminator_ = null;\n\n  function TemplateIterator(templateElement) {\n    this.closed = false;\n    this.templateElement_ = templateElement;\n    this.instances = [];\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    getLastInstanceNode: function(index) {\n      if (index == -1)\n        return this.templateElement_;\n      var instance = this.instances[index];\n      var terminator = instance.terminator_;\n      if (!terminator)\n        return this.getLastInstanceNode(index - 1);\n\n      if (terminator.nodeType !== Node.ELEMENT_NODE ||\n          this.templateElement_ === terminator) {\n        return terminator;\n      }\n\n      var subtemplateIterator = terminator.iterator_;\n      if (!subtemplateIterator)\n        return terminator;\n\n      return subtemplateIterator.getLastTemplateNode();\n    },\n\n    getLastTemplateNode: function() {\n      return this.getLastInstanceNode(this.instances.length - 1);\n    },\n\n    insertInstanceAt: function(index, fragment) {\n      var previousInstanceLast = this.getLastInstanceNode(index - 1);\n      var parent = this.templateElement_.parentNode;\n      this.instances.splice(index, 0, fragment);\n\n      parent.insertBefore(fragment, previousInstanceLast.nextSibling);\n    },\n\n    extractInstanceAt: function(index) {\n      var previousInstanceLast = this.getLastInstanceNode(index - 1);\n      var lastNode = this.getLastInstanceNode(index);\n      var parent = this.templateElement_.parentNode;\n      var instance = this.instances.splice(index, 1)[0];\n\n      while (lastNode !== previousInstanceLast) {\n        var node = previousInstanceLast.nextSibling;\n        if (node == lastNode)\n          lastNode = previousInstanceLast;\n\n        instance.appendChild(parent.removeChild(node));\n      }\n\n      return instance;\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      // Instance Removals\n      var instanceCache = new Map;\n      var removeDelta = 0;\n      for (var i = 0; i < splices.length; i++) {\n        var splice = splices[i];\n        var removed = splice.removed;\n        for (var j = 0; j < removed.length; j++) {\n          var model = removed[j];\n          var instance = this.extractInstanceAt(splice.index + removeDelta);\n          if (instance !== emptyInstance) {\n            instanceCache.set(model, instance);\n          }\n        }\n\n        removeDelta -= splice.addedCount;\n      }\n\n      // Instance Insertions\n      for (var i = 0; i < splices.length; i++) {\n        var splice = splices[i];\n        var addIndex = splice.index;\n        for (; addIndex < splice.index + splice.addedCount; addIndex++) {\n          var model = this.iteratedValue[addIndex];\n          var instance = instanceCache.get(model);\n          if (instance) {\n            instanceCache.delete(model);\n          } else {\n            if (this.instanceModelFn_) {\n              model = this.instanceModelFn_(model);\n            }\n\n            if (model === undefined) {\n              instance = emptyInstance;\n            } else {\n              instance = template.createInstance(model, undefined, delegate);\n            }\n          }\n\n          this.insertInstanceAt(addIndex, instance);\n        }\n      }\n\n      instanceCache.forEach(function(instance) {\n        this.closeInstanceBindings(instance);\n      }, this);\n\n      if (this.instancePositionChangedFn_)\n        this.reportInstancesMoved(splices);\n    },\n\n    reportInstanceMoved: function(index) {\n      var instance = this.instances[index];\n      if (instance === emptyInstance)\n        return;\n\n      this.instancePositionChangedFn_(instance.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.instances.length;\n      while (index < length) {\n        this.reportInstanceMoved(index);\n        index++;\n      }\n    },\n\n    closeInstanceBindings: function(instance) {\n      var bindings = instance.bindings_;\n      for (var i = 0; i < bindings.length; i++) {\n        bindings[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 = 0; i < this.instances.length; i++) {\n        this.closeInstanceBindings(this.instances[i]);\n      }\n\n      this.instances.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 (c) 2014 The Polymer Project Authors. All rights reserved.\n// This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt\n// The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt\n// The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt\n// Code distributed by Google as part of the polymer project is also\n// subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt\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      // captures deps.\n      var firstValue = this.getValue(model, observer, filterRegistry);\n      var firstTime = true;\n      var self = this;\n\n      function valueFn() {\n        // deps cannot have changed on first value retrieval.\n        if (firstTime) {\n          firstTime = false;\n          return firstValue;\n        }\n\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 isLiteralExpression(pathString) {\n    switch (pathString) {\n      case '':\n        return false;\n\n      case 'false':\n      case 'null':\n      case 'true':\n        return true;\n    }\n\n    if (!isNaN(Number(pathString)))\n      return true;\n\n    return false;\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 (!isLiteralExpression(pathString) && 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        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\n// flush periodically if platform does not have object observe.\nif (!Observer.hasObjectObserve) {\n  var FLUSH_POLL_INTERVAL = 125;\n  window.addEventListener('WebComponentsReady', function() {\n    flush();\n    scope.flushPoll = setInterval(flush, FLUSH_POLL_INTERVAL);\n  });\n} else {\n  // make flush a no-op when we have Object.observe\n  flush = function() {};\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/runtime/bin/vmservice/client/lib/service_html.dart b/runtime/bin/vmservice/client/lib/service_html.dart
index bd611a5..1a892aa 100644
--- a/runtime/bin/vmservice/client/lib/service_html.dart
+++ b/runtime/bin/vmservice/client/lib/service_html.dart
@@ -50,8 +50,84 @@
   }
 }
 
+class WebSocketVM extends VM {
+  final Map<int, Completer> _pendingRequests =
+      new Map<int, Completer>();
+  int _requestSerial = 0;
+
+  String _host;
+  Future<WebSocket> _socketFuture;
+
+  bool runningInJavaScript() => identical(1.0, 1);
+
+  WebSocketVM() : super() {
+    if (runningInJavaScript()) {
+      // When we are running as JavaScript use the same hostname:port
+      // that the Observatory is loaded from.
+      _host = 'ws://${window.location.host}/ws';
+    } else {
+      // Otherwise, assume we are running from the Dart Editor and
+      // want to connect on the default port.
+      _host = 'ws://127.0.0.1:8181/ws';
+    }
+
+    var completer = new Completer<WebSocket>();
+    _socketFuture = completer.future;
+    var socket = new WebSocket(_host);
+    socket.onOpen.first.then((_) {
+        socket.onMessage.listen(_handleMessage);
+        socket.onClose.first.then((_) {
+            _socketFuture = null;
+          });
+        completer.complete(socket);
+      });
+    socket.onError.first.then((_) {
+        _socketFuture = null;
+      });
+  }
+
+  void _handleMessage(MessageEvent event) {
+    var map = JSON.decode(event.data);
+    int seq = map['seq'];
+    var response = map['response'];
+    var completer = _pendingRequests.remove(seq);
+    if (completer == null) {
+      Logger.root.severe('Received unexpected message: ${map}');
+    } else {
+      completer.complete(response);
+    }
+  }
+
+  Future<String> getString(String id) {
+    if (_socketFuture == null) {
+      var errorResponse = JSON.encode({
+              'type': 'ServiceException',
+              'id': '',
+              'response': '',
+              'kind': 'NetworkException',
+              'message': 'Could not connect to service. Check that you started the'
+              ' VM with the following flags:\n --enable-vm-service'
+              ' --pause-isolates-on-exit'
+          });
+      return new Future.value(errorResponse);
+    }
+    return _socketFuture.then((socket) {
+        int seq = _requestSerial++;
+        if (!id.endsWith('/profile/tag')) {
+          Logger.root.info('Fetching $id from $_host');
+        }
+        var completer = new Completer<String>();
+        _pendingRequests[seq] = completer;
+        var message = JSON.encode({'seq': seq, 'request': id});
+        socket.send(message);
+        return completer.future;
+      });
+  }
+}
+
 class DartiumVM extends VM {
-  final Map _outstandingRequests = new Map();
+  final Map<String, Completer> _pendingRequests =
+      new Map<String, Completer>();
   int _requestSerial = 0;
 
   DartiumVM() : super() {
@@ -66,9 +142,9 @@
     if (name != 'observatoryData') {
       return;
     }
-    var completer = _outstandingRequests[id];
+    var completer = _pendingRequests[id];
     assert(completer != null);
-    _outstandingRequests.remove(id);
+    _pendingRequests.remove(id);
     completer.complete(data);
   }
 
@@ -80,7 +156,7 @@
     message['query'] = '/$path';
     _requestSerial++;
     var completer = new Completer();
-    _outstandingRequests[idString] = completer;
+    _pendingRequests[idString] = completer;
     window.parent.postMessage(JSON.encode(message), '*');
     return completer.future;
   }
diff --git a/runtime/bin/vmservice/client/lib/src/app/application.dart b/runtime/bin/vmservice/client/lib/src/app/application.dart
index 3ebdc7b..e10fa76 100644
--- a/runtime/bin/vmservice/client/lib/src/app/application.dart
+++ b/runtime/bin/vmservice/client/lib/src/app/application.dart
@@ -50,7 +50,7 @@
 
   ObservatoryApplication() :
       locationManager = new LocationManager(),
-      vm = new HttpVM() {
+          vm = new WebSocketVM() {
     _initOnce();
   }
 }
diff --git a/runtime/bin/vmservice/server.dart b/runtime/bin/vmservice/server.dart
index 051ea43..da4cb4d 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/runtime/bin/vmservice/server.dart
@@ -29,9 +29,9 @@
         return;
       }
       var seq = map['seq'];
-      onMessage(seq, new Message.fromMap(map));
+      onMessage(seq, new Message.fromUri(Uri.parse(map['request'])));
     } else {
-      socket.close(BINARY_MESSAGE_ERROR_CODE, 'message must be a string.');
+      socket.close(BINARY_MESSAGE_ERROR_CODE, 'Message must be a string.');
     }
   }
 
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 2f844f3..c7fd018 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -1262,13 +1262,18 @@
 /**
  * Returns the null object.
  *
- * Requires there to be a current isolate.
- *
  * \return A handle to the null object.
  */
 DART_EXPORT Dart_Handle Dart_Null();
 
 /**
+ * Returns the empty string object.
+ *
+ * \return A handle to the empty string object.
+ */
+DART_EXPORT Dart_Handle Dart_EmptyString();
+
+/**
  * Is this object null?
  */
 DART_EXPORT bool Dart_IsNull(Dart_Handle object);
@@ -1325,6 +1330,7 @@
 DART_EXPORT bool Dart_IsStringLatin1(Dart_Handle object);  /* (ISO-8859-1) */
 DART_EXPORT bool Dart_IsExternalString(Dart_Handle object);
 DART_EXPORT bool Dart_IsList(Dart_Handle object);
+DART_EXPORT bool Dart_IsMap(Dart_Handle object);
 DART_EXPORT bool Dart_IsLibrary(Dart_Handle object);
 DART_EXPORT bool Dart_IsType(Dart_Handle handle);
 DART_EXPORT bool Dart_IsFunction(Dart_Handle handle);
@@ -1776,7 +1782,7 @@
  * \param list A List.
  * \param index A valid index into the List.
  *
- * \return The Object in the List at the specified index if no errors
+ * \return The Object in the List at the specified index if no error
  *   occurs. Otherwise returns an error handle.
  */
 DART_EXPORT Dart_Handle Dart_ListGetAt(Dart_Handle list,
@@ -1817,6 +1823,50 @@
 
 
 /*
+ * ====
+ * Maps
+ * ====
+ */
+
+/**
+ * Gets the Object at some key of a Map.
+ *
+ * May generate an unhandled exception error.
+ *
+ * \param map A Map.
+ * \param key An Object.
+ *
+ * \return The value in the map at the specified key, null if the map does not
+ *   contain the key, or an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_MapGetAt(Dart_Handle map, Dart_Handle key);
+
+/**
+ * Returns whether the Map contains a given key.
+ *
+ * May generate an unhandled exception error.
+ *
+ * \param map A Map.
+ *
+ * \return A handle on a boolean indicating whether map contains the key.
+ *   Otherwise returns an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_MapContainsKey(Dart_Handle map, Dart_Handle key);
+
+/**
+ * Gets the list of keys of a Map.
+ *
+ * May generate an unhandled exception error.
+ *
+ * \param map A Map.
+ *
+ * \return The list of key Objects if no error occurs. Otherwise returns an
+ *   error handle.
+ */
+DART_EXPORT Dart_Handle Dart_MapKeys(Dart_Handle map);
+
+
+/*
  * ==========
  * Typed Data
  * ==========
diff --git a/runtime/lib/integers.dart b/runtime/lib/integers.dart
index 3ed280b..0252960 100644
--- a/runtime/lib/integers.dart
+++ b/runtime/lib/integers.dart
@@ -117,11 +117,10 @@
   }
 
   int compareTo(num other) {
-    final int EQUAL = 0, LESS = -1, GREATER = 1;
+    const int EQUAL = 0, LESS = -1, GREATER = 1;
     if (other is double) {
-      // TODO(floitsch): the following locals should be 'const'.
-      int MAX_EXACT_INT_TO_DOUBLE = 9007199254740992;  // 2^53.
-      int MIN_EXACT_INT_TO_DOUBLE = -MAX_EXACT_INT_TO_DOUBLE;
+      const int MAX_EXACT_INT_TO_DOUBLE = 9007199254740992;  // 2^53.
+      const int MIN_EXACT_INT_TO_DOUBLE = -MAX_EXACT_INT_TO_DOUBLE;
       double d = other;
       if (d.isInfinite) {
         return d == double.NEGATIVE_INFINITY ? GREATER : LESS;
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 7b139fe..c84c972 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -162,15 +162,16 @@
 
 
 DEFINE_NATIVE_ENTRY(Object_instanceOf, 5) {
-  const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0));
+  const Instance& instance =
+      Instance::CheckedHandle(isolate, arguments->NativeArgAt(0));
   // 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 TypeArguments& instantiator_type_arguments =
-      TypeArguments::CheckedHandle(arguments->NativeArgAt(2));
+      TypeArguments::CheckedHandle(isolate, arguments->NativeArgAt(2));
   const AbstractType& type =
-      AbstractType::CheckedHandle(arguments->NativeArgAt(3));
-  const Bool& negate = Bool::CheckedHandle(arguments->NativeArgAt(4));
+      AbstractType::CheckedHandle(isolate, arguments->NativeArgAt(3));
+  const Bool& negate = Bool::CheckedHandle(isolate, arguments->NativeArgAt(4));
   ASSERT(type.IsFinalized());
   ASSERT(!type.IsMalformed());
   ASSERT(!type.IsMalbounded());
@@ -180,7 +181,7 @@
     WarnOnJSIntegralNumTypeTest(instance, instantiator_type_arguments, type);
   }
 
-  Error& bound_error = Error::Handle();
+  Error& bound_error = Error::Handle(isolate, Error::null());
   const bool is_instance_of = instance.IsInstanceOf(type,
                                                     instantiator_type_arguments,
                                                     &bound_error);
@@ -202,7 +203,7 @@
     ASSERT(caller_frame != NULL);
     const intptr_t location = caller_frame->GetTokenPos();
     String& bound_error_message = String::Handle(
-        String::New(bound_error.ToErrorCString()));
+        isolate, String::New(bound_error.ToErrorCString()));
     Exceptions::CreateAndThrowTypeError(
         location, Symbols::Empty(), Symbols::Empty(),
         Symbols::Empty(), bound_error_message);
diff --git a/runtime/tools/create_resources.py b/runtime/tools/create_resources.py
index 32ffdb1..b4f7fa8 100644
--- a/runtime/tools/create_resources.py
+++ b/runtime/tools/create_resources.py
@@ -127,6 +127,9 @@
           src_path = os.path.join(dirname, f)
           if (os.path.isdir(src_path)):
               continue
+          # Skip devtools version
+          if (src_path.find("index_devtools") != -1):
+              continue
           files.append(src_path)
 
     for arg in args:
@@ -145,4 +148,4 @@
     return -1
 
 if __name__ == '__main__':
-  sys.exit(main(sys.argv))
\ No newline at end of file
+  sys.exit(main(sys.argv))
diff --git a/runtime/vm/assembler_arm64.cc b/runtime/vm/assembler_arm64.cc
index 07ab448..0b3ddf1 100644
--- a/runtime/vm/assembler_arm64.cc
+++ b/runtime/vm/assembler_arm64.cc
@@ -1081,9 +1081,7 @@
     AddImmediate(SP, SP, -frame_space, kNoPP);
   }
   if (OS::ActivationFrameAlignment() > 1) {
-    mov(TMP, SP);  // SP can't be register operand of andi.
-    andi(TMP, TMP, ~(OS::ActivationFrameAlignment() - 1));
-    mov(SP, TMP);
+    andi(SP, SP, ~(OS::ActivationFrameAlignment() - 1));
   }
 }
 
@@ -1194,9 +1192,7 @@
 
   for (int i = kDartFirstVolatileCpuReg; i <= kDartLastVolatileCpuReg; i++) {
     const Register reg = static_cast<Register>(i);
-    if ((reg != TMP) && (reg != TMP2)) {
-      Push(reg);
-    }
+    Push(reg);
   }
 
   ReserveAlignedFrameSpace(frame_size);
@@ -1207,16 +1203,13 @@
   // SP might have been modified to reserve space for arguments
   // and ensure proper alignment of the stack frame.
   // We need to restore it before restoring registers.
-  // TODO(zra): Also include FPU regs in this count once they are added.
   const intptr_t kPushedRegistersSize =
       kDartVolatileCpuRegCount * kWordSize +
       kDartVolatileFpuRegCount * kWordSize;
   AddImmediate(SP, FP, -kPushedRegistersSize, PP);
   for (int i = kDartLastVolatileCpuReg; i >= kDartFirstVolatileCpuReg; i--) {
     const Register reg = static_cast<Register>(i);
-    if ((reg != TMP) && (reg != TMP2)) {
-      Pop(reg);
-    }
+    Pop(reg);
   }
 
   for (int i = 0; i < kNumberOfVRegisters; i++) {
diff --git a/runtime/vm/assembler_arm64.h b/runtime/vm/assembler_arm64.h
index 9529137..f6f01d0 100644
--- a/runtime/vm/assembler_arm64.h
+++ b/runtime/vm/assembler_arm64.h
@@ -167,7 +167,7 @@
   Address(Register rn, Register rm,
           Extend ext = UXTX, Scaling scale = Unscaled) {
     ASSERT((rn != R31) && (rn != ZR));
-    ASSERT((rm != R31) && (rm != SP));
+    ASSERT((rm != R31) && (rm != CSP));
     // Can only scale when ext = UXTX.
     ASSERT((scale != Scaled) || (ext == UXTX));
     ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
@@ -281,7 +281,7 @@
   }
 
   explicit Operand(Register rm) {
-    ASSERT((rm != R31) && (rm != SP));
+    ASSERT((rm != R31) && (rm != CSP));
     const Register crm = ConcreteRegister(rm);
     encoding_ = (static_cast<int32_t>(crm) << kRmShift);
     type_ = Shifted;
@@ -289,7 +289,7 @@
 
   Operand(Register rm, Shift shift, int32_t imm) {
     ASSERT(Utils::IsUint(6, imm));
-    ASSERT((rm != R31) && (rm != SP));
+    ASSERT((rm != R31) && (rm != CSP));
     const Register crm = ConcreteRegister(rm);
     encoding_ =
         (imm << kImm6Shift) |
@@ -300,7 +300,7 @@
 
   Operand(Register rm, Extend extend, int32_t imm) {
     ASSERT(Utils::IsUint(3, imm));
-    ASSERT((rm != R31) && (rm != SP));
+    ASSERT((rm != R31) && (rm != CSP));
     const Register crm = ConcreteRegister(rm);
     encoding_ =
         B21 |
@@ -463,7 +463,7 @@
   static bool IsSafeSmi(const Object& object) { return object.IsSmi(); }
 
   // Addition and subtraction.
-  // For add and sub, to use SP for rn, o must be of type Operand::Extend.
+  // For add and sub, to use CSP for rn, o must be of type Operand::Extend.
   // For an unmodified rm in this case, use Operand(rm, UXTX, 0);
   void add(Register rd, Register rn, Operand o) {
     AddSubHelper(kDoubleWord, false, false, rd, rn, o);
@@ -572,17 +572,17 @@
 
   // Move wide immediate.
   void movk(Register rd, uint16_t imm, int hw_idx) {
-    ASSERT(rd != SP);
+    ASSERT(rd != CSP);
     const Register crd = ConcreteRegister(rd);
     EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord);
   }
   void movn(Register rd, uint16_t imm, int hw_idx) {
-    ASSERT(rd != SP);
+    ASSERT(rd != CSP);
     const Register crd = ConcreteRegister(rd);
     EmitMoveWideOp(MOVN, crd, imm, hw_idx, kDoubleWord);
   }
   void movz(Register rd, uint16_t imm, int hw_idx) {
-    ASSERT(rd != SP);
+    ASSERT(rd != CSP);
     const Register crd = ConcreteRegister(rd);
     EmitMoveWideOp(MOVZ, crd, imm, hw_idx, kDoubleWord);
   }
@@ -635,7 +635,7 @@
 
   // Comparison.
   // rn cmp o.
-  // For add and sub, to use SP for rn, o must be of type Operand::Extend.
+  // For add and sub, to use CSP for rn, o must be of type Operand::Extend.
   // For an unmodified rm in this case, use Operand(rm, UXTX, 0);
   void cmp(Register rn, Operand o) {
     subs(ZR, rn, o);
@@ -646,10 +646,10 @@
   }
 
   void CompareRegisters(Register rn, Register rm) {
-    if (rn == SP) {
+    if (rn == CSP) {
       // UXTX 0 on a 64-bit register (rm) is a nop, but forces R31 to be
-      // interpreted as SP.
-      cmp(SP, Operand(rm, UXTX, 0));
+      // interpreted as CSP.
+      cmp(CSP, Operand(rm, UXTX, 0));
     } else {
       cmp(rn, Operand(rm));
     }
@@ -702,25 +702,25 @@
   }
   void fmovdr(VRegister vd, Register rn) {
     ASSERT(rn != R31);
-    ASSERT(rn != SP);
+    ASSERT(rn != CSP);
     const Register crn = ConcreteRegister(rn);
     EmitFPIntCvtOp(FMOVDR, static_cast<Register>(vd), crn);
   }
   void fmovrd(Register rd, VRegister vn) {
     ASSERT(rd != R31);
-    ASSERT(rd != SP);
+    ASSERT(rd != CSP);
     const Register crd = ConcreteRegister(rd);
     EmitFPIntCvtOp(FMOVRD, crd, static_cast<Register>(vn));
   }
   void scvtfd(VRegister vd, Register rn) {
     ASSERT(rn != R31);
-    ASSERT(rn != SP);
+    ASSERT(rn != CSP);
     const Register crn = ConcreteRegister(rn);
     EmitFPIntCvtOp(SCVTFD, static_cast<Register>(vd), crn);
   }
   void fcvtzds(Register rd, VRegister vn) {
     ASSERT(rd != R31);
-    ASSERT(rd != SP);
+    ASSERT(rd != CSP);
     const Register crd = ConcreteRegister(rd);
     EmitFPIntCvtOp(FCVTZDS, crd, static_cast<Register>(vn));
   }
@@ -933,7 +933,7 @@
 
   // Aliases.
   void mov(Register rd, Register rn) {
-    if ((rd == SP) || (rn == SP)) {
+    if ((rd == CSP) || (rn == CSP)) {
       add(rd, rn, Operand(0));
     } else {
       orr(rd, ZR, Operand(rn));
@@ -1174,6 +1174,15 @@
   void EnterFrame(intptr_t frame_size);
   void LeaveFrame();
 
+  // When entering Dart code from C++, we copy the system stack pointer (CSP)
+  // to the Dart stack pointer (SP), and reserve a little space for the stack
+  // to grow.
+  void SetupDartSP(intptr_t reserved_space) {
+    ASSERT(Utils::IsAligned(reserved_space, 16));
+    mov(SP, CSP);
+    sub(CSP, CSP, Operand(reserved_space));
+  }
+
   void EnterDartFrame(intptr_t frame_size);
   void EnterDartFrameWithInfo(intptr_t frame_size, Register new_pp);
   void EnterOsrFrame(intptr_t extra_size, Register new_pp);
@@ -1286,11 +1295,11 @@
       ASSERT(rn != ZR);
       EmitAddSubImmOp(subtract ? SUBI : ADDI, crd, crn, o, os, set_flags);
     } else if (o.type() == Operand::Shifted) {
-      ASSERT((rd != SP) && (rn != SP));
+      ASSERT((rd != CSP) && (rn != CSP));
       EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags);
     } else {
       ASSERT(o.type() == Operand::Extended);
-      ASSERT((rd != SP) && (rn != ZR));
+      ASSERT((rd != CSP) && (rn != ZR));
       EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags);
     }
   }
@@ -1312,9 +1321,9 @@
                         Operand o, OperandSize sz) {
     ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord));
     ASSERT((rd != R31) && (rn != R31));
-    ASSERT(rn != SP);
+    ASSERT(rn != CSP);
     ASSERT((op == ANDIS) || (rd != ZR));  // op != ANDIS => rd != ZR.
-    ASSERT((op != ANDIS) || (rd != SP));  // op == ANDIS => rd != SP.
+    ASSERT((op != ANDIS) || (rd != CSP));  // op == ANDIS => rd != CSP.
     ASSERT(o.type() == Operand::BitfieldImm);
     const int32_t size = (sz == kDoubleWord) ? B31 : 0;
     const Register crd = ConcreteRegister(rd);
@@ -1331,7 +1340,7 @@
                           Register rd, Register rn, Operand o, OperandSize sz) {
     ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord));
     ASSERT((rd != R31) && (rn != R31));
-    ASSERT((rd != SP) && (rn != SP));
+    ASSERT((rd != CSP) && (rn != CSP));
     ASSERT(o.type() == Operand::Shifted);
     const int32_t size = (sz == kDoubleWord) ? B31 : 0;
     const Register crd = ConcreteRegister(rd);
@@ -1398,7 +1407,7 @@
                             OperandSize sz) {
     ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord));
     ASSERT(Utils::IsInt(21, imm) && ((imm & 0x3) == 0));
-    ASSERT((rt != SP) && (rt != R31));
+    ASSERT((rt != CSP) && (rt != R31));
     const Register crt = ConcreteRegister(rt);
     const int32_t size = (sz == kDoubleWord) ? B31 : 0;
     const int32_t encoded_offset = EncodeImm19BranchOffset(imm, 0);
@@ -1463,7 +1472,7 @@
   }
 
   void EmitUnconditionalBranchRegOp(UnconditionalBranchRegOp op, Register rn) {
-    ASSERT((rn != SP) && (rn != R31));
+    ASSERT((rn != CSP) && (rn != R31));
     const Register crn = ConcreteRegister(rn);
     const int32_t encoding =
         op | (static_cast<int32_t>(crn) << kRnShift);
@@ -1503,7 +1512,7 @@
   void EmitLoadRegLiteral(LoadRegLiteralOp op, Register rt, Address a,
                           OperandSize sz) {
     ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord));
-    ASSERT((rt != SP) && (rt != R31));
+    ASSERT((rt != CSP) && (rt != R31));
     const Register crt = ConcreteRegister(rt);
     const int32_t size = (sz == kDoubleWord) ? B30 : 0;
     const int32_t encoding =
@@ -1515,7 +1524,7 @@
 
   void EmitPCRelOp(PCRelOp op, Register rd, int64_t imm) {
     ASSERT(Utils::IsInt(21, imm));
-    ASSERT((rd != R31) && (rd != SP));
+    ASSERT((rd != R31) && (rd != CSP));
     const Register crd = ConcreteRegister(rd);
     const int32_t loimm = (imm & 0x3) << 29;
     const int32_t hiimm = ((imm >> 2) << kImm19Shift) & kImm19Mask;
@@ -1528,7 +1537,7 @@
   void EmitMiscDP2Source(MiscDP2SourceOp op,
                          Register rd, Register rn, Register rm,
                          OperandSize sz) {
-    ASSERT((rd != SP) && (rn != SP) && (rm != SP));
+    ASSERT((rd != CSP) && (rn != CSP) && (rm != CSP));
     ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord));
     const Register crd = ConcreteRegister(rd);
     const Register crn = ConcreteRegister(rn);
@@ -1545,7 +1554,7 @@
   void EmitMiscDP3Source(MiscDP3SourceOp op,
                          Register rd, Register rn, Register rm, Register ra,
                          OperandSize sz) {
-    ASSERT((rd != SP) && (rn != SP) && (rm != SP) && (ra != SP));
+    ASSERT((rd != CSP) && (rn != CSP) && (rm != CSP) && (ra != CSP));
     ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord));
     const Register crd = ConcreteRegister(rd);
     const Register crn = ConcreteRegister(rn);
@@ -1564,7 +1573,7 @@
   void EmitConditionalSelect(ConditionalSelectOp op,
                              Register rd, Register rn, Register rm,
                              Condition cond, OperandSize sz) {
-    ASSERT((rd != SP) && (rn != SP) && (rm != SP));
+    ASSERT((rd != CSP) && (rn != CSP) && (rm != CSP));
     ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord));
     const Register crd = ConcreteRegister(rd);
     const Register crn = ConcreteRegister(rn);
diff --git a/runtime/vm/assembler_arm64_test.cc b/runtime/vm/assembler_arm64_test.cc
index e629a1f..1b9588a 100644
--- a/runtime/vm/assembler_arm64_test.cc
+++ b/runtime/vm/assembler_arm64_test.cc
@@ -13,6 +13,8 @@
 
 namespace dart {
 
+static const intptr_t kTestStackSpace = 512 * kWordSize;
+
 #define __ assembler->
 
 ASSEMBLER_TEST_GENERATE(Simple, assembler) {
@@ -23,8 +25,8 @@
 
 
 ASSEMBLER_TEST_RUN(Simple, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -37,8 +39,8 @@
 
 
 ASSEMBLER_TEST_RUN(Movz0, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -50,8 +52,8 @@
 
 
 ASSEMBLER_TEST_RUN(Movz1, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42LL << 16, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42LL << 16, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -62,8 +64,8 @@
 
 
 ASSEMBLER_TEST_RUN(Movz2, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42LL << 32, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42LL << 32, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -74,8 +76,8 @@
 
 
 ASSEMBLER_TEST_RUN(Movz3, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42LL << 48, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42LL << 48, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -87,8 +89,8 @@
 
 
 ASSEMBLER_TEST_RUN(Movn0, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(~42LL, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(~42LL, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -99,8 +101,8 @@
 
 
 ASSEMBLER_TEST_RUN(Movn1, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(~(42LL << 16), EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(~(42LL << 16), EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -111,8 +113,8 @@
 
 
 ASSEMBLER_TEST_RUN(Movn2, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(~(42LL << 32), EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(~(42LL << 32), EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -123,8 +125,8 @@
 
 
 ASSEMBLER_TEST_RUN(Movn3, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(~(42LL << 48), EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(~(42LL << 48), EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 // movk
@@ -136,9 +138,9 @@
 
 
 ASSEMBLER_TEST_RUN(Movk0, test) {
-  typedef int (*SimpleCode)();
+  typedef int64_t (*Int64Return)();
   EXPECT_EQ(
-      42LL | (1LL << 48), EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+      42LL | (1LL << 48), EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -150,9 +152,9 @@
 
 
 ASSEMBLER_TEST_RUN(Movk1, test) {
-  typedef int (*SimpleCode)();
+  typedef int64_t (*Int64Return)();
   EXPECT_EQ(
-      (42LL << 16) | 1, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+      (42LL << 16) | 1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -164,9 +166,9 @@
 
 
 ASSEMBLER_TEST_RUN(Movk2, test) {
-  typedef int (*SimpleCode)();
+  typedef int64_t (*Int64Return)();
   EXPECT_EQ(
-      (42LL << 32) | 1, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+      (42LL << 32) | 1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -178,9 +180,9 @@
 
 
 ASSEMBLER_TEST_RUN(Movk3, test) {
-  typedef int (*SimpleCode)();
+  typedef int64_t (*Int64Return)();
   EXPECT_EQ(
-      (42LL << 48) | 1, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+      (42LL << 48) | 1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -191,8 +193,8 @@
 
 
 ASSEMBLER_TEST_RUN(MovzBig, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(0x8000, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(0x8000, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -206,8 +208,8 @@
 
 
 ASSEMBLER_TEST_RUN(AddReg, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -220,8 +222,8 @@
 
 
 ASSEMBLER_TEST_RUN(AddLSLReg, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -234,8 +236,8 @@
 
 
 ASSEMBLER_TEST_RUN(AddLSRReg, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -248,8 +250,8 @@
 
 
 ASSEMBLER_TEST_RUN(AddASRReg, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -263,8 +265,8 @@
 
 
 ASSEMBLER_TEST_RUN(AddASRNegReg, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -279,44 +281,49 @@
 
 
 ASSEMBLER_TEST_RUN(AddExtReg, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
 // Loads and Stores.
 ASSEMBLER_TEST_GENERATE(SimpleLoadStore, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ movz(R0, 43, 0);
   __ movz(R1, 42, 0);
   __ str(R1, Address(SP, -1*kWordSize, Address::PreIndex));
   __ ldr(R0, Address(SP, 1*kWordSize, Address::PostIndex));
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(SimpleLoadStore, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(SimpleLoadStoreHeapTag, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ movz(R0, 43, 0);
   __ movz(R1, 42, 0);
   __ add(R2, SP, Operand(1));
   __ str(R1, Address(R2, -1));
   __ ldr(R0, Address(R2, -1));
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(SimpleLoadStoreHeapTag, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(LoadStoreLargeIndex, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ movz(R0, 43, 0);
   __ movz(R1, 42, 0);
   // Largest negative offset that can fit in the signed 9-bit immediate field.
@@ -325,34 +332,38 @@
   __ ldr(R0, Address(SP, 31*kWordSize, Address::PostIndex));
   // Correction.
   __ add(SP, SP, Operand(kWordSize));  // Restore SP.
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(LoadStoreLargeIndex, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(LoadStoreLargeOffset, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ movz(R0, 43, 0);
   __ movz(R1, 42, 0);
   __ sub(SP, SP, Operand(512*kWordSize));
   __ str(R1, Address(SP, 512*kWordSize, Address::Offset));
   __ add(SP, SP, Operand(512*kWordSize));
   __ ldr(R0, Address(SP));
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(LoadStoreLargeOffset, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(LoadStoreExtReg, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ movz(R0, 43, 0);
   __ movz(R1, 42, 0);
   __ movz(R2, 0xfff8, 0);
@@ -363,17 +374,19 @@
   __ sub(SP, SP, Operand(kWordSize));
   __ ldr(R0, Address(SP));
   __ add(SP, SP, Operand(kWordSize));
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(LoadStoreExtReg, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(LoadStoreScaledReg, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ movz(R0, 43, 0);
   __ movz(R1, 42, 0);
   __ movz(R2, 10, 0);
@@ -382,28 +395,31 @@
   __ str(R1, Address(SP, R2, UXTX, Address::Scaled));
   __ ldr(R0, Address(SP, R2, UXTX, Address::Scaled));
   __ add(SP, SP, Operand(10*kWordSize));
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(LoadStoreScaledReg, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(LoadSigned32Bit, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ LoadImmediate(R1, 0xffffffff, kNoPP);
   __ str(R1, Address(SP, -4, Address::PreIndex, kWord), kWord);
   __ ldr(R0, Address(SP), kWord);
   __ ldr(R1, Address(SP, 4, Address::PostIndex, kWord), kWord);
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(LoadSigned32Bit, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -417,8 +433,8 @@
 
 
 ASSEMBLER_TEST_RUN(AndRegs, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -431,8 +447,8 @@
 
 
 ASSEMBLER_TEST_RUN(AndShiftRegs, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -445,8 +461,8 @@
 
 
 ASSEMBLER_TEST_RUN(BicRegs, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -459,8 +475,8 @@
 
 
 ASSEMBLER_TEST_RUN(OrrRegs, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -474,8 +490,8 @@
 
 
 ASSEMBLER_TEST_RUN(OrnRegs, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -488,8 +504,8 @@
 
 
 ASSEMBLER_TEST_RUN(EorRegs, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -502,8 +518,8 @@
 
 
 ASSEMBLER_TEST_RUN(EonRegs, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -516,8 +532,8 @@
 
 
 ASSEMBLER_TEST_RUN(AndImm, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -529,8 +545,8 @@
 
 
 ASSEMBLER_TEST_RUN(AndOneImm, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(1, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -546,8 +562,8 @@
 
 
 ASSEMBLER_TEST_RUN(OrrImm, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -562,8 +578,8 @@
 
 
 ASSEMBLER_TEST_RUN(EorImm, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -579,8 +595,8 @@
 
 
 ASSEMBLER_TEST_RUN(BranchALForward, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -602,8 +618,8 @@
 
 
 ASSEMBLER_TEST_RUN(BranchALBackwards, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -623,8 +639,8 @@
 
 
 ASSEMBLER_TEST_RUN(CmpEqBranch, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -644,8 +660,8 @@
 
 
 ASSEMBLER_TEST_RUN(CmpEqBranchNotTaken, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -664,8 +680,8 @@
 
 
 ASSEMBLER_TEST_RUN(CmpEq1Branch, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -684,8 +700,8 @@
 
 
 ASSEMBLER_TEST_RUN(CmnEq1Branch, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -705,8 +721,8 @@
 
 
 ASSEMBLER_TEST_RUN(CmpLtBranch, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -726,13 +742,11 @@
 
 
 ASSEMBLER_TEST_RUN(CmpLtBranchNotTaken, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
-
-
 ASSEMBLER_TEST_GENERATE(FcmpEqBranch, assembler) {
   Label l;
 
@@ -749,8 +763,8 @@
 
 
 ASSEMBLER_TEST_RUN(FcmpEqBranch, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -770,8 +784,8 @@
 
 
 ASSEMBLER_TEST_RUN(FcmpEqBranchNotTaken, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -791,8 +805,8 @@
 
 
 ASSEMBLER_TEST_RUN(FcmpLtBranch, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -812,8 +826,8 @@
 
 
 ASSEMBLER_TEST_RUN(FcmpLtBranchNotTaken, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -834,8 +848,8 @@
 
 
 ASSEMBLER_TEST_RUN(FcmpzGtBranch, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -855,8 +869,8 @@
 
 
 ASSEMBLER_TEST_RUN(AndsBranch, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -876,8 +890,8 @@
 
 
 ASSEMBLER_TEST_RUN(AndsBranchNotTaken, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -897,8 +911,8 @@
 
 
 ASSEMBLER_TEST_RUN(BicsBranch, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -918,8 +932,8 @@
 
 
 ASSEMBLER_TEST_RUN(BicsBranchNotTaken, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -938,8 +952,8 @@
 
 
 ASSEMBLER_TEST_RUN(AndisBranch, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -958,8 +972,8 @@
 
 
 ASSEMBLER_TEST_RUN(AndisBranchNotTaken, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -977,8 +991,8 @@
 
 
 ASSEMBLER_TEST_RUN(AdrBr, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -997,8 +1011,8 @@
 
 
 ASSEMBLER_TEST_RUN(AdrBlr, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1014,8 +1028,8 @@
 
 ASSEMBLER_TEST_RUN(Udiv, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)();
-  EXPECT_EQ(3, EXECUTE_TEST_CODE_INT64(Tst, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(3, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1031,8 +1045,8 @@
 
 ASSEMBLER_TEST_RUN(Sdiv, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)();
-  EXPECT_EQ(-3, EXECUTE_TEST_CODE_INT64(Tst, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(-3, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1047,8 +1061,8 @@
 
 ASSEMBLER_TEST_RUN(Udiv_zero, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)();
-  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT64(Tst, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1063,8 +1077,8 @@
 
 ASSEMBLER_TEST_RUN(Sdiv_zero, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)();
-  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT64(Tst, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1079,8 +1093,8 @@
 
 ASSEMBLER_TEST_RUN(Udiv_corner, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)();
-  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT64(Tst, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1095,9 +1109,9 @@
 
 ASSEMBLER_TEST_RUN(Sdiv_corner, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)();
+  typedef int64_t (*Int64Return)();
   EXPECT_EQ(static_cast<int64_t>(0x8000000000000000),
-            EXECUTE_TEST_CODE_INT64(Tst, test->entry()));
+            EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1110,8 +1124,8 @@
 
 
 ASSEMBLER_TEST_RUN(Lslv, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1124,8 +1138,8 @@
 
 
 ASSEMBLER_TEST_RUN(Lsrv, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1139,8 +1153,8 @@
 
 
 ASSEMBLER_TEST_RUN(LShiftingV, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(1, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1154,8 +1168,8 @@
 
 
 ASSEMBLER_TEST_RUN(RShiftingV, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1168,8 +1182,8 @@
 
 
 ASSEMBLER_TEST_RUN(Mult_pos, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1183,8 +1197,8 @@
 
 
 ASSEMBLER_TEST_RUN(Mult_neg, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(-42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(-42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1197,8 +1211,8 @@
 
 
 ASSEMBLER_TEST_RUN(Smulh_pos, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1212,8 +1226,8 @@
 
 
 ASSEMBLER_TEST_RUN(Smulh_neg, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1225,8 +1239,8 @@
 
 
 ASSEMBLER_TEST_RUN(LoadImmediateSmall, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1237,8 +1251,8 @@
 
 
 ASSEMBLER_TEST_RUN(LoadImmediateMed, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(0xf1234123, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(0xf1234123, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1249,8 +1263,9 @@
 
 
 ASSEMBLER_TEST_RUN(LoadImmediateMed2, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(0x4321f1234123, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(
+      0x4321f1234123, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1261,9 +1276,9 @@
 
 
 ASSEMBLER_TEST_RUN(LoadImmediateLarge, test) {
-  typedef int (*SimpleCode)();
+  typedef int64_t (*Int64Return)();
   EXPECT_EQ(static_cast<int64_t>(0x9287436598237465),
-            EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+            EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1274,8 +1289,8 @@
 
 
 ASSEMBLER_TEST_RUN(LoadImmediateSmallNeg, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(-42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(-42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1286,8 +1301,8 @@
 
 
 ASSEMBLER_TEST_RUN(LoadImmediateMedNeg, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(-0x1212341234, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(-0x1212341234, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1298,8 +1313,8 @@
 
 
 ASSEMBLER_TEST_RUN(LoadImmediateMedNeg2, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(-0x1212340000, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(-0x1212340000, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1310,8 +1325,8 @@
 
 
 ASSEMBLER_TEST_RUN(LoadImmediateMedNeg3, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(-0x1200001234, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(-0x1200001234, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1322,119 +1337,134 @@
 
 
 ASSEMBLER_TEST_RUN(LoadImmediateMedNeg4, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(-0x12341234, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(-0x12341234, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
 // Loading immediate values with the object pool.
 ASSEMBLER_TEST_GENERATE(LoadImmediatePPSmall, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
   __ LoadPoolPointer(PP);
   __ LoadImmediate(R0, 42, PP);
   __ PopAndUntagPP();
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(LoadImmediatePPSmall, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(LoadImmediatePPMed, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
   __ LoadPoolPointer(PP);
   __ LoadImmediate(R0, 0xf1234123, PP);
   __ PopAndUntagPP();
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(LoadImmediatePPMed, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(0xf1234123, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(0xf1234123, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(LoadImmediatePPMed2, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
   __ LoadPoolPointer(PP);
   __ LoadImmediate(R0, 0x4321f1234124, PP);
   __ PopAndUntagPP();
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(LoadImmediatePPMed2, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(0x4321f1234124, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(
+      0x4321f1234124, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(LoadImmediatePPLarge, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
   __ LoadPoolPointer(PP);
   __ LoadImmediate(R0, 0x9287436598237465, PP);
   __ PopAndUntagPP();
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(LoadImmediatePPLarge, test) {
-  typedef int (*SimpleCode)();
+  typedef int64_t (*Int64Return)();
   EXPECT_EQ(static_cast<int64_t>(0x9287436598237465),
-            EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+            EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
 // LoadObject null.
 ASSEMBLER_TEST_GENERATE(LoadObjectNull, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
   __ LoadPoolPointer(PP);
   __ LoadObject(R0, Object::null_object(), PP);
   __ PopAndUntagPP();
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(LoadObjectNull, test) {
-  typedef int (*SimpleCode)();
+  typedef int64_t (*Int64Return)();
   EXPECT_EQ(reinterpret_cast<int64_t>(Object::null()),
-            EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+            EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(LoadObjectTrue, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
   __ LoadPoolPointer(PP);
   __ LoadObject(R0, Bool::True(), PP);
   __ PopAndUntagPP();
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(LoadObjectTrue, test) {
-  typedef int (*SimpleCode)();
+  typedef int64_t (*Int64Return)();
   EXPECT_EQ(reinterpret_cast<int64_t>(Bool::True().raw()),
-            EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+            EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(LoadObjectFalse, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
   __ LoadPoolPointer(PP);
   __ LoadObject(R0, Bool::False(), PP);
   __ PopAndUntagPP();
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(LoadObjectFalse, test) {
-  typedef int (*SimpleCode)();
+  typedef int64_t (*Int64Return)();
   EXPECT_EQ(reinterpret_cast<int64_t>(Bool::False().raw()),
-            EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+            EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1448,8 +1478,8 @@
 
 
 ASSEMBLER_TEST_RUN(CSelTrue, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1463,8 +1493,8 @@
 
 
 ASSEMBLER_TEST_RUN(CSelFalse, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(1234, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(1234, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1478,8 +1508,8 @@
 
 
 ASSEMBLER_TEST_RUN(CsincFalse, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(43, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(43, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1493,8 +1523,8 @@
 
 
 ASSEMBLER_TEST_RUN(CsincTrue, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(1234, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(1234, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1508,8 +1538,8 @@
 
 
 ASSEMBLER_TEST_RUN(CsinvFalse, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(~42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(~42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1523,8 +1553,8 @@
 
 
 ASSEMBLER_TEST_RUN(CsinvTrue, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(1234, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(1234, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1536,8 +1566,8 @@
 
 
 ASSEMBLER_TEST_RUN(Fmovdi, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(1.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(1.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -1548,9 +1578,9 @@
 
 
 ASSEMBLER_TEST_RUN(Fmovdi2, test) {
-  typedef int (*SimpleCode)();
+  typedef double (*DoubleReturn)();
   EXPECT_FLOAT_EQ(123412983.1324524315,
-      EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()), 0.0001f);
+      EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()), 0.0001f);
 }
 
 
@@ -1562,9 +1592,9 @@
 
 
 ASSEMBLER_TEST_RUN(Fmovrd, test) {
-  typedef int (*SimpleCode)();
+  typedef int64_t (*Int64Return)();
   const int64_t one = bit_cast<int64_t, double>(1.0);
-  EXPECT_EQ(one, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  EXPECT_EQ(one, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1577,42 +1607,47 @@
 
 
 ASSEMBLER_TEST_RUN(Fmovdr, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(1.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(1.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(FldrdFstrdPrePostIndex, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ LoadDImmediate(V1, 42.0, kNoPP);
   __ fstrd(V1, Address(SP, -1*kWordSize, Address::PreIndex));
   __ fldrd(V0, Address(SP, 1*kWordSize, Address::PostIndex));
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(FldrdFstrdPrePostIndex, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(FldrsFstrsPrePostIndex, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ LoadDImmediate(V1, 42.0, kNoPP);
   __ fcvtsd(V2, V1);
   __ fstrs(V2, Address(SP, -1*kWordSize, Address::PreIndex));
   __ fldrs(V3, Address(SP, 1*kWordSize, Address::PostIndex));
   __ fcvtds(V0, V3);
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(FldrsFstrsPrePostIndex, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(FldrqFstrqPrePostIndex, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ LoadDImmediate(V1, 21.0, kNoPP);
   __ LoadDImmediate(V2, 21.0, kNoPP);
   __ LoadImmediate(R1, 42, kNoPP);
@@ -1625,13 +1660,14 @@
   __ PopDouble(V0);
   __ PopDouble(V1);
   __ faddd(V0, V0, V1);
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(FldrqFstrqPrePostIndex, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -1643,8 +1679,8 @@
 
 
 ASSEMBLER_TEST_RUN(Fcvtzds, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1656,8 +1692,8 @@
 
 
 ASSEMBLER_TEST_RUN(Scvtfd, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -1669,8 +1705,8 @@
 
 
 ASSEMBLER_TEST_RUN(FabsdPos, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -1682,8 +1718,8 @@
 
 
 ASSEMBLER_TEST_RUN(FabsdNeg, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -1695,8 +1731,8 @@
 
 
 ASSEMBLER_TEST_RUN(FnegdPos, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(-42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(-42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -1708,8 +1744,8 @@
 
 
 ASSEMBLER_TEST_RUN(FnegdNeg, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -1721,8 +1757,8 @@
 
 
 ASSEMBLER_TEST_RUN(Fsqrtd, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(8.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(8.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -1735,8 +1771,8 @@
 
 
 ASSEMBLER_TEST_RUN(Fmuld, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -1749,8 +1785,8 @@
 
 
 ASSEMBLER_TEST_RUN(Fdivd, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -1763,8 +1799,8 @@
 
 
 ASSEMBLER_TEST_RUN(Faddd, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -1777,12 +1813,13 @@
 
 
 ASSEMBLER_TEST_RUN(Fsubd, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(FldrdFstrdHeapTag, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ LoadDImmediate(V0, 43.0, kNoPP);
   __ LoadDImmediate(V1, 42.0, kNoPP);
   __ AddImmediate(SP, SP, -1 * kWordSize, kNoPP);
@@ -1790,17 +1827,19 @@
   __ fstrd(V1, Address(R2, -1));
   __ fldrd(V0, Address(R2, -1));
   __ AddImmediate(SP, SP, 1 * kWordSize, kNoPP);
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(FldrdFstrdHeapTag, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(FldrdFstrdLargeIndex, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ LoadDImmediate(V0, 43.0, kNoPP);
   __ LoadDImmediate(V1, 42.0, kNoPP);
   // Largest negative offset that can fit in the signed 9-bit immediate field.
@@ -1809,34 +1848,38 @@
   __ fldrd(V0, Address(SP, 31*kWordSize, Address::PostIndex));
   // Correction.
   __ add(SP, SP, Operand(kWordSize));  // Restore SP.
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(FldrdFstrdLargeIndex, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(FldrdFstrdLargeOffset, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ LoadDImmediate(V0, 43.0, kNoPP);
   __ LoadDImmediate(V1, 42.0, kNoPP);
   __ sub(SP, SP, Operand(512*kWordSize));
   __ fstrd(V1, Address(SP, 512*kWordSize, Address::Offset));
   __ add(SP, SP, Operand(512*kWordSize));
   __ fldrd(V0, Address(SP));
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(FldrdFstrdLargeOffset, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(FldrdFstrdExtReg, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ LoadDImmediate(V0, 43.0, kNoPP);
   __ LoadDImmediate(V1, 42.0, kNoPP);
   __ movz(R2, 0xfff8, 0);
@@ -1847,17 +1890,19 @@
   __ sub(SP, SP, Operand(kWordSize));
   __ fldrd(V0, Address(SP));
   __ add(SP, SP, Operand(kWordSize));
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(FldrdFstrdExtReg, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(FldrdFstrdScaledReg, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ LoadDImmediate(V0, 43.0, kNoPP);
   __ LoadDImmediate(V1, 42.0, kNoPP);
   __ movz(R2, 10, 0);
@@ -1866,13 +1911,14 @@
   __ fstrd(V1, Address(SP, R2, UXTX, Address::Scaled));
   __ fldrd(V0, Address(SP, R2, UXTX, Address::Scaled));
   __ add(SP, SP, Operand(10*kWordSize));
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(FldrdFstrdScaledReg, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -1901,8 +1947,8 @@
 
 ASSEMBLER_TEST_RUN(VinswVmovrs, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)();
-  EXPECT_EQ(174, EXECUTE_TEST_CODE_INT64(Tst, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(174, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1923,8 +1969,8 @@
 
 ASSEMBLER_TEST_RUN(VinsxVmovrd, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)();
-  EXPECT_EQ(85, EXECUTE_TEST_CODE_INT64(Tst, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(85, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1951,8 +1997,8 @@
 
 ASSEMBLER_TEST_RUN(Vnot, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)();
-  EXPECT_EQ(2, EXECUTE_TEST_CODE_INT64(Tst, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(2, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -1981,8 +2027,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vabss, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2004,8 +2050,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vabsd, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2033,8 +2079,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vnegs, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2056,8 +2102,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vnegd, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2097,8 +2143,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vadds, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(12.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(12.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2139,8 +2185,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vsubs, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(-6.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(-6.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2180,8 +2226,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vmuls, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(14.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(14.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2221,8 +2267,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vdivs, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(4.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(4.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2244,8 +2290,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vaddd, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(10.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(10.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2268,8 +2314,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vsubd, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(-5.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(-5.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2291,8 +2337,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vmuld, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(13.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(13.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2314,12 +2360,13 @@
 
 
 ASSEMBLER_TEST_RUN(Vdivd, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(2.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(2.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(Vdupd, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ LoadDImmediate(V0, 21.0, kNoPP);
   __ vdupd(V1, V0, 0);
 
@@ -2331,22 +2378,23 @@
   __ fldrd(V3, Address(SP, 1 * dword_bytes, Address::PostIndex));
 
   __ faddd(V0, V2, V3);
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(Vdupd, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(Vdups, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ LoadDImmediate(V0, 21.0, kNoPP);
   __ fcvtsd(V0, V0);
   __ vdups(V1, V0, 0);
 
-
   const int sword_bytes = 1 << Log2OperandSizeBytes(kSWord);
   const int qword_bytes = 1 << Log2OperandSizeBytes(kQWord);
   __ fstrq(V1, Address(SP, -1 * qword_bytes, Address::PreIndex));
@@ -2364,17 +2412,19 @@
   __ faddd(V0, V1, V1);
   __ faddd(V0, V0, V2);
   __ faddd(V0, V0, V3);
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(Vdups, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(84.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(84.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(Vinsd, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ LoadDImmediate(V5, 42.0, kNoPP);
   __ vinsd(V1, 1, V5, 0);  // V1[1] <- V0[0].
 
@@ -2386,17 +2436,19 @@
   __ fldrd(V3, Address(SP, 1 * dword_bytes, Address::PostIndex));
 
   __ fmovdd(V0, V3);
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(Vinsd, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(Vinss, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ LoadDImmediate(V0, 21.0, kNoPP);
   __ fcvtsd(V0, V0);
   __ vinss(V1, 3, V0, 0);
@@ -2419,13 +2471,14 @@
   __ faddd(V0, V0, V1);
   __ faddd(V0, V0, V2);
   __ faddd(V0, V0, V3);
+  __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(Vinss, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2461,8 +2514,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vand, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2499,8 +2552,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vorr, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2533,8 +2586,8 @@
 
 
 ASSEMBLER_TEST_RUN(Veor, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -2558,8 +2611,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vaddw, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(168, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(168, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -2584,8 +2637,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vsubw, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(84, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(84, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -2605,8 +2658,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vaddx, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(84, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(84, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -2627,8 +2680,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vsubx, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -2660,8 +2713,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vceqs, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(0xfffffffe, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(0xfffffffe, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -2684,8 +2737,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vceqd, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -2717,8 +2770,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vcgts, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(0xfffffffe, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(0xfffffffe, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -2741,8 +2794,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vcgtd, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -2774,8 +2827,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vcges, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(0xfffffffe, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(0xfffffffe, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -2798,8 +2851,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vcged, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry()));
+  typedef int64_t (*Int64Return)();
+  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
 
@@ -2836,8 +2889,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vmaxs, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2860,8 +2913,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vmaxd, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2898,8 +2951,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vmins, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2922,8 +2975,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vmind, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2952,8 +3005,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vsqrts, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(15.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(15.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -2975,8 +3028,8 @@
 
 
 ASSEMBLER_TEST_RUN(Vsqrtd, test) {
-  typedef int (*SimpleCode)();
-  EXPECT_EQ(15.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry()));
+  typedef double (*DoubleReturn)();
+  EXPECT_EQ(15.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
 
@@ -3030,8 +3083,8 @@
 
 ASSEMBLER_TEST_RUN(Vrecpes, test) {
   EXPECT(test != NULL);
-  typedef double (*Vrecpes)();
-  float res = EXECUTE_TEST_CODE_DOUBLE(Vrecpes, test->entry());
+  typedef double (*DoubleReturn)();
+  float res = EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry());
   EXPECT_FLOAT_EQ(arm_recip_estimate(147.0), res, 0.0001);
 }
 
@@ -3052,8 +3105,8 @@
 
 ASSEMBLER_TEST_RUN(Vrecpss, test) {
   EXPECT(test != NULL);
-  typedef double (*Vrecpss)();
-  double res = EXECUTE_TEST_CODE_DOUBLE(Vrecpss, test->entry());
+  typedef double (*DoubleReturn)();
+  double res = EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry());
   EXPECT_FLOAT_EQ(2.0 - 10.0 * 5.0, res, 0.0001);
 }
 
@@ -3084,8 +3137,8 @@
 
 
 ASSEMBLER_TEST_RUN(VRecps, test) {
-  typedef double (*VRecps)();
-  double res = EXECUTE_TEST_CODE_DOUBLE(VRecps, test->entry());
+  typedef double (*DoubleReturn)();
+  double res = EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry());
   EXPECT_FLOAT_EQ(42.0, res, 0.0001);
 }
 
@@ -3154,8 +3207,8 @@
 
 ASSEMBLER_TEST_RUN(Vrsqrtes, test) {
   EXPECT(test != NULL);
-  typedef double (*Vrsqrtes)();
-  double res = EXECUTE_TEST_CODE_DOUBLE(Vrsqrtes, test->entry());
+  typedef double (*DoubleReturn)();
+  double res = EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry());
   EXPECT_FLOAT_EQ(arm_reciprocal_sqrt_estimate(147.0), res, 0.0001);
 }
 
@@ -3176,8 +3229,8 @@
 
 ASSEMBLER_TEST_RUN(Vrsqrtss, test) {
   EXPECT(test != NULL);
-  typedef double (*Vrsqrtss)();
-  double res = EXECUTE_TEST_CODE_DOUBLE(Vrsqrtss, test->entry());
+  typedef double (*DoubleReturn)();
+  double res = EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry());
   EXPECT_FLOAT_EQ((3.0 - 10.0 * 5.0)/2.0, res, 0.0001);
 }
 
@@ -3195,8 +3248,8 @@
 
 ASSEMBLER_TEST_RUN(ReciprocalSqrt, test) {
   EXPECT(test != NULL);
-  typedef double (*ReciprocalSqrt)();
-  double res = EXECUTE_TEST_CODE_DOUBLE(ReciprocalSqrt, test->entry());
+  typedef double (*DoubleReturn)();
+  double res = EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry());
   EXPECT_FLOAT_EQ(1.0/sqrt(147000.0), res, 0.0001);
 }
 
@@ -3207,6 +3260,7 @@
 // R1: value.
 // R2: growable array.
 ASSEMBLER_TEST_GENERATE(StoreIntoObject, assembler) {
+  __ SetupDartSP(kTestStackSpace);
   __ TagAndPushPP();
   __ LoadPoolPointer(PP);
   __ Push(CTX);
@@ -3218,6 +3272,7 @@
   __ Pop(LR);
   __ Pop(CTX);
   __ PopAndUntagPP();
+  __ mov(CSP, SP);
   __ ret();
 }
 
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index c2f79f6..72706ac 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1533,7 +1533,7 @@
 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) {
   const Field& field = Field::CheckedHandle(arguments.ArgAt(0));
   const Object& value = Object::Handle(arguments.ArgAt(1));
-  field.UpdateGuardedCidAndLength(value);
+  field.RecordStore(value);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index 898c8a4..6fe74ee 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -29,7 +29,7 @@
   R15 = 15,
   R16 = 16,  // IP0 aka TMP
   R17 = 17,  // IP1 aka TMP2
-  R18 = 18,
+  R18 = 18,  // SP in Dart code.
   R19 = 19,
   R20 = 20,
   R21 = 21,
@@ -43,18 +43,19 @@
   R28 = 28,  // CTX
   R29 = 29,  // FP
   R30 = 30,  // LR
-  R31 = 31,  // ZR, SP
+  R31 = 31,  // ZR, CSP
   kNumberOfCpuRegisters = 32,
   kNoRegister = -1,
 
   // These registers both use the encoding R31, but to avoid mistakes we give
   // them different values, and then translate before encoding.
-  SP = 32,
+  CSP = 32,
   ZR = 33,
 
   // Aliases.
   IP0 = R16,
   IP1 = R17,
+  SP = R18,
   FP = R29,
   LR = R30,
 };
@@ -112,7 +113,7 @@
 const Register PP = R27;  // Caches object pool pointer in generated code.
 const Register kNoPP = kNoRegister;
 const Register FPREG = FP;  // Frame pointer register.
-const Register SPREG = R31;  // Stack pointer register.
+const Register SPREG = R18;  // Stack pointer register.
 const Register ICREG = R5;  // IC data register.
 
 // Exception object is passed in this register to the catch handlers when an
@@ -155,20 +156,19 @@
     (1 << R4)  | (1 << R5)  | (1 << R6)  | (1 << R7)  |
     (1 << R8)  | (1 << R9)  | (1 << R10) | (1 << R11) |
     (1 << R12) | (1 << R13) | (1 << R14) | (1 << R15) |
-    (1 << R18) | (1 << R19) | (1 << R20) | (1 << R21) |
-    (1 << R22) | (1 << R23) | (1 << R24) | (1 << R25) |
-    (1 << R26);
+    (1 << R19) | (1 << R20) | (1 << R21) | (1 << R22) |
+    (1 << R23) | (1 << R24) | (1 << R25) | (1 << R26);
 
 // Registers available to Dart that are not preserved by runtime calls.
 const RegList kDartVolatileCpuRegs =
     kDartAvailableCpuRegs & ~kAbiPreservedCpuRegs;
 const Register kDartFirstVolatileCpuReg = R0;
-const Register kDartLastVolatileCpuReg = R18;
-const int kDartVolatileCpuRegCount = 17;  // Excluding R16 and R17.
+const Register kDartLastVolatileCpuReg = R15;
+const int kDartVolatileCpuRegCount = 16;
 const int kDartVolatileFpuRegCount = 24;
 
 static inline Register ConcreteRegister(Register r) {
-  return ((r == ZR) || (r == SP)) ? R31 : r;
+  return ((r == ZR) || (r == CSP)) ? R31 : r;
 }
 
 // Values for the condition field as defined in section A3.2.
@@ -907,10 +907,10 @@
 
   inline bool HasS() const { return (SField() == 1); }
 
-  // Indicate whether Rd can be the SP or ZR. This does not check that the
+  // Indicate whether Rd can be the CSP or ZR. This does not check that the
   // instruction actually has an Rd field.
   R31Type RdMode() const {
-    // The following instructions use SP as Rd:
+    // The following instructions use CSP as Rd:
     //  Add/sub (immediate) when not setting the flags.
     //  Add/sub (extended) when not setting the flags.
     //  Logical (immediate) when not setting the flags.
@@ -926,10 +926,10 @@
     return R31IsZR;
   }
 
-  // Indicate whether Rn can be SP or ZR. This does not check that the
+  // Indicate whether Rn can be CSP or ZR. This does not check that the
   // instruction actually has an Rn field.
   R31Type RnMode() const {
-    // The following instructions use SP as Rn:
+    // The following instructions use CSP as Rn:
     //  All loads and stores.
     //  Add/sub (immediate).
     //  Add/sub (extended).
diff --git a/runtime/vm/cpuinfo.h b/runtime/vm/cpuinfo.h
index b468ee2..3ccf2d4 100644
--- a/runtime/vm/cpuinfo.h
+++ b/runtime/vm/cpuinfo.h
@@ -58,8 +58,11 @@
   // Returns the field describing the CPU model. Caller is responsible for
   // freeing the result.
   static const char* GetCpuModel() {
-    ASSERT(HasField(FieldName(kCpuInfoHardware)));
-    return ExtractField(kCpuInfoHardware);
+    if (HasField(FieldName(kCpuInfoHardware))) {
+      return ExtractField(kCpuInfoHardware);
+    } else {
+      return "";
+    }
   }
 
  private:
diff --git a/runtime/vm/cpuinfo_linux.cc b/runtime/vm/cpuinfo_linux.cc
index 77ace90..0341530 100644
--- a/runtime/vm/cpuinfo_linux.cc
+++ b/runtime/vm/cpuinfo_linux.cc
@@ -28,15 +28,15 @@
   fields_[kCpuInfoFeatures] = "flags";
   method_ = kCpuInfoCpuId;
   CpuId::InitOnce();
-#elif defined(HOST_ARCH_ARM)
+#elif defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64)
+  // TODO(zra): Verify that these field names are correct for arm64.
   fields_[kCpuInfoProcessor] = "Processor";
   fields_[kCpuInfoModel] = "model name";
   fields_[kCpuInfoHardware] = "Hardware";
   fields_[kCpuInfoFeatures] = "Features";
   method_ = kCpuInfoSystem;
   ProcCpuInfo::InitOnce();
-#elif defined(HOST_ARCH_MIPS) || defined(HOST_ARCH_ARM64)
-// TODO(zra): Verify that these field names are correct for arm64.
+#elif defined(HOST_ARCH_MIPS)
   fields_[kCpuInfoProcessor] = "system type";
   fields_[kCpuInfoModel] = "cpu model";
   fields_[kCpuInfoHardware] = "cpu model";
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 6c89434..e849594 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -51,6 +51,7 @@
 Dart_Handle Api::true_handle_ = NULL;
 Dart_Handle Api::false_handle_ = NULL;
 Dart_Handle Api::null_handle_ = NULL;
+Dart_Handle Api::empty_string_handle_ = NULL;
 
 
 const char* CanonicalFunction(const char* func) {
@@ -82,6 +83,26 @@
   return Instance::null();
 }
 
+static RawInstance* GetMapInstance(Isolate* isolate, const Object& obj) {
+  if (obj.IsInstance()) {
+    const Library& core_lib = Library::Handle(Library::CoreLibrary());
+    const Class& map_class =
+        Class::Handle(core_lib.LookupClass(Symbols::Map()));
+    ASSERT(!map_class.IsNull());
+    const Instance& instance = Instance::Cast(obj);
+    const Class& obj_class = Class::Handle(isolate, obj.clazz());
+    Error& malformed_type_error = Error::Handle(isolate);
+    if (obj_class.IsSubtypeOf(TypeArguments::Handle(isolate),
+                              map_class,
+                              TypeArguments::Handle(isolate),
+                              &malformed_type_error)) {
+      ASSERT(malformed_type_error.IsNull());  // Type is a raw Map.
+      return instance.raw();
+    }
+  }
+  return Instance::null();
+}
+
 
 static bool GetNativeStringArgument(NativeArguments* arguments,
                                     int arg_index,
@@ -231,6 +252,40 @@
 }
 
 
+static RawObject* Send0Arg(const Instance& receiver,
+                           const String& selector) {
+  const intptr_t kNumArgs = 1;
+  ArgumentsDescriptor args_desc(
+      Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
+  const Function& function = Function::Handle(
+      Resolver::ResolveDynamic(receiver, selector, args_desc));
+  if (function.IsNull()) {
+    return ApiError::New(String::Handle(String::New("")));
+  }
+  const Array& args = Array::Handle(Array::New(kNumArgs));
+  args.SetAt(0, receiver);
+  return DartEntry::InvokeFunction(function, args);
+}
+
+
+static RawObject* Send1Arg(const Instance& receiver,
+                           const String& selector,
+                           const Instance& argument) {
+  const intptr_t kNumArgs = 2;
+  ArgumentsDescriptor args_desc(
+      Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
+  const Function& function = Function::Handle(
+      Resolver::ResolveDynamic(receiver, selector, args_desc));
+  if (function.IsNull()) {
+    return ApiError::New(String::Handle(String::New("")));
+  }
+  const Array& args = Array::Handle(Array::New(kNumArgs));
+  args.SetAt(0, receiver);
+  args.SetAt(1, argument);
+  return DartEntry::InvokeFunction(function, args);
+}
+
+
 WeakReferenceSetBuilder* ApiState::NewWeakReferenceSetBuilder() {
   return new WeakReferenceSetBuilder(this);
 }
@@ -372,21 +427,6 @@
 }
 
 
-Dart_Handle Api::Null() {
-  return null_handle_;
-}
-
-
-Dart_Handle Api::True() {
-  return true_handle_;
-}
-
-
-Dart_Handle Api::False() {
-  return false_handle_;
-}
-
-
 ApiLocalScope* Api::TopScope(Isolate* isolate) {
   ASSERT(isolate != NULL);
   ApiState* state = isolate->api_state();
@@ -418,6 +458,9 @@
 
   ASSERT(null_handle_ == NULL);
   null_handle_ = Api::InitNewHandle(isolate, Object::null());
+
+  ASSERT(empty_string_handle_ == NULL);
+  empty_string_handle_ = Api::InitNewHandle(isolate, Symbols::Empty().raw());
 }
 
 
@@ -1673,12 +1716,17 @@
 // --- Objects ----
 
 DART_EXPORT Dart_Handle Dart_Null() {
-  Isolate* isolate = Isolate::Current();
-  CHECK_ISOLATE(isolate);
+  ASSERT(Isolate::Current() != NULL);
   return Api::Null();
 }
 
 
+DART_EXPORT Dart_Handle Dart_EmptyString() {
+  ASSERT(Isolate::Current() != NULL);
+  return Api::EmptyString();
+}
+
+
 DART_EXPORT bool Dart_IsNull(Dart_Handle object) {
   return Api::UnwrapHandle(object) == Object::null();
 }
@@ -1810,6 +1858,14 @@
 }
 
 
+DART_EXPORT bool Dart_IsMap(Dart_Handle object) {
+  Isolate* isolate = Isolate::Current();
+  DARTSCOPE(isolate);
+  const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
+  return GetMapInstance(isolate, obj) != Instance::null();
+}
+
+
 DART_EXPORT bool Dart_IsLibrary(Dart_Handle object) {
   TRACE_API_CALL(CURRENT_FUNC);
   return Api::ClassId(object) == kLibraryCid;
@@ -2056,15 +2112,13 @@
 // --- Booleans ----
 
 DART_EXPORT Dart_Handle Dart_True() {
-  Isolate* isolate = Isolate::Current();
-  CHECK_ISOLATE(isolate);
+  ASSERT(Isolate::Current() != NULL);
   return Api::True();
 }
 
 
 DART_EXPORT Dart_Handle Dart_False() {
-  Isolate* isolate = Isolate::Current();
-  CHECK_ISOLATE(isolate);
+  ASSERT(Isolate::Current() != NULL);
   return Api::False();
 }
 
@@ -2505,25 +2559,14 @@
     return list;
   } else {
     CHECK_CALLBACK_STATE(isolate);
-
     // Check and handle a dart object that implements the List interface.
     const Instance& instance =
         Instance::Handle(isolate, GetListInstance(isolate, obj));
     if (!instance.IsNull()) {
-      const int kNumArgs = 2;
-      ArgumentsDescriptor args_desc(
-          Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
-      const Function& function = Function::Handle(
-          isolate,
-          Resolver::ResolveDynamic(instance, Symbols::IndexToken(), args_desc));
-      if (!function.IsNull()) {
-        const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
-        const Integer& indexobj = Integer::Handle(isolate, Integer::New(index));
-        args.SetAt(0, instance);
-        args.SetAt(1, indexobj);
-        return Api::NewHandle(isolate, DartEntry::InvokeFunction(function,
-                                                                 args));
-      }
+      return Api::NewHandle(isolate, Send1Arg(
+          instance,
+          Symbols::IndexToken(),
+          Instance::Handle(isolate, Integer::New(index))));
     }
     return Api::NewError("Object does not implement the 'List' interface");
   }
@@ -2902,6 +2945,71 @@
 }
 
 
+// --- Maps ---
+
+DART_EXPORT Dart_Handle Dart_MapGetAt(Dart_Handle map, Dart_Handle key) {
+  Isolate* isolate = Isolate::Current();
+  DARTSCOPE(isolate);
+  CHECK_CALLBACK_STATE(isolate);
+  const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(map));
+  const Instance& instance =
+      Instance::Handle(isolate, GetMapInstance(isolate, obj));
+  if (!instance.IsNull()) {
+    const Object& key_obj = Object::Handle(Api::UnwrapHandle(key));
+    if (!(key_obj.IsInstance() || key_obj.IsNull())) {
+      return Api::NewError("Key is not an instance");
+    }
+    return Api::NewHandle(isolate, Send1Arg(
+       instance,
+       Symbols::IndexToken(),
+       Instance::Cast(key_obj)));
+  }
+  return Api::NewError("Object does not implement the 'Map' interface");
+}
+
+
+DART_EXPORT Dart_Handle Dart_MapContainsKey(Dart_Handle map, Dart_Handle key) {
+  Isolate* isolate = Isolate::Current();
+  DARTSCOPE(isolate);
+  CHECK_CALLBACK_STATE(isolate);
+  const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(map));
+  const Instance& instance =
+      Instance::Handle(isolate, GetMapInstance(isolate, obj));
+  if (!instance.IsNull()) {
+    const Object& key_obj = Object::Handle(Api::UnwrapHandle(key));
+    if (!(key_obj.IsInstance() || key_obj.IsNull())) {
+      return Api::NewError("Key is not an instance");
+    }
+    return Api::NewHandle(isolate, Send1Arg(
+       instance,
+       String::Handle(isolate, String::New("containsKey")),
+       Instance::Cast(key_obj)));
+  }
+  return Api::NewError("Object does not implement the 'Map' interface");
+}
+
+
+DART_EXPORT Dart_Handle Dart_MapKeys(Dart_Handle map) {
+  Isolate* isolate = Isolate::Current();
+  DARTSCOPE(isolate);
+  CHECK_CALLBACK_STATE(isolate);
+  Object& obj = Object::Handle(isolate, Api::UnwrapHandle(map));
+  Instance& instance =
+      Instance::Handle(isolate, GetMapInstance(isolate, obj));
+  if (!instance.IsNull()) {
+    const Object& iterator = Object::Handle(Send0Arg(
+        instance, String::Handle(String::New("get:keys"))));
+    if (!iterator.IsInstance()) {
+      return Api::NewHandle(isolate, iterator.raw());
+    }
+    return Api::NewHandle(isolate, Send0Arg(
+        Instance::Cast(iterator),
+        String::Handle(String::New("toList"))));
+  }
+  return Api::NewError("Object does not implement the 'Map' interface");
+}
+
+
 // --- Typed Data ---
 
 // Helper method to get the type of a TypedData object.
@@ -3524,7 +3632,7 @@
         if (field.is_static()) {
           continue;
         }
-        field.UpdateGuardedCidAndLength(Object::null_object());
+        field.RecordStore(Object::null_object());
       }
     }
   }
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index 7595911..213590e 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -194,13 +194,24 @@
   static Dart_Handle NewError(const char* format, ...) PRINTF_ATTRIBUTE(1, 2);
 
   // Gets a handle to Null.
-  static Dart_Handle Null();
+  static Dart_Handle Null() {
+    return null_handle_;
+  }
 
   // Gets a handle to True.
-  static Dart_Handle True();
+  static Dart_Handle True() {
+    return true_handle_;
+  }
 
-  // Gets a handle to False
-  static Dart_Handle False();
+  // Gets a handle to False.
+  static Dart_Handle False() {
+    return false_handle_;
+  }
+
+  // Gets a handle to EmptyString.
+  static Dart_Handle EmptyString() {
+    return empty_string_handle_;
+  }
 
   // Retrieves the top ApiLocalScope.
   static ApiLocalScope* TopScope(Isolate* isolate);
@@ -265,6 +276,7 @@
   static Dart_Handle true_handle_;
   static Dart_Handle false_handle_;
   static Dart_Handle null_handle_;
+  static Dart_Handle empty_string_handle_;
 
   friend class ApiNativeScope;
 };
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 00c847f..40fdf74 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -520,6 +520,13 @@
 }
 
 
+TEST_CASE(EmptyString) {
+  Dart_Handle empty = Dart_EmptyString();
+  EXPECT_VALID(empty);
+  EXPECT(!Dart_IsNull(empty));
+}
+
+
 TEST_CASE(IdentityEquals) {
   Dart_Handle five = Dart_NewInteger(5);
   Dart_Handle five_again = Dart_NewInteger(5);
@@ -1285,6 +1292,98 @@
 }
 
 
+TEST_CASE(MapAccess) {
+  const char* kScriptChars =
+      "Map testMain() {"
+      "  return {"
+      "    'a' : 1,"
+      "    'b' : null,"
+      "  };"
+      "}";
+  Dart_Handle result;
+
+  // Create a test library and Load up a test script in it.
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+
+  // Invoke a function which returns an object of type Map.
+  result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
+  EXPECT_VALID(result);
+
+  // First ensure that the returned object is a map.
+  Dart_Handle map = result;
+  Dart_Handle a = NewString("a");
+  Dart_Handle b = NewString("b");
+  Dart_Handle c = NewString("c");
+
+  EXPECT(Dart_IsMap(map));
+  EXPECT(!Dart_IsMap(a));
+
+  // Access values in the map.
+  int64_t value;
+  result = Dart_MapGetAt(map, a);
+  EXPECT_VALID(result);
+  result = Dart_IntegerToInt64(result, &value);
+  EXPECT_VALID(result);
+  EXPECT_EQ(value, 1);
+
+  result = Dart_MapGetAt(map, b);
+  EXPECT(Dart_IsNull(result));
+
+  result = Dart_MapGetAt(map, c);
+  EXPECT(Dart_IsNull(result));
+
+  EXPECT(Dart_IsError(Dart_MapGetAt(a, a)));
+
+  // Test for presence of keys.
+  bool contains = false;
+  result = Dart_MapContainsKey(map, a);
+  EXPECT_VALID(result);
+  result = Dart_BooleanValue(result, &contains);
+  EXPECT_VALID(result);
+  EXPECT(contains);
+
+  contains = false;
+  result = Dart_MapContainsKey(map, NewString("b"));
+  EXPECT_VALID(result);
+  result = Dart_BooleanValue(result, &contains);
+  EXPECT_VALID(result);
+  EXPECT(contains);
+
+  contains = true;
+  result = Dart_MapContainsKey(map, NewString("c"));
+  EXPECT_VALID(result);
+  result = Dart_BooleanValue(result, &contains);
+  EXPECT_VALID(result);
+  EXPECT(!contains);
+
+  EXPECT(Dart_IsError(Dart_MapContainsKey(a, a)));
+
+  // Enumerate keys. (Note literal maps guarantee key order.)
+  Dart_Handle keys = Dart_MapKeys(map);
+  EXPECT_VALID(keys);
+
+  intptr_t len = 0;
+  bool equals;
+  result = Dart_ListLength(keys, &len);
+  EXPECT_VALID(result);
+  EXPECT_EQ(2, len);
+
+  result = Dart_ListGetAt(keys, 0);
+  EXPECT(Dart_IsString(result));
+  equals = false;
+  EXPECT_VALID(Dart_ObjectEquals(result, a, &equals));
+  EXPECT(equals);
+
+  result = Dart_ListGetAt(keys, 1);
+  EXPECT(Dart_IsString(result));
+  equals = false;
+  EXPECT_VALID(Dart_ObjectEquals(result, b, &equals));
+  EXPECT(equals);
+
+  EXPECT(Dart_IsError(Dart_MapKeys(a)));
+}
+
+
 TEST_CASE(TypedDataViewListGetAsBytes) {
   const int kSize = 1000;
 
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 47b580c..f153fb5 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -188,8 +188,7 @@
     case DeoptInstr::kConstant:
     case DeoptInstr::kStackSlot:
     case DeoptInstr::kDoubleStackSlot:
-    case DeoptInstr::kInt64StackSlot:
-    case DeoptInstr::kInt64StackSlotPair:
+    case DeoptInstr::kMintStackSlotPair:
     case DeoptInstr::kFloat32x4StackSlot:
     case DeoptInstr::kInt32x4StackSlot:
     case DeoptInstr::kFloat64x2StackSlot:
@@ -200,8 +199,8 @@
 
     case DeoptInstr::kRegister:
     case DeoptInstr::kFpuRegister:
-    case DeoptInstr::kInt64RegisterPair:
-    case DeoptInstr::kInt64StackSlotRegister:
+    case DeoptInstr::kMintRegisterPair:
+    case DeoptInstr::kMintStackSlotRegister:
     case DeoptInstr::kFloat32x4FpuRegister:
     case DeoptInstr::kInt32x4FpuRegister:
     case DeoptInstr::kFloat64x2FpuRegister:
@@ -441,43 +440,6 @@
 };
 
 
-class DeoptInt64StackSlotInstr : public DeoptInstr {
- public:
-  explicit DeoptInt64StackSlotInstr(intptr_t source_index)
-      : stack_slot_index_(source_index) {
-    ASSERT(stack_slot_index_ >= 0);
-  }
-
-  virtual intptr_t source_index() const { return stack_slot_index_; }
-  virtual DeoptInstr::Kind kind() const { return kInt64StackSlot; }
-
-  virtual const char* ToCString() const {
-    return Isolate::Current()->current_zone()->PrintToString(
-        "int64 stack slot:%" Pd "", stack_slot_index_);
-  }
-
-  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
-    intptr_t source_index =
-       deopt_context->source_frame_size() - stack_slot_index_ - 1;
-    int64_t* source_addr = reinterpret_cast<int64_t*>(
-        deopt_context->GetSourceFrameAddressAt(source_index));
-    *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0);
-    if (Smi::IsValid64(*source_addr)) {
-      *dest_addr = reinterpret_cast<intptr_t>(
-          Smi::New(static_cast<intptr_t>(*source_addr)));
-    } else {
-      deopt_context->DeferMintMaterialization(
-          *source_addr, reinterpret_cast<RawMint**>(dest_addr));
-    }
-  }
-
- private:
-  const intptr_t stack_slot_index_;  // First argument is 0, always >= 0.
-
-  DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotInstr);
-};
-
-
 class DeoptFloat32x4StackSlotInstr : public DeoptInstr {
  public:
   explicit DeoptFloat32x4StackSlotInstr(intptr_t source_index)
@@ -721,9 +683,9 @@
 };
 
 
-class DeoptInt64RegisterPairInstr: public DeoptInstr {
+class DeoptMintRegisterPairInstr: public DeoptInstr {
  public:
-  DeoptInt64RegisterPairInstr(intptr_t lo_reg_as_int, intptr_t hi_reg_as_int)
+  DeoptMintRegisterPairInstr(intptr_t lo_reg_as_int, intptr_t hi_reg_as_int)
       : lo_reg_(static_cast<Register>(lo_reg_as_int)),
         hi_reg_(static_cast<Register>(hi_reg_as_int)) {}
 
@@ -731,7 +693,7 @@
     return EncodeRegisters(static_cast<intptr_t>(lo_reg_),
                            static_cast<intptr_t>(hi_reg_));
   }
-  virtual DeoptInstr::Kind kind() const { return kInt64RegisterPair; }
+  virtual DeoptInstr::Kind kind() const { return kMintRegisterPair; }
 
   virtual const char* ToCString() const {
     return Isolate::Current()->current_zone()->PrintToString(
@@ -774,13 +736,13 @@
   const Register lo_reg_;
   const Register hi_reg_;
 
-  DISALLOW_COPY_AND_ASSIGN(DeoptInt64RegisterPairInstr);
+  DISALLOW_COPY_AND_ASSIGN(DeoptMintRegisterPairInstr);
 };
 
 
-class DeoptInt64StackSlotPairInstr: public DeoptInstr {
+class DeoptMintStackSlotPairInstr: public DeoptInstr {
  public:
-  DeoptInt64StackSlotPairInstr(intptr_t lo_slot, intptr_t hi_slot)
+  DeoptMintStackSlotPairInstr(intptr_t lo_slot, intptr_t hi_slot)
       : lo_slot_(static_cast<Register>(lo_slot)),
         hi_slot_(static_cast<Register>(hi_slot)) {}
 
@@ -788,7 +750,7 @@
     return EncodeSlots(static_cast<intptr_t>(lo_slot_),
                        static_cast<intptr_t>(hi_slot_));
   }
-  virtual DeoptInstr::Kind kind() const { return kInt64StackSlotPair; }
+  virtual DeoptInstr::Kind kind() const { return kMintStackSlotPair; }
 
   virtual const char* ToCString() const {
     return Isolate::Current()->current_zone()->PrintToString(
@@ -836,15 +798,15 @@
   const intptr_t lo_slot_;
   const intptr_t hi_slot_;
 
-  DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotPairInstr);
+  DISALLOW_COPY_AND_ASSIGN(DeoptMintStackSlotPairInstr);
 };
 
 
-class DeoptInt64StackSlotRegisterInstr : public DeoptInstr {
+class DeoptMintStackSlotRegisterInstr : public DeoptInstr {
  public:
-  DeoptInt64StackSlotRegisterInstr(intptr_t source_index,
-                                   intptr_t reg_as_int,
-                                   bool flip)
+  DeoptMintStackSlotRegisterInstr(intptr_t source_index,
+                                  intptr_t reg_as_int,
+                                  bool flip)
       : slot_(source_index),
         reg_(static_cast<Register>(reg_as_int)),
         flip_(flip) {
@@ -857,7 +819,7 @@
                   static_cast<intptr_t>(reg_),
                   flip_ ? 1 : 0);
   }
-  virtual DeoptInstr::Kind kind() const { return kInt64StackSlotRegister; }
+  virtual DeoptInstr::Kind kind() const { return kMintStackSlotRegister; }
 
   virtual const char* ToCString() const {
     if (flip_) {
@@ -924,7 +886,7 @@
   const intptr_t slot_;
   const Register reg_;
   const bool flip_;
-  DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotRegisterInstr);
+  DISALLOW_COPY_AND_ASSIGN(DeoptMintStackSlotRegisterInstr);
 };
 
 
@@ -1305,7 +1267,6 @@
   switch (kind) {
     case kStackSlot: return new DeoptStackSlotInstr(source_index);
     case kDoubleStackSlot: return new DeoptDoubleStackSlotInstr(source_index);
-    case kInt64StackSlot: return new DeoptInt64StackSlotInstr(source_index);
     case kFloat32x4StackSlot:
         return new DeoptFloat32x4StackSlotInstr(source_index);
     case kFloat64x2StackSlot:
@@ -1316,27 +1277,27 @@
     case kConstant: return new DeoptConstantInstr(source_index);
     case kRegister: return new DeoptRegisterInstr(source_index);
     case kFpuRegister: return new DeoptFpuRegisterInstr(source_index);
-    case kInt64RegisterPair: {
+    case kMintRegisterPair: {
       intptr_t lo_reg_as_int =
-          DeoptInt64RegisterPairInstr::LoRegister::decode(source_index);
+          DeoptMintRegisterPairInstr::LoRegister::decode(source_index);
       intptr_t hi_reg_as_int =
-          DeoptInt64RegisterPairInstr::HiRegister::decode(source_index);
-      return new DeoptInt64RegisterPairInstr(lo_reg_as_int, hi_reg_as_int);
+          DeoptMintRegisterPairInstr::HiRegister::decode(source_index);
+      return new DeoptMintRegisterPairInstr(lo_reg_as_int, hi_reg_as_int);
     }
-    case kInt64StackSlotPair: {
+    case kMintStackSlotPair: {
       intptr_t lo_slot =
-          DeoptInt64StackSlotPairInstr::LoSlot::decode(source_index);
+          DeoptMintStackSlotPairInstr::LoSlot::decode(source_index);
       intptr_t hi_slot =
-          DeoptInt64StackSlotPairInstr::HiSlot::decode(source_index);
-      return new DeoptInt64StackSlotPairInstr(lo_slot, hi_slot);
+          DeoptMintStackSlotPairInstr::HiSlot::decode(source_index);
+      return new DeoptMintStackSlotPairInstr(lo_slot, hi_slot);
     }
-    case kInt64StackSlotRegister: {
+    case kMintStackSlotRegister: {
       intptr_t slot =
-          DeoptInt64StackSlotRegisterInstr::Slot::decode(source_index);
+          DeoptMintStackSlotRegisterInstr::Slot::decode(source_index);
       intptr_t reg_as_int =
-          DeoptInt64StackSlotRegisterInstr::Reg::decode(source_index);
-      bool flip = DeoptInt64StackSlotRegisterInstr::Flip::decode(source_index);
-      return new DeoptInt64StackSlotRegisterInstr(slot, reg_as_int, flip);
+          DeoptMintStackSlotRegisterInstr::Reg::decode(source_index);
+      bool flip = DeoptMintStackSlotRegisterInstr::Flip::decode(source_index);
+      return new DeoptMintStackSlotRegisterInstr(slot, reg_as_int, flip);
     }
     case kFloat32x4FpuRegister:
         return new DeoptFloat32x4FpuRegisterInstr(source_index);
@@ -1487,13 +1448,9 @@
     intptr_t source_index = CalculateStackIndex(source_loc);
     deopt_instr = new(isolate()) DeoptStackSlotInstr(source_index);
   } else if (source_loc.IsDoubleStackSlot()) {
+    ASSERT(value->definition()->representation() == kUnboxedDouble);
     intptr_t source_index = CalculateStackIndex(source_loc);
-    if (value->definition()->representation() == kUnboxedDouble) {
-      deopt_instr = new(isolate()) DeoptDoubleStackSlotInstr(source_index);
-    } else {
-      ASSERT(value->definition()->representation() == kUnboxedMint);
-      deopt_instr = new(isolate()) DeoptInt64StackSlotInstr(source_index);
-    }
+    deopt_instr = new(isolate()) DeoptDoubleStackSlotInstr(source_index);
   } else if (source_loc.IsQuadStackSlot()) {
     intptr_t source_index = CalculateStackIndex(source_loc);
     if (value->definition()->representation() == kUnboxedFloat32x4) {
@@ -1515,20 +1472,20 @@
     PairLocation* pair = source_loc.AsPairLocation();
     if (pair->At(0).IsRegister() && pair->At(1).IsRegister()) {
       deopt_instr =
-          new(isolate()) DeoptInt64RegisterPairInstr(pair->At(0).reg(),
-                                                     pair->At(1).reg());
+          new(isolate()) DeoptMintRegisterPairInstr(pair->At(0).reg(),
+                                                    pair->At(1).reg());
     } else if (pair->At(0).IsStackSlot() && pair->At(1).IsStackSlot()) {
-      deopt_instr = new(isolate()) DeoptInt64StackSlotPairInstr(
+      deopt_instr = new(isolate()) DeoptMintStackSlotPairInstr(
           CalculateStackIndex(pair->At(0)),
           CalculateStackIndex(pair->At(1)));
     } else if (pair->At(0).IsRegister() && pair->At(1).IsStackSlot()) {
-      deopt_instr = new(isolate()) DeoptInt64StackSlotRegisterInstr(
+      deopt_instr = new(isolate()) DeoptMintStackSlotRegisterInstr(
           CalculateStackIndex(pair->At(1)),
           pair->At(0).reg(),
           true);
     } else {
       ASSERT(pair->At(0).IsStackSlot() && pair->At(1).IsRegister());
-      deopt_instr = new(isolate()) DeoptInt64StackSlotRegisterInstr(
+      deopt_instr = new(isolate()) DeoptMintStackSlotRegisterInstr(
           CalculateStackIndex(pair->At(0)),
           pair->At(1).reg(),
           false);
diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h
index c287e34..889ce1d 100644
--- a/runtime/vm/deopt_instructions.h
+++ b/runtime/vm/deopt_instructions.h
@@ -224,18 +224,19 @@
     kConstant,
     kRegister,
     kFpuRegister,
-    kInt64RegisterPair,
     kFloat32x4FpuRegister,
     kFloat64x2FpuRegister,
     kInt32x4FpuRegister,
     kStackSlot,
     kDoubleStackSlot,
-    kInt64StackSlot,
-    kInt64StackSlotPair,
     kFloat32x4StackSlot,
     kFloat64x2StackSlot,
     kInt32x4StackSlot,
-    kInt64StackSlotRegister,
+    // Mints are split into low and high words. Each word can be in a register
+    // or stack slot. Note Mints are only used on 32-bit architectures.
+    kMintRegisterPair,
+    kMintStackSlotPair,
+    kMintStackSlotRegister,
     kPcMarker,
     kPp,
     kCallerFp,
diff --git a/runtime/vm/disassembler_arm64.cc b/runtime/vm/disassembler_arm64.cc
index d04a941..6b38b78 100644
--- a/runtime/vm/disassembler_arm64.cc
+++ b/runtime/vm/disassembler_arm64.cc
@@ -87,7 +87,7 @@
 static const char* reg_names[kNumberOfCpuRegisters] = {
   "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
   "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
-  "ip0", "ip1", "r18", "r19", "r20", "r21", "r22", "r23",
+  "ip0", "ip1", "sp", "r19", "r20", "r21", "r22", "r23",
   "r24", "r25", "r26", "pp",  "ctx", "fp",  "lr",  "r31",
 };
 
@@ -97,7 +97,7 @@
   ASSERT(0 <= reg);
   ASSERT(reg < kNumberOfCpuRegisters);
   if (reg == 31) {
-    const char* rstr = (r31t == R31IsZR) ? "zr" : "sp";
+    const char* rstr = (r31t == R31IsZR) ? "zr" : "csp";
     Print(rstr);
   } else {
     Print(reg_names[reg]);
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index ca4b604..c0eff97 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -89,11 +89,14 @@
       : owner_(owner),
         label_(label),
         outer_(owner->nesting_stack_),
-        break_target_(NULL) {
+        break_target_(NULL),
+        try_index_(owner->try_index()) {
     // Push on the owner's nesting stack.
     owner->nesting_stack_ = this;
   }
 
+  intptr_t try_index() const { return try_index_; }
+
   virtual ~NestedStatement() {
     // Pop from the owner's nesting stack.
     ASSERT(owner_->nesting_stack_ == this);
@@ -106,6 +109,7 @@
   NestedStatement* outer_;
 
   JoinEntryInstr* break_target_;
+  intptr_t try_index_;
 };
 
 
@@ -181,7 +185,7 @@
   if (label != this->label()) return NULL;
   if (continue_target_ == NULL) {
     continue_target_ =
-        new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
+        new JoinEntryInstr(owner()->AllocateBlockId(), try_index());
   }
   return continue_target_;
 }
@@ -224,7 +228,7 @@
     if (label != case_labels_[i]) continue;
     if (case_targets_[i] == NULL) {
       case_targets_[i] =
-          new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
+          new JoinEntryInstr(owner()->AllocateBlockId(), try_index());
     }
     return case_targets_[i];
   }
@@ -3183,9 +3187,18 @@
   }
 
   store_value = Bind(BuildStoreExprTemp(store_value));
-  GuardFieldInstr* guard =
-      new GuardFieldInstr(store_value, node->field(), I->GetNextDeoptId());
-  AddInstruction(guard);
+  GuardFieldClassInstr* guard_field_class =
+      new GuardFieldClassInstr(store_value,
+                               node->field(),
+                               I->GetNextDeoptId());
+  AddInstruction(guard_field_class);
+
+  store_value = Bind(BuildLoadExprTemp());
+  GuardFieldLengthInstr* guard_field_length =
+      new GuardFieldLengthInstr(store_value,
+                                node->field(),
+                                I->GetNextDeoptId());
+  AddInstruction(guard_field_length);
 
   store_value = Bind(BuildLoadExprTemp());
   StoreInstanceFieldInstr* store =
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 063415f..3a6c97e 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -256,11 +256,10 @@
       AddCurrentDescriptor(PcDescriptors::kDeopt,
                            assert->deopt_id(),
                            assert->token_pos());
-    } else if (instr->IsGuardField() ||
-               (instr->CanBecomeDeoptimizationTarget() && !instr->IsGoto())) {
-      // GuardField and instructions that can be deoptimization targets need
-      // to record their deopt id.  GotoInstr records its own so that it can
-      // control the placement.
+    } else if (instr->CanBecomeDeoptimizationTarget() && !instr->IsGoto()) {
+      // Instructions that can be deoptimization targets need to record kDeopt
+      // PcDescriptor corresponding to their deopt id. GotoInstr records its
+      // own so that it can control the placement.
       AddCurrentDescriptor(PcDescriptors::kDeopt,
                            instr->deopt_id(),
                            Scanner::kNoSourcePos);
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 7e46f82..542ac99 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -1281,8 +1281,7 @@
   // be invoked as a normal Dart function.
   __ add(IP, R2, Operand(R3, LSL, 2));
   __ ldr(R0, FieldAddress(IP, base + kWordSize));
-  __ ldr(R1, FieldAddress(R0, Function::code_offset()));
-  __ ldr(R1, FieldAddress(R1, Code::instructions_offset()));
+  __ ldr(R1, FieldAddress(R0, Function::instructions_offset()));
   __ LoadObject(R5, ic_data);
   __ LoadObject(R4, arguments_descriptor);
   __ AddImmediate(R1, Instructions::HeaderSize() - kHeapObjectTag);
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc
index 0bc1a5e..c4ac888 100644
--- a/runtime/vm/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/flow_graph_compiler_arm64.cc
@@ -1287,8 +1287,7 @@
   // be invoked as a normal Dart function.
   __ add(TMP, R2, Operand(R3, LSL, 3));
   __ LoadFieldFromOffset(R0, TMP, base + kWordSize, PP);
-  __ LoadFieldFromOffset(R1, R0, Function::code_offset(), PP);
-  __ LoadFieldFromOffset(R1, R1, Code::instructions_offset(), PP);
+  __ LoadFieldFromOffset(R1, R0, Function::instructions_offset(), PP);
   __ LoadObject(R5, ic_data, PP);
   __ LoadObject(R4, arguments_descriptor, PP);
   __ AddImmediate(R1, R1, Instructions::HeaderSize() - kHeapObjectTag, PP);
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 3394965..b58ded0 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -1325,8 +1325,7 @@
   // illegal class id was found, the target is a cache miss handler that can
   // be invoked as a normal Dart function.
   __ movl(EAX, FieldAddress(EDI, ECX, TIMES_4, base + kWordSize));
-  __ movl(EBX, FieldAddress(EAX, Function::code_offset()));
-  __ movl(EBX, FieldAddress(EBX, Code::instructions_offset()));
+  __ movl(EBX, FieldAddress(EAX, Function::instructions_offset()));
   __ LoadObject(ECX, ic_data);
   __ LoadObject(EDX, arguments_descriptor);
   __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 319c7ad..68538fe 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -1323,8 +1323,7 @@
   __ addu(T1, T2, T1);
   __ lw(T0, FieldAddress(T1, base + kWordSize));
 
-  __ lw(T1, FieldAddress(T0, Function::code_offset()));
-  __ lw(T1, FieldAddress(T1, Code::instructions_offset()));
+  __ lw(T1, FieldAddress(T0, Function::instructions_offset()));
   __ LoadObject(S5, ic_data);
   __ LoadObject(S4, arguments_descriptor);
   __ AddImmediate(T1, Instructions::HeaderSize() - kHeapObjectTag);
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 06c1ebd..be3a6b0 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -1364,8 +1364,7 @@
   // illegal class id was found, the target is a cache miss handler that can
   // be invoked as a normal Dart function.
   __ movq(RAX, FieldAddress(RDI, RCX, TIMES_8, base + kWordSize));
-  __ movq(RCX, FieldAddress(RAX, Function::code_offset()));
-  __ movq(RCX, FieldAddress(RCX, Code::instructions_offset()));
+  __ movq(RCX, FieldAddress(RAX, Function::instructions_offset()));
   __ LoadObject(RBX, ic_data, PP);
   __ LoadObject(R10, arguments_descriptor, PP);
   __ AddImmediate(
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 2eb069e..1dc4c07 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -4529,7 +4529,17 @@
 
   if (field.guarded_cid() != kDynamicCid) {
     InsertBefore(instr,
-                 new(isolate()) GuardFieldInstr(
+                 new(isolate()) GuardFieldClassInstr(
+                     new(isolate()) Value(instr->ArgumentAt(1)),
+                      field,
+                      instr->deopt_id()),
+                 instr->env(),
+                 FlowGraph::kEffect);
+  }
+
+  if (field.needs_length_check()) {
+    InsertBefore(instr,
+                 new(isolate()) GuardFieldLengthInstr(
                      new(isolate()) Value(instr->ArgumentAt(1)),
                       field,
                       instr->deopt_id()),
@@ -7882,7 +7892,9 @@
 
 void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) { }
 
-void ConstantPropagator::VisitGuardField(GuardFieldInstr* instr) { }
+void ConstantPropagator::VisitGuardFieldClass(GuardFieldClassInstr* instr) { }
+
+void ConstantPropagator::VisitGuardFieldLength(GuardFieldLengthInstr* instr) { }
 
 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) { }
 
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index 282972f..179cdee 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -276,7 +276,8 @@
 }
 
 
-void FlowGraphTypePropagator::VisitGuardField(GuardFieldInstr* guard) {
+void FlowGraphTypePropagator::VisitGuardFieldClass(
+    GuardFieldClassInstr* guard) {
   const intptr_t cid = guard->field().guarded_cid();
   if ((cid == kIllegalCid) || (cid == kDynamicCid)) {
     return;
diff --git a/runtime/vm/flow_graph_type_propagator.h b/runtime/vm/flow_graph_type_propagator.h
index f445868..95b19bf 100644
--- a/runtime/vm/flow_graph_type_propagator.h
+++ b/runtime/vm/flow_graph_type_propagator.h
@@ -29,7 +29,7 @@
   virtual void VisitJoinEntry(JoinEntryInstr* instr);
   virtual void VisitCheckSmi(CheckSmiInstr* instr);
   virtual void VisitCheckClass(CheckClassInstr* instr);
-  virtual void VisitGuardField(GuardFieldInstr* instr);
+  virtual void VisitGuardFieldClass(GuardFieldClassInstr* instr);
 
   // Current reaching type of the definition. Valid only during dominator tree
   // traversal.
diff --git a/runtime/vm/gc_marker.cc b/runtime/vm/gc_marker.cc
index 1e9eab5..7bf9e35 100644
--- a/runtime/vm/gc_marker.cc
+++ b/runtime/vm/gc_marker.cc
@@ -244,12 +244,13 @@
   void DetachCode() {
     for (int i = 0; i < skipped_code_functions_.length(); i++) {
       RawFunction* func = skipped_code_functions_[i];
-      RawCode* code = func->ptr()->code_;
+      RawCode* code = func->ptr()->instructions_->ptr()->code_;
       if (!code->IsMarked()) {
         // If the code wasn't strongly visited through other references
         // after skipping the function's code pointer, then we disconnect the
         // code from the function.
-        func->ptr()->code_ = StubCode::LazyCompile_entry()->code();
+        func->ptr()->instructions_ =
+            StubCode::LazyCompile_entry()->code()->ptr()->instructions_;
         func->ptr()->unoptimized_code_ = Code::null();
         if (FLAG_log_code_drop) {
           // NOTE: This code runs while GC is in progress and runs within
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index 9a2002e..1ea3469 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -439,17 +439,9 @@
 
 
 void GuardFieldInstr::PrintOperandsTo(BufferFormatter* f) const {
-  const char* expected = "?";
-  if (field().guarded_cid() != kIllegalCid) {
-    const Class& cls = Class::Handle(
-            Isolate::Current()->class_table()->At(field().guarded_cid()));
-    expected = String::Handle(cls.Name()).ToCString();
-  }
-
-  f->Print("%s [%s %s], ",
+  f->Print("%s %s, ",
            String::Handle(field().name()).ToCString(),
-           field().is_nullable() ? "nullable" : "non-nullable",
-           expected);
+           field().GuardedPropertiesAsCString());
   value()->PrintTo(f);
 }
 
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index fb04faa..ea4f0ba 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -219,8 +219,13 @@
 }
 
 
-bool GuardFieldInstr::AttributesEqual(Instruction* other) const {
-  return field().raw() == other->AsGuardField()->field().raw();
+bool GuardFieldClassInstr::AttributesEqual(Instruction* other) const {
+  return field().raw() == other->AsGuardFieldClass()->field().raw();
+}
+
+
+bool GuardFieldLengthInstr::AttributesEqual(Instruction* other) const {
+  return field().raw() == other->AsGuardFieldLength()->field().raw();
 }
 
 
@@ -1954,9 +1959,6 @@
 
 
 Instruction* CheckClassInstr::Canonicalize(FlowGraph* flow_graph) {
-  // TODO(vegorov): Replace class checks with null checks when ToNullableCid
-  // matches.
-
   const intptr_t value_cid = value()->Type()->ToCid();
   if (value_cid == kDynamicCid) {
     return this;
@@ -1966,32 +1968,11 @@
 }
 
 
-Instruction* GuardFieldInstr::Canonicalize(FlowGraph* flow_graph) {
+Instruction* GuardFieldClassInstr::Canonicalize(FlowGraph* flow_graph) {
   if (field().guarded_cid() == kDynamicCid) {
     return NULL;  // Nothing to guard.
   }
 
-  if (field().guarded_list_length() != Field::kNoFixedLength) {
-    // We are still guarding the list length. Check if length is statically
-    // known.
-    StaticCallInstr* call = value()->definition()->AsStaticCall();
-    if (call != NULL) {
-      ConstantInstr* length = NULL;
-      if (call->is_known_list_constructor() &&
-          LoadFieldInstr::IsFixedLengthArrayCid(call->Type()->ToCid())) {
-        length = call->ArgumentAt(1)->AsConstant();
-      }
-      if (call->is_native_list_factory()) {
-        length = call->ArgumentAt(0)->AsConstant();
-      }
-      if ((length != NULL) && length->value().IsSmi()) {
-        intptr_t known_length = Smi::Cast(length->value()).Value();
-        return (known_length != field().guarded_list_length()) ? this : NULL;
-      }
-    }
-    return this;
-  }
-
   if (field().is_nullable() && value()->Type()->IsNull()) {
     return NULL;
   }
@@ -2006,6 +1987,40 @@
 }
 
 
+Instruction* GuardFieldLengthInstr::Canonicalize(FlowGraph* flow_graph) {
+  if (!field().needs_length_check()) {
+    return NULL;  // Nothing to guard.
+  }
+
+  const intptr_t expected_length = field().guarded_list_length();
+  if (expected_length == Field::kUnknownFixedLength) {
+    return this;
+  }
+
+  // Check if length is statically known.
+  StaticCallInstr* call = value()->definition()->AsStaticCall();
+  if (call == NULL) {
+    return this;
+  }
+
+  ConstantInstr* length = NULL;
+  if (call->is_known_list_constructor() &&
+      LoadFieldInstr::IsFixedLengthArrayCid(call->Type()->ToCid())) {
+    length = call->ArgumentAt(1)->AsConstant();
+  }
+  if (call->is_native_list_factory()) {
+    length = call->ArgumentAt(0)->AsConstant();
+  }
+  if ((length != NULL) &&
+      length->value().IsSmi() &&
+      Smi::Cast(length->value()).Value() == expected_length) {
+    return NULL;  // Expected length matched.
+  }
+
+  return this;
+}
+
+
 Instruction* CheckSmiInstr::Canonicalize(FlowGraph* flow_graph) {
   return (value()->Type()->ToCid() == kSmiCid) ?  NULL : this;
 }
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index bc2b3cf..d813c15 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -747,7 +747,8 @@
   M(StringInterpolate)                                                         \
   M(InvokeMathCFunction)                                                       \
   M(MergedMath)                                                                \
-  M(GuardField)                                                                \
+  M(GuardFieldClass)                                                           \
+  M(GuardFieldLength)                                                          \
   M(IfThenElse)                                                                \
   M(BinaryFloat32x4Op)                                                         \
   M(Simd32x4Shuffle)                                                           \
@@ -3815,23 +3816,22 @@
 
   const Field& field() const { return field_; }
 
-  DECLARE_INSTRUCTION(GuardField)
-
   virtual intptr_t ArgumentCount() const { return 0; }
 
   virtual bool CanDeoptimize() const { return true; }
-
-  virtual Instruction* Canonicalize(FlowGraph* flow_graph);
-
-  virtual void PrintOperandsTo(BufferFormatter* f) const;
+  virtual bool CanBecomeDeoptimizationTarget() const {
+    // Ensure that we record kDeopt PC descriptor in unoptimized code.
+    return true;
+  }
 
   virtual bool AllowsCSE() const { return true; }
   virtual EffectSet Effects() const { return EffectSet::None(); }
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
-  virtual bool AttributesEqual(Instruction* other) const;
 
   virtual bool MayThrow() const { return false; }
 
+  virtual void PrintOperandsTo(BufferFormatter* f) const;
+
  private:
   const Field& field_;
 
@@ -3839,6 +3839,42 @@
 };
 
 
+class GuardFieldClassInstr : public GuardFieldInstr {
+ public:
+  GuardFieldClassInstr(Value* value,
+                       const Field& field,
+                       intptr_t deopt_id)
+    : GuardFieldInstr(value, field, deopt_id) { }
+
+  DECLARE_INSTRUCTION(GuardFieldClass)
+
+  virtual Instruction* Canonicalize(FlowGraph* flow_graph);
+
+  virtual bool AttributesEqual(Instruction* other) const;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(GuardFieldClassInstr);
+};
+
+
+class GuardFieldLengthInstr : public GuardFieldInstr {
+ public:
+  GuardFieldLengthInstr(Value* value,
+                       const Field& field,
+                       intptr_t deopt_id)
+    : GuardFieldInstr(value, field, deopt_id) { }
+
+  DECLARE_INSTRUCTION(GuardFieldLength)
+
+  virtual Instruction* Canonicalize(FlowGraph* flow_graph);
+
+  virtual bool AttributesEqual(Instruction* other) const;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(GuardFieldLengthInstr);
+};
+
+
 class LoadStaticFieldInstr : public TemplateDefinition<1> {
  public:
   explicit LoadStaticFieldInstr(Value* field_value) {
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 6312efa..5be62b3 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -211,12 +211,11 @@
   // R4: Arguments descriptor.
   // R0: Function.
   ASSERT(locs()->in(0).reg() == R0);
-  __ ldr(R2, FieldAddress(R0, Function::code_offset()));
+  __ ldr(R2, FieldAddress(R0, Function::instructions_offset()));
 
-  // R2: code.
+  // R2: instructions.
   // R5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
   __ LoadImmediate(R5, 0);
-  __ ldr(R2, FieldAddress(R2, Code::instructions_offset()));
   __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag);
   __ blx(R2);
   compiler->AddCurrentDescriptor(PcDescriptors::kClosureCall,
@@ -1596,50 +1595,65 @@
 }
 
 
-LocationSummary* GuardFieldInstr::MakeLocationSummary(Isolate* isolate,
-                                                      bool opt) const {
+LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Isolate* isolate,
+                                                           bool opt) const {
   const intptr_t kNumInputs = 1;
-  LocationSummary* summary = new(isolate) LocationSummary(
-      isolate, kNumInputs, 0, LocationSummary::kNoCall);
-  summary->set_in(0, Location::RequiresRegister());
-  const bool field_has_length = field().needs_length_check();
-  summary->AddTemp(Location::RequiresRegister());
-  summary->AddTemp(Location::RequiresRegister());
-  const bool need_field_temp_reg =
-      field_has_length || (field().guarded_cid() == kIllegalCid);
-  if (need_field_temp_reg) {
-    summary->AddTemp(Location::RequiresRegister());
+
+  const intptr_t value_cid = value()->Type()->ToCid();
+  const intptr_t field_cid = field().guarded_cid();
+
+  const bool emit_full_guard =
+      !opt || (field_cid == kIllegalCid);
+
+  const bool needs_value_cid_temp_reg = emit_full_guard ||
+      ((value_cid == kDynamicCid) && (field_cid != kSmiCid));
+
+  const bool needs_field_temp_reg = emit_full_guard;
+
+  intptr_t num_temps = 0;
+  if (needs_value_cid_temp_reg) {
+    num_temps++;
   }
+  if (needs_field_temp_reg) {
+    num_temps++;
+  }
+
+  LocationSummary* summary = new(isolate) LocationSummary(
+      isolate, kNumInputs, num_temps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+
+  for (intptr_t i = 0; i < num_temps; i++) {
+    summary->set_temp(i, Location::RequiresRegister());
+  }
+
   return summary;
 }
 
 
-void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t field_cid = field().guarded_cid();
   const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
-  const intptr_t field_length = field().guarded_list_length();
-  const bool field_has_length = field().needs_length_check();
-  const bool needs_field_temp_reg =
-      field_has_length || (field().guarded_cid() == kIllegalCid);
-  if (field_has_length) {
-    // Currently, we should only see final fields that remember length.
-    ASSERT(field().is_final());
-  }
 
   if (field_cid == kDynamicCid) {
     ASSERT(!compiler->is_optimizing());
     return;  // Nothing to emit.
   }
 
-  const intptr_t value_cid = value()->Type()->ToCid();
+  const bool emit_full_guard =
+      !compiler->is_optimizing() || (field_cid == kIllegalCid);
+
+  const bool needs_value_cid_temp_reg = emit_full_guard ||
+      ((value_cid == kDynamicCid) && (field_cid != kSmiCid));
+
+  const bool needs_field_temp_reg = emit_full_guard;
 
   const Register value_reg = locs()->in(0).reg();
 
-  const Register value_cid_reg = locs()->temp(0).reg();
+  const Register value_cid_reg = needs_value_cid_temp_reg ?
+      locs()->temp(0).reg() : kNoRegister;
 
-  const Register temp_reg = locs()->temp(1).reg();
-
-  Register field_reg = needs_field_temp_reg ?
+  const Register field_reg = needs_field_temp_reg ?
       locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister;
 
   Label ok, fail_label;
@@ -1649,194 +1663,59 @@
 
   Label* fail = (deopt != NULL) ? deopt : &fail_label;
 
-  if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) {
-    if (!compiler->is_optimizing() && (field_reg == kNoRegister)) {
-      // Currently we can't have different location summaries for optimized
-      // and non-optimized code. So instead we manually pick up a register
-      // that is known to be free because we know how non-optimizing compiler
-      // allocates registers.
-      field_reg = R2;
-      ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg));
-    }
-
+  if (emit_full_guard) {
     __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
 
     FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
     FieldAddress field_nullability_operand(
         field_reg, Field::is_nullable_offset());
-    FieldAddress field_length_operand(
-        field_reg, Field::guarded_list_length_offset());
-
-    ASSERT(value_cid_reg != kNoRegister);
-    ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
 
     if (value_cid == kDynamicCid) {
       LoadValueCid(compiler, value_cid_reg, value_reg);
-      Label skip_length_check;
       __ ldr(IP, field_cid_operand);
       __ cmp(value_cid_reg, Operand(IP));
-      __ b(&skip_length_check, NE);
-      if (field_has_length) {
-        ASSERT(temp_reg != kNoRegister);
-        // Field guard may have remembered list length, check it.
-        if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
-          __ ldr(temp_reg,
-                 FieldAddress(value_reg, Array::length_offset()));
-          __ CompareImmediate(temp_reg, Smi::RawValue(field_length));
-        } else if (RawObject::IsTypedDataClassId(field_cid)) {
-          __ ldr(temp_reg,
-                 FieldAddress(value_reg, TypedData::length_offset()));
-          __ CompareImmediate(temp_reg, Smi::RawValue(field_length));
-        } else {
-          ASSERT(field_cid == kIllegalCid);
-          ASSERT(field_length == Field::kUnknownFixedLength);
-          // At compile time we do not know the type of the field nor its
-          // length. At execution time we may have set the class id and
-          // list length so we compare the guarded length with the
-          // list length here, without this check the list length could change
-          // without triggering a deoptimization.
-          Label check_array, length_compared, no_fixed_length;
-          // If length is negative the length guard is either disabled or
-          // has not been initialized, either way it is safe to skip the
-          // length check.
-          __ ldr(IP, field_length_operand);
-          __ CompareImmediate(IP, 0);
-          __ b(&skip_length_check, LT);
-          __ CompareImmediate(value_cid_reg, kNullCid);
-          __ b(&no_fixed_length, EQ);
-          // Check for typed data array.
-          __ CompareImmediate(value_cid_reg, kTypedDataInt32x4ArrayCid);
-          __ b(&no_fixed_length, GT);
-          __ CompareImmediate(value_cid_reg, kTypedDataInt8ArrayCid);
-          // Could still be a regular array.
-          __ b(&check_array, LT);
-          __ ldr(temp_reg,
-                 FieldAddress(value_reg, TypedData::length_offset()));
-          __ ldr(IP, field_length_operand);
-          __ cmp(temp_reg, Operand(IP));
-          __ b(&length_compared);
-          // Check for regular array.
-          __ Bind(&check_array);
-          __ CompareImmediate(value_cid_reg, kImmutableArrayCid);
-          __ b(&no_fixed_length, GT);
-          __ CompareImmediate(value_cid_reg, kArrayCid);
-          __ b(&no_fixed_length, LT);
-          __ ldr(temp_reg,
-                 FieldAddress(value_reg, Array::length_offset()));
-          __ ldr(IP, field_length_operand);
-          __ cmp(temp_reg, Operand(IP));
-          __ b(&length_compared);
-          __ Bind(&no_fixed_length);
-          __ b(fail);
-          __ Bind(&length_compared);
-          // Following branch cannot not occur, fall through.
-        }
-        __ b(fail, NE);
-      }
-      __ Bind(&skip_length_check);
+      __ b(&ok, EQ);
       __ ldr(IP, field_nullability_operand);
       __ cmp(value_cid_reg, Operand(IP));
     } else if (value_cid == kNullCid) {
       __ ldr(value_cid_reg, field_nullability_operand);
       __ CompareImmediate(value_cid_reg, value_cid);
     } else {
-      Label skip_length_check;
       __ ldr(value_cid_reg, field_cid_operand);
       __ CompareImmediate(value_cid_reg, value_cid);
-      __ b(&skip_length_check, NE);
-      if (field_has_length) {
-        ASSERT(value_cid_reg != kNoRegister);
-        ASSERT(temp_reg != kNoRegister);
-        if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
-          __ ldr(temp_reg,
-                  FieldAddress(value_reg, Array::length_offset()));
-          __ CompareImmediate(temp_reg, Smi::RawValue(field_length));
-        } else if (RawObject::IsTypedDataClassId(value_cid)) {
-          __ ldr(temp_reg,
-                  FieldAddress(value_reg, TypedData::length_offset()));
-          __ CompareImmediate(temp_reg, Smi::RawValue(field_length));
-        } else if (field_cid != kIllegalCid) {
-          ASSERT(field_cid != value_cid);
-          ASSERT(field_length >= 0);
-          // Field has a known class id and length. At compile time it is
-          // known that the value's class id is not a fixed length list.
-          __ b(fail);
-        } else {
-          ASSERT(field_cid == kIllegalCid);
-          ASSERT(field_length == Field::kUnknownFixedLength);
-          // Following jump cannot not occur, fall through.
-        }
-        __ b(fail, NE);
-      }
-      // Not identical, possibly null.
-      __ Bind(&skip_length_check);
     }
     __ b(&ok, EQ);
 
-    __ ldr(IP, field_cid_operand);
-    __ CompareImmediate(IP, kIllegalCid);
-    __ b(fail, NE);
+    // Check if the tracked state of the guarded field can be initialized
+    // inline. If the field needs length check we fall through to runtime
+    // which is responsible for computing offset of the length field
+    // based on the class id.
+    // Length guard will be emitted separately when needed via GuardFieldLength
+    // instruction after GuardFieldClass.
+    if (!field().needs_length_check()) {
+      // Uninitialized field can be handled inline. Check if the
+      // field is still unitialized.
+      __ ldr(IP, field_cid_operand);
+      __ CompareImmediate(IP, kIllegalCid);
+      __ b(fail, NE);
 
-    if (value_cid == kDynamicCid) {
-      __ str(value_cid_reg, field_cid_operand);
-      __ str(value_cid_reg, field_nullability_operand);
-      if (field_has_length) {
-        Label check_array, length_set, no_fixed_length;
-        __ CompareImmediate(value_cid_reg, kNullCid);
-        __ b(&no_fixed_length, EQ);
-        // Check for typed data array.
-        __ CompareImmediate(value_cid_reg, kTypedDataInt32x4ArrayCid);
-        __ b(&no_fixed_length, GT);
-        __ CompareImmediate(value_cid_reg, kTypedDataInt8ArrayCid);
-        // Could still be a regular array.
-        __ b(&check_array, LT);
-        // Destroy value_cid_reg (safe because we are finished with it).
-        __ ldr(value_cid_reg,
-               FieldAddress(value_reg, TypedData::length_offset()));
-        __ str(value_cid_reg, field_length_operand);
-        __ b(&length_set);  // Updated field length typed data array.
-        // Check for regular array.
-        __ Bind(&check_array);
-        __ CompareImmediate(value_cid_reg, kImmutableArrayCid);
-        __ b(&no_fixed_length, GT);
-        __ CompareImmediate(value_cid_reg, kArrayCid);
-        __ b(&no_fixed_length, LT);
-        // Destroy value_cid_reg (safe because we are finished with it).
-        __ ldr(value_cid_reg,
-               FieldAddress(value_reg, Array::length_offset()));
-        __ str(value_cid_reg, field_length_operand);
-        // Updated field length from regular array.
-        __ b(&length_set);
-        __ Bind(&no_fixed_length);
-        __ LoadImmediate(IP, Smi::RawValue(Field::kNoFixedLength));
-        __ str(IP, field_length_operand);
-        __ Bind(&length_set);
+      if (value_cid == kDynamicCid) {
+        __ str(value_cid_reg, field_cid_operand);
+        __ str(value_cid_reg, field_nullability_operand);
+      } else {
+        __ LoadImmediate(IP, value_cid);
+        __ str(IP, field_cid_operand);
+        __ str(IP, field_nullability_operand);
       }
-    } else {
-      __ LoadImmediate(IP, value_cid);
-      __ str(IP, field_cid_operand);
-      __ str(IP, field_nullability_operand);
-      if (field_has_length) {
-        if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ ldr(value_cid_reg,
-                 FieldAddress(value_reg, Array::length_offset()));
-          __ str(value_cid_reg, field_length_operand);
-        } else if (RawObject::IsTypedDataClassId(value_cid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ ldr(value_cid_reg,
-                  FieldAddress(value_reg, TypedData::length_offset()));
-          __ str(value_cid_reg, field_length_operand);
-        } else {
-          __ LoadImmediate(IP, Smi::RawValue(Field::kNoFixedLength));
-          __ str(IP, field_length_operand);
-        }
+
+      if (deopt == NULL) {
+        ASSERT(!compiler->is_optimizing());
+        __ b(&ok);
       }
     }
 
     if (deopt == NULL) {
       ASSERT(!compiler->is_optimizing());
-      __ b(&ok);
       __ Bind(fail);
 
       __ ldr(IP, FieldAddress(field_reg, Field::guarded_cid_offset()));
@@ -1851,10 +1730,8 @@
   } else {
     ASSERT(compiler->is_optimizing());
     ASSERT(deopt != NULL);
+
     // Field guard class has been initialized and is known.
-    if (field_reg != kNoRegister) {
-      __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
-    }
     if (value_cid == kDynamicCid) {
       // Field's guarded class id is fixed by value's class id is not known.
       __ tst(value_reg, Operand(kSmiTagMask));
@@ -1865,58 +1742,119 @@
         __ CompareImmediate(value_cid_reg, field_cid);
       }
 
-      if (field_has_length) {
-        __ b(fail, NE);
-        // Classes are same, perform guarded list length check.
-        ASSERT(field_reg != kNoRegister);
-        ASSERT(value_cid_reg != kNoRegister);
-        FieldAddress field_length_operand(
-            field_reg, Field::guarded_list_length_offset());
-        if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ ldr(value_cid_reg,
-                 FieldAddress(value_reg, Array::length_offset()));
-        } else if (RawObject::IsTypedDataClassId(field_cid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ ldr(value_cid_reg,
-                 FieldAddress(value_reg, TypedData::length_offset()));
-        }
-        __ ldr(IP, field_length_operand);
-        __ cmp(value_cid_reg, Operand(IP));
-      }
-
       if (field().is_nullable() && (field_cid != kNullCid)) {
         __ b(&ok, EQ);
-        __ CompareImmediate(value_reg,
-                            reinterpret_cast<intptr_t>(Object::null()));
+        if (field_cid != kSmiCid) {
+          __ CompareImmediate(value_cid_reg, kNullCid);
+        } else {
+          __ CompareImmediate(value_reg,
+                              reinterpret_cast<intptr_t>(Object::null()));
+        }
       }
       __ b(fail, NE);
     } else {
       // Both value's and field's class id is known.
-      if ((value_cid != field_cid) && (value_cid != nullability)) {
-        __ b(fail);
-      } else if (field_has_length && (value_cid == field_cid)) {
-        ASSERT(value_cid_reg != kNoRegister);
-        if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ ldr(value_cid_reg,
-                 FieldAddress(value_reg, Array::length_offset()));
-        } else if (RawObject::IsTypedDataClassId(field_cid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ ldr(value_cid_reg,
-                 FieldAddress(value_reg, TypedData::length_offset()));
-        }
-        __ CompareImmediate(value_cid_reg, field_length);
-        __ b(fail, NE);
-      } else {
-        UNREACHABLE();
-      }
+      ASSERT((value_cid != field_cid) && (value_cid != nullability));
+      __ b(fail);
     }
   }
   __ Bind(&ok);
 }
 
 
+LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Isolate* isolate,
+                                                            bool opt) const {
+  const intptr_t kNumInputs = 1;
+  if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) {
+    const intptr_t kNumTemps = 3;
+    LocationSummary* summary = new(isolate) LocationSummary(
+        isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    summary->set_in(0, Location::RequiresRegister());
+    // We need temporaries for field object, length offset and expected length.
+    summary->set_temp(0, Location::RequiresRegister());
+    summary->set_temp(1, Location::RequiresRegister());
+    summary->set_temp(2, Location::RequiresRegister());
+    return summary;
+  } else {
+    // TODO(vegorov): can use TMP when length is small enough to fit into
+    // immediate.
+    const intptr_t kNumTemps = 1;
+    LocationSummary* summary = new(isolate) LocationSummary(
+        isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    summary->set_in(0, Location::RequiresRegister());
+    summary->set_temp(0, Location::RequiresRegister());
+    return summary;
+  }
+  UNREACHABLE();
+}
+
+
+void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (field().guarded_list_length() == Field::kNoFixedLength) {
+    ASSERT(!compiler->is_optimizing());
+    return;  // Nothing to emit.
+  }
+
+  Label* deopt = compiler->is_optimizing() ?
+      compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL;
+
+  const Register value_reg = locs()->in(0).reg();
+
+  if (!compiler->is_optimizing() ||
+      (field().guarded_list_length() == Field::kUnknownFixedLength)) {
+    const Register field_reg = locs()->temp(0).reg();
+    const Register offset_reg = locs()->temp(1).reg();
+    const Register length_reg = locs()->temp(2).reg();
+
+    Label ok;
+
+    __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
+
+    __ ldrsb(offset_reg, FieldAddress(field_reg,
+        Field::guarded_list_length_in_object_offset_offset()));
+    __ ldr(length_reg, FieldAddress(field_reg,
+        Field::guarded_list_length_offset()));
+
+    __ tst(offset_reg, Operand(offset_reg));
+    __ b(&ok, MI);
+
+    // Load the length from the value. GuardFieldClass already verified that
+    // value's class matches guarded class id of the field.
+    // offset_reg contains offset already corrected by -kHeapObjectTag that is
+    // why we use Address instead of FieldAddress.
+    __ ldr(IP, Address(value_reg, offset_reg));
+    __ cmp(length_reg, Operand(IP));
+
+    if (deopt == NULL) {
+      __ b(&ok, EQ);
+
+      __ Push(field_reg);
+      __ Push(value_reg);
+      __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
+      __ Drop(2);  // Drop the field and the value.
+    } else {
+      __ b(deopt, NE);
+    }
+
+    __ Bind(&ok);
+  } else {
+    ASSERT(compiler->is_optimizing());
+    ASSERT(field().guarded_list_length() >= 0);
+    ASSERT(field().guarded_list_length_in_object_offset() !=
+        Field::kUnknownLengthOffset);
+
+    const Register length_reg = locs()->temp(0).reg();
+
+    __ ldr(length_reg,
+           FieldAddress(value_reg,
+                        field().guarded_list_length_in_object_offset()));
+    __ CompareImmediate(length_reg,
+                        Smi::RawValue(field().guarded_list_length()));
+    __ b(deopt, NE);
+  }
+}
+
+
 class StoreInstanceFieldSlowPath : public SlowPathCode {
  public:
   StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction,
@@ -1954,7 +1892,9 @@
 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Isolate* isolate,
                                                               bool opt) const {
   const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps =
+      (IsUnboxedStore() && opt) ? 2 :
+          ((IsPotentialUnboxedStore()) ? 3 : 0);
   LocationSummary* summary = new(isolate) LocationSummary(
       isolate, kNumInputs, kNumTemps,
           !field().IsNull() &&
@@ -1965,16 +1905,16 @@
   summary->set_in(0, Location::RequiresRegister());
   if (IsUnboxedStore() && opt) {
     summary->set_in(1, Location::RequiresFpuRegister());
-    summary->AddTemp(Location::RequiresRegister());
-    summary->AddTemp(Location::RequiresRegister());
+    summary->set_temp(0, Location::RequiresRegister());
+    summary->set_temp(1, Location::RequiresRegister());
   } else if (IsPotentialUnboxedStore()) {
     summary->set_in(1, ShouldEmitStoreBarrier()
         ? Location::WritableRegister()
         :  Location::RequiresRegister());
-    summary->AddTemp(Location::RequiresRegister());
-    summary->AddTemp(Location::RequiresRegister());
-    summary->AddTemp(opt ? Location::RequiresFpuRegister()
-                         : Location::FpuRegisterLocation(Q1));
+    summary->set_temp(0, Location::RequiresRegister());
+    summary->set_temp(1, Location::RequiresRegister());
+    summary->set_temp(2, opt ? Location::RequiresFpuRegister()
+                             : Location::FpuRegisterLocation(Q1));
   } else {
     summary->set_in(1, ShouldEmitStoreBarrier()
                        ? Location::WritableRegister()
@@ -2496,7 +2436,10 @@
 LocationSummary* LoadFieldInstr::MakeLocationSummary(Isolate* isolate,
                                                      bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps =
+      (IsUnboxedLoad() && opt) ? 1 :
+          ((IsPotentialUnboxedLoad()) ? 3 : 0);
+
   LocationSummary* locs = new(isolate) LocationSummary(
       isolate, kNumInputs, kNumTemps,
           (opt && !IsPotentialUnboxedLoad())
@@ -2506,12 +2449,12 @@
   locs->set_in(0, Location::RequiresRegister());
 
   if (IsUnboxedLoad() && opt) {
-    locs->AddTemp(Location::RequiresRegister());
+    locs->set_temp(0, Location::RequiresRegister());
   } else if (IsPotentialUnboxedLoad()) {
-    locs->AddTemp(opt ? Location::RequiresFpuRegister()
-                      : Location::FpuRegisterLocation(Q1));
-    locs->AddTemp(Location::RequiresRegister());
-    locs->AddTemp(Location::RequiresRegister());
+    locs->set_temp(0, opt ? Location::RequiresFpuRegister()
+                          : Location::FpuRegisterLocation(Q1));
+    locs->set_temp(1, Location::RequiresRegister());
+    locs->set_temp(2, Location::RequiresRegister());
   }
   locs->set_out(0, Location::RequiresRegister());
   return locs;
@@ -3036,19 +2979,35 @@
 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Isolate* isolate,
                                                        bool opt) const {
   const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
+  // Calculate number of temporaries.
+  intptr_t num_temps = 0;
+  if (op_kind() == Token::kTRUNCDIV) {
+    if (RightIsPowerOfTwoConstant()) {
+      num_temps = 1;
+    } else {
+      num_temps = 2;
+    }
+  } else if (op_kind() == Token::kMOD) {
+    num_temps = 2;
+  } else if (((op_kind() == Token::kSHL) && !is_truncating()) ||
+             (op_kind() == Token::kSHR)) {
+    num_temps = 1;
+  } else if ((op_kind() == Token::kMUL) &&
+             (TargetCPUFeatures::arm_version() != ARMv7)) {
+    num_temps = 1;
+  }
   LocationSummary* summary = new(isolate) LocationSummary(
-      isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+      isolate, kNumInputs, num_temps, LocationSummary::kNoCall);
   if (op_kind() == Token::kTRUNCDIV) {
     summary->set_in(0, Location::RequiresRegister());
     if (RightIsPowerOfTwoConstant()) {
       ConstantInstr* right_constant = right()->definition()->AsConstant();
       summary->set_in(1, Location::Constant(right_constant->value()));
-      summary->AddTemp(Location::RequiresRegister());
+      summary->set_temp(0, Location::RequiresRegister());
     } else {
       summary->set_in(1, Location::RequiresRegister());
-      summary->AddTemp(Location::RequiresRegister());
-      summary->AddTemp(Location::RequiresFpuRegister());
+      summary->set_temp(0, Location::RequiresRegister());
+      summary->set_temp(1, Location::RequiresFpuRegister());
     }
     summary->set_out(0, Location::RequiresRegister());
     return summary;
@@ -3056,8 +3015,8 @@
   if (op_kind() == Token::kMOD) {
     summary->set_in(0, Location::RequiresRegister());
     summary->set_in(1, Location::RequiresRegister());
-    summary->AddTemp(Location::RequiresRegister());
-    summary->AddTemp(Location::RequiresFpuRegister());
+    summary->set_temp(0, Location::RequiresRegister());
+    summary->set_temp(1, Location::RequiresFpuRegister());
     summary->set_out(0, Location::RequiresRegister());
     return summary;
   }
@@ -3065,11 +3024,11 @@
   summary->set_in(1, Location::RegisterOrSmiConstant(right()));
   if (((op_kind() == Token::kSHL) && !is_truncating()) ||
       (op_kind() == Token::kSHR)) {
-    summary->AddTemp(Location::RequiresRegister());
+    summary->set_temp(0, Location::RequiresRegister());
   }
   if (op_kind() == Token::kMUL) {
     if (TargetCPUFeatures::arm_version() != ARMv7) {
-      summary->AddTemp(Location::RequiresFpuRegister());
+      summary->set_temp(0, Location::RequiresFpuRegister());
     }
   }
   // We make use of 3-operand instructions by not requiring result register
@@ -4927,16 +4886,16 @@
                                                      bool opt) const {
   if ((kind() == MathUnaryInstr::kSin) || (kind() == MathUnaryInstr::kCos)) {
     const intptr_t kNumInputs = 1;
-    const intptr_t kNumTemps = 0;
+    const intptr_t kNumTemps = TargetCPUFeatures::hardfp_supported() ? 0 : 4;
     LocationSummary* summary = new(isolate) LocationSummary(
         isolate, kNumInputs, kNumTemps, LocationSummary::kCall);
     summary->set_in(0, Location::FpuRegisterLocation(Q0));
     summary->set_out(0, Location::FpuRegisterLocation(Q0));
     if (!TargetCPUFeatures::hardfp_supported()) {
-      summary->AddTemp(Location::RegisterLocation(R0));
-      summary->AddTemp(Location::RegisterLocation(R1));
-      summary->AddTemp(Location::RegisterLocation(R2));
-      summary->AddTemp(Location::RegisterLocation(R3));
+      summary->set_temp(0, Location::RegisterLocation(R0));
+      summary->set_temp(1, Location::RegisterLocation(R1));
+      summary->set_temp(2, Location::RegisterLocation(R2));
+      summary->set_temp(3, Location::RegisterLocation(R3));
     }
     return summary;
   }
@@ -5282,7 +5241,9 @@
 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Isolate* isolate,
                                                                bool opt) const {
   ASSERT((InputCount() == 1) || (InputCount() == 2));
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps =
+      (TargetCPUFeatures::hardfp_supported()) ?
+        ((recognized_kind() == MethodRecognizer::kMathDoublePow) ? 1 : 0) : 4;
   LocationSummary* result = new(isolate) LocationSummary(
       isolate, InputCount(), kNumTemps, LocationSummary::kCall);
   result->set_in(0, Location::FpuRegisterLocation(Q0));
@@ -5290,16 +5251,17 @@
     result->set_in(1, Location::FpuRegisterLocation(Q1));
   }
   if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
-    result->AddTemp(Location::RegisterLocation(R2));
-  }
-  if (!TargetCPUFeatures::hardfp_supported()) {
-    result->AddTemp(Location::RegisterLocation(R0));
-    result->AddTemp(Location::RegisterLocation(R1));
-    // Check if R2 is already added.
-    if (recognized_kind() != MethodRecognizer::kMathDoublePow) {
-      result->AddTemp(Location::RegisterLocation(R2));
+    result->set_temp(0, Location::RegisterLocation(R2));
+    if (!TargetCPUFeatures::hardfp_supported()) {
+      result->set_temp(1, Location::RegisterLocation(R0));
+      result->set_temp(2, Location::RegisterLocation(R1));
+      result->set_temp(3, Location::RegisterLocation(R3));
     }
-    result->AddTemp(Location::RegisterLocation(R3));
+  } else if (!TargetCPUFeatures::hardfp_supported()) {
+    result->set_temp(0, Location::RegisterLocation(R0));
+    result->set_temp(1, Location::RegisterLocation(R1));
+    result->set_temp(2, Location::RegisterLocation(R2));
+    result->set_temp(3, Location::RegisterLocation(R3));
   }
   result->set_out(0, Location::FpuRegisterLocation(Q0));
   return result;
@@ -5657,12 +5619,12 @@
 LocationSummary* CheckClassInstr::MakeLocationSummary(Isolate* isolate,
                                                       bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps = !IsNullCheck() ? 1 : 0;
   LocationSummary* summary = new(isolate) LocationSummary(
       isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
   if (!IsNullCheck()) {
-    summary->AddTemp(Location::RequiresRegister());
+    summary->set_temp(0, Location::RequiresRegister());
   }
   return summary;
 }
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index 4354d22..1e1ae77 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -89,9 +89,7 @@
   const intptr_t fp_sp_dist =
       (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize;
   ASSERT(fp_sp_dist <= 0);
-  // UXTX 0 on a 64-bit register (FP) is a nop, but forces R31 to be
-  // interpreted as SP.
-  __ sub(R2, SP, Operand(FP, UXTX, 0));
+  __ sub(R2, SP, Operand(FP));
   __ CompareImmediate(R2, fp_sp_dist, PP);
   __ b(&stack_ok, EQ);
   __ hlt(0);
@@ -208,12 +206,11 @@
   // R4: Arguments descriptor.
   // R0: Function.
   ASSERT(locs()->in(0).reg() == R0);
-  __ LoadFieldFromOffset(R2, R0, Function::code_offset(), PP);
+  __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), PP);
 
-  // R2: code.
+  // R2: instructions.
   // R5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
   __ LoadImmediate(R5, 0, PP);
-  __ LoadFieldFromOffset(R2, R2, Code::instructions_offset(), PP);
   __ AddImmediate(R2, R2, Instructions::HeaderSize() - kHeapObjectTag, PP);
   __ blr(R2);
   compiler->AddCurrentDescriptor(PcDescriptors::kClosureCall,
@@ -1351,50 +1348,65 @@
 }
 
 
-LocationSummary* GuardFieldInstr::MakeLocationSummary(Isolate* isolate,
-                                                      bool opt) const {
+LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Isolate* isolate,
+                                                           bool opt) const {
   const intptr_t kNumInputs = 1;
-  LocationSummary* summary = new(isolate) LocationSummary(
-      isolate, kNumInputs, 0, LocationSummary::kNoCall);
-  summary->set_in(0, Location::RequiresRegister());
-  const bool field_has_length = field().needs_length_check();
-  summary->AddTemp(Location::RequiresRegister());
-  summary->AddTemp(Location::RequiresRegister());
-  const bool need_field_temp_reg =
-      field_has_length || (field().guarded_cid() == kIllegalCid);
-  if (need_field_temp_reg) {
-    summary->AddTemp(Location::RequiresRegister());
+
+  const intptr_t value_cid = value()->Type()->ToCid();
+  const intptr_t field_cid = field().guarded_cid();
+
+  const bool emit_full_guard =
+      !opt || (field_cid == kIllegalCid);
+
+  const bool needs_value_cid_temp_reg = emit_full_guard ||
+      ((value_cid == kDynamicCid) && (field_cid != kSmiCid));
+
+  const bool needs_field_temp_reg = emit_full_guard;
+
+  intptr_t num_temps = 0;
+  if (needs_value_cid_temp_reg) {
+    num_temps++;
   }
+  if (needs_field_temp_reg) {
+    num_temps++;
+  }
+
+  LocationSummary* summary = new(isolate) LocationSummary(
+      isolate, kNumInputs, num_temps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+
+  for (intptr_t i = 0; i < num_temps; i++) {
+    summary->set_temp(i, Location::RequiresRegister());
+  }
+
   return summary;
 }
 
 
-void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t field_cid = field().guarded_cid();
   const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
-  const intptr_t field_length = field().guarded_list_length();
-  const bool field_has_length = field().needs_length_check();
-  const bool needs_field_temp_reg =
-      field_has_length || (field().guarded_cid() == kIllegalCid);
-  if (field_has_length) {
-    // Currently, we should only see final fields that remember length.
-    ASSERT(field().is_final());
-  }
 
   if (field_cid == kDynamicCid) {
     ASSERT(!compiler->is_optimizing());
     return;  // Nothing to emit.
   }
 
-  const intptr_t value_cid = value()->Type()->ToCid();
+  const bool emit_full_guard =
+      !compiler->is_optimizing() || (field_cid == kIllegalCid);
+
+  const bool needs_value_cid_temp_reg = emit_full_guard ||
+      ((value_cid == kDynamicCid) && (field_cid != kSmiCid));
+
+  const bool needs_field_temp_reg = emit_full_guard;
 
   const Register value_reg = locs()->in(0).reg();
 
-  const Register value_cid_reg = locs()->temp(0).reg();
+  const Register value_cid_reg = needs_value_cid_temp_reg ?
+      locs()->temp(0).reg() : kNoRegister;
 
-  const Register temp_reg = locs()->temp(1).reg();
-
-  Register field_reg = needs_field_temp_reg ?
+  const Register field_reg = needs_field_temp_reg ?
       locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister;
 
   Label ok, fail_label;
@@ -1404,91 +1416,19 @@
 
   Label* fail = (deopt != NULL) ? deopt : &fail_label;
 
-  if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) {
-    if (!compiler->is_optimizing() && (field_reg == kNoRegister)) {
-      // Currently we can't have different location summaries for optimized
-      // and non-optimized code. So instead we manually pick up a register
-      // that is known to be free because we know how non-optimizing compiler
-      // allocates registers.
-      field_reg = R2;
-      ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg));
-    }
-
+  if (emit_full_guard) {
     __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
 
     FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
     FieldAddress field_nullability_operand(
         field_reg, Field::is_nullable_offset());
-    FieldAddress field_length_operand(
-        field_reg, Field::guarded_list_length_offset());
-
-    ASSERT(value_cid_reg != kNoRegister);
-    ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
 
     if (value_cid == kDynamicCid) {
       LoadValueCid(compiler, value_cid_reg, value_reg);
       Label skip_length_check;
       __ ldr(TMP, field_cid_operand);
       __ CompareRegisters(value_cid_reg, TMP);
-      __ b(&skip_length_check, NE);
-      if (field_has_length) {
-        ASSERT(temp_reg != kNoRegister);
-        // Field guard may have remembered list length, check it.
-        if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
-          __ LoadFieldFromOffset(
-              temp_reg, value_reg, Array::length_offset(), PP);
-          __ CompareImmediate(temp_reg, Smi::RawValue(field_length), PP);
-        } else if (RawObject::IsTypedDataClassId(field_cid)) {
-          __ LoadFieldFromOffset(
-              temp_reg, value_reg, TypedData::length_offset(), PP);
-          __ CompareImmediate(temp_reg, Smi::RawValue(field_length), PP);
-        } else {
-          ASSERT(field_cid == kIllegalCid);
-          ASSERT(field_length == Field::kUnknownFixedLength);
-          // At compile time we do not know the type of the field nor its
-          // length. At execution time we may have set the class id and
-          // list length so we compare the guarded length with the
-          // list length here, without this check the list length could change
-          // without triggering a deoptimization.
-          Label check_array, length_compared, no_fixed_length;
-          // If length is negative the length guard is either disabled or
-          // has not been initialized, either way it is safe to skip the
-          // length check.
-          __ ldr(TMP, field_length_operand);
-          __ CompareImmediate(TMP, 0, PP);
-          __ b(&skip_length_check, LT);
-          __ CompareImmediate(value_cid_reg, kNullCid, PP);
-          __ b(&no_fixed_length, EQ);
-          // Check for typed data array.
-          __ CompareImmediate(value_cid_reg, kTypedDataInt32x4ArrayCid, PP);
-          __ b(&no_fixed_length, GT);
-          __ CompareImmediate(value_cid_reg, kTypedDataInt8ArrayCid, PP);
-          // Could still be a regular array.
-          __ b(&check_array, LT);
-          __ LoadFieldFromOffset(
-              temp_reg, value_reg, TypedData::length_offset(), PP);
-          __ ldr(TMP, field_length_operand);
-          __ CompareRegisters(temp_reg, TMP);
-          __ b(&length_compared);
-          // Check for regular array.
-          __ Bind(&check_array);
-          __ CompareImmediate(value_cid_reg, kImmutableArrayCid, PP);
-          __ b(&no_fixed_length, GT);
-          __ CompareImmediate(value_cid_reg, kArrayCid, PP);
-          __ b(&no_fixed_length, LT);
-          __ LoadFieldFromOffset(
-              temp_reg, value_reg, Array::length_offset(), PP);
-          __ ldr(TMP, field_length_operand);
-          __ CompareRegisters(temp_reg, TMP);
-          __ b(&length_compared);
-          __ Bind(&no_fixed_length);
-          __ b(fail);
-          __ Bind(&length_compared);
-          // Following branch cannot not occur, fall through.
-        }
-        __ b(fail, NE);
-      }
-      __ Bind(&skip_length_check);
+      __ b(&ok, EQ);
       __ ldr(TMP, field_nullability_operand);
       __ CompareRegisters(value_cid_reg, TMP);
     } else if (value_cid == kNullCid) {
@@ -1498,100 +1438,39 @@
       Label skip_length_check;
       __ ldr(value_cid_reg, field_cid_operand);
       __ CompareImmediate(value_cid_reg, value_cid, PP);
-      __ b(&skip_length_check, NE);
-      if (field_has_length) {
-        ASSERT(value_cid_reg != kNoRegister);
-        ASSERT(temp_reg != kNoRegister);
-        if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
-          __ LoadFieldFromOffset(
-              temp_reg, value_reg, Array::length_offset(), PP);
-          __ CompareImmediate(temp_reg, Smi::RawValue(field_length), PP);
-        } else if (RawObject::IsTypedDataClassId(value_cid)) {
-          __ LoadFieldFromOffset(
-              temp_reg, value_reg, TypedData::length_offset(), PP);
-          __ CompareImmediate(temp_reg, Smi::RawValue(field_length), PP);
-        } else if (field_cid != kIllegalCid) {
-          ASSERT(field_cid != value_cid);
-          ASSERT(field_length >= 0);
-          // Field has a known class id and length. At compile time it is
-          // known that the value's class id is not a fixed length list.
-          __ b(fail);
-        } else {
-          ASSERT(field_cid == kIllegalCid);
-          ASSERT(field_length == Field::kUnknownFixedLength);
-          // Following jump cannot not occur, fall through.
-        }
-        __ b(fail, NE);
-      }
-      // Not identical, possibly null.
-      __ Bind(&skip_length_check);
     }
     __ b(&ok, EQ);
 
-    __ ldr(TMP, field_cid_operand);
-    __ CompareImmediate(TMP, kIllegalCid, PP);
-    __ b(fail, NE);
+    // Check if the tracked state of the guarded field can be initialized
+    // inline. If the field needs length check we fall through to runtime
+    // which is responsible for computing offset of the length field
+    // based on the class id.
+    // Length guard will be emitted separately when needed via GuardFieldLength
+    // instruction after GuardFieldClass.
+    if (!field().needs_length_check()) {
+      // Uninitialized field can be handled inline. Check if the
+      // field is still unitialized.
+      __ ldr(TMP, field_cid_operand);
+      __ CompareImmediate(TMP, kIllegalCid, PP);
+      __ b(fail, NE);
 
-    if (value_cid == kDynamicCid) {
-      __ str(value_cid_reg, field_cid_operand);
-      __ str(value_cid_reg, field_nullability_operand);
-      if (field_has_length) {
-        Label check_array, length_set, no_fixed_length;
-        __ CompareImmediate(value_cid_reg, kNullCid, PP);
-        __ b(&no_fixed_length, EQ);
-        // Check for typed data array.
-        __ CompareImmediate(value_cid_reg, kTypedDataInt32x4ArrayCid, PP);
-        __ b(&no_fixed_length, GT);
-        __ CompareImmediate(value_cid_reg, kTypedDataInt8ArrayCid, PP);
-        // Could still be a regular array.
-        __ b(&check_array, LT);
-        // Destroy value_cid_reg (safe because we are finished with it).
-        __ LoadFieldFromOffset(
-            value_cid_reg, value_reg, TypedData::length_offset(), PP);
-        __ str(value_cid_reg, field_length_operand);
-        __ b(&length_set);  // Updated field length typed data array.
-        // Check for regular array.
-        __ Bind(&check_array);
-        __ CompareImmediate(value_cid_reg, kImmutableArrayCid, PP);
-        __ b(&no_fixed_length, GT);
-        __ CompareImmediate(value_cid_reg, kArrayCid, PP);
-        __ b(&no_fixed_length, LT);
-        // Destroy value_cid_reg (safe because we are finished with it).
-        __ LoadFieldFromOffset(
-            value_cid_reg, value_reg, Array::length_offset(), PP);
-        __ str(value_cid_reg, field_length_operand);
-        // Updated field length from regular array.
-        __ b(&length_set);
-        __ Bind(&no_fixed_length);
-        __ LoadImmediate(TMP, Smi::RawValue(Field::kNoFixedLength), PP);
-        __ str(TMP, field_length_operand);
-        __ Bind(&length_set);
+      if (value_cid == kDynamicCid) {
+        __ str(value_cid_reg, field_cid_operand);
+        __ str(value_cid_reg, field_nullability_operand);
+      } else {
+        __ LoadImmediate(TMP, value_cid, PP);
+        __ str(TMP, field_cid_operand);
+        __ str(TMP, field_nullability_operand);
       }
-    } else {
-      __ LoadImmediate(TMP, value_cid, PP);
-      __ str(TMP, field_cid_operand);
-      __ str(TMP, field_nullability_operand);
-      if (field_has_length) {
-        if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ LoadFieldFromOffset(
-              value_cid_reg, value_reg, Array::length_offset(), PP);
-          __ str(value_cid_reg, field_length_operand);
-        } else if (RawObject::IsTypedDataClassId(value_cid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ LoadFieldFromOffset(
-              value_cid_reg, value_reg, TypedData::length_offset(), PP);
-          __ str(value_cid_reg, field_length_operand);
-        } else {
-          __ LoadImmediate(TMP, Smi::RawValue(Field::kNoFixedLength), PP);
-          __ str(TMP, field_length_operand);
-        }
+
+      if (deopt == NULL) {
+        ASSERT(!compiler->is_optimizing());
+        __ b(&ok);
       }
     }
 
     if (deopt == NULL) {
       ASSERT(!compiler->is_optimizing());
-      __ b(&ok);
       __ Bind(fail);
 
       __ LoadFieldFromOffset(TMP, field_reg, Field::guarded_cid_offset(), PP);
@@ -1606,12 +1485,10 @@
   } else {
     ASSERT(compiler->is_optimizing());
     ASSERT(deopt != NULL);
+
     // Field guard class has been initialized and is known.
-    if (field_reg != kNoRegister) {
-      __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
-    }
     if (value_cid == kDynamicCid) {
-      // Field's guarded class id is fixed by value's class id is not known.
+      // Value's class id is not known.
       __ tsti(value_reg, kSmiTagMask);
 
       if (field_cid != kSmiCid) {
@@ -1620,57 +1497,109 @@
         __ CompareImmediate(value_cid_reg, field_cid, PP);
       }
 
-      if (field_has_length) {
-        __ b(fail, NE);
-        // Classes are same, perform guarded list length check.
-        ASSERT(field_reg != kNoRegister);
-        ASSERT(value_cid_reg != kNoRegister);
-        FieldAddress field_length_operand(
-            field_reg, Field::guarded_list_length_offset());
-        if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ LoadFieldFromOffset(
-              value_cid_reg, value_reg, Array::length_offset(), PP);
-        } else if (RawObject::IsTypedDataClassId(field_cid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ LoadFieldFromOffset(
-              value_cid_reg, value_reg, TypedData::length_offset(), PP);
-        }
-        __ ldr(TMP, field_length_operand);
-        __ CompareRegisters(value_cid_reg, TMP);
-      }
-
       if (field().is_nullable() && (field_cid != kNullCid)) {
         __ b(&ok, EQ);
         __ CompareObject(value_reg, Object::null_object(), PP);
       }
+
       __ b(fail, NE);
     } else {
       // Both value's and field's class id is known.
-      if ((value_cid != field_cid) && (value_cid != nullability)) {
-        __ b(fail);
-      } else if (field_has_length && (value_cid == field_cid)) {
-        ASSERT(value_cid_reg != kNoRegister);
-        if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ LoadFieldFromOffset(
-              value_cid_reg, value_reg, Array::length_offset(), PP);
-        } else if (RawObject::IsTypedDataClassId(field_cid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ LoadFieldFromOffset(
-              value_cid_reg, value_reg, TypedData::length_offset(), PP);
-        }
-        __ CompareImmediate(value_cid_reg, field_length, PP);
-        __ b(fail, NE);
-      } else {
-        UNREACHABLE();
-      }
+      ASSERT((value_cid != field_cid) && (value_cid != nullability));
+      __ b(fail);
     }
   }
   __ Bind(&ok);
 }
 
 
+LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Isolate* isolate,
+                                                            bool opt) const {
+  const intptr_t kNumInputs = 1;
+  if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) {
+    const intptr_t kNumTemps = 3;
+    LocationSummary* summary = new(isolate) LocationSummary(
+        isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    summary->set_in(0, Location::RequiresRegister());
+    // We need temporaries for field object, length offset and expected length.
+    summary->set_temp(0, Location::RequiresRegister());
+    summary->set_temp(1, Location::RequiresRegister());
+    summary->set_temp(2, Location::RequiresRegister());
+    return summary;
+  } else {
+    LocationSummary* summary = new(isolate) LocationSummary(
+        isolate, kNumInputs, 0, LocationSummary::kNoCall);
+    summary->set_in(0, Location::RequiresRegister());
+    return summary;
+  }
+  UNREACHABLE();
+}
+
+
+void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (field().guarded_list_length() == Field::kNoFixedLength) {
+    ASSERT(!compiler->is_optimizing());
+    return;  // Nothing to emit.
+  }
+
+  Label* deopt = compiler->is_optimizing() ?
+      compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL;
+
+  const Register value_reg = locs()->in(0).reg();
+
+  if (!compiler->is_optimizing() ||
+      (field().guarded_list_length() == Field::kUnknownFixedLength)) {
+    const Register field_reg = locs()->temp(0).reg();
+    const Register offset_reg = locs()->temp(1).reg();
+    const Register length_reg = locs()->temp(2).reg();
+
+    Label ok;
+
+    __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
+
+    __ ldr(offset_reg,
+           FieldAddress(field_reg,
+                        Field::guarded_list_length_in_object_offset_offset()),
+           kByte);
+    __ ldr(length_reg, FieldAddress(field_reg,
+        Field::guarded_list_length_offset()));
+
+    __ tst(offset_reg, Operand(offset_reg));
+    __ b(&ok, MI);
+
+    // Load the length from the value. GuardFieldClass already verified that
+    // value's class matches guarded class id of the field.
+    // offset_reg contains offset already corrected by -kHeapObjectTag that is
+    // why we use Address instead of FieldAddress.
+    __ ldr(TMP, Address(value_reg, offset_reg));
+    __ CompareRegisters(length_reg, TMP);
+
+    if (deopt == NULL) {
+      __ b(&ok, EQ);
+
+      __ Push(field_reg);
+      __ Push(value_reg);
+      __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
+      __ Drop(2);  // Drop the field and the value.
+    } else {
+      __ b(deopt, NE);
+    }
+
+    __ Bind(&ok);
+  } else {
+    ASSERT(compiler->is_optimizing());
+    ASSERT(field().guarded_list_length() >= 0);
+    ASSERT(field().guarded_list_length_in_object_offset() !=
+        Field::kUnknownLengthOffset);
+
+    __ ldr(TMP, FieldAddress(value_reg,
+                            field().guarded_list_length_in_object_offset()));
+    __ CompareImmediate(TMP, Smi::RawValue(field().guarded_list_length()), PP);
+    __ b(deopt, NE);
+  }
+}
+
+
 class StoreInstanceFieldSlowPath : public SlowPathCode {
  public:
   StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction,
@@ -1708,7 +1637,9 @@
 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Isolate* isolate,
                                                               bool opt) const {
   const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps =
+      (IsUnboxedStore() && opt) ? 2 :
+          ((IsPotentialUnboxedStore()) ? 2 : 0);
   LocationSummary* summary = new(isolate) LocationSummary(
       isolate, kNumInputs, kNumTemps,
       !field().IsNull() &&
@@ -1719,14 +1650,14 @@
   summary->set_in(0, Location::RequiresRegister());
   if (IsUnboxedStore() && opt) {
     summary->set_in(1, Location::RequiresFpuRegister());
-    summary->AddTemp(Location::RequiresRegister());
-    summary->AddTemp(Location::RequiresRegister());
+    summary->set_temp(0, Location::RequiresRegister());
+    summary->set_temp(1, Location::RequiresRegister());
   } else if (IsPotentialUnboxedStore()) {
       summary->set_in(1, ShouldEmitStoreBarrier()
           ? Location::WritableRegister()
           :  Location::RequiresRegister());
-      summary->AddTemp(Location::RequiresRegister());
-      summary->AddTemp(Location::RequiresRegister());
+      summary->set_temp(0, Location::RequiresRegister());
+      summary->set_temp(1, Location::RequiresRegister());
   } else {
     summary->set_in(1, ShouldEmitStoreBarrier()
                        ? Location::WritableRegister()
@@ -2139,7 +2070,9 @@
 LocationSummary* LoadFieldInstr::MakeLocationSummary(Isolate* isolate,
                                                      bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps =
+      (IsUnboxedLoad() && opt) ? 1 :
+          ((IsPotentialUnboxedLoad()) ? 1 : 0);
   LocationSummary* locs = new(isolate) LocationSummary(
       isolate, kNumInputs, kNumTemps,
       (opt && !IsPotentialUnboxedLoad())
@@ -2149,9 +2082,9 @@
   locs->set_in(0, Location::RequiresRegister());
 
   if (IsUnboxedLoad() && opt) {
-    locs->AddTemp(Location::RequiresRegister());
+    locs->set_temp(0, Location::RequiresRegister());
   } else if (IsPotentialUnboxedLoad()) {
-    locs->AddTemp(Location::RequiresRegister());
+    locs->set_temp(0, Location::RequiresRegister());
   }
   locs->set_out(0, Location::RequiresRegister());
   return locs;
@@ -2696,7 +2629,9 @@
 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Isolate* isolate,
                                                        bool opt) const {
   const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps =
+      (((op_kind() == Token::kSHL) && !is_truncating()) ||
+       (op_kind() == Token::kSHR)) ? 1 : 0;
   LocationSummary* summary = new(isolate) LocationSummary(
       isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   if (op_kind() == Token::kTRUNCDIV) {
@@ -2720,7 +2655,7 @@
   summary->set_in(1, Location::RegisterOrSmiConstant(right()));
   if (((op_kind() == Token::kSHL) && !is_truncating()) ||
       (op_kind() == Token::kSHR)) {
-    summary->AddTemp(Location::RequiresRegister());
+    summary->set_temp(0, Location::RequiresRegister());
   }
   // We make use of 3-operand instructions by not requiring result register
   // to be identical to first input register as on Intel.
@@ -4661,7 +4596,8 @@
 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Isolate* isolate,
                                                                bool opt) const {
   ASSERT((InputCount() == 1) || (InputCount() == 2));
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps =
+      (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 1 : 0;
   LocationSummary* result = new(isolate) LocationSummary(
       isolate, InputCount(), kNumTemps, LocationSummary::kCall);
   result->set_in(0, Location::FpuRegisterLocation(V0));
@@ -4669,7 +4605,7 @@
     result->set_in(1, Location::FpuRegisterLocation(V1));
   }
   if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
-    result->AddTemp(Location::FpuRegisterLocation(V30));
+    result->set_temp(0, Location::FpuRegisterLocation(V30));
   }
   result->set_out(0, Location::FpuRegisterLocation(V0));
   return result;
@@ -4990,12 +4926,12 @@
 LocationSummary* CheckClassInstr::MakeLocationSummary(Isolate* isolate,
                                                       bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps = !IsNullCheck() ? 1 : 0;
   LocationSummary* summary = new(isolate) LocationSummary(
       isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
   if (!IsNullCheck()) {
-    summary->AddTemp(Location::RequiresRegister());
+    summary->set_temp(0, Location::RequiresRegister());
   }
   return summary;
 }
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 5b6f8b8..e25e90e 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -1451,55 +1451,62 @@
 }
 
 
-LocationSummary* GuardFieldInstr::MakeLocationSummary(Isolate* isolate,
-                                                      bool opt) const {
+LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Isolate* isolate,
+                                                           bool opt) const {
   const intptr_t kNumInputs = 1;
+
+  const intptr_t value_cid = value()->Type()->ToCid();
+  const intptr_t field_cid = field().guarded_cid();
+
+  const bool emit_full_guard = !opt || (field_cid == kIllegalCid);
+  const bool needs_value_cid_temp_reg =
+    (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid));
+  const bool needs_field_temp_reg = emit_full_guard;
+
+  intptr_t num_temps = 0;
+  if (needs_value_cid_temp_reg) {
+    num_temps++;
+  }
+  if (needs_field_temp_reg) {
+    num_temps++;
+  }
+
   LocationSummary* summary = new(isolate) LocationSummary(
-      isolate, kNumInputs, 0, LocationSummary::kNoCall);
+      isolate, kNumInputs, num_temps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
-  const bool field_has_length = field().needs_length_check();
-  const bool need_value_temp_reg =
-      (field_has_length || ((value()->Type()->ToCid() == kDynamicCid) &&
-                            (field().guarded_cid() != kSmiCid)));
-  if (need_value_temp_reg) {
-    summary->AddTemp(Location::RequiresRegister());
+
+  for (intptr_t i = 0; i < num_temps; i++) {
+    summary->set_temp(i, Location::RequiresRegister());
   }
-  const bool need_field_temp_reg =
-      field_has_length || (field().guarded_cid() == kIllegalCid);
-  if (need_field_temp_reg) {
-    summary->AddTemp(Location::RequiresRegister());
-  }
+
   return summary;
 }
 
 
-void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t field_cid = field().guarded_cid();
   const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
-  const intptr_t field_length = field().guarded_list_length();
-  const bool field_has_length = field().needs_length_check();
-  const bool needs_value_temp_reg =
-      (field_has_length || ((value()->Type()->ToCid() == kDynamicCid) &&
-                            (field().guarded_cid() != kSmiCid)));
-  const bool needs_field_temp_reg =
-      field_has_length || (field().guarded_cid() == kIllegalCid);
-  if (field_has_length) {
-    // Currently, we should only see final fields that remember length.
-    ASSERT(field().is_final());
-  }
 
   if (field_cid == kDynamicCid) {
     ASSERT(!compiler->is_optimizing());
     return;  // Nothing to emit.
   }
-  const intptr_t value_cid = value()->Type()->ToCid();
 
-  Register value_reg = locs()->in(0).reg();
+  const bool emit_full_guard =
+      !compiler->is_optimizing() || (field_cid == kIllegalCid);
 
-  Register value_cid_reg = needs_value_temp_reg ?
+  const bool needs_value_cid_temp_reg =
+      (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid));
+
+  const bool needs_field_temp_reg = emit_full_guard;
+
+  const Register value_reg = locs()->in(0).reg();
+
+  const Register value_cid_reg = needs_value_cid_temp_reg ?
       locs()->temp(0).reg() : kNoRegister;
 
-  Register field_reg = needs_field_temp_reg ?
+  const Register field_reg = needs_field_temp_reg ?
       locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister;
 
   Label ok, fail_label;
@@ -1509,98 +1516,17 @@
 
   Label* fail = (deopt != NULL) ? deopt : &fail_label;
 
-  if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) {
-    if (!compiler->is_optimizing() && (field_reg == kNoRegister)) {
-      // Currently we can't have different location summaries for optimized
-      // and non-optimized code. So instead we manually pick up a register
-      // that is known to be free because we know how non-optimizing compiler
-      // allocates registers.
-      field_reg = EBX;
-      ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg));
-    }
-
+  if (emit_full_guard) {
     __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
 
     FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
     FieldAddress field_nullability_operand(
         field_reg, Field::is_nullable_offset());
-    FieldAddress field_length_operand(
-        field_reg, Field::guarded_list_length_offset());
 
     if (value_cid == kDynamicCid) {
-      if (value_cid_reg == kNoRegister) {
-        ASSERT(!compiler->is_optimizing());
-        value_cid_reg = EDX;
-        ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
-      }
-
       LoadValueCid(compiler, value_cid_reg, value_reg);
-      Label skip_length_check;
       __ cmpl(value_cid_reg, field_cid_operand);
-      // Value CID != Field guard CID, skip length check.
-      __ j(NOT_EQUAL, &skip_length_check);
-      if (field_has_length) {
-        // Field guard may have remembered list length, check it.
-        if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
-          __ pushl(value_cid_reg);
-          __ movl(value_cid_reg,
-                  FieldAddress(value_reg, Array::length_offset()));
-          __ cmpl(value_cid_reg, Immediate(Smi::RawValue(field_length)));
-          __ popl(value_cid_reg);
-        } else if (RawObject::IsTypedDataClassId(field_cid)) {
-          __ pushl(value_cid_reg);
-          __ movl(value_cid_reg,
-                  FieldAddress(value_reg, TypedData::length_offset()));
-          __ cmpl(value_cid_reg, Immediate(Smi::RawValue(field_length)));
-          __ popl(value_cid_reg);
-        } else {
-          ASSERT(field_cid == kIllegalCid);
-          ASSERT(field_length == Field::kUnknownFixedLength);
-          // At compile time we do not know the type of the field nor its
-          // length. At execution time we may have set the class id and
-          // list length so we compare the guarded length with the
-          // list length here, without this check the list length could change
-          // without triggering a deoptimization.
-          Label check_array, length_compared, no_fixed_length;
-          // If length is negative the length guard is either disabled or
-          // has not been initialized, either way it is safe to skip the
-          // length check.
-          __ cmpl(field_length_operand, Immediate(Smi::RawValue(0)));
-          __ j(LESS, &skip_length_check);
-          __ cmpl(value_cid_reg, Immediate(kNullCid));
-          __ j(EQUAL, &no_fixed_length, Assembler::kNearJump);
-          // Check for typed data array.
-          __ cmpl(value_cid_reg, Immediate(kTypedDataInt32x4ArrayCid));
-          // Not a typed array or a regular array.
-          __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
-          __ cmpl(value_cid_reg, Immediate(kTypedDataInt8ArrayCid));
-          // Could still be a regular array.
-          __ j(LESS, &check_array, Assembler::kNearJump);
-          __ pushl(value_cid_reg);
-          __ movl(value_cid_reg,
-                  FieldAddress(value_reg, TypedData::length_offset()));
-          __ cmpl(field_length_operand, value_cid_reg);
-          __ popl(value_cid_reg);
-          __ jmp(&length_compared, Assembler::kNearJump);
-          // Check for regular array.
-          __ Bind(&check_array);
-          __ cmpl(value_cid_reg, Immediate(kImmutableArrayCid));
-          __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
-          __ cmpl(value_cid_reg, Immediate(kArrayCid));
-          __ j(LESS, &no_fixed_length, Assembler::kNearJump);
-          __ pushl(value_cid_reg);
-          __ movl(value_cid_reg,
-                  FieldAddress(value_reg, Array::length_offset()));
-          __ cmpl(field_length_operand, value_cid_reg);
-          __ popl(value_cid_reg);
-          __ jmp(&length_compared, Assembler::kNearJump);
-          __ Bind(&no_fixed_length);
-          __ jmp(fail);
-          __ Bind(&length_compared);
-        }
-        __ j(NOT_EQUAL, fail);
-      }
-      __ Bind(&skip_length_check);
+      __ j(EQUAL, &ok);
       __ cmpl(value_cid_reg, field_nullability_operand);
     } else if (value_cid == kNullCid) {
       // Value in graph known to be null.
@@ -1608,110 +1534,43 @@
       __ cmpl(field_nullability_operand, Immediate(value_cid));
     } else {
       // Value in graph known to be non-null.
-      Label skip_length_check;
       // Compare class id with guard field class id.
       __ cmpl(field_cid_operand, Immediate(value_cid));
-      // If not equal, skip over length check.
-      __ j(NOT_EQUAL, &skip_length_check);
-      // Insert length check.
-      if (field_has_length) {
-        ASSERT(value_cid_reg != kNoRegister);
-        if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
-          __ cmpl(FieldAddress(value_reg, Array::length_offset()),
-                  Immediate(Smi::RawValue(field_length)));
-        } else if (RawObject::IsTypedDataClassId(value_cid)) {
-          __ cmpl(FieldAddress(value_reg, TypedData::length_offset()),
-                  Immediate(Smi::RawValue(field_length)));
-        } else if (field_cid != kIllegalCid) {
-          ASSERT(field_cid != value_cid);
-          ASSERT(field_length >= 0);
-          // Field has a known class id and length. At compile time it is
-          // known that the value's class id is not a fixed length list.
-          __ jmp(fail);
-        } else {
-          ASSERT(field_cid == kIllegalCid);
-          ASSERT(field_length == Field::kUnknownFixedLength);
-          // Following jump cannot not occur, fall through.
-        }
-        __ j(NOT_EQUAL, fail);
-      }
-      // Not identical, possibly null.
-      __ Bind(&skip_length_check);
     }
-    // Jump when class id guard and list length guard are okay.
     __ j(EQUAL, &ok);
 
-    // Check if guard field is uninitialized.
-    __ cmpl(field_cid_operand, Immediate(kIllegalCid));
-    // Jump to failure path when guard field has been initialized and
-    // the field and value class ids do not not match.
-    __ j(NOT_EQUAL, fail);
+    // Check if the tracked state of the guarded field can be initialized
+    // inline. If the field needs length check we fall through to runtime
+    // which is responsible for computing offset of the length field
+    // based on the class id.
+    // Length guard will be emitted separately when needed via GuardFieldLength
+    // instruction after GuardFieldClass.
+    if (!field().needs_length_check()) {
+      // Uninitialized field can be handled inline. Check if the
+      // field is still unitialized.
+      __ cmpl(field_cid_operand, Immediate(kIllegalCid));
+      // Jump to failure path when guard field has been initialized and
+      // the field and value class ids do not not match.
+      __ j(NOT_EQUAL, fail);
 
-    // At this point the field guard is being initialized for the first time.
-    if (value_cid == kDynamicCid) {
-      // Do not know value's class id.
-      __ movl(field_cid_operand, value_cid_reg);
-      __ movl(field_nullability_operand, value_cid_reg);
-      if (field_has_length) {
-        Label check_array, length_set, no_fixed_length;
-        __ cmpl(value_cid_reg, Immediate(kNullCid));
-        __ j(EQUAL, &no_fixed_length, Assembler::kNearJump);
-        // Check for typed data array.
-        __ cmpl(value_cid_reg, Immediate(kTypedDataInt32x4ArrayCid));
-        // Not a typed array or a regular array.
-        __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
-        __ cmpl(value_cid_reg, Immediate(kTypedDataInt8ArrayCid));
-        // Could still be a regular array.
-        __ j(LESS, &check_array, Assembler::kNearJump);
-        // Destroy value_cid_reg (safe because we are finished with it).
-        __ movl(value_cid_reg,
-                FieldAddress(value_reg, TypedData::length_offset()));
-        __ movl(field_length_operand, value_cid_reg);
-        // Updated field length typed data array.
-        __ jmp(&length_set, Assembler::kNearJump);
-        // Check for regular array.
-        __ Bind(&check_array);
-        __ cmpl(value_cid_reg, Immediate(kImmutableArrayCid));
-        __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
-        __ cmpl(value_cid_reg, Immediate(kArrayCid));
-        __ j(LESS, &no_fixed_length, Assembler::kNearJump);
-        // Destroy value_cid_reg (safe because we are finished with it).
-        __ movl(value_cid_reg,
-                FieldAddress(value_reg, Array::length_offset()));
-        __ movl(field_length_operand, value_cid_reg);
-        // Updated field length from regular array.
-        __ jmp(&length_set, Assembler::kNearJump);
-        __ Bind(&no_fixed_length);
-        __ movl(field_length_operand,
-                Immediate(Smi::RawValue(Field::kNoFixedLength)));
-        __ Bind(&length_set);
+      if (value_cid == kDynamicCid) {
+        // Do not know value's class id.
+        __ movl(field_cid_operand, value_cid_reg);
+        __ movl(field_nullability_operand, value_cid_reg);
+      } else {
+        ASSERT(field_reg != kNoRegister);
+        __ movl(field_cid_operand, Immediate(value_cid));
+        __ movl(field_nullability_operand, Immediate(value_cid));
       }
-    } else {
-      ASSERT(field_reg != kNoRegister);
-      __ movl(field_cid_operand, Immediate(value_cid));
-      __ movl(field_nullability_operand, Immediate(value_cid));
-      if (field_has_length) {
-        ASSERT(value_cid_reg != kNoRegister);
-        if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ movl(value_cid_reg,
-                  FieldAddress(value_reg, Array::length_offset()));
-          __ movl(field_length_operand, value_cid_reg);
-        } else if (RawObject::IsTypedDataClassId(value_cid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ movl(value_cid_reg,
-                  FieldAddress(value_reg, TypedData::length_offset()));
-          __ movl(field_length_operand, value_cid_reg);
-        } else {
-          __ movl(field_length_operand,
-                  Immediate(Smi::RawValue(Field::kNoFixedLength)));
-        }
+
+      if (deopt == NULL) {
+        ASSERT(!compiler->is_optimizing());
+        __ jmp(&ok);
       }
     }
 
     if (deopt == NULL) {
       ASSERT(!compiler->is_optimizing());
-      __ jmp(&ok);
       __ Bind(fail);
 
       __ cmpl(FieldAddress(field_reg, Field::guarded_cid_offset()),
@@ -1726,11 +1585,9 @@
   } else {
     ASSERT(compiler->is_optimizing());
     ASSERT(deopt != NULL);
-    // Field guard class has been initialized and is known.
-    if (field_reg != kNoRegister) {
-      __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
-    }
+    ASSERT(fail == deopt);
 
+    // Field guard class has been initialized and is known.
     if (value_cid == kDynamicCid) {
       // Value's class id is not known.
       __ testl(value_reg, Immediate(kSmiTagMask));
@@ -1741,60 +1598,111 @@
         __ cmpl(value_cid_reg, Immediate(field_cid));
       }
 
-      if (field_has_length) {
-        // Jump when Value CID != Field guard CID
-        __ j(NOT_EQUAL, fail);
-
-        // Classes are same, perform guarded list length check.
-        ASSERT(field_reg != kNoRegister);
-        ASSERT(value_cid_reg != kNoRegister);
-        FieldAddress field_length_operand(
-            field_reg, Field::guarded_list_length_offset());
-        if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ movl(value_cid_reg,
-                  FieldAddress(value_reg, Array::length_offset()));
-        } else if (RawObject::IsTypedDataClassId(field_cid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ movl(value_cid_reg,
-                  FieldAddress(value_reg, TypedData::length_offset()));
-        }
-        __ cmpl(value_cid_reg, field_length_operand);
-      }
-
       if (field().is_nullable() && (field_cid != kNullCid)) {
         __ j(EQUAL, &ok);
-        const Immediate& raw_null =
-            Immediate(reinterpret_cast<intptr_t>(Object::null()));
-        __ cmpl(value_reg, raw_null);
+        if (field_cid != kSmiCid) {
+          __ cmpl(value_cid_reg, Immediate(kNullCid));
+        } else {
+          const Immediate& raw_null =
+              Immediate(reinterpret_cast<intptr_t>(Object::null()));
+          __ cmpl(value_reg, raw_null);
+        }
       }
       __ j(NOT_EQUAL, fail);
     } else {
       // Both value's and field's class id is known.
-      if ((value_cid != field_cid) && (value_cid != nullability)) {
-        __ jmp(fail);
-      } else if (field_has_length && (value_cid == field_cid)) {
-        ASSERT(value_cid_reg != kNoRegister);
-        if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ movl(value_cid_reg,
-                  FieldAddress(value_reg, Array::length_offset()));
-        } else if (RawObject::IsTypedDataClassId(field_cid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ movl(value_cid_reg,
-                  FieldAddress(value_reg, TypedData::length_offset()));
-        }
-        __ cmpl(value_cid_reg, Immediate(Smi::RawValue(field_length)));
-        __ j(NOT_EQUAL, fail);
-      } else {
-        UNREACHABLE();
-      }
+      ASSERT((value_cid != field_cid) && (value_cid != nullability));
+      __ jmp(fail);
     }
   }
   __ Bind(&ok);
 }
 
 
+LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Isolate* isolate,
+                                                            bool opt) const {
+  const intptr_t kNumInputs = 1;
+  if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) {
+    const intptr_t kNumTemps = 3;
+    LocationSummary* summary = new(isolate) LocationSummary(
+        isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    summary->set_in(0, Location::RequiresRegister());
+    // We need temporaries for field object, length offset and expected length.
+    summary->set_temp(0, Location::RequiresRegister());
+    summary->set_temp(1, Location::RequiresRegister());
+    summary->set_temp(2, Location::RequiresRegister());
+    return summary;
+  } else {
+    LocationSummary* summary = new(isolate) LocationSummary(
+        isolate, kNumInputs, 0, LocationSummary::kNoCall);
+    summary->set_in(0, Location::RequiresRegister());
+    return summary;
+  }
+  UNREACHABLE();
+}
+
+
+void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (field().guarded_list_length() == Field::kNoFixedLength) {
+    ASSERT(!compiler->is_optimizing());
+    return;  // Nothing to emit.
+  }
+
+  Label* deopt = compiler->is_optimizing() ?
+      compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL;
+
+  const Register value_reg = locs()->in(0).reg();
+
+  if (!compiler->is_optimizing() ||
+      (field().guarded_list_length() == Field::kUnknownFixedLength)) {
+    const Register field_reg = locs()->temp(0).reg();
+    const Register offset_reg = locs()->temp(1).reg();
+    const Register length_reg = locs()->temp(2).reg();
+
+    Label ok;
+
+    __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
+
+    __ movsxb(offset_reg, FieldAddress(field_reg,
+        Field::guarded_list_length_in_object_offset_offset()));
+    __ movl(length_reg, FieldAddress(field_reg,
+        Field::guarded_list_length_offset()));
+
+    __ cmpl(offset_reg, Immediate(0));
+    __ j(NEGATIVE, &ok);
+
+    // Load the length from the value. GuardFieldClass already verified that
+    // value's class matches guarded class id of the field.
+    // offset_reg contains offset already corrected by -kHeapObjectTag that is
+    // why we use Address instead of FieldAddress.
+    __ cmpl(length_reg, Address(value_reg, offset_reg, TIMES_1, 0));
+
+    if (deopt == NULL) {
+      __ j(EQUAL, &ok);
+
+      __ pushl(field_reg);
+      __ pushl(value_reg);
+      __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
+      __ Drop(2);  // Drop the field and the value.
+    } else {
+      __ j(NOT_EQUAL, deopt);
+    }
+
+    __ Bind(&ok);
+  } else {
+    ASSERT(compiler->is_optimizing());
+    ASSERT(field().guarded_list_length() >= 0);
+    ASSERT(field().guarded_list_length_in_object_offset() !=
+        Field::kUnknownLengthOffset);
+
+    __ cmpl(FieldAddress(value_reg,
+                         field().guarded_list_length_in_object_offset()),
+            Immediate(Smi::RawValue(field().guarded_list_length())));
+    __ j(NOT_EQUAL, deopt);
+  }
+}
+
+
 class StoreInstanceFieldSlowPath : public SlowPathCode {
  public:
   StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction,
@@ -1829,7 +1737,9 @@
 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Isolate* isolate,
                                                               bool opt) const {
   const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps =
+      (IsUnboxedStore() && opt) ? 2 :
+          ((IsPotentialUnboxedStore()) ? 3 : 0);
   LocationSummary* summary = new(isolate) LocationSummary(
       isolate, kNumInputs, kNumTemps,
           !field().IsNull() &&
@@ -1840,16 +1750,16 @@
   summary->set_in(0, Location::RequiresRegister());
   if (IsUnboxedStore() && opt) {
     summary->set_in(1, Location::RequiresFpuRegister());
-    summary->AddTemp(Location::RequiresRegister());
-    summary->AddTemp(Location::RequiresRegister());
+    summary->set_temp(0, Location::RequiresRegister());
+    summary->set_temp(1, Location::RequiresRegister());
   } else if (IsPotentialUnboxedStore()) {
     summary->set_in(1, ShouldEmitStoreBarrier()
         ? Location::WritableRegister()
         :  Location::RequiresRegister());
-    summary->AddTemp(Location::RequiresRegister());
-    summary->AddTemp(Location::RequiresRegister());
-    summary->AddTemp(opt ? Location::RequiresFpuRegister()
-                         : Location::FpuRegisterLocation(XMM1));
+    summary->set_temp(0, Location::RequiresRegister());
+    summary->set_temp(1, Location::RequiresRegister());
+    summary->set_temp(2, opt ? Location::RequiresFpuRegister()
+                             : Location::FpuRegisterLocation(XMM1));
   } else {
     summary->set_in(1, ShouldEmitStoreBarrier()
                        ? Location::WritableRegister()
@@ -2383,7 +2293,10 @@
 LocationSummary* LoadFieldInstr::MakeLocationSummary(Isolate* isolate,
                                                      bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps =
+      (IsUnboxedLoad() && opt) ? 1 :
+          ((IsPotentialUnboxedLoad()) ? 2 : 0);
+
   LocationSummary* locs = new(isolate) LocationSummary(
       isolate, kNumInputs, kNumTemps,
           (opt && !IsPotentialUnboxedLoad())
@@ -2393,11 +2306,11 @@
   locs->set_in(0, Location::RequiresRegister());
 
   if (IsUnboxedLoad() && opt) {
-    locs->AddTemp(Location::RequiresRegister());
+    locs->set_temp(0, Location::RequiresRegister());
   } else if (IsPotentialUnboxedLoad()) {
-    locs->AddTemp(opt ? Location::RequiresFpuRegister()
-                      : Location::FpuRegisterLocation(XMM1));
-    locs->AddTemp(Location::RequiresRegister());
+    locs->set_temp(0, opt ? Location::RequiresFpuRegister()
+                          : Location::FpuRegisterLocation(XMM1));
+    locs->set_temp(1, Location::RequiresRegister());
   }
   locs->set_out(0, Location::RequiresRegister());
   return locs;
@@ -3080,13 +2993,13 @@
     summary->set_out(0, Location::SameAsFirstInput());
     return summary;
   } else if (op_kind() == Token::kSHL) {
-    const intptr_t kNumTemps = 0;
+    const intptr_t kNumTemps = !is_truncating() ? 1 : 0;
     LocationSummary* summary = new(isolate) LocationSummary(
         isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
     summary->set_in(0, Location::RequiresRegister());
     summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
     if (!is_truncating()) {
-      summary->AddTemp(Location::RequiresRegister());
+      summary->set_temp(0, Location::RequiresRegister());
     }
     summary->set_out(0, Location::SameAsFirstInput());
     return summary;
@@ -5135,7 +5048,8 @@
 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Isolate* isolate,
                                                                bool opt) const {
   ASSERT((InputCount() == 1) || (InputCount() == 2));
-  const intptr_t kNumTemps = 1;
+  const intptr_t kNumTemps =
+      (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1;
   LocationSummary* result = new(isolate) LocationSummary(
       isolate, InputCount(), kNumTemps, LocationSummary::kCall);
   // EDI is chosen because it is callee saved so we do not need to back it
@@ -5147,9 +5061,9 @@
   }
   if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
     // Temp index 1.
-    result->AddTemp(Location::RegisterLocation(EAX));
+    result->set_temp(1, Location::RegisterLocation(EAX));
     // Temp index 2.
-    result->AddTemp(Location::FpuRegisterLocation(XMM4));
+    result->set_temp(2, Location::FpuRegisterLocation(XMM4));
   }
   result->set_out(0, Location::FpuRegisterLocation(XMM3));
   return result;
@@ -5552,12 +5466,12 @@
 LocationSummary* CheckClassInstr::MakeLocationSummary(Isolate* isolate,
                                                       bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps = !IsNullCheck() ? 1 : 0;
   LocationSummary* summary = new(isolate) LocationSummary(
       isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
   if (!IsNullCheck()) {
-    summary->AddTemp(Location::RequiresRegister());
+    summary->set_temp(0, Location::RequiresRegister());
   }
   return summary;
 }
@@ -6318,13 +6232,12 @@
 
   // EBX: Code (compiled code or lazy compile stub).
   ASSERT(locs()->in(0).reg() == EAX);
-  __ movl(EBX, FieldAddress(EAX, Function::code_offset()));
+  __ movl(EBX, FieldAddress(EAX, Function::instructions_offset()));
 
   // EAX: Function.
   // EDX: Arguments descriptor array.
   // ECX: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
   __ xorl(ECX, ECX);
-  __ movl(EBX, FieldAddress(EBX, Code::instructions_offset()));
   __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
   __ call(EBX);
   compiler->AddCurrentDescriptor(PcDescriptors::kClosureCall,
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index e4213a7..b8ba0c0 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -235,8 +235,7 @@
   // S5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
   ASSERT(locs()->in(0).reg() == T0);
   __ LoadImmediate(S5, 0);
-  __ lw(T2, FieldAddress(T0, Function::code_offset()));
-  __ lw(T2, FieldAddress(T2, Code::instructions_offset()));
+  __ lw(T2, FieldAddress(T0, Function::instructions_offset()));
   __ AddImmediate(T2, Instructions::HeaderSize() - kHeapObjectTag);
   __ jalr(T2);
   compiler->AddCurrentDescriptor(PcDescriptors::kClosureCall,
@@ -1466,57 +1465,64 @@
 }
 
 
-LocationSummary* GuardFieldInstr::MakeLocationSummary(Isolate* isolate,
-                                                      bool opt) const {
+LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Isolate* isolate,
+                                                           bool opt) const {
   const intptr_t kNumInputs = 1;
+
+  const intptr_t value_cid = value()->Type()->ToCid();
+  const intptr_t field_cid = field().guarded_cid();
+
+  const bool emit_full_guard = !opt || (field_cid == kIllegalCid);
+  const bool needs_value_cid_temp_reg =
+    (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid));
+  const bool needs_field_temp_reg = emit_full_guard;
+
+  intptr_t num_temps = 0;
+  if (needs_value_cid_temp_reg) {
+    num_temps++;
+  }
+  if (needs_field_temp_reg) {
+    num_temps++;
+  }
+
   LocationSummary* summary = new(isolate) LocationSummary(
-      isolate, kNumInputs, 0, LocationSummary::kNoCall);
+      isolate, kNumInputs, num_temps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
-  const bool field_has_length = field().needs_length_check();
-  const bool need_value_temp_reg =
-      (field_has_length || ((value()->Type()->ToCid() == kDynamicCid) &&
-                            (field().guarded_cid() != kSmiCid)));
-  if (need_value_temp_reg) {
-    summary->AddTemp(Location::RequiresRegister());
+
+  for (intptr_t i = 0; i < num_temps; i++) {
+    summary->set_temp(i, Location::RequiresRegister());
   }
-  const bool need_field_temp_reg =
-      field_has_length || (field().guarded_cid() == kIllegalCid);
-  if (need_field_temp_reg) {
-    summary->AddTemp(Location::RequiresRegister());
-  }
+
   return summary;
 }
 
 
-void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("GuardFieldInstr");
+void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  __ TraceSimMsg("GuardFieldClassInstr");
+
+  const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t field_cid = field().guarded_cid();
   const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
-  const intptr_t field_length = field().guarded_list_length();
-  const bool field_has_length = field().needs_length_check();
-  const bool needs_value_temp_reg =
-      (field_has_length || ((value()->Type()->ToCid() == kDynamicCid) &&
-                            (field().guarded_cid() != kSmiCid)));
-  const bool needs_field_temp_reg =
-      field_has_length || (field().guarded_cid() == kIllegalCid);
-  if (field_has_length) {
-    // Currently, we should only see final fields that remember length.
-    ASSERT(field().is_final());
-  }
 
   if (field_cid == kDynamicCid) {
     ASSERT(!compiler->is_optimizing());
     return;  // Nothing to emit.
   }
 
-  const intptr_t value_cid = value()->Type()->ToCid();
+  const bool emit_full_guard =
+      !compiler->is_optimizing() || (field_cid == kIllegalCid);
 
-  Register value_reg = locs()->in(0).reg();
+  const bool needs_value_cid_temp_reg =
+      (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid));
 
-  Register value_cid_reg = needs_value_temp_reg ?
+  const bool needs_field_temp_reg = emit_full_guard;
+
+  const Register value_reg = locs()->in(0).reg();
+
+  const Register value_cid_reg = needs_value_cid_temp_reg ?
       locs()->temp(0).reg() : kNoRegister;
 
-  Register field_reg = needs_field_temp_reg ?
+  const Register field_reg = needs_field_temp_reg ?
       locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister;
 
   Label ok, fail_label;
@@ -1526,87 +1532,18 @@
 
   Label* fail = (deopt != NULL) ? deopt : &fail_label;
 
-  if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) {
-    if (!compiler->is_optimizing() && (field_reg == kNoRegister)) {
-      // Currently we can't have different location summaries for optimized
-      // and non-optimized code. So instead we manually pick up a register
-      // that is known to be free because we know how non-optimizing compiler
-      // allocates registers.
-      field_reg = A0;
-      ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg));
-    }
-
+  if (emit_full_guard) {
     __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
 
     FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
     FieldAddress field_nullability_operand(
         field_reg, Field::is_nullable_offset());
-    FieldAddress field_length_operand(
-            field_reg, Field::guarded_list_length_offset());
 
     if (value_cid == kDynamicCid) {
-      if (value_cid_reg == kNoRegister) {
-        ASSERT(!compiler->is_optimizing());
-        value_cid_reg = A1;
-        ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
-      }
-
       LoadValueCid(compiler, value_cid_reg, value_reg);
 
-      Label skip_length_check;
-
       __ lw(CMPRES1, field_cid_operand);
-      __ bne(value_cid_reg, CMPRES1, &skip_length_check);
-      if (field_has_length) {
-        // Field guard may have remembered list length, check it.
-        if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
-          __ lw(TMP, FieldAddress(value_reg, Array::length_offset()));
-          __ LoadImmediate(CMPRES1, Smi::RawValue(field_length));
-          __ subu(CMPRES1, TMP, CMPRES1);
-        } else if (RawObject::IsTypedDataClassId(field_cid)) {
-          __ lw(TMP, FieldAddress(value_reg, TypedData::length_offset()));
-          __ LoadImmediate(CMPRES1, Smi::RawValue(field_length));
-          __ subu(CMPRES1, TMP, CMPRES1);
-        } else {
-          ASSERT(field_cid == kIllegalCid);
-          ASSERT(field_length == Field::kUnknownFixedLength);
-          // At compile time we do not know the type of the field nor its
-          // length. At execution time we may have set the class id and
-          // list length so we compare the guarded length with the
-          // list length here, without this check the list length could change
-          // without triggering a deoptimization.
-          Label check_array, length_compared, no_fixed_length;
-          // If length is negative the length guard is either disabled or
-          // has not been initialized, either way it is safe to skip the
-          // length check.
-          __ lw(CMPRES1, field_length_operand);
-          __ BranchSignedLess(CMPRES1, 0, &skip_length_check);
-          __ BranchEqual(value_cid_reg, kNullCid, &no_fixed_length);
-          // Check for typed data array.
-          __ BranchSignedGreater(value_cid_reg, kTypedDataInt32x4ArrayCid,
-                                 &no_fixed_length);
-          __ BranchSignedLess(value_cid_reg, kTypedDataInt8ArrayCid,
-                              &check_array);
-          __ lw(TMP, FieldAddress(value_reg, TypedData::length_offset()));
-          __ lw(CMPRES1, field_length_operand);
-          __ subu(CMPRES1, TMP, CMPRES1);
-          __ b(&length_compared);
-          // Check for regular array.
-          __ Bind(&check_array);
-          __ BranchSignedGreater(value_cid_reg, kImmutableArrayCid,
-                                 &no_fixed_length);
-          __ BranchSignedLess(value_cid_reg, kArrayCid, &no_fixed_length);
-          __ lw(TMP, FieldAddress(value_reg, Array::length_offset()));
-          __ lw(CMPRES1, field_length_operand);
-          __ subu(CMPRES1, TMP, CMPRES1);
-          __ b(&length_compared);
-          __ Bind(&no_fixed_length);
-          __ b(fail);
-          __ Bind(&length_compared);
-        }
-        __ bne(CMPRES1, ZR, fail);
-      }
-      __ Bind(&skip_length_check);
+      __ beq(value_cid_reg, CMPRES1, &ok);
       __ lw(TMP, field_nullability_operand);
       __ subu(CMPRES1, value_cid_reg, TMP);
     } else if (value_cid == kNullCid) {
@@ -1614,103 +1551,41 @@
       __ LoadImmediate(CMPRES1, value_cid);
       __ subu(CMPRES1, TMP, CMPRES1);
     } else {
-      Label skip_length_check;
       __ lw(TMP, field_cid_operand);
       __ LoadImmediate(CMPRES1, value_cid);
       __ subu(CMPRES1, TMP, CMPRES1);
-      __ bne(CMPRES1, ZR, &skip_length_check);
-      // Insert length check.
-      if (field_has_length) {
-        ASSERT(value_cid_reg != kNoRegister);
-        if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
-          __ lw(TMP, FieldAddress(value_reg, Array::length_offset()));
-          __ LoadImmediate(CMPRES1, Smi::RawValue(field_length));
-          __ subu(CMPRES1, TMP, CMPRES1);
-        } else if (RawObject::IsTypedDataClassId(value_cid)) {
-          __ lw(TMP, FieldAddress(value_reg, TypedData::length_offset()));
-          __ LoadImmediate(CMPRES1, Smi::RawValue(field_length));
-          __ subu(CMPRES1, TMP, CMPRES1);
-        } else if (field_cid != kIllegalCid) {
-          ASSERT(field_cid != value_cid);
-          ASSERT(field_length >= 0);
-          // Field has a known class id and length. At compile time it is
-          // known that the value's class id is not a fixed length list.
-          __ b(fail);
-        } else {
-          ASSERT(field_cid == kIllegalCid);
-          ASSERT(field_length == Field::kUnknownFixedLength);
-          // Following jump cannot not occur, fall through.
-        }
-        __ bne(CMPRES1, ZR, fail);
-      }
-      __ Bind(&skip_length_check);
     }
     __ beq(CMPRES1, ZR, &ok);
 
-    __ lw(CMPRES1, field_cid_operand);
-    __ BranchNotEqual(CMPRES1, kIllegalCid, fail);
+    // Check if the tracked state of the guarded field can be initialized
+    // inline. If the field needs length check we fall through to runtime
+    // which is responsible for computing offset of the length field
+    // based on the class id.
+    // Length guard will be emitted separately when needed via GuardFieldLength
+    // instruction after GuardFieldClass.
+    if (!field().needs_length_check()) {
+      // Uninitialized field can be handled inline. Check if the
+      // field is still unitialized.
+      __ lw(CMPRES1, field_cid_operand);
+      __ BranchNotEqual(CMPRES1, kIllegalCid, fail);
 
-    if (value_cid == kDynamicCid) {
-      __ sw(value_cid_reg, field_cid_operand);
-      __ sw(value_cid_reg, field_nullability_operand);
-      if (field_has_length) {
-        Label check_array, length_set, no_fixed_length;
-        __ BranchEqual(value_cid_reg, kNullCid, &no_fixed_length);
-        // Check for typed data array.
-        __ BranchSignedGreater(value_cid_reg, kTypedDataInt32x4ArrayCid,
-                               &no_fixed_length);
-        __ BranchSignedLess(value_cid_reg, kTypedDataInt8ArrayCid,
-                            &check_array);
-        // Destroy value_cid_reg (safe because we are finished with it).
-        __ lw(value_cid_reg,
-              FieldAddress(value_reg, TypedData::length_offset()));
-        __ sw(value_cid_reg, field_length_operand);
-        // Updated field length typed data array.
-        __ b(&length_set);
-        // Check for regular array.
-        __ Bind(&check_array);
-        __ BranchSignedGreater(value_cid_reg, kImmutableArrayCid,
-                               &no_fixed_length);
-        __ BranchSignedLess(value_cid_reg, kArrayCid, &no_fixed_length);
-        // Destroy value_cid_reg (safe because we are finished with it).
-        __ lw(value_cid_reg,
-                FieldAddress(value_reg, Array::length_offset()));
-        __ sw(value_cid_reg, field_length_operand);
-        // Updated field length from regular array.
-        __ b(&length_set);
-        __ Bind(&no_fixed_length);
-        __ LoadImmediate(TMP, Smi::RawValue(Field::kNoFixedLength));
-        __ sw(TMP, field_length_operand);
-        __ Bind(&length_set);
+      if (value_cid == kDynamicCid) {
+        __ sw(value_cid_reg, field_cid_operand);
+        __ sw(value_cid_reg, field_nullability_operand);
+      } else {
+        __ LoadImmediate(TMP, value_cid);
+        __ sw(TMP, field_cid_operand);
+        __ sw(TMP, field_nullability_operand);
       }
-    } else {
-      ASSERT(field_reg != kNoRegister);
-      __ LoadImmediate(TMP, value_cid);
-      __ sw(TMP, field_cid_operand);
-      __ sw(TMP, field_nullability_operand);
-      if (field_has_length) {
-        ASSERT(value_cid_reg != kNoRegister);
-        if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ lw(value_cid_reg,
-                FieldAddress(value_reg, Array::length_offset()));
-          __ sw(value_cid_reg, field_length_operand);
-        } else if (RawObject::IsTypedDataClassId(value_cid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ lw(value_cid_reg,
-                FieldAddress(value_reg, TypedData::length_offset()));
-          __ sw(value_cid_reg, field_length_operand);
-        } else {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ LoadImmediate(value_cid_reg, Smi::RawValue(Field::kNoFixedLength));
-          __ sw(value_cid_reg, field_length_operand);
-        }
+
+      if (deopt == NULL) {
+        ASSERT(!compiler->is_optimizing());
+        __ b(&ok);
       }
     }
 
     if (deopt == NULL) {
       ASSERT(!compiler->is_optimizing());
-      __ b(&ok);
       __ Bind(fail);
 
       __ lw(CMPRES1, FieldAddress(field_reg, Field::guarded_cid_offset()));
@@ -1725,12 +1600,10 @@
   } else {
     ASSERT(compiler->is_optimizing());
     ASSERT(deopt != NULL);
+
     // Field guard class has been initialized and is known.
-    if (field_reg != kNoRegister) {
-      __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
-    }
     if (value_cid == kDynamicCid) {
-      // Field's guarded class id is fixed by value's class id is not known.
+      // Value's class id is not known.
       __ andi(CMPRES1, value_reg, Immediate(kSmiTagMask));
 
       if (field_cid != kSmiCid) {
@@ -1740,61 +1613,111 @@
         __ subu(CMPRES1, value_cid_reg, TMP);
       }
 
-      if (field_has_length) {
-        // Jump when Value CID != Field guard CID
-        __ bne(CMPRES1, ZR, fail);
-        // Classes are same, perform guarded list length check.
-        ASSERT(field_reg != kNoRegister);
-        ASSERT(value_cid_reg != kNoRegister);
-        FieldAddress field_length_operand(
-            field_reg, Field::guarded_list_length_offset());
-        if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ lw(value_cid_reg,
-                FieldAddress(value_reg, Array::length_offset()));
-        } else if (RawObject::IsTypedDataClassId(field_cid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ lw(value_cid_reg,
-                FieldAddress(value_reg, TypedData::length_offset()));
-        }
-        __ lw(TMP, field_length_operand);
-        __ subu(CMPRES1, value_cid_reg, TMP);
-      }
-
       if (field().is_nullable() && (field_cid != kNullCid)) {
         __ beq(CMPRES1, ZR, &ok);
-        __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null()));
-        __ subu(CMPRES1, value_reg, TMP);
+        if (field_cid != kSmiCid) {
+          __ LoadImmediate(TMP, kNullCid);
+          __ subu(CMPRES1, value_cid_reg, TMP);
+        } else {
+          __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null()));
+          __ subu(CMPRES1, value_reg, TMP);
+        }
       }
 
       __ bne(CMPRES1, ZR, fail);
     } else {
       // Both value's and field's class id is known.
-      if ((value_cid != field_cid) && (value_cid != nullability)) {
-        __ b(fail);
-      } else if (field_has_length && (value_cid == field_cid)) {
-        ASSERT(value_cid_reg != kNoRegister);
-        if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ lw(value_cid_reg,
-                FieldAddress(value_reg, Array::length_offset()));
-        } else if (RawObject::IsTypedDataClassId(field_cid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ lw(value_cid_reg,
-                FieldAddress(value_reg, TypedData::length_offset()));
-        }
-        __ LoadImmediate(TMP, Smi::RawValue(field_length));
-        __ subu(CMPRES1, value_cid_reg, TMP);
-        __ bne(CMPRES1, ZR, fail);
-      } else {
-        UNREACHABLE();
-      }
+      ASSERT((value_cid != field_cid) && (value_cid != nullability));
+      __ b(fail);
     }
   }
   __ Bind(&ok);
 }
 
 
+LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Isolate* isolate,
+                                                            bool opt) const {
+  const intptr_t kNumInputs = 1;
+
+  if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) {
+    const intptr_t kNumTemps = 1;
+    LocationSummary* summary = new(isolate) LocationSummary(
+        isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    summary->set_in(0, Location::RequiresRegister());
+    // We need temporaries for field object.
+    summary->set_temp(0, Location::RequiresRegister());
+    return summary;
+  } else {
+    LocationSummary* summary = new(isolate) LocationSummary(
+        isolate, kNumInputs, 0, LocationSummary::kNoCall);
+    summary->set_in(0, Location::RequiresRegister());
+    return summary;
+  }
+  UNREACHABLE();
+}
+
+
+void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (field().guarded_list_length() == Field::kNoFixedLength) {
+    ASSERT(!compiler->is_optimizing());
+    return;  // Nothing to emit.
+  }
+
+  Label* deopt = compiler->is_optimizing() ?
+      compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL;
+
+  const Register value_reg = locs()->in(0).reg();
+
+  if (!compiler->is_optimizing() ||
+      (field().guarded_list_length() == Field::kUnknownFixedLength)) {
+    const Register field_reg = locs()->temp(0).reg();
+
+    Label ok;
+
+    __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
+
+    __ lb(CMPRES1, FieldAddress(field_reg,
+        Field::guarded_list_length_in_object_offset_offset()));
+    __ blez(CMPRES1, &ok);
+
+    __ lw(CMPRES2, FieldAddress(field_reg,
+        Field::guarded_list_length_offset()));
+
+    // Load the length from the value. GuardFieldClass already verified that
+    // value's class matches guarded class id of the field.
+    // CMPRES1 contains offset already corrected by -kHeapObjectTag that is
+    // why we can use Address instead of FieldAddress.
+    __ addu(TMP, value_reg, CMPRES1);
+    __ lw(TMP, Address(TMP));
+
+    if (deopt == NULL) {
+      __ beq(CMPRES2, TMP, &ok);
+
+      __ addiu(SP, SP, Immediate(-2 * kWordSize));
+      __ sw(field_reg, Address(SP, 1 * kWordSize));
+      __ sw(value_reg, Address(SP, 0 * kWordSize));
+      __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
+      __ Drop(2);  // Drop the field and the value.
+    } else {
+      __ bne(CMPRES2, TMP, deopt);
+    }
+
+    __ Bind(&ok);
+  } else {
+    ASSERT(compiler->is_optimizing());
+    ASSERT(field().guarded_list_length() >= 0);
+    ASSERT(field().guarded_list_length_in_object_offset() !=
+        Field::kUnknownLengthOffset);
+
+    __ lw(CMPRES1,
+          FieldAddress(value_reg,
+                       field().guarded_list_length_in_object_offset()));
+    __ LoadImmediate(TMP, Smi::RawValue(field().guarded_list_length()));
+    __ bne(CMPRES1, TMP, deopt);
+  }
+}
+
+
 class StoreInstanceFieldSlowPath : public SlowPathCode {
  public:
   StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction,
@@ -1831,7 +1754,9 @@
 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Isolate* isolate,
                                                               bool opt) const {
   const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps =
+      (IsUnboxedStore() && opt) ? 2 :
+          ((IsPotentialUnboxedStore()) ? 3 : 0);
   LocationSummary* summary = new(isolate) LocationSummary(
       isolate, kNumInputs, kNumTemps,
           !field().IsNull() &&
@@ -1842,16 +1767,16 @@
   summary->set_in(0, Location::RequiresRegister());
   if (IsUnboxedStore() && opt) {
     summary->set_in(1, Location::RequiresFpuRegister());
-    summary->AddTemp(Location::RequiresRegister());
-    summary->AddTemp(Location::RequiresRegister());
+    summary->set_temp(0, Location::RequiresRegister());
+    summary->set_temp(1, Location::RequiresRegister());
   } else if (IsPotentialUnboxedStore()) {
     summary->set_in(1, ShouldEmitStoreBarrier()
         ? Location::WritableRegister()
         :  Location::RequiresRegister());
-    summary->AddTemp(Location::RequiresRegister());
-    summary->AddTemp(Location::RequiresRegister());
-    summary->AddTemp(opt ? Location::RequiresFpuRegister()
-                         : Location::FpuRegisterLocation(D1));
+    summary->set_temp(0, Location::RequiresRegister());
+    summary->set_temp(1, Location::RequiresRegister());
+    summary->set_temp(2, opt ? Location::RequiresFpuRegister()
+                             : Location::FpuRegisterLocation(D1));
   } else {
     summary->set_in(1, ShouldEmitStoreBarrier()
                        ? Location::WritableRegister()
@@ -2238,7 +2163,9 @@
 LocationSummary* LoadFieldInstr::MakeLocationSummary(Isolate* isolate,
                                                      bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps =
+      (IsUnboxedLoad() && opt) ? 1 :
+          ((IsPotentialUnboxedLoad()) ? 2 : 0);
   LocationSummary* locs = new(isolate) LocationSummary(
       isolate, kNumInputs, kNumTemps,
           (opt && !IsPotentialUnboxedLoad())
@@ -2248,11 +2175,11 @@
   locs->set_in(0, Location::RequiresRegister());
 
   if (IsUnboxedLoad() && opt) {
-    locs->AddTemp(Location::RequiresRegister());
+    locs->set_temp(0, Location::RequiresRegister());
   } else if (IsPotentialUnboxedLoad()) {
-    locs->AddTemp(opt ? Location::RequiresFpuRegister()
-                      : Location::FpuRegisterLocation(D1));
-    locs->AddTemp(Location::RequiresRegister());
+    locs->set_temp(0, opt ? Location::RequiresFpuRegister()
+                          : Location::FpuRegisterLocation(D1));
+    locs->set_temp(1, Location::RequiresRegister());
   }
   locs->set_out(0, Location::RequiresRegister());
   return locs;
@@ -2756,7 +2683,12 @@
 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Isolate* isolate,
                                                        bool opt) const {
   const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = op_kind() == Token::kADD ? 1 : 0;
+  const intptr_t kNumTemps =
+      ((op_kind() == Token::kADD) ||
+       (op_kind() == Token::kMOD) ||
+       (op_kind() == Token::kTRUNCDIV) ||
+       (((op_kind() == Token::kSHL) && !is_truncating()) ||
+         (op_kind() == Token::kSHR))) ? 1 : 0;
   LocationSummary* summary = new(isolate) LocationSummary(
       isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   if (op_kind() == Token::kTRUNCDIV) {
@@ -2767,14 +2699,14 @@
     } else {
       summary->set_in(1, Location::RequiresRegister());
     }
-    summary->AddTemp(Location::RequiresRegister());
+    summary->set_temp(0, Location::RequiresRegister());
     summary->set_out(0, Location::RequiresRegister());
     return summary;
   }
   if (op_kind() == Token::kMOD) {
     summary->set_in(0, Location::RequiresRegister());
     summary->set_in(1, Location::RequiresRegister());
-    summary->AddTemp(Location::RequiresRegister());
+    summary->set_temp(0, Location::RequiresRegister());
     summary->set_out(0, Location::RequiresRegister());
     return summary;
   }
@@ -2782,7 +2714,7 @@
   summary->set_in(1, Location::RegisterOrSmiConstant(right()));
   if (((op_kind() == Token::kSHL) && !is_truncating()) ||
       (op_kind() == Token::kSHR)) {
-    summary->AddTemp(Location::RequiresRegister());
+    summary->set_temp(0, Location::RequiresRegister());
   } else if (op_kind() == Token::kADD) {
     // Need an extra temp for the overflow detection code.
     summary->set_temp(0, Location::RequiresRegister());
@@ -4348,12 +4280,12 @@
 LocationSummary* CheckClassInstr::MakeLocationSummary(Isolate* isolate,
                                                       bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps = !IsNullCheck() ? 1 : 0;
   LocationSummary* summary = new(isolate) LocationSummary(
       isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
   if (!IsNullCheck()) {
-    summary->AddTemp(Location::RequiresRegister());
+    summary->set_temp(0, Location::RequiresRegister());
   }
   return summary;
 }
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 0e2102e..90aeed8 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -1303,56 +1303,63 @@
 }
 
 
-LocationSummary* GuardFieldInstr::MakeLocationSummary(Isolate* isolate,
-                                                      bool opt) const {
+LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Isolate* isolate,
+                                                           bool opt) const {
   const intptr_t kNumInputs = 1;
+
+  const intptr_t value_cid = value()->Type()->ToCid();
+  const intptr_t field_cid = field().guarded_cid();
+
+  const bool emit_full_guard = !opt || (field_cid == kIllegalCid);
+  const bool needs_value_cid_temp_reg =
+    (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid));
+  const bool needs_field_temp_reg = emit_full_guard;
+
+  intptr_t num_temps = 0;
+  if (needs_value_cid_temp_reg) {
+    num_temps++;
+  }
+  if (needs_field_temp_reg) {
+    num_temps++;
+  }
+
   LocationSummary* summary = new(isolate) LocationSummary(
-      isolate, kNumInputs, 0, LocationSummary::kNoCall);
+      isolate, kNumInputs, num_temps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
-  const bool field_has_length = field().needs_length_check();
-  const bool need_value_temp_reg =
-      (field_has_length || ((value()->Type()->ToCid() == kDynamicCid) &&
-                            (field().guarded_cid() != kSmiCid)));
-  if (need_value_temp_reg) {
-    summary->AddTemp(Location::RequiresRegister());
+
+  for (intptr_t i = 0; i < num_temps; i++) {
+    summary->set_temp(i, Location::RequiresRegister());
   }
-  const bool need_field_temp_reg =
-      field_has_length || (field().guarded_cid() == kIllegalCid);
-  if (need_field_temp_reg) {
-    summary->AddTemp(Location::RequiresRegister());
-  }
+
+
   return summary;
 }
 
 
-void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t field_cid = field().guarded_cid();
   const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
-  const intptr_t field_length = field().guarded_list_length();
-  const bool field_has_length = field().needs_length_check();
-  const bool needs_value_temp_reg =
-      (field_has_length || ((value()->Type()->ToCid() == kDynamicCid) &&
-                            (field().guarded_cid() != kSmiCid)));
-  const bool needs_field_temp_reg =
-      field_has_length || (field().guarded_cid() == kIllegalCid);
-  if (field_has_length) {
-    // Currently, we should only see final fields that remember length.
-    ASSERT(field().is_final());
-  }
 
   if (field_cid == kDynamicCid) {
     ASSERT(!compiler->is_optimizing());
     return;  // Nothing to emit.
   }
 
-  const intptr_t value_cid = value()->Type()->ToCid();
+  const bool emit_full_guard =
+      !compiler->is_optimizing() || (field_cid == kIllegalCid);
 
-  Register value_reg = locs()->in(0).reg();
+  const bool needs_value_cid_temp_reg =
+      (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid));
 
-  Register value_cid_reg = needs_value_temp_reg ?
+  const bool needs_field_temp_reg = emit_full_guard;
+
+  const Register value_reg = locs()->in(0).reg();
+
+  const Register value_cid_reg = needs_value_cid_temp_reg ?
       locs()->temp(0).reg() : kNoRegister;
 
-  Register field_reg = needs_field_temp_reg ?
+  const Register field_reg = needs_field_temp_reg ?
       locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister;
 
   Label ok, fail_label;
@@ -1362,207 +1369,53 @@
 
   Label* fail = (deopt != NULL) ? deopt : &fail_label;
 
-  if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) {
-    if (!compiler->is_optimizing() && (field_reg == kNoRegister)) {
-      // Currently we can't have different location summaries for optimized
-      // and non-optimized code. So instead we manually pick up a register
-      // that is known to be free because we know how non-optimizing compiler
-      // allocates registers.
-      field_reg = RBX;
-      ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg));
-    }
-
+  if (emit_full_guard) {
     __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
 
     FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
     FieldAddress field_nullability_operand(
         field_reg, Field::is_nullable_offset());
-    FieldAddress field_length_operand(
-        field_reg, Field::guarded_list_length_offset());
 
     if (value_cid == kDynamicCid) {
-      if (value_cid_reg == kNoRegister) {
-        ASSERT(!compiler->is_optimizing());
-        value_cid_reg = RDX;
-        ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
-      }
-
       LoadValueCid(compiler, value_cid_reg, value_reg);
 
-      Label skip_length_check;
       __ cmpq(value_cid_reg, field_cid_operand);
-      __ j(NOT_EQUAL, &skip_length_check);
-      if (field_has_length) {
-        // Field guard may have remembered list length, check it.
-        if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
-          __ pushq(value_cid_reg);
-          __ movq(value_cid_reg,
-                  FieldAddress(value_reg, Array::length_offset()));
-          __ CompareImmediate(
-              value_cid_reg, Immediate(Smi::RawValue(field_length)), PP);
-          __ popq(value_cid_reg);
-        } else if (RawObject::IsTypedDataClassId(field_cid)) {
-          __ pushq(value_cid_reg);
-          __ movq(value_cid_reg,
-                  FieldAddress(value_reg, TypedData::length_offset()));
-          __ CompareImmediate(
-              value_cid_reg, Immediate(Smi::RawValue(field_length)), PP);
-          __ popq(value_cid_reg);
-        } else {
-          ASSERT(field_cid == kIllegalCid);
-          ASSERT(field_length == Field::kUnknownFixedLength);
-          // At compile time we do not know the type of the field nor its
-          // length. At execution time we may have set the class id and
-          // list length so we compare the guarded length with the
-          // list length here, without this check the list length could change
-          // without triggering a deoptimization.
-          Label check_array, length_compared, no_fixed_length;
-          // If length is negative the length guard is either disabled or
-          // has not been initialized, either way it is safe to skip the
-          // length check.
-          __ CompareImmediate(
-              field_length_operand, Immediate(Smi::RawValue(0)), PP);
-          __ j(LESS, &skip_length_check);
-          __ CompareImmediate(value_cid_reg, Immediate(kNullCid), PP);
-          __ j(EQUAL, &no_fixed_length, Assembler::kNearJump);
-          // Check for typed data array.
-          __ CompareImmediate(
-              value_cid_reg, Immediate(kTypedDataInt32x4ArrayCid), PP);
-          // Not a typed array or a regular array.
-          __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
-          __ CompareImmediate(
-              value_cid_reg, Immediate(kTypedDataInt8ArrayCid), PP);
-          // Could still be a regular array.
-          __ j(LESS, &check_array, Assembler::kNearJump);
-          __ pushq(value_cid_reg);
-          __ movq(value_cid_reg,
-                  FieldAddress(value_reg, TypedData::length_offset()));
-          __ cmpq(field_length_operand, value_cid_reg);
-          __ popq(value_cid_reg);
-          __ jmp(&length_compared, Assembler::kNearJump);
-          // Check for regular array.
-          __ Bind(&check_array);
-          __ CompareImmediate(value_cid_reg, Immediate(kImmutableArrayCid), PP);
-          __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
-          __ CompareImmediate(value_cid_reg, Immediate(kArrayCid), PP);
-          __ j(LESS, &no_fixed_length, Assembler::kNearJump);
-          __ pushq(value_cid_reg);
-          __ movq(value_cid_reg,
-                  FieldAddress(value_reg, Array::length_offset()));
-          __ cmpq(field_length_operand, value_cid_reg);
-          __ popq(value_cid_reg);
-          __ jmp(&length_compared, Assembler::kNearJump);
-          __ Bind(&no_fixed_length);
-          __ jmp(fail);
-          __ Bind(&length_compared);
-        }
-        __ j(NOT_EQUAL, fail);
-      }
-      __ Bind(&skip_length_check);
+      __ j(EQUAL, &ok);
       __ cmpq(value_cid_reg, field_nullability_operand);
     } else if (value_cid == kNullCid) {
       __ CompareImmediate(field_nullability_operand, Immediate(value_cid), PP);
     } else {
-      Label skip_length_check;
       __ CompareImmediate(field_cid_operand, Immediate(value_cid), PP);
-      // If not equal, skip over length check.
-      __ j(NOT_EQUAL, &skip_length_check);
-      // Insert length check.
-      if (field_has_length) {
-        ASSERT(value_cid_reg != kNoRegister);
-        if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
-          __ CompareImmediate(FieldAddress(value_reg, Array::length_offset()),
-                              Immediate(Smi::RawValue(field_length)), PP);
-        } else if (RawObject::IsTypedDataClassId(value_cid)) {
-          __ CompareImmediate(
-            FieldAddress(value_reg, TypedData::length_offset()),
-            Immediate(Smi::RawValue(field_length)), PP);
-        } else if (field_cid != kIllegalCid) {
-          ASSERT(field_cid != value_cid);
-          ASSERT(field_length >= 0);
-          // Field has a known class id and length. At compile time it is
-          // known that the value's class id is not a fixed length list.
-          __ jmp(fail);
-        } else {
-          ASSERT(field_cid == kIllegalCid);
-          ASSERT(field_length == Field::kUnknownFixedLength);
-          // Following jump cannot not occur, fall through.
-        }
-        __ j(NOT_EQUAL, fail);
-      }
-      // Not identical, possibly null.
-      __ Bind(&skip_length_check);
     }
     __ j(EQUAL, &ok);
 
-    __ CompareImmediate(field_cid_operand, Immediate(kIllegalCid), PP);
-    __ j(NOT_EQUAL, fail);
+    // Check if the tracked state of the guarded field can be initialized
+    // inline. If the field needs length check we fall through to runtime
+    // which is responsible for computing offset of the length field
+    // based on the class id.
+    if (!field().needs_length_check()) {
+      // Uninitialized field can be handled inline. Check if the
+      // field is still unitialized.
+      __ CompareImmediate(field_cid_operand, Immediate(kIllegalCid), PP);
+      __ j(NOT_EQUAL, fail);
 
-    if (value_cid == kDynamicCid) {
-      __ movq(field_cid_operand, value_cid_reg);
-      __ movq(field_nullability_operand, value_cid_reg);
-      if (field_has_length) {
-        Label check_array, length_set, no_fixed_length;
-        __ CompareImmediate(value_cid_reg, Immediate(kNullCid), PP);
-        __ j(EQUAL, &no_fixed_length, Assembler::kNearJump);
-        // Check for typed data array.
-        __ CompareImmediate(value_cid_reg,
-                            Immediate(kTypedDataInt32x4ArrayCid), PP);
-        // Not a typed array or a regular array.
-        __ j(GREATER, &no_fixed_length);
-        __ CompareImmediate(
-            value_cid_reg, Immediate(kTypedDataInt8ArrayCid), PP);
-        // Could still be a regular array.
-        __ j(LESS, &check_array, Assembler::kNearJump);
-        // Destroy value_cid_reg (safe because we are finished with it).
-        __ movq(value_cid_reg,
-                FieldAddress(value_reg, TypedData::length_offset()));
-        __ movq(field_length_operand, value_cid_reg);
-        // Updated field length typed data array.
-        __ jmp(&length_set);
-        // Check for regular array.
-        __ Bind(&check_array);
-        __ CompareImmediate(value_cid_reg, Immediate(kImmutableArrayCid), PP);
-        __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
-        __ CompareImmediate(value_cid_reg, Immediate(kArrayCid), PP);
-        __ j(LESS, &no_fixed_length, Assembler::kNearJump);
-        // Destroy value_cid_reg (safe because we are finished with it).
-        __ movq(value_cid_reg,
-                FieldAddress(value_reg, Array::length_offset()));
-        __ movq(field_length_operand, value_cid_reg);
-        // Updated field length from regular array.
-        __ jmp(&length_set, Assembler::kNearJump);
-        __ Bind(&no_fixed_length);
-        __ LoadImmediate(field_length_operand,
-            Immediate(Smi::RawValue(Field::kNoFixedLength)), PP);
-        __ Bind(&length_set);
+      if (value_cid == kDynamicCid) {
+        __ movq(field_cid_operand, value_cid_reg);
+        __ movq(field_nullability_operand, value_cid_reg);
+      } else {
+        ASSERT(field_reg != kNoRegister);
+        __ LoadImmediate(field_cid_operand, Immediate(value_cid), PP);
+        __ LoadImmediate(field_nullability_operand, Immediate(value_cid), PP);
       }
-    } else {
-      ASSERT(field_reg != kNoRegister);
-      __ LoadImmediate(field_cid_operand, Immediate(value_cid), PP);
-      __ LoadImmediate(field_nullability_operand, Immediate(value_cid), PP);
-      if (field_has_length) {
-        ASSERT(value_cid_reg != kNoRegister);
-        if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ movq(value_cid_reg,
-                  FieldAddress(value_reg, Array::length_offset()));
-          __ movq(field_length_operand, value_cid_reg);
-        } else if (RawObject::IsTypedDataClassId(value_cid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ movq(value_cid_reg,
-                  FieldAddress(value_reg, TypedData::length_offset()));
-          __ movq(field_length_operand, value_cid_reg);
-        } else {
-          __ LoadImmediate(field_length_operand,
-                  Immediate(Smi::RawValue(Field::kNoFixedLength)), PP);
-        }
+
+      if (deopt == NULL) {
+        ASSERT(!compiler->is_optimizing());
+        __ jmp(&ok);
       }
     }
 
     if (deopt == NULL) {
       ASSERT(!compiler->is_optimizing());
-      __ jmp(&ok);
       __ Bind(fail);
 
       __ CompareImmediate(FieldAddress(field_reg, Field::guarded_cid_offset()),
@@ -1577,13 +1430,10 @@
   } else {
     ASSERT(compiler->is_optimizing());
     ASSERT(deopt != NULL);
-    // Field guard class has been initialized and is known.
-    if (field_reg != kNoRegister) {
-      __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
-    }
 
+    // Field guard class has been initialized and is known.
     if (value_cid == kDynamicCid) {
-      // Field's guarded class id is fixed but value's class id is not known.
+      // Value's class id is not known.
       __ testq(value_reg, Immediate(kSmiTagMask));
 
       if (field_cid != kSmiCid) {
@@ -1592,59 +1442,108 @@
         __ CompareImmediate(value_cid_reg, Immediate(field_cid), PP);
       }
 
-      if (field_has_length) {
-        // Jump when Value CID != Field guard CID
-        __ j(NOT_EQUAL, fail);
-
-        // Classes are same, perform guarded list length check.
-        ASSERT(field_reg != kNoRegister);
-        ASSERT(value_cid_reg != kNoRegister);
-        FieldAddress field_length_operand(
-            field_reg, Field::guarded_list_length_offset());
-        if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ movq(value_cid_reg,
-                  FieldAddress(value_reg, Array::length_offset()));
-        } else if (RawObject::IsTypedDataClassId(field_cid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ movq(value_cid_reg,
-                  FieldAddress(value_reg, TypedData::length_offset()));
-        }
-        __ cmpq(value_cid_reg, field_length_operand);
-      }
-
       if (field().is_nullable() && (field_cid != kNullCid)) {
         __ j(EQUAL, &ok);
         __ CompareObject(value_reg, Object::null_object(), PP);
       }
+
       __ j(NOT_EQUAL, fail);
     } else {
       // Both value's and field's class id is known.
-      if ((value_cid != field_cid) && (value_cid != nullability)) {
-        __ jmp(fail);
-      } else if (field_has_length && (value_cid == field_cid)) {
-        ASSERT(value_cid_reg != kNoRegister);
-        if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ movq(value_cid_reg,
-                  FieldAddress(value_reg, Array::length_offset()));
-        } else if (RawObject::IsTypedDataClassId(field_cid)) {
-          // Destroy value_cid_reg (safe because we are finished with it).
-          __ movq(value_cid_reg,
-                  FieldAddress(value_reg, TypedData::length_offset()));
-        }
-        __ CompareImmediate(
-            value_cid_reg, Immediate(Smi::RawValue(field_length)), PP);
-        __ j(NOT_EQUAL, fail);
-      } else {
-        UNREACHABLE();
-      }
+      ASSERT((value_cid != field_cid) && (value_cid != nullability));
+      __ jmp(fail);
     }
   }
   __ Bind(&ok);
 }
 
 
+LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Isolate* isolate,
+                                                            bool opt) const {
+  const intptr_t kNumInputs = 1;
+  if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) {
+    const intptr_t kNumTemps = 3;
+    LocationSummary* summary = new(isolate) LocationSummary(
+        isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    summary->set_in(0, Location::RequiresRegister());
+    // We need temporaries for field object, length offset and expected length.
+    summary->set_temp(0, Location::RequiresRegister());
+    summary->set_temp(1, Location::RequiresRegister());
+    summary->set_temp(2, Location::RequiresRegister());
+    return summary;
+  } else {
+    LocationSummary* summary = new(isolate) LocationSummary(
+        isolate, kNumInputs, 0, LocationSummary::kNoCall);
+    summary->set_in(0, Location::RequiresRegister());
+    return summary;
+  }
+  UNREACHABLE();
+}
+
+
+void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (field().guarded_list_length() == Field::kNoFixedLength) {
+    ASSERT(!compiler->is_optimizing());
+    return;  // Nothing to emit.
+  }
+
+  Label* deopt = compiler->is_optimizing() ?
+      compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL;
+
+  const Register value_reg = locs()->in(0).reg();
+
+  if (!compiler->is_optimizing() ||
+      (field().guarded_list_length() == Field::kUnknownFixedLength)) {
+    const Register field_reg = locs()->temp(0).reg();
+    const Register offset_reg = locs()->temp(1).reg();
+    const Register length_reg = locs()->temp(2).reg();
+
+    Label ok;
+
+    __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
+
+    __ movsxb(offset_reg, FieldAddress(field_reg,
+        Field::guarded_list_length_in_object_offset_offset()));
+    __ movq(length_reg, FieldAddress(field_reg,
+        Field::guarded_list_length_offset()));
+
+    __ cmpq(offset_reg, Immediate(0));
+    __ j(NEGATIVE, &ok);
+
+    // Load the length from the value. GuardFieldClass already verified that
+    // value's class matches guarded class id of the field.
+    // offset_reg contains offset already corrected by -kHeapObjectTag that is
+    // why we use Address instead of FieldAddress.
+    __ cmpq(length_reg, Address(value_reg, offset_reg, TIMES_1, 0));
+
+    if (deopt == NULL) {
+      __ j(EQUAL, &ok);
+
+      __ pushq(field_reg);
+      __ pushq(value_reg);
+      __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
+      __ Drop(2);  // Drop the field and the value.
+    } else {
+      __ j(NOT_EQUAL, deopt);
+    }
+
+    __ Bind(&ok);
+  } else {
+    ASSERT(compiler->is_optimizing());
+    ASSERT(field().guarded_list_length() >= 0);
+    ASSERT(field().guarded_list_length_in_object_offset() !=
+        Field::kUnknownLengthOffset);
+
+    __ CompareImmediate(
+            FieldAddress(value_reg,
+                         field().guarded_list_length_in_object_offset()),
+            Immediate(Smi::RawValue(field().guarded_list_length())),
+            PP);
+    __ j(NOT_EQUAL, deopt);
+  }
+}
+
+
 class StoreInstanceFieldSlowPath : public SlowPathCode {
  public:
   StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction,
@@ -1681,7 +1580,9 @@
 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Isolate* isolate,
                                                               bool opt) const {
   const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps =
+      (IsUnboxedStore() && opt) ? 2 :
+          ((IsPotentialUnboxedStore()) ? 3 : 0);
   LocationSummary* summary = new(isolate) LocationSummary(
       isolate, kNumInputs, kNumTemps,
           !field().IsNull() &&
@@ -1692,16 +1593,16 @@
   summary->set_in(0, Location::RequiresRegister());
   if (IsUnboxedStore() && opt) {
     summary->set_in(1, Location::RequiresFpuRegister());
-    summary->AddTemp(Location::RequiresRegister());
-    summary->AddTemp(Location::RequiresRegister());
+    summary->set_temp(0, Location::RequiresRegister());
+    summary->set_temp(1, Location::RequiresRegister());
   } else if (IsPotentialUnboxedStore()) {
     summary->set_in(1, ShouldEmitStoreBarrier()
         ? Location::WritableRegister()
         :  Location::RequiresRegister());
-    summary->AddTemp(Location::RequiresRegister());
-    summary->AddTemp(Location::RequiresRegister());
-    summary->AddTemp(opt ? Location::RequiresFpuRegister()
-                         : Location::FpuRegisterLocation(XMM1));
+    summary->set_temp(0, Location::RequiresRegister());
+    summary->set_temp(1, Location::RequiresRegister());
+    summary->set_temp(2, opt ? Location::RequiresFpuRegister()
+                             : Location::FpuRegisterLocation(XMM1));
   } else {
     summary->set_in(1, ShouldEmitStoreBarrier()
                        ? Location::WritableRegister()
@@ -2227,7 +2128,9 @@
 LocationSummary* LoadFieldInstr::MakeLocationSummary(Isolate* isolate,
                                                      bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps =
+      (IsUnboxedLoad() && opt) ? 1 :
+          ((IsPotentialUnboxedLoad()) ? 2 : 0);
   LocationSummary* locs = new(isolate) LocationSummary(
       isolate, kNumInputs, kNumTemps,
           (opt && !IsPotentialUnboxedLoad())
@@ -2237,11 +2140,11 @@
   locs->set_in(0, Location::RequiresRegister());
 
   if (IsUnboxedLoad() && opt) {
-    locs->AddTemp(Location::RequiresRegister());
+    locs->set_temp(0, Location::RequiresRegister());
   } else if (IsPotentialUnboxedLoad()) {
-    locs->AddTemp(opt ? Location::RequiresFpuRegister()
-                      : Location::FpuRegisterLocation(XMM1));
-    locs->AddTemp(Location::RequiresRegister());
+    locs->set_temp(0, opt ? Location::RequiresFpuRegister()
+                          : Location::FpuRegisterLocation(XMM1));
+    locs->set_temp(1, Location::RequiresRegister());
   }
   locs->set_out(0, Location::RequiresRegister());
   return locs;
@@ -2867,13 +2770,13 @@
     summary->set_out(0, Location::SameAsFirstInput());
     return summary;
   } else if (op_kind() == Token::kSHL) {
-    const intptr_t kNumTemps = 0;
+    const intptr_t kNumTemps = !is_truncating() ? 1 : 0;
     LocationSummary* summary = new(isolate) LocationSummary(
         isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
     summary->set_in(0, Location::RequiresRegister());
     summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX));
     if (!is_truncating()) {
-      summary->AddTemp(Location::RequiresRegister());
+      summary->set_temp(0, Location::RequiresRegister());
     }
     summary->set_out(0, Location::SameAsFirstInput());
     return summary;
@@ -5004,7 +4907,8 @@
   // assumes that XMM0 is free at all times.
   // TODO(vegorov): allow XMM0 to be used.
   ASSERT((InputCount() == 1) || (InputCount() == 2));
-  const intptr_t kNumTemps = 1;
+  const intptr_t kNumTemps =
+      (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1;
   LocationSummary* result = new(isolate) LocationSummary(
       isolate, InputCount(), kNumTemps, LocationSummary::kCall);
   result->set_temp(0, Location::RegisterLocation(R13));
@@ -5014,9 +4918,9 @@
   }
   if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
     // Temp index 1.
-    result->AddTemp(Location::RegisterLocation(RAX));
+    result->set_temp(1, Location::RegisterLocation(RAX));
     // Temp index 2.
-    result->AddTemp(Location::FpuRegisterLocation(XMM4));
+    result->set_temp(2, Location::FpuRegisterLocation(XMM4));
   }
   result->set_out(0, Location::FpuRegisterLocation(XMM3));
   return result;
@@ -5462,12 +5366,12 @@
 LocationSummary* CheckClassInstr::MakeLocationSummary(Isolate* isolate,
                                                       bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps = !IsNullCheck() ? 1 : 0;
   LocationSummary* summary = new(isolate) LocationSummary(
       isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
   if (!IsNullCheck()) {
-    summary->AddTemp(Location::RequiresRegister());
+    summary->set_temp(0, Location::RequiresRegister());
   }
   return summary;
 }
@@ -5857,13 +5761,12 @@
 
   // Function in RAX.
   ASSERT(locs()->in(0).reg() == RAX);
-  __ movq(RCX, FieldAddress(RAX, Function::code_offset()));
+  __ movq(RCX, FieldAddress(RAX, Function::instructions_offset()));
 
   // RAX: Function.
   // R10: Arguments descriptor array.
   // RBX: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
   __ xorq(RBX, RBX);
-  __ movq(RCX, FieldAddress(RCX, Code::instructions_offset()));
   __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
   __ call(RCX);
   compiler->AddCurrentDescriptor(PcDescriptors::kClosureCall,
diff --git a/runtime/vm/intrinsifier.h b/runtime/vm/intrinsifier.h
index 98b2267..d619f5b 100644
--- a/runtime/vm/intrinsifier.h
+++ b/runtime/vm/intrinsifier.h
@@ -131,6 +131,8 @@
   V(_Float32x4Array, ., TypedData_Float32x4Array_factory, 879975401)           \
   V(_Int32x4Array, ., TypedData_Int32x4Array_factory, 924582681)               \
   V(_Float64x2Array, ., TypedData_Float64x2Array_factory, 1654170890)          \
+  V(_Uint8Array, [], Uint8Array_getIndexed, 738731818)                         \
+  V(_ExternalUint8Array, [], ExternalUint8Array_getIndexed, 2067666479)        \
 
 
 #define PROFILER_LIB_INTRINSIC_LIST(V)                                         \
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index f523d9f..b0dd01c 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -43,7 +43,7 @@
   __ tst(R0, Operand(kSmiTagMask));
   __ b(&fall_through, NE);  // Index is not an smi, fall through
 
-  // range check
+  // Range check.
   __ ldr(R6, FieldAddress(R1, Array::length_offset()));
   __ cmp(R0, Operand(R6));
 
@@ -228,7 +228,7 @@
   __ tst(R0, Operand(kSmiTagMask));
   __ b(&fall_through, NE);  // Index is not an smi, fall through
 
-  // range check
+  // Range check.
   __ ldr(R6, FieldAddress(R1, GrowableObjectArray::length_offset()));
   __ cmp(R0, Operand(R6));
 
@@ -431,6 +431,50 @@
 }
 
 
+void Intrinsifier::Uint8Array_getIndexed(Assembler* assembler) {
+  Label fall_through;
+  __ ldr(R0, Address(SP, + 0 * kWordSize));  // Index.
+  __ ldr(R1, Address(SP, + 1 * kWordSize));  // Array.
+  __ tst(R0, Operand(kSmiTagMask));
+  __ b(&fall_through, NE);  // Index is not a smi, fall through.
+
+  // Range check.
+  __ ldr(R6, FieldAddress(R1, TypedData::length_offset()));
+  __ cmp(R0, Operand(R6));
+  __ b(&fall_through, CS);
+
+  __ SmiUntag(R0);
+  __ AddImmediate(R1, TypedData::data_offset() - kHeapObjectTag);
+  __ ldrb(R0, Address(R1, R0));
+  __ SmiTag(R0);
+  __ Ret();
+  __ Bind(&fall_through);
+}
+
+
+void Intrinsifier::ExternalUint8Array_getIndexed(Assembler* assembler) {
+  Label fall_through;
+
+  __ ldr(R0, Address(SP, + 0 * kWordSize));  // Index.
+  __ ldr(R1, Address(SP, + 1 * kWordSize));  // Array.
+  __ tst(R0, Operand(kSmiTagMask));
+  __ b(&fall_through, NE);  // Index is not a smi, fall through.
+
+  // Range check.
+  __ ldr(R6, FieldAddress(R1, TypedData::length_offset()));
+  __ cmp(R0, Operand(R6));
+  __ b(&fall_through, CS);
+
+  __ LoadFromOffset(kWord, R1, R1,
+      ExternalTypedData::data_offset() - kHeapObjectTag);
+  __ SmiUntag(R0);
+  __ ldrb(R0, Address(R1, R0));
+  __ SmiTag(R0);
+  __ Ret();
+  __ Bind(&fall_through);
+}
+
+
 static int GetScaleFactor(intptr_t size) {
   switch (size) {
     case 1: return 0;
diff --git a/runtime/vm/intrinsifier_arm64.cc b/runtime/vm/intrinsifier_arm64.cc
index 5d9d5bd..e8a5ee4 100644
--- a/runtime/vm/intrinsifier_arm64.cc
+++ b/runtime/vm/intrinsifier_arm64.cc
@@ -41,7 +41,7 @@
   __ tsti(R0, kSmiTagMask);
   __ b(&fall_through, NE);  // Index is not an smi, fall through.
 
-  // range check
+  // Range check.
   __ ldr(R6, FieldAddress(R1, Array::length_offset()));
   __ cmp(R0, Operand(R6));
   __ b(&fall_through, CS);
@@ -228,7 +228,7 @@
   __ tsti(R0, kSmiTagMask);
   __ b(&fall_through, NE);  // Index is not an smi, fall through.
 
-  // range check
+  // Range check.
   __ ldr(R6, FieldAddress(R1, GrowableObjectArray::length_offset()));
   __ cmp(R0, Operand(R6));
   __ b(&fall_through, CS);
@@ -354,6 +354,52 @@
 }
 
 
+void Intrinsifier::Uint8Array_getIndexed(Assembler* assembler) {
+  Label fall_through;
+  __ ldr(R0, Address(SP, + 0 * kWordSize));  // Index.
+  __ ldr(R1, Address(SP, + 1 * kWordSize));  // Array.
+  __ tsti(R0, kSmiTagMask);
+  __ b(&fall_through, NE);  // Index is not a smi, fall through.
+
+  // Range check.
+  __ ldr(R6, FieldAddress(R1, TypedData::length_offset()));
+  __ cmp(R0, Operand(R6));
+  __ b(&fall_through, CS);
+
+  // Array element at R1 + R0 + TypedData::data_offset - 1.
+  // Untag R0.
+  __ add(R1, R1, Operand(R0, LSR, 1));
+  __ ldr(R0, FieldAddress(R1, TypedData::data_offset()), kUnsignedByte);
+  __ SmiTag(R0);
+  __ ret();
+  __ Bind(&fall_through);
+}
+
+
+void Intrinsifier::ExternalUint8Array_getIndexed(Assembler* assembler) {
+  Label fall_through;
+
+  __ ldr(R0, Address(SP, + 0 * kWordSize));  // Index.
+  __ ldr(R1, Address(SP, + 1 * kWordSize));  // Array.
+  __ tsti(R0, kSmiTagMask);
+  __ b(&fall_through, NE);  // Index is not a smi, fall through.
+
+  // Range check.
+  __ ldr(R6, FieldAddress(R1, TypedData::length_offset()));
+  __ cmp(R0, Operand(R6));
+  __ b(&fall_through, CS);
+
+  __ ldr(R1, FieldAddress(R1, ExternalTypedData::data_offset()));
+
+  // Untag R0.
+  __ add(R1, R1, Operand(R0, LSR, 1));
+  __ ldr(R0, Address(R1, 0), kUnsignedByte);
+  __ SmiTag(R0);
+  __ ret();
+  __ Bind(&fall_through);
+}
+
+
 static int GetScaleFactor(intptr_t size) {
   switch (size) {
     case 1: return 0;
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index bce10c3..ab3948d 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -442,6 +442,45 @@
 }
 
 
+void Intrinsifier::Uint8Array_getIndexed(Assembler* assembler) {
+  Label fall_through;
+  __ movl(EBX, Address(ESP, + 1 * kWordSize));  // Index.
+  __ movl(EAX, Address(ESP, + 2 * kWordSize));  // Array.
+  __ testl(EBX, Immediate(kSmiTagMask));
+  __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);  // Non-smi index.
+  // Range check.
+  __ cmpl(EBX, FieldAddress(EAX, TypedData::length_offset()));
+  // Runtime throws exception.
+  __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
+
+  __ SmiUntag(EBX);
+  __ movzxb(EAX, FieldAddress(EAX, EBX, TIMES_1, TypedData::data_offset()));
+  __ SmiTag(EAX);
+  __ ret();
+  __ Bind(&fall_through);
+}
+
+
+void Intrinsifier::ExternalUint8Array_getIndexed(Assembler* assembler) {
+  Label fall_through;
+  __ movl(EBX, Address(ESP, + 1 * kWordSize));  // Index.
+  __ movl(EAX, Address(ESP, + 2 * kWordSize));  // Array.
+  __ testl(EBX, Immediate(kSmiTagMask));
+  __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);  // Non-smi index.
+  // Range check.
+  __ cmpl(EBX, FieldAddress(EAX, TypedData::length_offset()));
+  // Runtime throws exception.
+  __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
+
+  __ movl(EAX, FieldAddress(EAX, ExternalTypedData::data_offset()));
+  __ SmiUntag(EBX);
+  __ movzxb(EAX, Address(EAX, EBX, TIMES_1, 0));
+  __ SmiTag(EAX);
+  __ ret();
+  __ Bind(&fall_through);
+}
+
+
 static ScaleFactor GetScaleFactor(intptr_t size) {
   switch (size) {
     case 1: return TIMES_1;
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index e69fba9..d1f7e35 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -42,7 +42,7 @@
   __ bne(CMPRES1, ZR, &fall_through);  // Index is not an smi, fall through
   __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize));  // Array
 
-  // range check
+  // Range check.
   __ lw(T2, FieldAddress(T1, Array::length_offset()));
   __ BranchUnsignedGreaterEqual(T0, T2, &fall_through);
 
@@ -225,7 +225,7 @@
   __ bne(CMPRES1, ZR, &fall_through);  // Index is not an smi, fall through
   __ delay_slot()->lw(T1, Address(SP, 1 * kWordSize));  // Array
 
-  // range check
+  // Range check.
   __ lw(T2, FieldAddress(T1, GrowableObjectArray::length_offset()));
   __ BranchUnsignedGreaterEqual(T0, T2, &fall_through);
 
@@ -437,6 +437,53 @@
 }
 
 
+void Intrinsifier::Uint8Array_getIndexed(Assembler* assembler) {
+  Label fall_through;
+
+  __ lw(T0, Address(SP, + 0 * kWordSize));  // Index.
+
+  __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
+  __ bne(CMPRES1, ZR, &fall_through);  // Index is not an smi, fall through.
+  __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize));  // Array.
+
+  // Range check.
+  __ lw(T2, FieldAddress(T1, TypedData::length_offset()));
+  __ BranchUnsignedGreaterEqual(T0, T2, &fall_through);
+
+  __ SmiUntag(T0);
+  __ addu(T1, T1, T0);
+  __ lbu(V0, FieldAddress(T1, TypedData::data_offset()));
+  __ Ret();
+  __ delay_slot()->SmiTag(V0);
+
+  __ Bind(&fall_through);
+}
+
+
+void Intrinsifier::ExternalUint8Array_getIndexed(Assembler* assembler) {
+  Label fall_through;
+
+  __ lw(T0, Address(SP, + 0 * kWordSize));  // Index.
+
+  __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
+  __ bne(CMPRES1, ZR, &fall_through);  // Index is not an smi, fall through.
+  __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize));  // Array.
+
+  // Range check.
+  __ lw(T2, FieldAddress(T1, TypedData::length_offset()));
+  __ BranchUnsignedGreaterEqual(T0, T2, &fall_through);
+
+  __ lw(T1, FieldAddress(T1, ExternalTypedData::data_offset()));
+  __ SmiUntag(T0);
+  __ addu(T1, T1, T0);
+  __ lbu(V0, Address(T1, 0));
+  __ Ret();
+  __ delay_slot()->SmiTag(V0);
+
+  __ Bind(&fall_through);
+}
+
+
 static int GetScaleFactor(intptr_t size) {
   switch (size) {
     case 1: return 0;
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index e3edffe..eb7ae29 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -397,6 +397,45 @@
 }
 
 
+void Intrinsifier::Uint8Array_getIndexed(Assembler* assembler) {
+  Label fall_through;
+  __ movq(RCX, Address(RSP, + 1 * kWordSize));  // Index.
+  __ movq(RAX, Address(RSP, + 2 * kWordSize));  // Array.
+  __ testq(RCX, Immediate(kSmiTagMask));
+  __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);  // Non-smi index.
+  // Range check.
+  __ cmpq(RCX, FieldAddress(RAX, TypedData::length_offset()));
+  // Runtime throws exception.
+  __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
+
+  __ SmiUntag(RCX);
+  __ movzxb(RAX, FieldAddress(RAX, RCX, TIMES_1, TypedData::data_offset()));
+  __ SmiTag(RAX);
+  __ ret();
+  __ Bind(&fall_through);
+}
+
+
+void Intrinsifier::ExternalUint8Array_getIndexed(Assembler* assembler) {
+  Label fall_through;
+  __ movq(RCX, Address(RSP, + 1 * kWordSize));  // Index.
+  __ movq(RAX, Address(RSP, + 2 * kWordSize));  // Array.
+  __ testq(RCX, Immediate(kSmiTagMask));
+  __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);  // Non-smi index.
+  // Range check.
+  __ cmpq(RCX, FieldAddress(RAX, TypedData::length_offset()));
+  // Runtime throws exception.
+  __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
+
+  __ movq(RAX, FieldAddress(RAX, ExternalTypedData::data_offset()));
+  __ SmiUntag(RCX);
+  __ movzxb(RAX, Address(RAX, RCX, TIMES_1, 0));
+  __ SmiTag(RAX);
+  __ ret();
+  __ Bind(&fall_through);
+}
+
+
 static ScaleFactor GetScaleFactor(intptr_t size) {
   switch (size) {
     case 1: return TIMES_1;
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index d5fc12c..01c7c9d 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -232,6 +232,9 @@
   // The current stack limit.  This may be overwritten with a special
   // value to trigger interrupts.
   uword stack_limit() const { return stack_limit_; }
+  static intptr_t stack_limit_offset() {
+    return OFFSET_OF(Isolate, stack_limit_);
+  }
 
   // The true stack limit for this isolate.
   uword saved_stack_limit() const { return saved_stack_limit_; }
diff --git a/runtime/vm/locations.cc b/runtime/vm/locations.cc
index 31049c4..8397ef5 100644
--- a/runtime/vm/locations.cc
+++ b/runtime/vm/locations.cc
@@ -27,46 +27,13 @@
                                  intptr_t input_count,
                                  intptr_t temp_count,
                                  LocationSummary::ContainsCall contains_call)
-    : input_locations_(isolate, input_count),
-      temp_locations_(isolate, temp_count),
-      output_locations_(isolate, 1),
+    : num_inputs_(input_count),
+      num_temps_(temp_count),
       stack_bitmap_(NULL),
       contains_call_(contains_call),
       live_registers_() {
-  for (intptr_t i = 0; i < input_count; i++) {
-    input_locations_.Add(Location());
-  }
-  for (intptr_t i = 0; i < temp_count; i++) {
-    temp_locations_.Add(Location());
-  }
-  output_locations_.Add(Location());
-  ASSERT(output_locations_.length() == 1);
-}
-
-
-LocationSummary::LocationSummary(Isolate* isolate,
-                                 intptr_t input_count,
-                                 intptr_t temp_count,
-                                 intptr_t output_count,
-                                 LocationSummary::ContainsCall contains_call)
-    : input_locations_(isolate, input_count),
-      temp_locations_(isolate, temp_count),
-      output_locations_(isolate, output_count),
-      stack_bitmap_(NULL),
-      contains_call_(contains_call),
-      live_registers_() {
-  for (intptr_t i = 0; i < input_count; i++) {
-    input_locations_.Add(Location());
-  }
-  for (intptr_t i = 0; i < temp_count; i++) {
-    temp_locations_.Add(Location());
-  }
-  // TODO(johnmccutchan): Remove this assertion once support for multiple
-  // outputs is complete.
-  ASSERT(output_count == 1);
-  for (intptr_t i = 0; i < output_count; i++) {
-    output_locations_.Add(Location());
-  }
+  input_locations_ = isolate->current_zone()->Alloc<Location>(num_inputs_);
+  temp_locations_ = isolate->current_zone()->Alloc<Location>(num_temps_);
 }
 
 
diff --git a/runtime/vm/locations.h b/runtime/vm/locations.h
index 95764dc..7a617a3 100644
--- a/runtime/vm/locations.h
+++ b/runtime/vm/locations.h
@@ -505,74 +505,77 @@
     kCallOnSlowPath
   };
 
-  // Defaults to 1 output.
   LocationSummary(Isolate* isolate,
                   intptr_t input_count,
                   intptr_t temp_count,
                   LocationSummary::ContainsCall contains_call);
 
-  LocationSummary(Isolate* isolate,
-                  intptr_t input_count,
-                  intptr_t temp_count,
-                  intptr_t output_count,
-                  LocationSummary::ContainsCall contains_call);
-
   intptr_t input_count() const {
-    return input_locations_.length();
+    return num_inputs_;
   }
 
   Location in(intptr_t index) const {
+    ASSERT(index >= 0);
+    ASSERT(index < num_inputs_);
     return input_locations_[index];
   }
 
   Location* in_slot(intptr_t index) {
+    ASSERT(index >= 0);
+    ASSERT(index < num_inputs_);
     return &input_locations_[index];
   }
 
   void set_in(intptr_t index, Location loc) {
+    ASSERT(index >= 0);
+    ASSERT(index < num_inputs_);
     ASSERT(!always_calls() || loc.IsMachineRegister());
     input_locations_[index] = loc;
   }
 
   intptr_t temp_count() const {
-    return temp_locations_.length();
+    return num_temps_;
   }
 
   Location temp(intptr_t index) const {
+    ASSERT(index >= 0);
+    ASSERT(index < num_temps_);
     return temp_locations_[index];
   }
 
   Location* temp_slot(intptr_t index) {
+    ASSERT(index >= 0);
+    ASSERT(index < num_temps_);
     return &temp_locations_[index];
   }
 
   void set_temp(intptr_t index, Location loc) {
+    ASSERT(index >= 0);
+    ASSERT(index < num_temps_);
     ASSERT(!always_calls() || loc.IsMachineRegister());
     temp_locations_[index] = loc;
   }
 
-  void AddTemp(Location loc) {
-    ASSERT(!always_calls() || loc.IsMachineRegister());
-    temp_locations_.Add(loc);
-  }
-
   intptr_t output_count() const {
-    return output_locations_.length();
+    return 1;
   }
 
   Location out(intptr_t index) const {
-    return output_locations_[index];
+    ASSERT(index == 0);
+    return output_location_;
   }
 
   Location* out_slot(intptr_t index) {
-    return &output_locations_[index];
+    ASSERT(index == 0);
+    return &output_location_;
   }
 
   void set_out(intptr_t index, Location loc) {
+    ASSERT(index == 0);
     ASSERT(!always_calls() ||
            (loc.IsMachineRegister() || loc.IsInvalid() ||
             loc.IsPairLocation()));
-    output_locations_[index] = loc;
+    output_location_ = loc;
   }
 
   BitmapBuilder* stack_bitmap() {
@@ -609,9 +612,11 @@
   }
 
  private:
-  GrowableArray<Location> input_locations_;
-  GrowableArray<Location> temp_locations_;
-  GrowableArray<Location> output_locations_;
+  const intptr_t num_inputs_;
+  Location* input_locations_;
+  const intptr_t num_temps_;
+  Location* temp_locations_;
+  Location output_location_;
 
   BitmapBuilder* stack_bitmap_;
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 5b358b5..2f9559b 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -64,6 +64,7 @@
     "fit into a javascript integer.");
 DEFINE_FLAG(bool, use_field_guards, true, "Guard field cids.");
 DEFINE_FLAG(bool, use_lib_cache, true, "Use library name cache");
+DEFINE_FLAG(bool, trace_field_guards, false, "Trace changes in field's cids.");
 
 DECLARE_FLAG(bool, enable_type_checks);
 DECLARE_FLAG(bool, error_on_bad_override);
@@ -4926,12 +4927,12 @@
 }
 
 
-void Function::set_code(const Code& value) const {
-  StorePointer(&raw_ptr()->code_, value.raw());
+void Function::SetInstructions(const Code& value) const {
+  StorePointer(&raw_ptr()->instructions_, value.instructions());
 }
 
 void Function::AttachCode(const Code& value) const {
-  set_code(value);
+  SetInstructions(value);
   ASSERT(Function::Handle(value.function()).IsNull() ||
     (value.function() == this->raw()));
   value.set_owner(*this);
@@ -4939,14 +4940,16 @@
 
 
 bool Function::HasCode() const {
-  ASSERT(raw_ptr()->code_ != Code::null());
-  return raw_ptr()->code_ != StubCode::LazyCompile_entry()->code();
+  ASSERT(raw_ptr()->instructions_ != Instructions::null());
+  return raw_ptr()->instructions_ !=
+      StubCode::LazyCompile_entry()->code()->ptr()->instructions_;
 }
 
 
 void Function::ClearCode() const {
-  StorePointer(&raw_ptr()->code_, StubCode::LazyCompile_entry()->code());
   StorePointer(&raw_ptr()->unoptimized_code_, Code::null());
+  StorePointer(&raw_ptr()->instructions_,
+      Code::Handle(StubCode::LazyCompile_entry()->code()).instructions());
 }
 
 
@@ -5975,7 +5978,7 @@
   result.set_is_optimizable(is_native ? false : true);
   result.set_is_inlinable(true);
   result.set_allows_hoisting_check_class(true);
-  result.set_code(Code::Handle(StubCode::LazyCompile_entry()->code()));
+  result.SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code()));
   if (kind == RawFunction::kClosureFunction) {
     const ClosureData& data = ClosureData::Handle(ClosureData::New());
     result.set_data(data);
@@ -6300,7 +6303,8 @@
 
 
 bool Function::HasOptimizedCode() const {
-  return HasCode() && Code::Handle(raw_ptr()->code_).is_optimized();
+  return HasCode() &&  Code::Handle(Instructions::Handle(
+      raw_ptr()->instructions_).code()).is_optimized();
 }
 
 
@@ -6774,6 +6778,7 @@
   result.set_is_unboxing_candidate(true);
   result.set_guarded_cid(FLAG_use_field_guards ? kIllegalCid : kDynamicCid);
   result.set_is_nullable(FLAG_use_field_guards ? false : true);
+  result.set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset);
   // Presently, we only attempt to remember the list length for final fields.
   if (is_final && FLAG_use_field_guards) {
     result.set_guarded_list_length(Field::kUnknownFixedLength);
@@ -6822,6 +6827,19 @@
 }
 
 
+intptr_t Field::guarded_list_length_in_object_offset() const {
+  return raw_ptr()->guarded_list_length_in_object_offset_ + kHeapObjectTag;
+}
+
+
+void Field::set_guarded_list_length_in_object_offset(
+    intptr_t list_length_offset) const {
+  raw_ptr()->guarded_list_length_in_object_offset_ =
+      static_cast<int8_t>(list_length_offset - kHeapObjectTag);
+  ASSERT(guarded_list_length_in_object_offset() == list_length_offset);
+}
+
+
 bool Field::IsUnboxedField() const {
   bool valid_class = (FlowGraphCompiler::SupportsUnboxedDoubles() &&
                       (guarded_cid() == kDoubleCid)) ||
@@ -6983,9 +7001,6 @@
 
 
 static intptr_t GetListLength(const Object& value) {
-  const intptr_t cid = value.GetClassId();
-  ASSERT(RawObject::IsBuiltinListClassId(cid));
-  // Extract list length.
   if (value.IsTypedData()) {
     const TypedData& list = TypedData::Cast(value);
     return list.Length();
@@ -6998,41 +7013,115 @@
   } else if (value.IsExternalTypedData()) {
     // TODO(johnmccutchan): Enable for external typed data.
     return Field::kNoFixedLength;
-  } else if (RawObject::IsTypedDataViewClassId(cid)) {
+  } else if (RawObject::IsTypedDataViewClassId(value.GetClassId())) {
     // TODO(johnmccutchan): Enable for typed data views.
     return Field::kNoFixedLength;
   }
-  UNIMPLEMENTED();
   return Field::kNoFixedLength;
 }
 
 
+static intptr_t GetListLengthOffset(intptr_t cid) {
+  if (RawObject::IsTypedDataClassId(cid)) {
+    return TypedData::length_offset();
+  } else if (cid == kArrayCid || cid == kImmutableArrayCid) {
+    return Array::length_offset();
+  } else if (cid == kGrowableObjectArrayCid) {
+    // List length is variable.
+    return Field::kUnknownLengthOffset;
+  } else if (RawObject::IsExternalTypedDataClassId(cid)) {
+    // TODO(johnmccutchan): Enable for external typed data.
+    return Field::kUnknownLengthOffset;
+  } else if (RawObject::IsTypedDataViewClassId(cid)) {
+    // TODO(johnmccutchan): Enable for typed data views.
+    return Field::kUnknownLengthOffset;
+  }
+  return Field::kUnknownLengthOffset;
+}
+
+
+const char* Field::GuardedPropertiesAsCString() const {
+  if (guarded_cid() == kIllegalCid) {
+    return "<?>";
+  } else if (guarded_cid() == kDynamicCid) {
+    return "<*>";
+  }
+
+  const Class& cls = Class::Handle(
+      Isolate::Current()->class_table()->At(guarded_cid()));
+  const char* class_name = String::Handle(cls.Name()).ToCString();
+
+  if (RawObject::IsBuiltinListClassId(guarded_cid()) &&
+      !is_nullable() &&
+      is_final()) {
+    ASSERT(guarded_list_length() != kUnknownFixedLength);
+    if (guarded_list_length() == kNoFixedLength) {
+      return Isolate::Current()->current_zone()->PrintToString(
+          "<%s [*]>", class_name);
+    } else {
+      return Isolate::Current()->current_zone()->PrintToString(
+          "<%s [%" Pd " @%" Pd "]>",
+          class_name,
+          guarded_list_length(),
+          guarded_list_length_in_object_offset());
+    }
+  }
+
+  return Isolate::Current()->current_zone()->PrintToString("<%s %s>",
+    is_nullable() ? "nullable" : "not-nullable",
+    class_name);
+}
+
+
+void Field::InitializeGuardedListLengthInObjectOffset() const {
+  if (needs_length_check() &&
+      (guarded_list_length() != Field::kUnknownFixedLength)) {
+    const intptr_t offset = GetListLengthOffset(guarded_cid());
+    set_guarded_list_length_in_object_offset(offset);
+    ASSERT(offset != Field::kUnknownLengthOffset);
+  } else {
+    set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset);
+  }
+}
+
+
 bool Field::UpdateGuardedCidAndLength(const Object& value) const {
   const intptr_t cid = value.GetClassId();
-  bool deoptimize = UpdateCid(cid);
-  intptr_t list_length = Field::kNoFixedLength;
-  if ((guarded_cid() != kDynamicCid) &&
-      is_final() && RawObject::IsBuiltinListClassId(cid)) {
-    list_length = GetListLength(value);
-  }
-  deoptimize = UpdateLength(list_length) || deoptimize;
-  if (deoptimize) {
-    DeoptimizeDependentCode();
-  }
-  return deoptimize;
-}
 
-
-bool Field::UpdateCid(intptr_t cid) const {
   if (guarded_cid() == kIllegalCid) {
     // Field is assigned first time.
     set_guarded_cid(cid);
     set_is_nullable(cid == kNullCid);
+
+    // Start tracking length if needed.
+    ASSERT((guarded_list_length() == Field::kUnknownFixedLength) ||
+           (guarded_list_length() == Field::kNoFixedLength));
+    if (needs_length_check()) {
+      ASSERT(guarded_list_length() == Field::kUnknownFixedLength);
+      set_guarded_list_length(GetListLength(value));
+      InitializeGuardedListLengthInObjectOffset();
+    }
+
+    if (FLAG_trace_field_guards) {
+      OS::Print("    => %s\n", GuardedPropertiesAsCString());
+    }
+
     return false;
   }
 
   if ((cid == guarded_cid()) || ((cid == kNullCid) && is_nullable())) {
     // Class id of the assigned value matches expected class id and nullability.
+
+    // If we are tracking length check if it has matches.
+    if (needs_length_check() &&
+        (guarded_list_length() != GetListLength(value))) {
+      ASSERT(guarded_list_length() != Field::kUnknownFixedLength);
+      set_guarded_list_length(Field::kNoFixedLength);
+      set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset);
+      return true;
+    }
+
+    // Everything matches.
     return false;
   }
 
@@ -7051,38 +7140,33 @@
     set_is_nullable(true);
   }
 
+  // If we were tracking length drop collected feedback.
+  if (needs_length_check()) {
+    ASSERT(guarded_list_length() != Field::kUnknownFixedLength);
+    set_guarded_list_length(Field::kNoFixedLength);
+    set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset);
+  }
+
   // Expected class id or nullability of the field changed.
   return true;
 }
 
 
-bool Field::UpdateLength(intptr_t list_length) const {
-  ASSERT(is_final() || (!is_final() &&
-                        (list_length < Field::kUnknownFixedLength)));
-  ASSERT((list_length == Field::kNoFixedLength) ||
-         (list_length > Field::kUnknownFixedLength));
-  ASSERT(guarded_cid() != kIllegalCid);
-
-  const bool force_invalidate = (guarded_cid() == kDynamicCid) &&
-                                (list_length != Field::kNoFixedLength);
-
-  const bool list_length_unknown =
-      (guarded_list_length() == Field::kUnknownFixedLength);
-  const bool list_length_changed = (guarded_list_length() != list_length);
-
-  if (list_length_unknown && list_length_changed && !force_invalidate) {
-    // List length set for first time.
-    set_guarded_list_length(list_length);
-    return false;
+void Field::RecordStore(const Object& value) const {
+  if (FLAG_trace_field_guards) {
+    OS::Print("Store %s %s <- %s\n",
+              ToCString(),
+              GuardedPropertiesAsCString(),
+              value.ToCString());
   }
 
-  if (!list_length_changed && !force_invalidate) {
-    // List length unchanged.
-    return false;
+  if (UpdateGuardedCidAndLength(value)) {
+    if (FLAG_trace_field_guards) {
+      OS::Print("    => %s\n", GuardedPropertiesAsCString());
+    }
+
+    DeoptimizeDependentCode();
   }
-  // Multiple list lengths assigned here, stop tracking length.
-  set_guarded_list_length(Field::kNoFixedLength);
-  return true;
 }
 
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index cbdba7d..6c7182e 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1576,7 +1576,7 @@
 
   // Sets function's code and code's function.
   void AttachCode(const Code& value) const;
-  void set_code(const Code& value) const;
+  void SetInstructions(const Code& value) const;
   void ClearCode() const;
 
   // Disables optimized code and switches to unoptimized code.
@@ -1584,16 +1584,21 @@
 
   // Return the most recently compiled and installed code for this function.
   // It is not the only Code object that points to this function.
-  RawCode* CurrentCode() const { return raw_ptr()->code_; }
+  RawCode* CurrentCode() const {
+    return raw_ptr()->instructions_->ptr()->code_;
+  }
 
   RawCode* unoptimized_code() const { return raw_ptr()->unoptimized_code_; }
   void set_unoptimized_code(const Code& value) const;
-  static intptr_t code_offset() { return OFFSET_OF(RawFunction, code_); }
   static intptr_t unoptimized_code_offset() {
     return OFFSET_OF(RawFunction, unoptimized_code_);
   }
   bool HasCode() const;
 
+  static intptr_t instructions_offset() {
+    return OFFSET_OF(RawFunction, instructions_);
+  }
+
   // Returns true if there is at least one debugger breakpoint
   // set in this function.
   bool HasBreakpoint() const;
@@ -2213,12 +2218,20 @@
   static intptr_t guarded_list_length_offset() {
     return OFFSET_OF(RawField, guarded_list_length_);
   }
+  intptr_t guarded_list_length_in_object_offset() const;
+  void set_guarded_list_length_in_object_offset(intptr_t offset) const;
+  static intptr_t guarded_list_length_in_object_offset_offset() {
+    return OFFSET_OF(RawField, guarded_list_length_in_object_offset_);
+  }
+
   bool needs_length_check() const {
     const bool r = guarded_list_length() >= Field::kUnknownFixedLength;
     ASSERT(!r || is_final());
     return r;
   }
 
+  const char* GuardedPropertiesAsCString() const;
+
   intptr_t UnboxedFieldCid() const {
     ASSERT(IsUnboxedField());
     return guarded_cid();
@@ -2240,6 +2253,7 @@
   }
 
   enum {
+    kUnknownLengthOffset = -1,
     kUnknownFixedLength = -1,
     kNoFixedLength = -2,
   };
@@ -2258,9 +2272,11 @@
     return OFFSET_OF(RawField, is_nullable_);
   }
 
-  // Update guarded cid and guarded length for this field. May trigger
+  // Record store of the given value into this field. May trigger
   // deoptimization of dependent optimized code.
-  bool UpdateGuardedCidAndLength(const Object& value) const;
+  void RecordStore(const Object& value) const;
+
+  void InitializeGuardedListLengthInObjectOffset() const;
 
   // Return the list of optimized code objects that were optimized under
   // assumptions about guarded class id and nullability of this field.
@@ -2305,15 +2321,9 @@
                                                kUnboxingCandidateBit, 1> {
   };
 
-  // Update guarded class id and nullability of the field to reflect assignment
-  // of the value with the given class id to this field. Returns true, if
+  // Update guarded cid and guarded length for this field. Returns true, if
   // deoptimization of dependent code is required.
-  bool UpdateCid(intptr_t cid) const;
-
-  // Update guarded class length of the field to reflect assignment of the
-  // value with the given length. Returns true if deoptimization of dependent
-  // code is required.
-  bool UpdateLength(intptr_t length) const;
+  bool UpdateGuardedCidAndLength(const Object& value) const;
 
   void set_name(const String& value) const;
   void set_is_static(bool is_static) const {
@@ -4158,7 +4168,7 @@
   }
 
   void SetField(const Field& field, const Object& value) const {
-    field.UpdateGuardedCidAndLength(value);
+    field.RecordStore(value);
     StorePointer(FieldAddr(field), value.raw());
   }
 
diff --git a/runtime/vm/object_arm64_test.cc b/runtime/vm/object_arm64_test.cc
index 29925e2..055ea85 100644
--- a/runtime/vm/object_arm64_test.cc
+++ b/runtime/vm/object_arm64_test.cc
@@ -17,6 +17,7 @@
 // Generate a simple dart code sequence.
 // This is used to test Code and Instruction object creation.
 void GenerateIncrement(Assembler* assembler) {
+  __ mov(SP, CSP);
   __ movz(R0, 0, 0);
   __ Push(R0);
   __ add(R0, R0, Operand(1));
@@ -34,6 +35,7 @@
 void GenerateEmbedStringInCode(Assembler* assembler, const char* str) {
   const String& string_object =
       String::ZoneHandle(String::New(str, Heap::kOld));
+  __ mov(SP, CSP);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
   __ LoadPoolPointer(PP);
   __ LoadObject(R0, string_object, PP);
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 21454f9..8667c20 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -274,7 +274,6 @@
       token_kind_(Token::kILLEGAL),
       current_block_(NULL),
       is_top_level_(false),
-      parsing_metadata_(false),
       current_member_(NULL),
       allow_function_literals_(true),
       parsed_function_(NULL),
@@ -301,7 +300,6 @@
       token_kind_(Token::kILLEGAL),
       current_block_(NULL),
       is_top_level_(false),
-      parsing_metadata_(false),
       current_member_(NULL),
       allow_function_literals_(true),
       parsed_function_(parsed_function),
@@ -886,10 +884,24 @@
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
     const Script& script = Script::Handle(isolate, cls.script());
-    const Library& lib = Library::Handle(isolate, cls.library());
-    Parser parser(script, lib, token_pos);
+    // Parsing metadata can involve following paths in the parser that are
+    // normally used for expressions and assume current_function is non-null,
+    // so we create a fake function to use as the current_function rather than
+    // scattering special cases throughout the parser.
+    const Function& fake_function = Function::ZoneHandle(Function::New(
+        Symbols::At(),
+        RawFunction::kRegularFunction,
+        true,  // is_static
+        false,  // is_const
+        false,  // is_abstract
+        false,  // is_external
+        false,  // is_native
+        cls,
+        token_pos));
+    ParsedFunction* parsed_function =
+        new ParsedFunction(isolate, fake_function);
+    Parser parser(script, parsed_function, token_pos);
     parser.set_current_class(cls);
-    parser.set_parsing_metadata(true);
 
     RawObject* metadata = parser.EvaluateMetadata();
     return metadata;
@@ -2297,7 +2309,7 @@
 
     if (found) continue;
 
-    field.UpdateGuardedCidAndLength(Object::Handle(isolate()));
+    field.RecordStore(Object::Handle(isolate()));
   }
 }
 
@@ -8490,13 +8502,7 @@
     // NoSuchMethodError to be thrown.
     // In an instance method, we convert this into a getter call
     // for a field (which may be defined in a subclass.)
-    // In metadata, an unresolved identifier cannot be a compile-time constant.
     String& name = String::CheckedZoneHandle(primary->primary().raw());
-    if (parsing_metadata_) {
-      ErrorMsg(primary->token_pos(),
-               "unresolved identifier '%s' is not a compile-time constant",
-               name.ToCString());
-    }
     if (current_function().is_static() ||
         current_function().IsInFactoryScope()) {
       StaticGetterNode* getter =
@@ -8530,11 +8536,6 @@
     return closure;
   } else {
     // Instance function access.
-    if (parsing_metadata_) {
-      ErrorMsg(primary->token_pos(),
-               "cannot access instance method '%s' from metadata",
-               funcname.ToCString());
-    }
     if (current_function().is_static() ||
         current_function().IsInFactoryScope()) {
       ErrorMsg(primary->token_pos(),
@@ -8737,14 +8738,6 @@
       } else {
         // Left is not a primary node; this must be a closure call.
         AstNode* closure = left;
-        if (parsing_metadata_) {
-            // Compiling closure calls involves saving the current context based
-            // on the current function, and metadata has no current function.
-            // Fail early rather than limping along only to discover later that
-            // we parsed something that isn't a compile-time constant.
-            ErrorMsg(closure->token_pos(),
-              "expression is not a valid compile-time constant");
-        }
         selector = ParseClosureCall(closure);
       }
     } else {
@@ -8954,11 +8947,6 @@
                                       const String& field_name) {
   // Fields are not accessible from a static function, except from a
   // constructor, which is considered as non-static by the compiler.
-  if (parsing_metadata_) {
-    ErrorMsg(field_pos,
-             "cannot access instance field '%s' from metadata",
-             field_name.ToCString());
-  }
   if (current_function().is_static()) {
     ErrorMsg(field_pos,
              "cannot access instance field '%s' from a static function",
@@ -9146,11 +9134,8 @@
   if (result.IsError()) {
       // An exception may not occur in every parse attempt, i.e., the
       // generated AST is not deterministic. Therefore mark the function as
-      // not optimizable. Unless we are evaluating metadata, in which case there
-      // is no current function.
-      if (!parsing_metadata_) {
-        current_function().SetIsOptimizable(false);
-      }
+      // not optimizable.
+      current_function().SetIsOptimizable(false);
       if (result.IsUnhandledException()) {
         return result.raw();
       } else {
@@ -9247,11 +9232,6 @@
         // be found.
         AstNode* receiver = NULL;
         const bool kTestOnly = true;
-        if (parsing_metadata_) {
-          ErrorMsg(ident_pos,
-                   "'%s' is not a compile-time constant",
-                   ident.ToCString());
-        }
         if (!current_function().is_static() &&
             (LookupReceiver(current_block_->scope, kTestOnly) != NULL)) {
           receiver = LoadReceiver(ident_pos);
@@ -10640,9 +10620,6 @@
   } else if (token == Token::kHASH) {
     primary = ParseSymbolLiteral();
   } else if (token == Token::kSUPER) {
-    if (parsing_metadata_) {
-      ErrorMsg("cannot access superclass from metadata");
-    }
     if (current_function().is_static()) {
       ErrorMsg("cannot access superclass from static method");
     }
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 64d83d7..f187032 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -693,11 +693,6 @@
   // global variables.
   bool is_top_level_;
 
-  // True when evaluating metadata. Used to make decisions otherwise based on
-  // the current_function().
-  void set_parsing_metadata(bool value) { parsing_metadata_ = value; }
-  bool parsing_metadata_;
-
   // The member currently being parsed during "top level" parsing.
   MemberDesc* current_member_;
 
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index abd9933..523151b 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -612,7 +612,7 @@
   RawArray* parameter_types_;
   RawArray* parameter_names_;
   RawObject* data_;  // Additional data specific to the function kind.
-  RawCode* code_;  // Compiled code for the function.
+  RawInstructions* instructions_;  // Instructions of currently active code.
   RawCode* unoptimized_code_;  // Unoptimized code, keep it after optimization.
   RawObject** to() {
     return reinterpret_cast<RawObject**>(&ptr()->unoptimized_code_);
@@ -685,6 +685,11 @@
   intptr_t guarded_cid_;
   intptr_t is_nullable_;  // kNullCid if field can contain null value and
                           // any other value otherwise.
+  // Offset to the guarded length field inside an instance of class matching
+  // guarded_cid_. Stored corrected by -kHeapObjectTag to simplify code
+  // generated on platforms with weak addressing modes (ARM, MIPS).
+  int8_t guarded_list_length_in_object_offset_;
+
   uint8_t kind_bits_;  // static, final, const, has initializer.
 };
 
@@ -839,6 +844,8 @@
   int32_t data_[0];
 
   friend class StackFrame;
+  friend class MarkingVisitor;
+  friend class Function;
 };
 
 
@@ -866,6 +873,8 @@
   friend class RawCode;
   friend class Code;
   friend class StackFrame;
+  friend class MarkingVisitor;
+  friend class Function;
 };
 
 
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index d2ce0df..e3c8a93 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -711,7 +711,7 @@
   }
 
   // Set up code pointer with the lazy-compile-stub.
-  func.set_code(Code::Handle(StubCode::LazyCompile_entry()->code()));
+  func.SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code()));
 
   return func.raw();
 }
@@ -747,7 +747,7 @@
   SnapshotWriterVisitor visitor(writer);
   visitor.VisitPointers(from(), to_no_code());
 
-  // Write null for the code and unoptimized code.
+  // Write null for the instructions and unoptimized code.
   writer->WriteVMIsolateObject(kNullObject);
   writer->WriteVMIsolateObject(kNullObject);
 }
@@ -783,6 +783,8 @@
     *(field.raw()->from() + i) = reader->ReadObjectRef();
   }
 
+  field.InitializeGuardedListLengthInObjectOffset();
+
   return field.raw();
 }
 
diff --git a/runtime/vm/runtime_entry_arm64.cc b/runtime/vm/runtime_entry_arm64.cc
index 01039c9..fcf228e 100644
--- a/runtime/vm/runtime_entry_arm64.cc
+++ b/runtime/vm/runtime_entry_arm64.cc
@@ -40,7 +40,10 @@
   if (is_leaf()) {
     ASSERT(argument_count == this->argument_count());
     ExternalLabel label(entry);
+    // Cache the stack pointer in a callee-saved register.
+    __ mov(R26, SP);
     __ BranchLink(&label, kNoPP);
+    __ mov(SP, R26);
   } else {
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
diff --git a/runtime/vm/scanner.cc b/runtime/vm/scanner.cc
index ceef56d..c207415 100644
--- a/runtime/vm/scanner.cc
+++ b/runtime/vm/scanner.cc
@@ -19,7 +19,8 @@
 DEFINE_FLAG(bool, print_tokens, false, "Print scanned tokens.");
 
 
-Scanner::KeywordTable Scanner::keywords_[Token::numKeywords];
+Scanner::KeywordTable Scanner::keywords_[Token::kNumKeywords];
+int Scanner::keywords_char_offset_[Scanner::kNumLowercaseChars];
 
 
 void Scanner::Reset() {
@@ -289,23 +290,25 @@
 
   // Check whether the characters we read are a known keyword.
   // Note, can't use strcmp since token_chars is not null-terminated.
-  int i = 0;
-  while (i < Token::numKeywords &&
-         keywords_[i].keyword_chars[0] <= ident_char0) {
-    if (keywords_[i].keyword_len == ident_length) {
-      const char* keyword = keywords_[i].keyword_chars;
-      int char_pos = 0;
-      while ((char_pos < ident_length) &&
-             (keyword[char_pos] == source_.CharAt(ident_pos + char_pos))) {
-        char_pos++;
+  if (('a' <= ident_char0) && (ident_char0 <= 'z')) {
+    int i = keywords_char_offset_[ident_char0 - 'a'];
+    while (i < Token::kNumKeywords &&
+           keywords_[i].keyword_chars[0] <= ident_char0) {
+      if (keywords_[i].keyword_len == ident_length) {
+        const char* keyword = keywords_[i].keyword_chars;
+        int char_pos = 1;
+        while ((char_pos < ident_length) &&
+               (keyword[char_pos] == source_.CharAt(ident_pos + char_pos))) {
+          char_pos++;
+        }
+        if (char_pos == ident_length) {
+          current_token_.literal = keywords_[i].keyword_symbol;
+          current_token_.kind = keywords_[i].kind;
+          return;
+        }
       }
-      if (char_pos == ident_length) {
-        current_token_.literal = keywords_[i].keyword_symbol;
-        current_token_.kind = keywords_[i].kind;
-        return;
-      }
+      i++;
     }
-    i++;
   }
 
   // We did not read a keyword.
@@ -937,12 +940,20 @@
 
 void Scanner::InitOnce() {
   ASSERT(Isolate::Current() == Dart::vm_isolate());
-  for (int i = 0; i < Token::numKeywords; i++) {
+  for (int i = 0; i < kNumLowercaseChars; i++) {
+    keywords_char_offset_[i] = Token::kNumKeywords;
+  }
+  for (int i = 0; i < Token::kNumKeywords; i++) {
     Token::Kind token = static_cast<Token::Kind>(Token::kFirstKeyword + i);
     keywords_[i].kind = token;
     keywords_[i].keyword_chars = Token::Str(token);
     keywords_[i].keyword_len = strlen(Token::Str(token));
     keywords_[i].keyword_symbol = &Symbols::Keyword(token);
+
+    int ch = keywords_[i].keyword_chars[0] - 'a';
+    if (keywords_char_offset_[ch] == Token::kNumKeywords) {
+      keywords_char_offset_[ch] = i;
+    }
   }
 }
 
diff --git a/runtime/vm/scanner.h b/runtime/vm/scanner.h
index 3e1407c..92c2919 100644
--- a/runtime/vm/scanner.h
+++ b/runtime/vm/scanner.h
@@ -85,6 +85,8 @@
                              const String** value);
 
  private:
+  static const int kNumLowercaseChars = 26;
+
   struct ScanContext {
     ScanContext* next;
     char string_delimiter;
@@ -205,7 +207,8 @@
 
   SourcePosition c0_pos_;      // Source position of lookahead character c0_.
 
-  static KeywordTable keywords_[Token::numKeywords];
+  static KeywordTable keywords_[Token::kNumKeywords];
+  static int keywords_char_offset_[kNumLowercaseChars];
 };
 
 
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index 18d5898..776bcf9 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -663,11 +663,22 @@
 
 
 // Sets the register in the architecture state.
-void Simulator::set_register(Register reg, int64_t value, R31Type r31t) {
-  // register is in range, and if it is R31, a mode is specified.
+void Simulator::set_register(
+    Instr* instr, Register reg, int64_t value, R31Type r31t) {
+  // Register is in range.
   ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
   if ((reg != R31) || (r31t != R31IsZR)) {
     registers_[reg] = value;
+    // If we're setting CSP, make sure it is 16-byte aligned. In truth, CSP
+    // can store addresses that are not 16-byte aligned, but loads and stores
+    // are not allowed through CSP when it is not aligned. Thus, this check is
+    // more conservative that necessary. However, it will likely be more
+    // useful to find the program locations where CSP is set to a bad value,
+    // than to find only the resulting loads/stores that would cause a fault on
+    // hardware.
+    if ((instr != NULL) && (reg == R31) && !Utils::IsAligned(value, 16)) {
+      UnalignedAccess("CSP set", value, instr);
+    }
   }
 }
 
@@ -1034,15 +1045,15 @@
   if (instr->SFField()) {
     if (instr->Bits(29, 2) == 0) {
       // Format(instr, "movn'sf 'rd, 'imm16 'hw");
-      set_register(rd, ~shifted_imm, instr->RdMode());
+      set_register(instr, rd, ~shifted_imm, instr->RdMode());
     } else if (instr->Bits(29, 2) == 2) {
       // Format(instr, "movz'sf 'rd, 'imm16 'hw");
-      set_register(rd, shifted_imm, instr->RdMode());
+      set_register(instr, rd, shifted_imm, instr->RdMode());
     } else if (instr->Bits(29, 2) == 3) {
       // Format(instr, "movk'sf 'rd, 'imm16 'hw");
       const int64_t rd_val = get_register(rd, instr->RdMode());
       const int64_t result = (rd_val & ~(0xffffL << shift)) | shifted_imm;
-      set_register(rd, result, instr->RdMode());
+      set_register(instr, rd, result, instr->RdMode());
     } else {
       UnimplementedInstruction(instr);
     }
@@ -1080,7 +1091,7 @@
     // 64-bit add.
     const int64_t rn_val = get_register(rn, instr->RnMode());
     const int64_t alu_out = addition ? (rn_val + imm) : (rn_val - imm);
-    set_register(rd, alu_out, instr->RdMode());
+    set_register(instr, rd, alu_out, instr->RdMode());
     if (instr->HasS()) {
       SetNZFlagsX(alu_out);
       if (addition) {
@@ -1151,7 +1162,7 @@
   }
 
   if (out_size == kXRegSizeInBits) {
-    set_register(rd, alu_out, instr->RdMode());
+    set_register(instr, rd, alu_out, instr->RdMode());
   } else {
     set_wregister(rd, alu_out, instr->RdMode());
   }
@@ -1167,7 +1178,7 @@
     const int64_t immlo = instr->Bits(29, 2);
     const int64_t off = (immhi << 2) | immlo;
     const int64_t dest = get_pc() + off;
-    set_register(rd, dest, instr->RdMode());
+    set_register(instr, rd, dest, instr->RdMode());
   } else {
     UnimplementedInstruction(instr);
   }
@@ -1287,17 +1298,14 @@
       set_top_exit_frame_info(reinterpret_cast<uword>(&buffer));
     }
     if (redirection->call_kind() == kRuntimeCall) {
-      NativeArguments arguments;
-      ASSERT(sizeof(NativeArguments) == 4*kWordSize);
-      arguments.isolate_ = reinterpret_cast<Isolate*>(get_register(R0));
-      arguments.argc_tag_ = get_register(R1);
-      arguments.argv_ = reinterpret_cast<RawObject*(*)[]>(get_register(R2));
-      arguments.retval_ = reinterpret_cast<RawObject**>(get_register(R3));
+      NativeArguments* arguments =
+          reinterpret_cast<NativeArguments*>(get_register(R0));
       SimulatorRuntimeCall target =
           reinterpret_cast<SimulatorRuntimeCall>(external);
-      target(arguments);
-      set_register(R0, icount_);  // Zap result register from void function.
-      set_register(R1, icount_);
+      target(*arguments);
+      // Zap result register from void function.
+      set_register(instr, R0, icount_);
+      set_register(instr, R1, icount_);
     } else if (redirection->call_kind() == kLeafRuntimeCall) {
       ASSERT((0 <= redirection->argument_count()) &&
              (redirection->argument_count() <= 8));
@@ -1312,8 +1320,8 @@
       const int64_t r6 = get_register(R6);
       const int64_t r7 = get_register(R7);
       const int64_t res = target(r0, r1, r2, r3, r4, r5, r6, r7);
-      set_register(R0, res);  // Set returned result from function.
-      set_register(R1, icount_);  // Zap unused result register.
+      set_register(instr, R0, res);  // Set returned result from function.
+      set_register(instr, R1, icount_);  // Zap unused result register.
     } else if (redirection->call_kind() == kLeafFloatRuntimeCall) {
       ASSERT((0 <= redirection->argument_count()) &&
              (redirection->argument_count() <= 8));
@@ -1336,7 +1344,8 @@
       SimulatorBootstrapNativeCall target =
           reinterpret_cast<SimulatorBootstrapNativeCall>(external);
       target(arguments);
-      set_register(R0, icount_);  // Zap result register from void function.
+      // Zap result register from void function.
+      set_register(instr, R0, icount_);
     } else {
       ASSERT(redirection->call_kind() == kNativeCall);
       NativeArguments* arguments;
@@ -1345,31 +1354,32 @@
       SimulatorNativeCall target =
           reinterpret_cast<SimulatorNativeCall>(external);
       target(arguments, target_func);
-      set_register(R0, icount_);  // Zap result register from void function.
-      set_register(R1, icount_);
+      // Zap result register from void function.
+      set_register(instr, R0, icount_);
+      set_register(instr, R1, icount_);
     }
     set_top_exit_frame_info(0);
 
     // Zap caller-saved registers, since the actual runtime call could have
     // used them.
-    set_register(R2, icount_);
-    set_register(R3, icount_);
-    set_register(R4, icount_);
-    set_register(R5, icount_);
-    set_register(R6, icount_);
-    set_register(R7, icount_);
-    set_register(R8, icount_);
-    set_register(R9, icount_);
-    set_register(R10, icount_);
-    set_register(R11, icount_);
-    set_register(R12, icount_);
-    set_register(R13, icount_);
-    set_register(R14, icount_);
-    set_register(R15, icount_);
-    set_register(IP0, icount_);
-    set_register(IP1, icount_);
-    set_register(R18, icount_);
-    set_register(LR, icount_);
+    set_register(instr, R2, icount_);
+    set_register(instr, R3, icount_);
+    set_register(instr, R4, icount_);
+    set_register(instr, R5, icount_);
+    set_register(instr, R6, icount_);
+    set_register(instr, R7, icount_);
+    set_register(instr, R8, icount_);
+    set_register(instr, R9, icount_);
+    set_register(instr, R10, icount_);
+    set_register(instr, R11, icount_);
+    set_register(instr, R12, icount_);
+    set_register(instr, R13, icount_);
+    set_register(instr, R14, icount_);
+    set_register(instr, R15, icount_);
+    set_register(instr, IP0, icount_);
+    set_register(instr, IP1, icount_);
+    set_register(instr, R18, icount_);
+    set_register(instr, LR, icount_);
 
     // TODO(zra): Zap caller-saved fpu registers.
 
@@ -1457,7 +1467,7 @@
   const int64_t ret = get_pc() + Instr::kInstrSize;
   set_pc(dest);
   if (link) {
-    set_register(LR, ret);
+    set_register(instr, LR, ret);
   }
 }
 
@@ -1479,7 +1489,7 @@
         const int64_t dest = get_register(rn, instr->RnMode());
         const int64_t ret = get_pc() + Instr::kInstrSize;
         set_pc(dest);
-        set_register(LR, ret);
+        set_register(instr, LR, ret);
         break;
       }
       case 2: {
@@ -1703,14 +1713,14 @@
       if (use_w) {
         set_wregister(rt, static_cast<int32_t>(val), R31IsZR);
       } else {
-        set_register(rt, val, R31IsZR);
+        set_register(instr, rt, val, R31IsZR);
       }
     }
   }
 
   // Do writeback.
   if (wb) {
-    set_register(rn, wb_address, R31IsSP);
+    set_register(instr, rn, wb_address, R31IsSP);
   }
 }
 
@@ -1728,7 +1738,7 @@
   const int64_t val = ReadX(address, instr);
   if (instr->Bit(30)) {
     // Format(instr, "ldrx 'rt, 'pcldr");
-    set_register(rt, val, R31IsZR);
+    set_register(instr, rt, val, R31IsZR);
   } else {
     // Format(instr, "ldrw 'rt, 'pcldr");
     set_wregister(rt, static_cast<int32_t>(val), R31IsZR);
@@ -1851,7 +1861,7 @@
     } else {
       alu_out = rn_val + rm_val;
     }
-    set_register(rd, alu_out, instr->RdMode());
+    set_register(instr, rd, alu_out, instr->RdMode());
     if (instr->HasS()) {
       SetNZFlagsX(alu_out);
       if (subtract) {
@@ -1942,7 +1952,7 @@
   }
 
   if (instr->SFField() == 1) {
-    set_register(rd, alu_out, instr->RdMode());
+    set_register(instr, rd, alu_out, instr->RdMode());
   } else {
     set_wregister(rd, alu_out & kWRegMask, instr->RdMode());
   }
@@ -2015,7 +2025,7 @@
       // Format(instr, "sdiv'sf 'rd, 'rn, 'rm");
       const bool signd = instr->Bit(10) == 1;
       if (instr->SFField() == 1) {
-        set_register(rd, divide64(rn_val64, rm_val64, signd), R31IsZR);
+        set_register(instr, rd, divide64(rn_val64, rm_val64, signd), R31IsZR);
       } else {
         set_wregister(rd, divide32(rn_val32, rm_val32, signd), R31IsZR);
       }
@@ -2025,7 +2035,7 @@
       // Format(instr, "lsl'sf 'rd, 'rn, 'rm");
       if (instr->SFField() == 1) {
         const int64_t alu_out = rn_val64 << (rm_val64 & (kXRegSizeInBits - 1));
-        set_register(rd, alu_out, R31IsZR);
+        set_register(instr, rd, alu_out, R31IsZR);
       } else {
         const int32_t alu_out = rn_val32 << (rm_val32 & (kXRegSizeInBits - 1));
         set_wregister(rd, alu_out, R31IsZR);
@@ -2037,7 +2047,7 @@
       if (instr->SFField() == 1) {
         const uint64_t rn_u64 = static_cast<uint64_t>(rn_val64);
         const int64_t alu_out = rn_u64 >> (rm_val64 & (kXRegSizeInBits - 1));
-        set_register(rd, alu_out, R31IsZR);
+        set_register(instr, rd, alu_out, R31IsZR);
       } else {
         const uint32_t rn_u32 = static_cast<uint32_t>(rn_val32);
         const int32_t alu_out = rn_u32 >> (rm_val32 & (kXRegSizeInBits - 1));
@@ -2049,7 +2059,7 @@
       // Format(instr, "asr'sf 'rd, 'rn, 'rm");
       if (instr->SFField() == 1) {
         const int64_t alu_out = rn_val64 >> (rm_val64 & (kXRegSizeInBits - 1));
-        set_register(rd, alu_out, R31IsZR);
+        set_register(instr, rd, alu_out, R31IsZR);
       } else {
         const int32_t alu_out = rn_val32 >> (rm_val32 & (kXRegSizeInBits - 1));
         set_wregister(rd, alu_out, R31IsZR);
@@ -2076,7 +2086,7 @@
       const int64_t rm_val = get_register(rm, R31IsZR);
       const int64_t ra_val = get_register(ra, R31IsZR);
       const int64_t alu_out = ra_val + (rn_val * rm_val);
-      set_register(rd, alu_out, R31IsZR);
+      set_register(instr, rd, alu_out, R31IsZR);
     } else {
       const int32_t rn_val = get_wregister(rn, R31IsZR);
       const int32_t rm_val = get_wregister(rm, R31IsZR);
@@ -2092,7 +2102,7 @@
       const int64_t rm_val = get_register(rm, R31IsZR);
       const int64_t ra_val = get_register(ra, R31IsZR);
       const int64_t alu_out = ra_val - (rn_val * rm_val);
-      set_register(rd, alu_out, R31IsZR);
+      set_register(instr, rd, alu_out, R31IsZR);
     } else {
       const int32_t rn_val = get_wregister(rn, R31IsZR);
       const int32_t rm_val = get_wregister(rm, R31IsZR);
@@ -2108,7 +2118,7 @@
     const __int128 res =
         static_cast<__int128>(rn_val) * static_cast<__int128>(rm_val);
     const int64_t alu_out = static_cast<int64_t>(res >> 64);
-    set_register(rd, alu_out, R31IsZR);
+    set_register(instr, rd, alu_out, R31IsZR);
   } else {
     UnimplementedInstruction(instr);
   }
@@ -2156,7 +2166,7 @@
   }
 
   if (instr->SFField() == 1) {
-    set_register(rd, result64, instr->RdMode());
+    set_register(instr, rd, result64, instr->RdMode());
   } else {
     set_wregister(rd, result32, instr->RdMode());
   }
@@ -2221,7 +2231,7 @@
       set_wregister(rd, get_vregisters(vn, idx5), R31IsZR);
     } else {
       // Format(instr, "vmovrd 'rd, 'vn'idx5");
-      set_register(rd, get_vregisterd(vn, idx5), R31IsZR);
+      set_register(instr, rd, get_vregisterd(vn, idx5), R31IsZR);
     }
   } else if ((Q == 1)  && (op == 0) && (imm4 == 0)) {
     // Format(instr, "vdup'csz 'vd, 'vn'idx5");
@@ -2672,7 +2682,7 @@
   } else if (instr->Bits(16, 5) == 6) {
     // Format(instr, "fmovrd 'rd, 'vn");
     const int64_t vn_val = get_vregisterd(vn, 0);
-    set_register(rd, vn_val, R31IsZR);
+    set_register(instr, rd, vn_val, R31IsZR);
   } else if (instr->Bits(16, 5) == 7) {
     // Format(instr, "fmovdr 'vd, 'rn");
     const int64_t rn_val = get_register(rn, R31IsZR);
@@ -2681,7 +2691,7 @@
   } else if (instr->Bits(16, 5) == 24) {
     // Format(instr, "fcvtzds 'rd, 'vn");
     const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0));
-    set_register(rd, static_cast<int64_t>(vn_val), instr->RdMode());
+    set_register(instr, rd, static_cast<int64_t>(vn_val), instr->RdMode());
   } else {
     UnimplementedInstruction(instr);
   }
@@ -2940,10 +2950,10 @@
     set_vregisterd(V3, 0, parameter3);
     set_vregisterd(V3, 1, 0);
   } else {
-    set_register(R0, parameter0);
-    set_register(R1, parameter1);
-    set_register(R2, parameter2);
-    set_register(R3, parameter3);
+    set_register(NULL, R0, parameter0);
+    set_register(NULL, R1, parameter1);
+    set_register(NULL, R2, parameter2);
+    set_register(NULL, R3, parameter3);
   }
 
   // Make sure the activation frames are properly aligned.
@@ -2952,14 +2962,14 @@
     stack_pointer =
         Utils::RoundDown(stack_pointer, OS::ActivationFrameAlignment());
   }
-  set_register(R31, stack_pointer, R31IsSP);
+  set_register(NULL, R31, stack_pointer, R31IsSP);
 
   // Prepare to execute the code at entry.
   set_pc(entry);
   // Put down marker for end of simulation. The simulator will stop simulation
   // when the PC reaches this value. By saving the "end simulation" value into
   // the LR the simulation stops when returning to this call point.
-  set_register(LR, kEndSimulatingPC);
+  set_register(NULL, LR, kEndSimulatingPC);
 
   // Remember the values of callee-saved registers, and set them up with a
   // known value so that we are able to check that they are preserved
@@ -2970,7 +2980,7 @@
   for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) {
     const Register r = static_cast<Register>(i);
     preserved_vals[i - kAbiFirstPreservedCpuReg] = get_register(r);
-    set_register(r, callee_saved_value);
+    set_register(NULL, r, callee_saved_value);
   }
 
   // Only the bottom half of the V registers must be preserved.
@@ -2990,7 +3000,7 @@
   for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) {
     const Register r = static_cast<Register>(i);
     ASSERT(callee_saved_value == get_register(r));
-    set_register(r, preserved_vals[i - kAbiFirstPreservedCpuReg]);
+    set_register(NULL, r, preserved_vals[i - kAbiFirstPreservedCpuReg]);
   }
 
   for (int i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg; i++) {
@@ -3001,7 +3011,7 @@
   }
 
   // Restore the SP register and return R0.
-  set_register(R31, sp_before_call, R31IsSP);
+  set_register(NULL, R31, sp_before_call, R31IsSP);
   int64_t return_value;
   if (fp_return) {
     return_value = get_vregisterd(V0, 0);
@@ -3037,12 +3047,12 @@
 
   // Unwind the C++ stack and continue simulation in the target frame.
   set_pc(static_cast<int64_t>(pc));
-  set_register(R31, static_cast<int64_t>(sp), R31IsSP);
-  set_register(FP, static_cast<int64_t>(fp));
+  set_register(NULL, SP, static_cast<int64_t>(sp));
+  set_register(NULL, FP, static_cast<int64_t>(fp));
 
   ASSERT(raw_exception != Object::null());
-  set_register(kExceptionObjectReg, bit_cast<int64_t>(raw_exception));
-  set_register(kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace));
+  set_register(NULL, kExceptionObjectReg, bit_cast<int64_t>(raw_exception));
+  set_register(NULL, kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace));
   buf->Longjmp();
 }
 
diff --git a/runtime/vm/simulator_arm64.h b/runtime/vm/simulator_arm64.h
index 6db0360..2d3f714 100644
--- a/runtime/vm/simulator_arm64.h
+++ b/runtime/vm/simulator_arm64.h
@@ -48,7 +48,8 @@
   // specifying the type. We also can't translate a dummy value for SPREG into
   // a real value because the architecture independent code expects SPREG to
   // be a real register value.
-  void set_register(Register reg, int64_t value, R31Type r31t = R31IsSP);
+  void set_register(
+      Instr* instr, Register reg, int64_t value, R31Type r31t = R31IsSP);
   int64_t get_register(Register reg, R31Type r31t = R31IsSP) const;
   void set_wregister(Register reg, int32_t value, R31Type r31t = R31IsSP);
   int32_t get_wregister(Register reg, R31Type r31t = R31IsSP) const;
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 74de207d..c8deea9 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -858,7 +858,7 @@
         field_ ^= array_.At(offset >> kWordSizeLog2);
         ASSERT(!field_.IsNull());
         ASSERT(field_.Offset() == offset);
-        field_.UpdateGuardedCidAndLength(obj_);
+        field_.RecordStore(obj_);
       }
       // TODO(fschneider): Verify the guarded cid and length for other kinds of
       // snapshot (kFull, kScript) with asserts.
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 797c286..4f1c8c3 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -590,8 +590,7 @@
   __ LeaveStubFrame();
 
   // Tail-call to target function.
-  __ ldr(R2, FieldAddress(R0, Function::code_offset()));
-  __ ldr(R2, FieldAddress(R2, Code::instructions_offset()));
+  __ ldr(R2, FieldAddress(R0, Function::instructions_offset()));
   __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag);
   __ bx(R2);
 }
@@ -1383,8 +1382,7 @@
 
   __ Bind(&call_target_function);
   // R0: target function.
-  __ ldr(R2, FieldAddress(R0, Function::code_offset()));
-  __ ldr(R2, FieldAddress(R2, Code::instructions_offset()));
+  __ ldr(R2, FieldAddress(R0, Function::instructions_offset()));
   __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag);
   __ bx(R2);
 
@@ -1519,11 +1517,10 @@
 
   // Get function and call it, if possible.
   __ LoadFromOffset(kWord, R0, R6, target_offset);
-  __ ldr(R2, FieldAddress(R0, Function::code_offset()));
+  __ ldr(R2, FieldAddress(R0, Function::instructions_offset()));
 
   // R0: function.
-  // R2: target code.
-  __ ldr(R2, FieldAddress(R2, Code::instructions_offset()));
+  // R2: target instructions.
   __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag);
   __ bx(R2);
 }
@@ -1550,8 +1547,7 @@
   __ PopList((1 << R4) | (1 << R5));  // Restore arg desc. and IC data.
   __ LeaveStubFrame();
 
-  __ ldr(R2, FieldAddress(R0, Function::code_offset()));
-  __ ldr(R2, FieldAddress(R2, Code::instructions_offset()));
+  __ ldr(R2, FieldAddress(R0, Function::instructions_offset()));
   __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag);
   __ bx(R2);
 }
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index 64d81bf..ef20898 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -51,8 +51,7 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to Dart VM C++ code.
-  __ mov(TMP, SP);  // Can't directly store SP.
-  __ StoreToOffset(TMP, R0, Isolate::top_exit_frame_info_offset(), kNoPP);
+  __ StoreToOffset(SP, R0, Isolate::top_exit_frame_info_offset(), kNoPP);
 
   // Save current Context pointer into Isolate structure.
   __ StoreToOffset(CTX, R0, Isolate::top_context_offset(), kNoPP);
@@ -77,8 +76,9 @@
   // Reserve space for arguments and align frame before entering C++ world.
   // NativeArguments are passed in registers.
   __ Comment("align stack");
+  // Reserve space for arguments.
   ASSERT(sizeof(NativeArguments) == 4 * kWordSize);
-  __ ReserveAlignedFrameSpace(4 * kWordSize);  // Reserve space for arguments.
+  __ ReserveAlignedFrameSpace(sizeof(NativeArguments));
 
   // Pass NativeArguments structure by value and call runtime.
   // Registers R0, R1, R2, and R3 are used.
@@ -101,12 +101,26 @@
     ASSERT(retval_offset == 3 * kWordSize);
   __ AddImmediate(R3, R2, kWordSize, kNoPP);
 
-  // TODO(zra): Check that the ABI allows calling through this register.
-  __ blr(R5);
+  __ StoreToOffset(R0, SP, isolate_offset, kNoPP);
+  __ StoreToOffset(R1, SP, argc_tag_offset, kNoPP);
+  __ StoreToOffset(R2, SP, argv_offset, kNoPP);
+  __ StoreToOffset(R3, SP, retval_offset, kNoPP);
+  __ mov(R0, SP);  // Pass the pointer to the NativeArguments.
 
-  // Retval is next to 1st argument.
+  // We are entering runtime code, so the C stack pointer must be restored from
+  // the stack limit to the top of the stack. We cache the stack limit address
+  // in a callee-saved register.
+  __ mov(R26, CSP);
+  __ mov(CSP, SP);
+
+  __ blr(R5);
   __ Comment("CallToRuntimeStub return");
 
+  // Restore SP and CSP.
+  __ mov(SP, CSP);
+  __ mov(CSP, R26);
+
+  // Retval is next to 1st argument.
   // Mark that the isolate is executing Dart code.
   __ LoadImmediate(R2, VMTag::kScriptTagId, kNoPP);
   __ StoreToOffset(R2, CTX, Isolate::vm_tag_offset(), kNoPP);
@@ -155,8 +169,7 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ mov(TMP, SP);
-  __ StoreToOffset(TMP, R0, Isolate::top_exit_frame_info_offset(), kNoPP);
+  __ StoreToOffset(SP, R0, Isolate::top_exit_frame_info_offset(), kNoPP);
 
   // Save current Context pointer into Isolate structure.
   __ StoreToOffset(CTX, R0, Isolate::top_context_offset(), kNoPP);
@@ -210,6 +223,12 @@
   __ StoreToOffset(R3, SP, retval_offset, kNoPP);
   __ mov(R0, SP);  // Pass the pointer to the NativeArguments.
 
+  // We are entering runtime code, so the C stack pointer must be restored from
+  // the stack limit to the top of the stack. We cache the stack limit address
+  // in the Dart SP register, which is callee-saved in the C ABI.
+  __ mov(R26, CSP);
+  __ mov(CSP, SP);
+
   // Call native function (setsup scope if not leaf function).
   Label leaf_call;
   Label done;
@@ -234,6 +253,9 @@
   __ blr(R5);
 
   __ Bind(&done);
+  // Restore SP and CSP.
+  __ mov(SP, CSP);
+  __ mov(CSP, R26);
 
   // Mark that the isolate is executing Dart code.
   __ LoadImmediate(R2, VMTag::kScriptTagId, kNoPP);
@@ -276,8 +298,7 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ mov(TMP, SP);  // Can't store SP directly, first copy to TMP.
-  __ StoreToOffset(TMP, R0, Isolate::top_exit_frame_info_offset(), kNoPP);
+  __ StoreToOffset(SP, R0, Isolate::top_exit_frame_info_offset(), kNoPP);
 
   // Save current Context pointer into Isolate structure.
   __ StoreToOffset(CTX, R0, Isolate::top_context_offset(), kNoPP);
@@ -331,9 +352,19 @@
   __ StoreToOffset(R3, SP, retval_offset, kNoPP);
   __ mov(R0, SP);  // Pass the pointer to the NativeArguments.
 
+  // We are entering runtime code, so the C stack pointer must be restored from
+  // the stack limit to the top of the stack. We cache the stack limit address
+  // in the Dart SP register, which is callee-saved in the C ABI.
+  __ mov(R26, CSP);
+  __ mov(CSP, SP);
+
   // Call native function or redirection via simulator.
   __ blr(R5);
 
+  // Restore SP and CSP.
+  __ mov(SP, CSP);
+  __ mov(CSP, R26);
+
   // Mark that the isolate is executing Dart code.
   __ LoadImmediate(R2, VMTag::kScriptTagId, kNoPP);
   __ StoreToOffset(R2, CTX, Isolate::vm_tag_offset(), kNoPP);
@@ -487,9 +518,7 @@
 
   for (intptr_t reg_idx = kNumberOfVRegisters - 1; reg_idx >= 0; reg_idx--) {
     VRegister vreg = static_cast<VRegister>(reg_idx);
-    // TODO(zra): Save whole V registers. For now, push twice.
-    __ PushDouble(vreg);
-    __ PushDouble(vreg);
+    __ PushQuad(vreg);
   }
 
   __ mov(R0, SP);  // Pass address of saved registers block.
@@ -504,8 +533,7 @@
 
   // There is a Dart Frame on the stack. We must restore PP and leave frame.
   __ LeaveDartFrame();
-  __ sub(TMP, FP, Operand(R0));
-  __ mov(SP, TMP);
+  __ sub(SP, FP, Operand(R0));
 
   // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there
   // is no need to set the correct PC marker or load PP, since they get patched.
@@ -547,8 +575,7 @@
   }
   __ LeaveStubFrame();
   // Remove materialization arguments.
-  __ add(TMP, SP, Operand(R1, UXTX, 0));
-  __ mov(SP, TMP);
+  __ add(SP, SP, Operand(R1));
   __ ret();
 }
 
@@ -598,8 +625,7 @@
   __ LeaveStubFrame();
 
   // Tail-call to target function.
-  __ LoadFieldFromOffset(R2, R0, Function::code_offset(), kNoPP);
-  __ LoadFieldFromOffset(R2, R2, Code::instructions_offset(), kNoPP);
+  __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), kNoPP);
   __ AddImmediate(R2, R2, Instructions::HeaderSize() - kHeapObjectTag, PP);
   __ br(R2);
 }
@@ -748,12 +774,19 @@
 //   R3 : new context containing the current isolate pointer.
 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
   __ Comment("InvokeDartCodeStub");
-  __ EnterFrame(0);
-
   // The new context, saved vm tag, the top exit frame, and the old context.
   const intptr_t kNewContextOffsetFromFp =
       -(1 + kAbiPreservedCpuRegCount + kAbiPreservedFpuRegCount) * kWordSize;
 
+  // Amount of space to reserve with the system stack pointer before setting it
+  // to the stack limit.
+  const intptr_t kRegSaveSpace = Utils::RoundUp(-kNewContextOffsetFromFp, 16);
+
+  // Copy the C stack pointer (R31) into the stack pointer we'll actually use
+  // to access the stack.
+  __ SetupDartSP(kRegSaveSpace);
+  __ EnterFrame(0);
+
   // Save the callee-saved registers.
   for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) {
     const Register r = static_cast<Register>(i);
@@ -786,9 +819,15 @@
   // Cache the new Context pointer into CTX while executing Dart code.
   __ LoadFromOffset(CTX, R3, VMHandles::kOffsetOfRawPtrInHandle, PP);
 
-  // Load Isolate pointer from Context structure into temporary register R4.
+  // Load Isolate pointer from Context structure into temporary register R5.
   __ LoadFieldFromOffset(R5, CTX, Context::isolate_offset(), PP);
 
+  // Load the stack limit address into the C stack pointer register.
+  __ LoadFromOffset(CSP, R5, Isolate::stack_limit_offset(), PP);
+
+  // Cache the new Context pointer into CTX while executing Dart code.
+  __ LoadFromOffset(CTX, R3, VMHandles::kOffsetOfRawPtrInHandle, PP);
+
   // Save the current VMTag on the stack.
   ASSERT(kSavedVMTagSlotFromEntryFp == -20);
   __ LoadFromOffset(R4, R5, Isolate::vm_tag_offset(), PP);
@@ -884,12 +923,14 @@
     Register r = static_cast<Register>(i);
     // We use ldr instead of the Pop macro because we will be popping the PP
     // register when it is not holding a pool-pointer since we are returning to
-    // C++ code.
+    // C++ code. We also skip the dart stack pointer SP, since we are still
+    // using it as the stack pointer.
     __ ldr(r, Address(SP, 1 * kWordSize, Address::PostIndex));
   }
 
-  // Restore the frame pointer and return.
+  // Restore the frame pointer and C stack pointer and return.
   __ LeaveFrame();
+  __ mov(CSP, SP);
   __ ret();
 }
 
@@ -1478,8 +1519,7 @@
 
   __ Bind(&call_target_function);
   // R0: target function.
-  __ LoadFieldFromOffset(R2, R0, Function::code_offset(), kNoPP);
-  __ LoadFieldFromOffset(R2, R2, Code::instructions_offset(), kNoPP);
+  __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), kNoPP);
   __ AddImmediate(
       R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP);
   __ br(R2);
@@ -1602,11 +1642,10 @@
 
   // Get function and call it, if possible.
   __ LoadFromOffset(R0, R6, target_offset, kNoPP);
-  __ LoadFieldFromOffset(R2, R0, Function::code_offset(), kNoPP);
+  __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), kNoPP);
 
   // R0: function.
-  // R2: target code.
-  __ LoadFieldFromOffset(R2, R2, Code::instructions_offset(), kNoPP);
+  // R2: target instructons.
   __ AddImmediate(
       R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP);
   __ br(R2);
@@ -1636,8 +1675,7 @@
   __ Pop(R5);  // Restore IC Data.
   __ LeaveStubFrame();
 
-  __ LoadFieldFromOffset(R2, R0, Function::code_offset(), kNoPP);
-  __ LoadFieldFromOffset(R2, R2, Code::instructions_offset(), kNoPP);
+  __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), kNoPP);
   __ AddImmediate(
       R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP);
   __ br(R2);
@@ -1786,7 +1824,8 @@
 
 
 void StubCode::GenerateGetStackPointerStub(Assembler* assembler) {
-  __ Stop("GenerateGetStackPointerStub");
+  __ mov(R0, SP);
+  __ ret();
 }
 
 
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index e33bded..8c1e3b9 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -591,8 +591,7 @@
   __ popl(ECX);  // Restore IC data.
   __ LeaveFrame();
 
-  __ movl(EBX, FieldAddress(EAX, Function::code_offset()));
-  __ movl(EBX, FieldAddress(EBX, Code::instructions_offset()));
+  __ movl(EBX, FieldAddress(EAX, Function::instructions_offset()));
   __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
   __ jmp(EBX);
 }
@@ -1416,8 +1415,7 @@
 
   __ Bind(&call_target_function);
   // EAX: Target function.
-  __ movl(EBX, FieldAddress(EAX, Function::code_offset()));
-  __ movl(EBX, FieldAddress(EBX, Code::instructions_offset()));
+  __ movl(EBX, FieldAddress(EAX, Function::instructions_offset()));
   __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
   __ jmp(EBX);
 
@@ -1565,10 +1563,9 @@
 
   // Get function and call it, if possible.
   __ movl(EAX, Address(EBX, target_offset));
-  __ movl(EBX, FieldAddress(EAX, Function::code_offset()));
+  __ movl(EBX, FieldAddress(EAX, Function::instructions_offset()));
 
-  // EBX: Target code.
-  __ movl(EBX, FieldAddress(EBX, Code::instructions_offset()));
+  // EBX: Target instructions.
   __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
   __ jmp(EBX);
 }
@@ -1596,8 +1593,7 @@
   __ popl(EDX);  // Restore arguments descriptor array.
   __ LeaveFrame();
 
-  __ movl(EAX, FieldAddress(EAX, Function::code_offset()));
-  __ movl(EAX, FieldAddress(EAX, Code::instructions_offset()));
+  __ movl(EAX, FieldAddress(EAX, Function::instructions_offset()));
   __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
   __ jmp(EAX);
 }
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index 37ba59a..604045a 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -670,8 +670,7 @@
 
   __ LeaveStubFrame();
 
-  __ lw(T2, FieldAddress(T0, Function::code_offset()));
-  __ lw(T2, FieldAddress(T2, Code::instructions_offset()));
+  __ lw(T2, FieldAddress(T0, Function::instructions_offset()));
   __ AddImmediate(T2, Instructions::HeaderSize() - kHeapObjectTag);
   __ jr(T2);
 }
@@ -1570,8 +1569,7 @@
   // T0 <- T3: Target function.
   __ mov(T0, T3);
   Label is_compiled;
-  __ lw(T4, FieldAddress(T0, Function::code_offset()));
-  __ lw(T4, FieldAddress(T4, Code::instructions_offset()));
+  __ lw(T4, FieldAddress(T0, Function::instructions_offset()));
   __ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag);
   __ jr(T4);
 
@@ -1715,10 +1713,9 @@
 
   // Get function and call it, if possible.
   __ lw(T0, Address(T0, target_offset));
-  __ lw(T4, FieldAddress(T0, Function::code_offset()));
+  __ lw(T4, FieldAddress(T0, Function::instructions_offset()));
 
-  // T4: target code.
-  __ lw(T4, FieldAddress(T4, Code::instructions_offset()));
+  // T4: target instructions.
   __ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag);
   __ jr(T4);
 }
@@ -1748,8 +1745,7 @@
   __ addiu(SP, SP, Immediate(3 * kWordSize));
   __ LeaveStubFrame();
 
-  __ lw(T2, FieldAddress(T0, Function::code_offset()));
-  __ lw(T2, FieldAddress(T2, Code::instructions_offset()));
+  __ lw(T2, FieldAddress(T0, Function::instructions_offset()));
   __ AddImmediate(T2, Instructions::HeaderSize() - kHeapObjectTag);
   __ jr(T2);
 }
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 69d0562..cafb218 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -548,8 +548,7 @@
   __ popq(RBX);  // Restore IC data.
   __ LeaveStubFrame();
 
-  __ movq(RCX, FieldAddress(RAX, Function::code_offset()));
-  __ movq(RCX, FieldAddress(RCX, Code::instructions_offset()));
+  __ movq(RCX, FieldAddress(RAX, Function::instructions_offset()));
   __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
   __ jmp(RCX);
 }
@@ -1341,8 +1340,7 @@
   __ Bind(&call_target_function);
   // RAX: Target function.
   Label is_compiled;
-  __ movq(RCX, FieldAddress(RAX, Function::code_offset()));
-  __ movq(RCX, FieldAddress(RCX, Code::instructions_offset()));
+  __ movq(RCX, FieldAddress(RAX, Function::instructions_offset()));
   __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
   __ jmp(RCX);
 
@@ -1488,9 +1486,8 @@
 
   // Get function and call it, if possible.
   __ movq(RAX, Address(R12, target_offset));
-  __ movq(RCX, FieldAddress(RAX, Function::code_offset()));
-  // RCX: Target code.
-  __ movq(RCX, FieldAddress(RCX, Code::instructions_offset()));
+  __ movq(RCX, FieldAddress(RAX, Function::instructions_offset()));
+  // RCX: Target instructions.
   __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
   __ jmp(RCX);
 }
@@ -1518,8 +1515,7 @@
   __ popq(R10);  // Restore arguments descriptor array.
   __ LeaveStubFrame();
 
-  __ movq(RAX, FieldAddress(RAX, Function::code_offset()));
-  __ movq(RAX, FieldAddress(RAX, Code::instructions_offset()));
+  __ movq(RAX, FieldAddress(RAX, Function::instructions_offset()));
   __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
   __ jmp(RAX);
 }
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index 754de7e..5f1d8d00 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -49,7 +49,7 @@
 
 const String& Symbols::Keyword(Token::Kind keyword) {
   const int kw_index = keyword - Token::kFirstKeyword;
-  ASSERT((0 <= kw_index) && (kw_index < Token::numKeywords));
+  ASSERT((0 <= kw_index) && (kw_index < Token::kNumKeywords));
   // First keyword symbol is in symbol_handles_[kKwTableStart + 1].
   const intptr_t keyword_id = Symbols::kKwTableStart + 1 + kw_index;
   ASSERT(symbol_handles_[keyword_id] != NULL);
diff --git a/runtime/vm/token.h b/runtime/vm/token.h
index 2a8fd18..b446076 100644
--- a/runtime/vm/token.h
+++ b/runtime/vm/token.h
@@ -208,7 +208,7 @@
 
   static const Kind kFirstKeyword = kABSTRACT;
   static const Kind kLastKeyword = kWITH;
-  static const int  numKeywords = kLastKeyword - kFirstKeyword + 1;
+  static const int kNumKeywords = kLastKeyword - kFirstKeyword + 1;
 
   static bool IsAssignmentOperator(Kind tok) {
     return kASSIGN <= tok && tok <= kASSIGN_MOD;
diff --git a/sdk/lib/_blink/dartium/_blink_dartium.dart b/sdk/lib/_blink/dartium/_blink_dartium.dart
index 1b2a534..749a403 100644
--- a/sdk/lib/_blink/dartium/_blink_dartium.dart
+++ b/sdk/lib/_blink/dartium/_blink_dartium.dart
@@ -3900,6 +3900,8 @@
 
 Native_ImageData_width_Getter(mthis) native "ImageData_width_Getter";
 
+Native_InjectedScriptHost_inspect_Callback(mthis, objectId, hints) native "InjectedScriptHost_inspect_Callback";
+
 Native_InputMethodContext_compositionEndOffset_Getter(mthis) native "InputMethodContext_compositionEndOffset_Getter";
 
 Native_InputMethodContext_compositionStartOffset_Getter(mthis) native "InputMethodContext_compositionStartOffset_Getter";
@@ -7186,10 +7188,10 @@
     if ((blob_OR_source_OR_stream is Blob || blob_OR_source_OR_stream == null)) {
       return Native_URL__createObjectURL_1_Callback(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 Native_URL__createObjectURL_2_Callback(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 MediaSource || blob_OR_source_OR_stream == null)) {
       return Native_URL__createObjectURL_3_Callback(blob_OR_source_OR_stream);
     }
     throw new ArgumentError("Incorrect number or type of arguments");
@@ -7197,9 +7199,9 @@
 
 Native_URL__createObjectURL_1_Callback(blob_OR_source_OR_stream) native "URL_createObjectURL_Callback_RESOLVER_STRING_1_Blob";
 
-Native_URL__createObjectURL_2_Callback(blob_OR_source_OR_stream) native "URL_createObjectURL_Callback_RESOLVER_STRING_1_MediaSource";
+Native_URL__createObjectURL_2_Callback(blob_OR_source_OR_stream) native "URL_createObjectURL_Callback_RESOLVER_STRING_1_MediaStream";
 
-Native_URL__createObjectURL_3_Callback(blob_OR_source_OR_stream) native "URL_createObjectURL_Callback_RESOLVER_STRING_1_MediaStream";
+Native_URL__createObjectURL_3_Callback(blob_OR_source_OR_stream) native "URL_createObjectURL_Callback_RESOLVER_STRING_1_MediaSource";
 
 Native_URL_createObjectUrlFromBlob_Callback(blob) native "URL_createObjectURL_Callback_RESOLVER_STRING_1_Blob";
 
diff --git a/sdk/lib/_internal/compiler/implementation/closure.dart b/sdk/lib/_internal/compiler/implementation/closure.dart
index a7ae252..b85551b 100644
--- a/sdk/lib/_internal/compiler/implementation/closure.dart
+++ b/sdk/lib/_internal/compiler/implementation/closure.dart
@@ -43,8 +43,7 @@
       if (node is FunctionExpression) {
         translator.translateFunction(element, node);
       } else if (element.isSynthesized) {
-        return new ClosureClassMap(null, null, null,
-            new ThisElement(element, compiler.types.dynamicType));
+        return new ClosureClassMap(null, null, null, new ThisElement(element));
       } else {
         assert(element.isField);
         VariableElement field = element;
@@ -54,8 +53,7 @@
         } else {
           assert(element.isInstanceMember);
           closureMappingCache[node] =
-              new ClosureClassMap(null, null, null,
-                  new ThisElement(element, compiler.types.dynamicType));
+              new ClosureClassMap(null, null, null, new ThisElement(element));
         }
       }
       assert(closureMappingCache[node] != null);
@@ -171,13 +169,13 @@
 // move these classes to elements/modelx.dart or see if we can find a
 // more general solution.
 class BoxElement extends ElementX implements TypedElement {
-  final DartType type;
-
-  BoxElement(String name, Element enclosingElement, this.type)
+  BoxElement(String name, Element enclosingElement)
       : super(name, ElementKind.VARIABLE_LIST, enclosingElement);
 
   DartType computeType(Compiler compiler) => type;
 
+  DartType get type => const DynamicType();
+
   accept(ElementVisitor visitor) => visitor.visitBoxElement(this);
 }
 
@@ -203,14 +201,14 @@
 // move these classes to elements/modelx.dart or see if we can find a
 // more general solution.
 class ThisElement extends ElementX implements TypedElement {
-  final DartType type;
-
-  ThisElement(Element enclosing, this.type)
+  ThisElement(Element enclosing)
       : super('this', ElementKind.PARAMETER, enclosing);
 
   bool get isAssignable => false;
 
-  DartType computeType(Compiler compiler) => compiler.types.dynamicType;
+  DartType computeType(Compiler compiler) => type;
+
+  DartType get type => const DynamicType();
 
   // Since there is no declaration corresponding to 'this', use the position of
   // the enclosing method.
@@ -637,7 +635,7 @@
           String boxName =
               namer.getClosureVariableName('box', closureFieldCounter++);
           box = new BoxElement(
-              boxName, currentElement, compiler.types.dynamicType);
+              boxName, currentElement);
         }
         String elementName = element.name;
         String boxedName =
@@ -766,7 +764,7 @@
       outermostElement = element;
       Element thisElement = null;
       if (element.isInstanceMember || element.isGenerativeConstructor) {
-        thisElement = new ThisElement(element, compiler.types.dynamicType);
+        thisElement = new ThisElement(element);
       }
       closureData = new ClosureClassMap(null, null, null, thisElement);
     }
diff --git a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
index 4bdad14..b1939b7 100644
--- a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
@@ -151,7 +151,7 @@
           value != null &&
           element.isField) {
         DartType elementType = element.type;
-        if (elementType.kind == TypeKind.MALFORMED_TYPE && !value.isNull) {
+        if (elementType.isMalformed && !value.isNull) {
           if (isConst) {
             ErroneousElement element = elementType.element;
             compiler.reportFatalError(
@@ -407,8 +407,7 @@
         node, type, compiler.symbolConstructor, createArguments);
   }
 
-  Constant makeTypeConstant(TypeDeclarationElement element) {
-    DartType elementType = element.rawType;
+  Constant makeTypeConstant(DartType elementType) {
     DartType constantType =
         compiler.backend.typeImplementation.computeType(compiler);
     return new TypeConstant(elementType, constantType);
@@ -425,7 +424,8 @@
   Constant visitIdentifier(Identifier node) {
     Element element = elements[node];
     if (Elements.isClass(element) || Elements.isTypedef(element)) {
-      return makeTypeConstant(element);
+      TypeDeclarationElement typeDeclarationElement = element;
+      return makeTypeConstant(typeDeclarationElement.rawType);
     }
     return signalNotCompileTimeConstant(node);
   }
@@ -450,7 +450,7 @@
         if (result != null) return result;
       } else if (Elements.isClass(element) || Elements.isTypedef(element)) {
         assert(elements.isTypeLiteral(send));
-        return makeTypeConstant(element);
+        return makeTypeConstant(elements.getTypeLiteralType(send));
       } else if (send.receiver != null) {
         // Fall through to error handling.
       } else if (!Elements.isUnresolved(element)
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index ddb053a..1fbc00d 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -269,7 +269,7 @@
 
   /// Called during resolution to notify to the backend that the
   /// program uses a type literal.
-  void registerTypeLiteral(Element element,
+  void registerTypeLiteral(DartType type,
                            Enqueuer enqueuer,
                            Registry registry) {}
 
@@ -586,7 +586,6 @@
   ClassElement objectClass;
   ClassElement closureClass;
   ClassElement boundClosureClass;
-  ClassElement dynamicClass;
   ClassElement boolClass;
   ClassElement numClass;
   ClassElement intClass;
@@ -960,14 +959,6 @@
    * set up.
    */
   Future onLibraryLoaded(LibraryElement library, Uri uri) {
-    if (dynamicClass != null) {
-      // When loading the built-in libraries, dynamicClass is null. We
-      // take advantage of this as core imports js_helper and sees [dynamic]
-      // this way.
-      withCurrentElement(dynamicClass, () {
-        library.addToScope(dynamicClass, this);
-      });
-    }
     if (uri == new Uri(scheme: 'dart', path: 'mirrors')) {
       mirrorsLibrary = library;
       mirrorSystemClass =
@@ -1070,7 +1061,6 @@
     jsInvocationMirrorClass = lookupHelperClass('JSInvocationMirror');
     boundClosureClass = lookupHelperClass('BoundClosure');
     closureClass = lookupHelperClass('Closure');
-    dynamicClass = lookupHelperClass('Dynamic_');
     if (!missingHelperClasses.isEmpty) {
       internalError(jsHelperLibrary,
           'dart:_js_helper library does not contain required classes: '
@@ -1078,12 +1068,10 @@
     }
 
     if (types == null) {
-      types = new Types(this, dynamicClass);
+      types = new Types(this);
     }
     backend.initializeHelperClasses();
 
-    dynamicClass.ensureResolved(this);
-
     proxyConstant =
         resolver.constantCompiler.compileConstant(coreLibrary.find('proxy'));
   }
diff --git a/sdk/lib/_internal/compiler/implementation/constants.dart b/sdk/lib/_internal/compiler/implementation/constants.dart
index 2aea6ff..d0b9d14 100644
--- a/sdk/lib/_internal/compiler/implementation/constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/constants.dart
@@ -544,7 +544,7 @@
 
   accept(ConstantVisitor visitor) => visitor.visitInterceptor(this);
 
-  DartType computeType(Compiler compiler) => compiler.types.dynamicType;
+  DartType computeType(Compiler compiler) => const DynamicType();
 
   ti.TypeMask computeMask(Compiler compiler) {
     return compiler.typesTask.nonNullType;
@@ -573,7 +573,7 @@
 
   accept(ConstantVisitor visitor) => visitor.visitDummy(this);
 
-  DartType computeType(Compiler compiler) => compiler.types.dynamicType;
+  DartType computeType(Compiler compiler) => const DynamicType();
 
   ti.TypeMask computeMask(Compiler compiler) => typeMask;
 
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
index 1d8b3e4..cd15e94 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
@@ -474,11 +474,11 @@
     return new Future.value();
   }
 
-  void registerTypeLiteral(Element element,
+  void registerTypeLiteral(DartType type,
                            Enqueuer enqueuer,
                            Registry registry) {
-    if (element.isClass) {
-      usedTypeLiterals.add(element);
+    if (type.isInterfaceType) {
+      usedTypeLiterals.add(type.element);
     }
   }
 
@@ -560,8 +560,8 @@
     final DartType type = treeElements.getType(typeAnnotation);
     assert(invariant(typeAnnotation, type != null,
         message: "Missing type for type annotation: $treeElements."));
-    if (type.kind == TypeKind.TYPEDEF) newTypedefElementCallback(type.element);
-    if (type.kind == TypeKind.INTERFACE) newClassElementCallback(type.element);
+    if (type.isTypedef) newTypedefElementCallback(type.element);
+    if (type.isInterfaceType) newClassElementCallback(type.element);
     typeAnnotation.visitChildren(this);
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
index d7951c5..45c7f3d 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
@@ -328,9 +328,6 @@
     if (element.library.isPlatformLibrary && !element.isTopLevel) {
       return;
     }
-    if (element == compiler.dynamicClass) {
-      return;
-    }
     elementNodes.putIfAbsent(element, () => new Set<Node>()).add(node);
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart
index 6ff101a..7874ba2 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart
@@ -87,6 +87,7 @@
   }
 
   String renameType(DartType type, Function renameElement) {
+    if (type.isDynamic) return 'dynamic';
     // TODO(smok): Do not rename type if it is in platform library or
     // js-helpers.
     StringBuffer result = new StringBuffer(renameElement(type.element));
diff --git a/sdk/lib/_internal/compiler/implementation/dart_types.dart b/sdk/lib/_internal/compiler/implementation/dart_types.dart
index 00851ce6..412c7e8 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_types.dart
@@ -28,6 +28,7 @@
   static const TypeKind TYPEDEF = const TypeKind('typedef');
   static const TypeKind TYPE_VARIABLE = const TypeKind('type variable');
   static const TypeKind MALFORMED_TYPE = const TypeKind('malformed');
+  static const TypeKind DYNAMIC = const TypeKind('dynamic');
   static const TypeKind VOID = const TypeKind('void');
 
   String toString() => id;
@@ -101,10 +102,25 @@
   bool get treatAsDynamic => false;
 
   /// Is [: true :] if this type is the dynamic type.
-  bool get isDynamic => false;
+  bool get isDynamic => kind == TypeKind.DYNAMIC;
 
   /// Is [: true :] if this type is the void type.
-  bool get isVoid => false;
+  bool get isVoid => kind == TypeKind.VOID;
+
+  /// Is [: true :] if this type is an interface type.
+  bool get isInterfaceType => kind == TypeKind.INTERFACE;
+
+  /// Is [: true :] if this type is a typedef.
+  bool get isTypedef => kind == TypeKind.TYPEDEF;
+
+  /// Is [: true :] if this type is a function type.
+  bool get isFunctionType => kind == TypeKind.FUNCTION;
+
+  /// Is [: true :] if this type is a type variable.
+  bool get isTypeVariable => kind == TypeKind.TYPE_VARIABLE;
+
+  /// Is [: true :] if this type is a malformed type.
+  bool get isMalformed => kind == TypeKind.MALFORMED_TYPE;
 
   /// Returns an occurrence of a type variable within this type, if any.
   TypeVariableType get typeVariableOccurrence => null;
@@ -283,8 +299,6 @@
     return visitor.visitVoidType(this, argument);
   }
 
-  bool get isVoid => true;
-
   String toString() => name;
 }
 
@@ -581,8 +595,8 @@
 
   factory FunctionType(
       FunctionTypedElement element,
-      DartType returnType,
-      [Link<DartType> parameterTypes = const Link<DartType>(),
+      [DartType returnType = const DynamicType(),
+       Link<DartType> parameterTypes = const Link<DartType>(),
        Link<DartType> optionalParameterTypes = const Link<DartType>(),
        Link<String> namedParameters = const Link<String>(),
        Link<DartType> namedParameterTypes = const Link<DartType>()]) {
@@ -594,8 +608,8 @@
   }
 
   factory FunctionType.synthesized(
-      DartType returnType,
-      [Link<DartType> parameterTypes = const Link<DartType>(),
+      [DartType returnType = const DynamicType(),
+       Link<DartType> parameterTypes = const Link<DartType>(),
        Link<DartType> optionalParameterTypes = const Link<DartType>(),
        Link<String> namedParameters = const Link<String>(),
        Link<DartType> namedParameterTypes = const Link<DartType>()]) {
@@ -605,8 +619,8 @@
   }
 
   FunctionType.internal(FunctionTypedElement this.element,
-                        DartType this.returnType,
-                        [this.parameterTypes = const Link<DartType>(),
+                        [DartType this.returnType = const DynamicType(),
+                         this.parameterTypes = const Link<DartType>(),
                          this.optionalParameterTypes = const Link<DartType>(),
                          this.namedParameters = const Link<String>(),
                          this.namedParameterTypes = const Link<DartType>()]) {
@@ -816,21 +830,28 @@
 }
 
 /**
- * Special type to hold the [dynamic] type. Used for correctly returning
- * 'dynamic' on [toString].
+ * Special type for the `dynamic` type.
  */
-class DynamicType extends InterfaceType {
-  DynamicType(ClassElement element) : super(element);
+class DynamicType extends DartType {
+  const DynamicType();
+
+  Element get element => null;
 
   String get name => 'dynamic';
 
   bool get treatAsDynamic => true;
 
-  bool get isDynamic => true;
+  TypeKind get kind => TypeKind.DYNAMIC;
+
+  DartType unalias(Compiler compiler) => this;
+
+  DartType subst(Link<DartType> arguments, Link<DartType> parameters) => this;
 
   accept(DartTypeVisitor visitor, var argument) {
     return visitor.visitDynamicType(this, argument);
   }
+
+  String toString() => name;
 }
 
 /**
@@ -903,7 +924,7 @@
       visitGenericType(type, argument);
 
   R visitDynamicType(DynamicType type, A argument) =>
-      visitInterfaceType(type, argument);
+      visitType(type, argument);
 }
 
 /**
@@ -911,10 +932,8 @@
  */
 abstract class AbstractTypeRelation extends DartTypeVisitor<bool, DartType> {
   final Compiler compiler;
-  final DynamicType dynamicType;
 
-  AbstractTypeRelation(Compiler this.compiler,
-                       DynamicType this.dynamicType);
+  AbstractTypeRelation(Compiler this.compiler);
 
   bool visitType(DartType t, DartType s) {
     throw 'internal error: unknown type kind ${t.kind}';
@@ -1089,9 +1108,7 @@
 }
 
 class MoreSpecificVisitor extends AbstractTypeRelation {
-  MoreSpecificVisitor(Compiler compiler,
-                      DynamicType dynamicType)
-      : super(compiler, dynamicType);
+  MoreSpecificVisitor(Compiler compiler) : super(compiler);
 
   bool isMoreSpecific(DartType t, DartType s) {
     if (identical(t, s) || s.treatAsDynamic ||
@@ -1136,9 +1153,7 @@
  */
 class SubtypeVisitor extends MoreSpecificVisitor {
 
-  SubtypeVisitor(Compiler compiler,
-                 DynamicType dynamicType)
-      : super(compiler, dynamicType);
+  SubtypeVisitor(Compiler compiler) : super(compiler);
 
   bool isSubtype(DartType t, DartType s) {
     return t.treatAsDynamic || isMoreSpecific(t, s);
@@ -1191,29 +1206,18 @@
 
 class Types {
   final Compiler compiler;
-  final DynamicType dynamicType;
   final MoreSpecificVisitor moreSpecificVisitor;
   final SubtypeVisitor subtypeVisitor;
   final PotentialSubtypeVisitor potentialSubtypeVisitor;
 
-  factory Types(Compiler compiler, BaseClassElementX dynamicElement) {
-    DynamicType dynamicType = new DynamicType(dynamicElement);
-    dynamicElement.rawTypeCache = dynamicElement.thisTypeCache = dynamicType;
-    return new Types.internal(compiler, dynamicType);
-  }
-
-  Types.internal(Compiler compiler, DynamicType dynamicType)
+  Types(Compiler compiler)
       : this.compiler = compiler,
-        this.dynamicType = dynamicType,
-        this.moreSpecificVisitor =
-          new MoreSpecificVisitor(compiler, dynamicType),
-        this.subtypeVisitor =
-          new SubtypeVisitor(compiler, dynamicType),
-        this.potentialSubtypeVisitor =
-          new PotentialSubtypeVisitor(compiler, dynamicType);
+        this.moreSpecificVisitor = new MoreSpecificVisitor(compiler),
+        this.subtypeVisitor = new SubtypeVisitor(compiler),
+        this.potentialSubtypeVisitor = new PotentialSubtypeVisitor(compiler);
 
   Types copy(Compiler compiler) {
-    return new Types.internal(compiler, dynamicType);
+    return new Types(compiler);
   }
 
   /** Returns true if [t] is more specific than [s]. */
@@ -1339,10 +1343,10 @@
    */
   static int compare(DartType a, DartType b) {
     if (a == b) return 0;
-    if (a.kind == TypeKind.VOID) {
+    if (a.isVoid) {
       // [b] is not void => a < b.
       return -1;
-    } else if (b.kind == TypeKind.VOID) {
+    } else if (b.isVoid) {
       // [a] is not void => a > b.
       return 1;
     }
@@ -1354,21 +1358,21 @@
       return 1;
     }
     bool isDefinedByDeclaration(DartType type) {
-      return type.kind == TypeKind.INTERFACE ||
-             type.kind == TypeKind.TYPEDEF ||
-             type.kind == TypeKind.TYPE_VARIABLE;
+      return type.isInterfaceType ||
+             type.isTypedef ||
+             type.isTypeVariable;
     }
 
     if (isDefinedByDeclaration(a)) {
       if (isDefinedByDeclaration(b)) {
         int result = Elements.compareByPosition(a.element, b.element);
         if (result != 0) return result;
-        if (a.kind == TypeKind.TYPE_VARIABLE) {
-          return b.kind == TypeKind.TYPE_VARIABLE
+        if (a.isTypeVariable) {
+          return b.isTypeVariable
               ? 0
               : 1; // [b] is not a type variable => a > b.
         } else {
-          if (b.kind == TypeKind.TYPE_VARIABLE) {
+          if (b.isTypeVariable) {
             // [a] is not a type variable => a < b.
             return -1;
           } else {
@@ -1386,8 +1390,8 @@
       // nor void => a > b.
       return 1;
     }
-    if (a.kind == TypeKind.FUNCTION) {
-      if (b.kind == TypeKind.FUNCTION) {
+    if (a.isFunctionType) {
+      if (b.isFunctionType) {
         FunctionType aFunc = a;
         FunctionType bFunc = b;
         int result = compare(aFunc.returnType, bFunc.returnType);
@@ -1418,7 +1422,7 @@
         // [b] is a malformed or statement type => a < b.
         return -1;
       }
-    } else if (b.kind == TypeKind.FUNCTION) {
+    } else if (b.isFunctionType) {
       // [b] is a malformed or statement type => a > b.
       return 1;
     }
@@ -1434,8 +1438,8 @@
       // [a] is a malformed type => a < b.
       return -1;
     }
-    assert (a.kind == TypeKind.MALFORMED_TYPE);
-    assert (b.kind == TypeKind.MALFORMED_TYPE);
+    assert (a.isMalformed);
+    assert (b.isMalformed);
     // TODO(johnniwinther): Can we do this better?
     return Elements.compareByPosition(a.element, b.element);
   }
@@ -1564,13 +1568,13 @@
   DartType computeLeastUpperBoundTypeVariableTypes(DartType a,
                                                    DartType b) {
     Set<DartType> typeVariableBounds = new Set<DartType>();
-    while (a.kind == TypeKind.TYPE_VARIABLE) {
+    while (a.isTypeVariable) {
       if (a == b) return a;
       typeVariableBounds.add(a);
       TypeVariableElement element = a.element;
       a = element.bound;
     }
-    while (b.kind == TypeKind.TYPE_VARIABLE) {
+    while (b.isTypeVariable) {
       if (typeVariableBounds.contains(b)) return b;
       TypeVariableElement element = b.element;
       b = element.bound;
@@ -1582,32 +1586,32 @@
   DartType computeLeastUpperBound(DartType a, DartType b) {
     if (a == b) return a;
 
-    if (a.kind == TypeKind.TYPE_VARIABLE ||
-           b.kind == TypeKind.TYPE_VARIABLE) {
+    if (a.isTypeVariable ||
+           b.isTypeVariable) {
       return computeLeastUpperBoundTypeVariableTypes(a, b);
     }
 
     a = a.unalias(compiler);
     b = b.unalias(compiler);
 
-    if (a.treatAsDynamic || b.treatAsDynamic) return dynamicType;
+    if (a.treatAsDynamic || b.treatAsDynamic) return const DynamicType();
     if (a.isVoid || b.isVoid) return const VoidType();
 
-    if (a.kind == TypeKind.FUNCTION && b.kind == TypeKind.FUNCTION) {
+    if (a.isFunctionType && b.isFunctionType) {
       return computeLeastUpperBoundFunctionTypes(a, b);
     }
 
-    if (a.kind == TypeKind.FUNCTION) {
+    if (a.isFunctionType) {
       a = compiler.functionClass.rawType;
     }
-    if (b.kind == TypeKind.FUNCTION) {
+    if (b.isFunctionType) {
       b = compiler.functionClass.rawType;
     }
 
-    if (a.kind == TypeKind.INTERFACE && b.kind == TypeKind.INTERFACE) {
+    if (a.isInterfaceType && b.isInterfaceType) {
       return computeLeastUpperBoundInterfaces(a, b);
     }
-    return dynamicType;
+    return const DynamicType();
   }
 }
 
@@ -1617,10 +1621,7 @@
  * [:false:] only if we are sure no such substitution exists.
  */
 class PotentialSubtypeVisitor extends SubtypeVisitor {
-  PotentialSubtypeVisitor(Compiler compiler,
-                          DynamicType dynamicType)
-      : super(compiler, dynamicType);
-
+  PotentialSubtypeVisitor(Compiler compiler) : super(compiler);
 
   bool isSubtype(DartType t, DartType s) {
     if (t is TypeVariableType || s is TypeVariableType) {
@@ -1656,7 +1657,7 @@
 
     constraintMap = new Map<TypeVariableType, DartType>();
     element.typeVariables.forEach((TypeVariableType typeVariable) {
-      constraintMap[typeVariable] = compiler.types.dynamicType;
+      constraintMap[typeVariable] = const DynamicType();
     });
     if (supertypeInstance.accept(this, supertype)) {
       LinkBuilder<DartType> typeArguments = new LinkBuilder<DartType>();
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index 3770c6f..880746a 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -1001,7 +1001,7 @@
 
   Element lookupLocalMember(String memberName) => importScope[memberName];
 
-  DartType computeType(Compiler compiler) => compiler.types.dynamicType;
+  DartType computeType(Compiler compiler) => const DynamicType();
 
   Token get position => firstPosition;
 
@@ -1623,7 +1623,7 @@
   FunctionSignature computeSignature(Compiler compiler) {
     if (functionSignatureCache != null) return functionSignature;
     compiler.withCurrentElement(this, () {
-      DartType inner = new FunctionType(this, compiler.types.dynamicType);
+      DartType inner = new FunctionType(this);
       functionSignatureCache = new FunctionSignatureX(const Link(),
           const Link(), 0, 0, false, [], inner);
     });
@@ -1795,7 +1795,7 @@
       Link<DartType> dynamicParameters = const Link<DartType>();
       typeParameters.forEach((_) {
         dynamicParameters =
-            dynamicParameters.prepend(compiler.types.dynamicType);
+            dynamicParameters.prepend(const DynamicType());
       });
       rawTypeCache = createType(dynamicParameters);
     }
diff --git a/sdk/lib/_internal/compiler/implementation/enqueue.dart b/sdk/lib/_internal/compiler/implementation/enqueue.dart
index a41bdec..a33db7f 100644
--- a/sdk/lib/_internal/compiler/implementation/enqueue.dart
+++ b/sdk/lib/_internal/compiler/implementation/enqueue.dart
@@ -130,9 +130,9 @@
     registerInstantiatedType(cls.rawType, registry);
   }
 
-  void registerTypeLiteral(Element element, Registry registry) {
+  void registerTypeLiteral(DartType type, Registry registry) {
     registerInstantiatedClass(compiler.typeClass, registry);
-    compiler.backend.registerTypeLiteral(element, this, registry);
+    compiler.backend.registerTypeLiteral(type, this, registry);
   }
 
   bool checkNoEnqueuedInvokedInstanceMethods() {
diff --git a/sdk/lib/_internal/compiler/implementation/helpers/trace.dart b/sdk/lib/_internal/compiler/implementation/helpers/trace.dart
index 42c122a..b592972 100644
--- a/sdk/lib/_internal/compiler/implementation/helpers/trace.dart
+++ b/sdk/lib/_internal/compiler/implementation/helpers/trace.dart
@@ -13,8 +13,16 @@
  * returns [:true:] on the stack trace text. This can be used to filter the
  * printed stack traces based on their content. For instance only print stack
  * traces that contain specific paths.
+ *
+ * If [limit] is provided, the stack trace is limited to [limit] entries.
+ *
+ * If [throwOnPrint] is `true`, [message] will be thrown after the stack trace
+ * has been printed. Together with [condition] this can be used to discover
+ * unknown call-sites in tests by filtering known call-sites and throwning
+ * otherwise.
  */
-void trace(String message, {bool condition(String stackTrace), int limit}) {
+void trace(String message, {bool condition(String stackTrace), int limit,
+                            bool throwOnPrint: false}) {
   try {
     throw '';
   } catch (e, s) {
@@ -24,13 +32,16 @@
       if (!condition(stackTrace)) return;
     }
     print('$message\n$stackTrace');
+    if (throwOnPrint) throw message;
   }
 }
 
 void traceAndReport(Compiler compiler, Spannable node, String message,
-                    {bool condition(String stackTrace), int limit}) {
+                    {bool condition(String stackTrace), int limit,
+                     bool throwOnPrint: false}) {
 
-  trace(message, condition: (String stackTrace) {
+  trace(message, limit: limit, throwOnPrint: throwOnPrint,
+        condition: (String stackTrace) {
     bool result = condition != null ? condition(stackTrace) : true;
     if (result) {
       reportHere(compiler, node, message);
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/concrete_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/concrete_types_inferrer.dart
index 358d74e..361d2f2 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/concrete_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/concrete_types_inferrer.dart
@@ -434,8 +434,6 @@
         return new TypeMask.nonNullSubclass(compiler.backend.numImplementation);
       } else if (element == compiler.backend.intImplementation) {
         return new TypeMask.nonNullSubclass(compiler.backend.intImplementation);
-      } else if (element == compiler.dynamicClass) {
-        return new TypeMask.nonNullSubclass(compiler.objectClass);
       } else {
         return new TypeMask.nonNullExact(element.declaration);
       }
@@ -495,14 +493,13 @@
     if (annotation.isVoid) return nullType;
     if (annotation.element == compiler.objectClass) return type;
     ConcreteType otherType;
-    if (annotation.kind == TypeKind.TYPEDEF
-        || annotation.kind == TypeKind.FUNCTION) {
+    if (annotation.isTypedef || annotation.isFunctionType) {
       otherType = functionType;
-    } else if (annotation.kind == TypeKind.TYPE_VARIABLE) {
+    } else if (annotation.isTypeVariable) {
       // TODO(polux): Narrow to bound.
       return type;
     } else {
-      assert(annotation.kind == TypeKind.INTERFACE);
+      assert(annotation.isInterfaceType);
       otherType = nonNullSubtype(annotation.element);
     }
     if (isNullable) otherType = otherType.union(nullType);
@@ -1799,7 +1796,7 @@
     // We trust the return type of native elements
     if (isNativeElement(element)) {
       var elementType = element.type;
-      assert(elementType.kind == TypeKind.FUNCTION);
+      assert(elementType.isFunctionType);
       return typeOfNativeBehavior(
           native.NativeBehavior.ofMethod(element, compiler));
     }
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
index c2c518c..4b3d0b5 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
@@ -1083,7 +1083,7 @@
       DartType type = elements.getType(node.type);
       T mask = type == null ||
                type.treatAsDynamic ||
-               type.kind == TypeKind.TYPE_VARIABLE
+               type.isTypeVariable
           ? types.dynamicType
           : types.nonNullSubtype(type.element);
       locals.update(elements[exception], mask, 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 efa3e868..e74d9ab 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
@@ -36,16 +36,15 @@
     if (annotation.treatAsDynamic) return type;
     if (annotation.element == compiler.objectClass) return type;
     TypeMask otherType;
-    if (annotation.kind == TypeKind.TYPEDEF
-        || annotation.kind == TypeKind.FUNCTION) {
+    if (annotation.isTypedef || annotation.isFunctionType) {
       otherType = functionType;
-    } else if (annotation.kind == TypeKind.TYPE_VARIABLE) {
+    } else if (annotation.isTypeVariable) {
       // TODO(ngeoffray): Narrow to bound.
       return type;
     } else if (annotation.isVoid) {
       otherType = nullType;
     } else {
-      assert(annotation.kind == TypeKind.INTERFACE);
+      assert(annotation.isInterfaceType);
       otherType = new TypeMask.nonNullSubtype(annotation.element);
     }
     if (isNullable) otherType = otherType.nullable();
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
index 53bea15..355ca78 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
@@ -215,14 +215,13 @@
     if (annotation.isVoid) return nullType;
     if (annotation.element == compiler.objectClass) return type;
     TypeMask otherType;
-    if (annotation.kind == TypeKind.TYPEDEF ||
-        annotation.kind == TypeKind.FUNCTION) {
+    if (annotation.isTypedef || annotation.isFunctionType) {
       otherType = functionType.type;
-    } else if (annotation.kind == TypeKind.TYPE_VARIABLE) {
+    } else if (annotation.isTypeVariable) {
       // TODO(ngeoffray): Narrow to bound.
       return type;
     } else {
-      assert(annotation.kind == TypeKind.INTERFACE);
+      assert(annotation.isInterfaceType);
       otherType = new TypeMask.nonNullSubtype(annotation.element);
     }
     if (isNullable) otherType = otherType.nullable();
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index 717366b..db13631 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -675,7 +675,7 @@
       registerInstantiatedConstantType(interceptor.dispatchedType, registry);
     } else if (constant.isType) {
       TypeConstant typeConstant = constant;
-      registerTypeLiteral(typeConstant.representedType.element,
+      registerTypeLiteral(typeConstant.representedType,
           compiler.enqueuer.codegen, registry);
     }
   }
@@ -683,17 +683,18 @@
   void registerInstantiatedConstantType(DartType type, Registry registry) {
     Enqueuer enqueuer = compiler.enqueuer.codegen;
     DartType instantiatedType =
-        type.kind == TypeKind.FUNCTION ? compiler.functionClass.rawType : type;
-    enqueuer.registerInstantiatedType(instantiatedType, registry);
-    if (type is InterfaceType && !type.treatAsRaw &&
-        classNeedsRti(type.element)) {
-      enqueuer.registerStaticUse(getSetRuntimeTypeInfo());
-    }
-    if (type.element == typeImplementation) {
-      // If we use a type literal in a constant, the compile time
-      // constant emitter will generate a call to the createRuntimeType
-      // helper so we register a use of that.
-      enqueuer.registerStaticUse(getCreateRuntimeType());
+        type.isFunctionType ? compiler.functionClass.rawType : type;
+    if (type is InterfaceType) {
+      enqueuer.registerInstantiatedType(instantiatedType, registry);
+      if (!type.treatAsRaw && classNeedsRti(type.element)) {
+        enqueuer.registerStaticUse(getSetRuntimeTypeInfo());
+      }
+      if (type.element == typeImplementation) {
+        // If we use a type literal in a constant, the compile time
+        // constant emitter will generate a call to the createRuntimeType
+        // helper so we register a use of that.
+        enqueuer.registerStaticUse(getCreateRuntimeType());
+      }
     }
   }
 
@@ -892,7 +893,7 @@
     enqueueInResolution(getCyclicThrowHelper(), registry);
   }
 
-  void registerTypeLiteral(Element element,
+  void registerTypeLiteral(DartType type,
                            Enqueuer enqueuer,
                            Registry registry) {
     enqueuer.registerInstantiatedClass(typeImplementation, registry);
@@ -900,10 +901,10 @@
     // TODO(ahe): Might want to register [element] as an instantiated class
     // when reflection is used.  However, as long as we disable tree-shaking
     // eagerly it doesn't matter.
-    if (element.isTypedef) {
-      typedefTypeLiterals.add(element);
+    if (type.isTypedef) {
+      typedefTypeLiterals.add(type.element);
     }
-    customElementsAnalysis.registerTypeLiteral(element, enqueuer);
+    customElementsAnalysis.registerTypeLiteral(type, enqueuer);
   }
 
   void registerStackTraceInCatch(Registry registry) {
@@ -982,8 +983,8 @@
         }
       }
     }
-    bool isTypeVariable = type.kind == TypeKind.TYPE_VARIABLE;
-    if (type.kind == TypeKind.MALFORMED_TYPE) {
+    bool isTypeVariable = type.isTypeVariable;
+    if (type.isMalformed) {
       enqueueInResolution(getThrowTypeError(), registry);
     }
     if (!type.treatAsRaw || type.containsTypeVariables) {
@@ -1307,7 +1308,7 @@
                                           {bool typeCast,
                                            bool nativeCheckOnly}) {
     assert(type.kind != TypeKind.TYPEDEF);
-    if (type.kind == TypeKind.MALFORMED_TYPE) {
+    if (type.isMalformed) {
       // The same error is thrown for type test and type cast of a malformed
       // type so we only need one check method.
       return 'checkMalformedType';
@@ -1390,15 +1391,15 @@
               : 'listSuperTypeCheck';
         }
       } else {
-        if (type.kind == TypeKind.INTERFACE && !type.treatAsRaw) {
+        if (type.isInterfaceType && !type.treatAsRaw) {
           return typeCast
               ? 'subtypeCast'
               : 'assertSubtype';
-        } else if (type.kind == TypeKind.TYPE_VARIABLE) {
+        } else if (type.isTypeVariable) {
           return typeCast
               ? 'subtypeOfRuntimeTypeCast'
               : 'assertSubtypeOfRuntimeType';
-        } else if (type.kind == TypeKind.FUNCTION) {
+        } else if (type.isFunctionType) {
           return null;
         } else {
           if (nativeCheck) {
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/checked_mode_helpers.dart b/sdk/lib/_internal/compiler/implementation/js_backend/checked_mode_helpers.dart
index de280c4..a958dba 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/checked_mode_helpers.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/checked_mode_helpers.dart
@@ -95,7 +95,7 @@
   void generateAdditionalArguments(SsaCodeGenerator codegen,
                                    HTypeConversion node,
                                    List<jsAst.Expression> arguments) {
-    assert(node.typeExpression.kind == TypeKind.TYPE_VARIABLE);
+    assert(node.typeExpression.isTypeVariable);
     codegen.use(node.typeRepresentation);
     arguments.add(codegen.pop());
   }
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/custom_elements_analysis.dart b/sdk/lib/_internal/compiler/implementation/js_backend/custom_elements_analysis.dart
index 807b896..60f1608 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/custom_elements_analysis.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/custom_elements_analysis.dart
@@ -73,16 +73,16 @@
     joinFor(enqueuer).instantiatedClasses.add(classElement);
   }
 
-  void registerTypeLiteral(Element element, Enqueuer enqueuer) {
+  void registerTypeLiteral(DartType type, Enqueuer enqueuer) {
     // In codegen we see the TypeConstants instead.
     if (!enqueuer.isResolutionQueue) return;
 
-    if (element.isClass) {
+    if (type.isInterfaceType) {
       // TODO(sra): If we had a flow query from the type literal expression to
       // the Type argument of the metadata lookup, we could tell if this type
       // literal is really a demand for the metadata.
-      resolutionJoin.selectedClasses.add(element);
-    } else {
+      resolutionJoin.selectedClasses.add(type.element);
+    } else if (type.isTypeVariable) {
       // This is a type parameter of a parameterized class.
       // TODO(sra): Is there a way to determine which types are bound to the
       // parameter?
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
index db55415..6c1efd0 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
@@ -725,7 +725,7 @@
 
   /// Returns the runtime name for [element].  The result is not safe as an id.
   String getRuntimeTypeName(Element element) {
-    if (identical(element, compiler.dynamicClass)) return 'dynamic';
+    if (element == null) return 'dynamic';
     return getNameForRti(element);
   }
 
@@ -910,7 +910,7 @@
   }
 
   String operatorIsType(DartType type) {
-    if (type.kind == TypeKind.FUNCTION) {
+    if (type.isFunctionType) {
       // TODO(erikcorry): Reduce from $isx to ix when we are minifying.
       return '${operatorIsPrefix()}_${getFunctionTypeName(type)}';
     }
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 57c4233..135e489 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
@@ -144,7 +144,7 @@
 
     Set<ClassElement> classesUsingTypeVariableTests = new Set<ClassElement>();
     compiler.resolverWorld.isChecks.forEach((DartType type) {
-      if (type.kind == TypeKind.TYPE_VARIABLE) {
+      if (type.isTypeVariable) {
         TypeVariableElement variable = type.element;
         classesUsingTypeVariableTests.add(variable.enclosingElement);
       }
@@ -163,7 +163,7 @@
     // Compute the set of all classes and methods that need runtime type
     // information.
     compiler.resolverWorld.isChecks.forEach((DartType type) {
-      if (type.kind == TypeKind.INTERFACE) {
+      if (type.isInterfaceType) {
         InterfaceType itf = type;
         if (!itf.treatAsRaw) {
           potentiallyAddForRti(itf.element);
@@ -176,7 +176,7 @@
           // variables and function types containing type variables.
           potentiallyAddForRti(contextClass);
         }
-        if (type.kind == TypeKind.FUNCTION) {
+        if (type.isFunctionType) {
           void analyzeMethod(TypedElement method) {
             DartType memberType = method.type;
             ClassElement contextClass = Types.getClassContext(memberType);
@@ -227,7 +227,6 @@
     // argument is a superclass of the element of an instantiated type.
     TypeCheckMapping result = new TypeCheckMapping();
     for (ClassElement element in instantiated) {
-      if (element == compiler.dynamicClass) continue;
       if (checked.contains(element)) {
         result.add(element, element, null);
       }
@@ -264,7 +263,7 @@
     Set<DartType> instantiatedTypes =
         new Set<DartType>.from(universe.instantiatedTypes);
     for (DartType instantiatedType in universe.instantiatedTypes) {
-      if (instantiatedType.kind == TypeKind.INTERFACE) {
+      if (instantiatedType.isInterfaceType) {
         InterfaceType interface = instantiatedType;
         FunctionType callType = interface.callType;
         if (callType != null) {
@@ -313,7 +312,7 @@
                               {bool isTypeArgument: false}) {
       for (DartType type in types) {
         directCollector.collect(type, isTypeArgument: isTypeArgument);
-        if (type.kind == TypeKind.INTERFACE) {
+        if (type.isInterfaceType) {
           ClassElement cls = type.element;
           for (DartType supertype in cls.allSupertypes) {
             superCollector.collect(supertype, isTypeArgument: isTypeArgument);
@@ -395,6 +394,7 @@
   String getTypeRepresentationForTypeConstant(DartType type) {
     JavaScriptBackend backend = compiler.backend;
     Namer namer = backend.namer;
+    if (type.isDynamic) return namer.getRuntimeTypeName(null);
     String name = namer.uniqueNameForTypeConstantElement(type.element);
     if (!type.element.isClass) return name;
     InterfaceType interface = type;
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
index 7430e33..a6386a3 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
@@ -810,7 +810,6 @@
     unneededClasses.add(backend.jsUInt32Class);
     unneededClasses.add(backend.jsUInt31Class);
     unneededClasses.add(backend.jsPositiveIntClass);
-    unneededClasses.add(compiler.dynamicClass);
 
     return (ClassElement cls) => !unneededClasses.contains(cls);
   }
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirrors.dart b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirrors.dart
index 1d21994..a81c258 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirrors.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirrors.dart
@@ -308,7 +308,7 @@
   Dart2JsMirrorSystem get mirrorSystem => this;
 
   TypeMirror get dynamicType =>
-      _convertTypeToTypeMirror(compiler.types.dynamicType);
+      _convertTypeToTypeMirror(const DynamicType());
 
   TypeMirror get voidType =>
       _convertTypeToTypeMirror(const VoidType());
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 d8073d0..4a3bfe7 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_type_mirrors.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_type_mirrors.dart
@@ -430,32 +430,42 @@
   bool isSubclassOf(ClassMirror other) => false;
 }
 
-class Dart2JsVoidMirror extends Dart2JsDeclarationMirror
+/// Common superclass for mirrors on `dynamic` and `void`.
+abstract class Dart2JsBuiltinTypeMirror extends Dart2JsDeclarationMirror
     with Dart2JsTypeMirror
     implements TypeSourceMirror {
   final Dart2JsMirrorSystem mirrorSystem;
-  final VoidType _type;
+  final DartType _type;
 
-  Dart2JsVoidMirror(Dart2JsMirrorSystem this.mirrorSystem, VoidType this._type);
+  Dart2JsBuiltinTypeMirror(Dart2JsMirrorSystem this.mirrorSystem,
+                           DartType this._type);
 
   Symbol get qualifiedName => simpleName;
 
   /**
-   * The void type has no location.
+   * The builtin types have has no location.
    */
   SourceLocation get location => null;
 
   /**
-   * The void type has no owner.
+   * The builtin types have has no owner.
    */
   Dart2JsDeclarationMirror get owner => null;
 
   /**
-   * The void type has no library.
+   * The builtin types have no library.
    */
   Dart2JsLibraryMirror get library => null;
 
+  /**
+   * The builtin types have no metadata.
+   */
   List<InstanceMirror> get metadata => const <InstanceMirror>[];
+}
+
+class Dart2JsVoidMirror extends Dart2JsBuiltinTypeMirror {
+  Dart2JsVoidMirror(Dart2JsMirrorSystem mirrorSystem, VoidType type)
+      : super(mirrorSystem, type);
 
   bool get isVoid => true;
 
@@ -474,23 +484,9 @@
   String toString() => 'Mirror on void';
 }
 
-class Dart2JsDynamicMirror extends Dart2JsTypeElementMirror {
-  Dart2JsDynamicMirror(Dart2JsMirrorSystem system, InterfaceType voidType)
-      : super(system, voidType);
-
-  InterfaceType get _dynamicType => _type;
-
-  Symbol get qualifiedName => simpleName;
-
-  /**
-   * The dynamic type has no location.
-   */
-  SourceLocation get location => null;
-
-  /**
-   * The dynamic type has no library.
-   */
-  LibraryMirror get library => null;
+class Dart2JsDynamicMirror extends Dart2JsBuiltinTypeMirror {
+  Dart2JsDynamicMirror(Dart2JsMirrorSystem mirrorSystem, DynamicType type)
+      : super(mirrorSystem, type);
 
   bool get isDynamic => true;
 
@@ -504,7 +500,7 @@
     return other.isDynamic;
   }
 
-  int get hashCode => 13 * _element.hashCode;
+  int get hashCode => 13 * _type.hashCode;
 
   String toString() => 'Mirror on dynamic';
 }
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors_used.dart b/sdk/lib/_internal/compiler/implementation/mirrors_used.dart
index 2a5cefb..5285027 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors_used.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors_used.dart
@@ -436,12 +436,12 @@
   DartType apiTypeOf(Constant constant) {
     DartType type = constant.computeType(compiler);
     LibraryElement library = type.element.library;
-    if (type.kind == TypeKind.INTERFACE && library.isInternalLibrary) {
+    if (type.isInterfaceType && library.isInternalLibrary) {
       InterfaceType interface = type;
       ClassElement cls = type.element;
       cls.ensureResolved(compiler);
       for (DartType supertype in cls.allSupertypes) {
-        if (supertype.kind == TypeKind.INTERFACE
+        if (supertype.isInterfaceType
             && !supertype.element.library.isInternalLibrary) {
           return interface.asInstanceOf(supertype.element);
         }
diff --git a/sdk/lib/_internal/compiler/implementation/native_handler.dart b/sdk/lib/_internal/compiler/implementation/native_handler.dart
index cf35086..f53d348 100644
--- a/sdk/lib/_internal/compiler/implementation/native_handler.dart
+++ b/sdk/lib/_internal/compiler/implementation/native_handler.dart
@@ -965,7 +965,7 @@
       lookup(name), locationNodeOrElement) {
     if (typeString == '=Object') return SpecialType.JsObject;
     if (typeString == 'dynamic') {
-      return  compiler.types.dynamicType;
+      return const DynamicType();
     }
     DartType type = lookup(typeString);
     if (type != null) return type;
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/class_members.dart b/sdk/lib/_internal/compiler/implementation/resolution/class_members.dart
index 6c34088..bb6efd9 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/class_members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/class_members.dart
@@ -206,7 +206,7 @@
           if (!functionType.parameterTypes.isEmpty) {
             type = functionType.parameterTypes.head;
           } else {
-            type = compiler.types.dynamicType;
+            type = const DynamicType();
           }
           name = name.setter;
           addDeclaredMember(name, type, functionType);
@@ -702,7 +702,7 @@
       if (member.isSetter) {
         requiredParameters = 1;
       }
-      if (member.type.kind == TypeKind.FUNCTION) {
+      if (member.type.isFunctionType) {
         FunctionType type = member.type;
         type.namedParameters.forEach(
             (String name) => names.add(name));
@@ -727,12 +727,12 @@
       Link<DartType> requiredParameterTypes = const Link<DartType>();
       while (--minRequiredParameters >= 0) {
         requiredParameterTypes =
-            requiredParameterTypes.prepend(compiler.types.dynamicType);
+            requiredParameterTypes.prepend(const DynamicType());
       }
       Link<DartType> optionalParameterTypes = const Link<DartType>();
       while (--optionalParameters >= 0) {
         optionalParameterTypes =
-            optionalParameterTypes.prepend(compiler.types.dynamicType);
+            optionalParameterTypes.prepend(const DynamicType());
       }
       Link<String> namedParameters = const Link<String>();
       Link<DartType> namedParameterTypes = const Link<DartType>();
@@ -741,17 +741,17 @@
       for (String name in namesReversed) {
         namedParameters = namedParameters.prepend(name);
         namedParameterTypes =
-            namedParameterTypes.prepend(compiler.types.dynamicType);
+            namedParameterTypes.prepend(const DynamicType());
       }
       FunctionType memberType = new FunctionType.synthesized(
-          compiler.types.dynamicType,
+          const DynamicType(),
           requiredParameterTypes,
           optionalParameterTypes,
           namedParameters, namedParameterTypes);
       DartType type = memberType;
       if (inheritedMembers.first.isGetter ||
           inheritedMembers.first.isSetter) {
-        type = compiler.types.dynamicType;
+        type = const DynamicType();
       }
       interfaceMembers[name] =
           new SyntheticMember(inheritedMembers, type, memberType);
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index af25fce..55ed565 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -37,10 +37,13 @@
    * Returns [:true:] if [node] is a type literal.
    *
    * Resolution marks this by setting the type on the node to be the
-   * [:Type:] type.
+   * type that the literal refers to.
    */
   bool isTypeLiteral(Send node);
 
+  /// Returns the type that the type literal [node] refers to.
+  DartType getTypeLiteralType(Send node);
+
   /// Register additional dependencies required by [currentElement].
   /// For example, elements that are used by a backend.
   void registerDependency(Element element);
@@ -183,6 +186,10 @@
     return getType(node) != null;
   }
 
+  DartType getTypeLiteralType(Send node) {
+    return getType(node);
+  }
+
   void registerDependency(Element element) {
     if (element == null) return;
     otherDependencies.add(element.implementation);
@@ -576,7 +583,7 @@
     if (tree.type != null) {
       element.variables.type = visitor.resolveTypeAnnotation(tree.type);
     } else {
-      element.variables.type = compiler.types.dynamicType;
+      element.variables.type = const DynamicType();
     }
     registry.useElement(tree, element);
 
@@ -626,11 +633,11 @@
   }
 
   DartType resolveReturnType(Element element, TypeAnnotation annotation) {
-    if (annotation == null) return compiler.types.dynamicType;
+    if (annotation == null) return const DynamicType();
     DartType result = visitorFor(element).resolveTypeAnnotation(annotation);
     if (result == null) {
       // TODO(karklose): warning.
-      return compiler.types.dynamicType;
+      return const DynamicType();
     }
     return result;
   }
@@ -1683,11 +1690,7 @@
       }
     } else {
       String stringValue = typeName.source;
-      if (identical(stringValue, 'dynamic')) {
-        element = compiler.dynamicClass;
-      } else {
-        element = lookupInScope(compiler, typeName, scope, typeName.source);
-      }
+      element = lookupInScope(compiler, typeName, scope, typeName.source);
     }
     return element;
   }
@@ -1726,6 +1729,11 @@
         checkNoTypeArguments(type);
         registry.useType(node, type);
         return type;
+      } else if (identical(typeName.source, 'dynamic')) {
+        type = const DynamicType();
+        checkNoTypeArguments(type);
+        registry.useType(node, type);
+        return type;
       }
     }
 
@@ -1772,9 +1780,7 @@
           MessageKind.NOT_A_TYPE, {'node': node.typeName});
     } else {
       bool addTypeVariableBoundsCheck = false;
-      if (identical(element, compiler.dynamicClass)) {
-        type = checkNoTypeArguments(element.computeType(compiler));
-      } else if (element.isClass) {
+      if (element.isClass) {
         ClassElement cls = element;
         // TODO(johnniwinther): [_ensureClassWillBeResolved] should imply
         // [computeType].
@@ -2121,7 +2127,11 @@
       String name = node.source;
       Element element = lookupInScope(compiler, node, scope, name);
       if (Elements.isUnresolved(element) && name == 'dynamic') {
-        element = compiler.dynamicClass;
+        // TODO(johnniwinther): Remove this hack when we can return more complex
+        // objects than [Element] from this method.
+        element = compiler.typeClass;
+        // Set the type to be `dynamic` to mark that this is a type literal.
+        registry.setType(node, const DynamicType());
       }
       element = reportLookupErrorIfAny(element, node, node.source);
       if (element == null) {
@@ -2593,13 +2603,22 @@
         registry.registerTypeVariableExpression();
         // Set the type of the node to [Type] to mark this send as a
         // type variable expression.
-        registry.setType(node, compiler.typeClass.computeType(compiler));
-        registry.registerTypeLiteral(target);
+        registry.registerTypeLiteral(node, target.computeType(compiler));
       } else if (target.impliesType && (!sendIsMemberAccess || node.isCall)) {
         // Set the type of the node to [Type] to mark this send as a
         // type literal.
-        registry.setType(node, compiler.typeClass.computeType(compiler));
-        registry.registerTypeLiteral(target);
+        DartType type;
+
+        // TODO(johnniwinther): Remove this hack when we can pass more complex
+        // information between methods than resolved elements.
+        if (target == compiler.typeClass && node.receiver == null) {
+          // Potentially a 'dynamic' type literal.
+          type = registry.getType(node.selector);
+        }
+        if (type == null) {
+          type = target.computeType(compiler);
+        }
+        registry.registerTypeLiteral(node, type);
 
         // Don't try to make constants of calls to type literals.
         if (!node.isCall) {
@@ -2985,7 +3004,7 @@
     if (node.type != null) {
       type = resolveTypeAnnotation(node.type);
     } else {
-      type = compiler.types.dynamicType;
+      type = const DynamicType();
     }
     VariableList variables = new VariableList.node(node, type);
     VariableDefinitionsVisitor visitor =
@@ -3781,7 +3800,7 @@
               const Link<TypeVariableElement>();
           seenTypeVariables = seenTypeVariables.prepend(variableElement);
           DartType bound = boundType;
-          while (bound.kind == TypeKind.TYPE_VARIABLE) {
+          while (bound.isTypeVariable) {
             TypeVariableElement element = bound.element;
             if (seenTypeVariables.contains(element)) {
               if (identical(element, variableElement)) {
@@ -4034,9 +4053,9 @@
     if (isBlackListed(mixinType)) {
       compiler.reportError(mixinNode,
           MessageKind.CANNOT_MIXIN, {'type': mixinType});
-    } else if (mixinType.kind == TypeKind.TYPE_VARIABLE) {
+    } else if (mixinType.isTypeVariable) {
       compiler.reportError(mixinNode, MessageKind.CLASS_NAME_EXPECTED);
-    } else if (mixinType.kind == TypeKind.MALFORMED_TYPE) {
+    } else if (mixinType.isMalformed) {
       compiler.reportError(mixinNode, MessageKind.CANNOT_MIXIN_MALFORMED);
     }
     return mixinType;
@@ -4151,7 +4170,7 @@
     // the interface of the class that was mixed in so always prepend
     // that to the interface list.
     if (mixinApplication.interfaces == null) {
-      if (mixinType.kind == TypeKind.INTERFACE) {
+      if (mixinType.isInterfaceType) {
         // Avoid malformed types in the interfaces.
         interfaces = interfaces.prepend(mixinType);
       }
@@ -4341,7 +4360,7 @@
       !identical(lib, compiler.coreLibrary) &&
       !identical(lib, compiler.jsHelperLibrary) &&
       !identical(lib, compiler.interceptorsLibrary) &&
-      (identical(type, compiler.types.dynamicType) ||
+      (type.isDynamic ||
        identical(type.element, compiler.boolClass) ||
        identical(type.element, compiler.numClass) ||
        identical(type.element, compiler.intClass) ||
@@ -4582,7 +4601,7 @@
     }
     if (type == null) {
       if (Elements.isUnresolved(element)) {
-        type = compiler.types.dynamicType;
+        type = const DynamicType();
       } else {
         type = element.enclosingClass.rawType;
       }
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/registry.dart b/sdk/lib/_internal/compiler/implementation/resolution/registry.dart
index 843684b..6c47af4 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/registry.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/registry.dart
@@ -247,8 +247,9 @@
     backend.registerTypeVariableExpression(this);
   }
 
-  void registerTypeLiteral(Element element) {
-    world.registerTypeLiteral(element, this);
+  void registerTypeLiteral(Send node, DartType type) {
+    mapping.setType(node, type);
+    world.registerTypeLiteral(type, this);
   }
 
   // TODO(johnniwinther): Remove the [ResolverVisitor] dependency. Its only
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/signatures.dart b/sdk/lib/_internal/compiler/implementation/resolution/signatures.dart
index 7467418..97326a3 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/signatures.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/signatures.dart
@@ -118,7 +118,7 @@
         if (fieldElement != null) {
           element.typeCache = fieldElement.computeType(compiler);
         } else {
-          element.typeCache = compiler.types.dynamicType;
+          element.typeCache = const DynamicType();
         }
       }
     }
@@ -343,10 +343,10 @@
   }
 
   DartType resolveReturnType(TypeAnnotation annotation) {
-    if (annotation == null) return compiler.types.dynamicType;
+    if (annotation == null) return const DynamicType();
     DartType result = resolver.resolveTypeAnnotation(annotation);
     if (result == null) {
-      return compiler.types.dynamicType;
+      return const DynamicType();
     }
     return result;
   }
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/listener.dart b/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
index 889590c..5ee68c2 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
@@ -2184,7 +2184,7 @@
       if (node.type != null) {
         type = compiler.resolver.resolveTypeAnnotation(element, node.type);
       } else {
-        type = compiler.types.dynamicType;
+        type = const DynamicType();
       }
     });
     assert(type != null);
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart b/sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart
index 5f3ddbe..88d7eba 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart
@@ -6,6 +6,7 @@
 
 import 'dart:collection' show IterableBase, HashSet;
 
+import '../dart_types.dart' show DynamicType;
 import '../elements/elements.dart';
 import '../elements/modelx.dart'
     show ElementX,
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 162d7a8..2b87a74 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -2200,18 +2200,18 @@
     if (type == null) return original;
     type = type.unalias(compiler);
     assert(assertTypeInContext(type, original));
-    if (type.kind == TypeKind.INTERFACE && !type.treatAsRaw) {
+    if (type.isInterfaceType && !type.treatAsRaw) {
       TypeMask subtype = new TypeMask.subtype(type.element);
       HInstruction representations = buildTypeArgumentRepresentations(type);
       add(representations);
       return new HTypeConversion.withTypeRepresentation(type, kind, subtype,
           original, representations);
-    } else if (type.kind == TypeKind.TYPE_VARIABLE) {
+    } else if (type.isTypeVariable) {
       TypeMask subtype = original.instructionType;
       HInstruction typeVariable = addTypeVariableReference(type);
       return new HTypeConversion.withTypeRepresentation(type, kind, subtype,
           original, typeVariable);
-    } else if (type.kind == TypeKind.FUNCTION) {
+    } else if (type.isFunctionType) {
       String name = kind == HTypeConversion.CAST_TYPE_CHECK
           ? '_asCheck' : '_assertCheck';
 
@@ -3142,7 +3142,7 @@
   HInstruction buildTypeArgumentRepresentations(DartType type) {
     // Compute the representation of the type arguments, including access
     // to the runtime type information for type variables as instructions.
-    if (type.kind == TypeKind.TYPE_VARIABLE) {
+    if (type.isTypeVariable) {
       return buildLiteralList(<HInstruction>[addTypeVariableReference(type)]);
     } else {
       assert(type.element.isClass);
@@ -3183,7 +3183,7 @@
       visit(node.receiver);
       HInstruction expression = pop();
       DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast);
-      if (type.kind == TypeKind.MALFORMED_TYPE) {
+      if (type.isMalformed) {
         ErroneousElement element = type.element;
         generateTypeError(node, element.message);
       } else {
@@ -3220,13 +3220,13 @@
                            DartType type,
                            HInstruction expression) {
     type = localsHandler.substInContext(type).unalias(compiler);
-    if (type.kind == TypeKind.FUNCTION) {
+    if (type.isFunctionType) {
       List arguments = [buildFunctionType(type), expression];
       pushInvokeDynamic(
           node, new Selector.call('_isTest', compiler.jsHelperLibrary, 1),
           arguments);
       return new HIs.compound(type, expression, pop(), backend.boolType);
-    } else if (type.kind == TypeKind.TYPE_VARIABLE) {
+    } else if (type.isTypeVariable) {
       HInstruction runtimeType = addTypeVariableReference(type);
       Element helper = backend.getCheckSubtypeOfRuntimeType();
       List<HInstruction> inputs = <HInstruction>[expression, runtimeType];
@@ -3251,7 +3251,7 @@
       pushInvokeStatic(node, helper, inputs, backend.boolType);
       HInstruction call = pop();
       return new HIs.compound(type, expression, call, backend.boolType);
-    } else if (type.kind == TypeKind.MALFORMED_TYPE) {
+    } else if (type.isMalformed) {
       ErroneousElement element = type.element;
       generateTypeError(node, element.message);
       HInstruction call = pop();
@@ -3929,7 +3929,7 @@
       return graph.addConstantNull(compiler);
     }
 
-    if (argument.kind == TypeKind.TYPE_VARIABLE) {
+    if (argument.isTypeVariable) {
       return addTypeVariableReference(argument);
     }
 
@@ -6325,7 +6325,7 @@
   }
 
   void visitMalformedType(MalformedType type, SsaBuilder builder) {
-    visitDynamicType(builder.compiler.types.dynamicType, builder);
+    visitDynamicType(const DynamicType(), builder);
   }
 
   void visitStatementType(StatementType type, SsaBuilder builder) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index baea02a..8a9fd0f 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -1719,7 +1719,7 @@
     native.NativeBehavior nativeBehavior = node.nativeBehavior;
     if (nativeBehavior == null) return;
     nativeBehavior.typesReturned.forEach((type) {
-      if (type is DartType) {
+      if (type is InterfaceType) {
         registry.registerInstantiatedType(type);
       }
     });
@@ -2410,7 +2410,7 @@
         handleListOrSupertypeCheck(
             input, interceptor, type, negative: negative);
         attachLocationToLast(node);
-      } else if (type.kind == TypeKind.FUNCTION) {
+      } else if (type.isFunctionType) {
         checkType(input, interceptor, type, negative: negative);
         attachLocationToLast(node);
       } else if ((input.canBePrimitive(compiler)
@@ -2552,7 +2552,7 @@
     assert(node.isCheckedModeCheck || node.isCastTypeCheck);
     DartType type = node.typeExpression;
     assert(type.kind != TypeKind.TYPEDEF);
-    if (type.kind == TypeKind.FUNCTION) {
+    if (type.isFunctionType) {
       // TODO(5022): We currently generate $isFunction checks for
       // function types.
       registry.registerIsCheck(compiler.functionClass.rawType);
@@ -2569,7 +2569,7 @@
     }
 
     if (helper == null) {
-      assert(type.kind == TypeKind.FUNCTION);
+      assert(type.isFunctionType);
       use(node.inputs[0]);
     } else {
       push(helper.generateCall(this, node));
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index a8107f4..5b1005e 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -1227,7 +1227,7 @@
     // instructions with generics. It has the generic type context
     // available.
     assert(type.kind != TypeKind.TYPE_VARIABLE);
-    assert(type.treatAsRaw || type.kind == TypeKind.FUNCTION);
+    assert(type.treatAsRaw || type.isFunctionType);
     if (type.isDynamic) return this;
     // The type element is either a class or the void element.
     Element element = type.element;
@@ -2496,12 +2496,12 @@
   }
 
   bool get hasTypeRepresentation {
-    return typeExpression.kind == TypeKind.INTERFACE && inputs.length > 1;
+    return typeExpression.isInterfaceType && inputs.length > 1;
   }
   HInstruction get typeRepresentation => inputs[1];
 
   bool get hasContext {
-    return typeExpression.kind == TypeKind.FUNCTION && inputs.length > 1;
+    return typeExpression.isFunctionType && inputs.length > 1;
   }
   HInstruction get context => inputs[1];
 
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index c006806..e92034c 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -577,7 +577,7 @@
 
     if (!node.isRawCheck) {
       return node;
-    } else if (element.isTypedef) {
+    } else if (type.isTypedef) {
       return node;
     } else if (element == compiler.functionClass) {
       return node;
@@ -646,15 +646,15 @@
     HInstruction value = node.inputs[0];
     DartType type = node.typeExpression;
     if (type != null) {
-      if (type.kind == TypeKind.MALFORMED_TYPE) {
+      if (type.isMalformed) {
         // Malformed types are treated as dynamic statically, but should
         // throw a type error at runtime.
         return node;
       }
-      if (!type.treatAsRaw || type.kind == TypeKind.TYPE_VARIABLE) {
+      if (!type.treatAsRaw || type.isTypeVariable) {
         return node;
       }
-      if (type.kind == TypeKind.FUNCTION) {
+      if (type.isFunctionType) {
         // TODO(johnniwinther): Optimize function type conversions.
         return node;
       }
@@ -770,7 +770,7 @@
     HInstruction value = node.inputs.last;
     if (compiler.enableTypeAssertions) {
       DartType type = field.type;
-      if (!type.treatAsRaw || type.kind == TypeKind.TYPE_VARIABLE) {
+      if (!type.treatAsRaw || type.isTypeVariable) {
         // We cannot generate the correct type representation here, so don't
         // inline this access.
         return node;
diff --git a/sdk/lib/_internal/compiler/implementation/typechecker.dart b/sdk/lib/_internal/compiler/implementation/typechecker.dart
index 22c0ad9..88f30dd 100644
--- a/sdk/lib/_internal/compiler/implementation/typechecker.dart
+++ b/sdk/lib/_internal/compiler/implementation/typechecker.dart
@@ -51,7 +51,7 @@
 
   /// Returns [: true :] if the element can be access as an invocation.
   bool isCallable(Compiler compiler) {
-    if (element.isAbstractField) {
+    if (element != null && element.isAbstractField) {
       AbstractFieldElement abstractFieldElement = element;
       if (abstractFieldElement.getter == null) {
         // Setters cannot be invoked as function invocations.
@@ -82,7 +82,7 @@
 
   Element get element => null;
 
-  DartType computeType(Compiler compiler) => compiler.types.dynamicType;
+  DartType computeType(Compiler compiler) => const DynamicType();
 
   bool isCallable(Compiler compiler) => true;
 
@@ -151,14 +151,17 @@
  * An access of a type literal.
  */
 class TypeLiteralAccess extends ElementAccess {
-  final Element element;
-  TypeLiteralAccess(Element this.element) {
-    assert(element != null);
+  final DartType type;
+
+  TypeLiteralAccess(this.type) {
+    assert(type != null);
   }
 
+  Element get element => type.element;
+
   DartType computeType(Compiler compiler) => compiler.typeClass.rawType;
 
-  String toString() => 'TypeLiteralAccess($element)';
+  String toString() => 'TypeLiteralAccess($type)';
 }
 
 
@@ -349,7 +352,7 @@
   }
 
   // TODO(karlklose): remove these functions.
-  DartType unhandledExpression() => types.dynamicType;
+  DartType unhandledExpression() => const DynamicType();
 
   DartType analyzeNonVoid(Node node) {
     DartType type = analyze(node);
@@ -557,10 +560,10 @@
     final FunctionElement element = elements[node];
     assert(invariant(node, element != null,
                      message: 'FunctionExpression with no element'));
-    if (Elements.isUnresolved(element)) return types.dynamicType;
+    if (Elements.isUnresolved(element)) return const DynamicType();
     if (identical(element.kind, ElementKind.GENERATIVE_CONSTRUCTOR) ||
         identical(element.kind, ElementKind.GENERATIVE_CONSTRUCTOR_BODY)) {
-      type = types.dynamicType;
+      type = const DynamicType();
       returnType = const VoidType();
 
       element.functionSignature.forEachParameter((ParameterElement parameter) {
@@ -659,8 +662,8 @@
           type = compiler.objectClass.rawType;
         }
       }
-      if (type.kind == TypeKind.MALFORMED_TYPE) {
-        return types.dynamicType;
+      if (type.isMalformed) {
+        return const DynamicType();
       }
       return type.unalias(compiler);
     }
@@ -669,10 +672,10 @@
     // interface type of the bound, for function types and typedefs it is the
     // `Function` type.
     InterfaceType computeInterfaceType(DartType type) {
-      if (type.kind == TypeKind.FUNCTION) {
+      if (type.isFunctionType) {
          type = compiler.functionClass.rawType;
       }
-      assert(invariant(node, type.kind == TypeKind.INTERFACE,
+      assert(invariant(node, type.isInterfaceType,
           message: "unexpected type kind ${type.kind}."));
       return type;
     }
@@ -690,15 +693,12 @@
     // 'call' method into account.
     ElementAccess getAccess(Name name,
                             DartType unaliasedBound, InterfaceType interface) {
-      if (interface.treatAsDynamic) {
-        return new DynamicAccess();
-      }
       MemberSignature member = lookupMemberSignature(memberName, interface);
       if (member != null) {
         return new MemberAccess(member);
       }
       if (name == const PublicName('call')) {
-        if (unaliasedBound.kind == TypeKind.FUNCTION) {
+        if (unaliasedBound.isFunctionType) {
           // This is an access the implicit 'call' method of a function type.
           return new FunctionCallAccess(receiverElement, unaliasedBound);
         }
@@ -706,13 +706,16 @@
           // This is an access of the special 'call' method implicitly defined
           // on 'Function'. This method can be called with any arguments, which
           // we ensure by giving it the type 'dynamic'.
-          return new FunctionCallAccess(null, types.dynamicType);
+          return new FunctionCallAccess(null, const DynamicType());
         }
       }
       return null;
     }
 
     DartType unaliasedBound = computeUnaliasedBound(receiverType);
+    if (unaliasedBound.treatAsDynamic) {
+      return new DynamicAccess();
+    }
     InterfaceType interface = computeInterfaceType(unaliasedBound);
     ElementAccess access = getAccess(memberName, unaliasedBound, interface);
     if (access != null) {
@@ -726,9 +729,11 @@
           TypePromotion typePromotion = typePromotions.head;
           if (!typePromotion.isValid) {
             DartType unaliasedBound = computeUnaliasedBound(typePromotion.type);
-            InterfaceType interface = computeInterfaceType(unaliasedBound);
-            if (getAccess(memberName, unaliasedBound, interface) != null) {
-              reportTypePromotionHint(typePromotion);
+            if (!unaliasedBound.treatAsDynamic) {
+              InterfaceType interface = computeInterfaceType(unaliasedBound);
+              if (getAccess(memberName, unaliasedBound, interface) != null) {
+                reportTypePromotionHint(typePromotion);
+              }
             }
           }
           typePromotions = typePromotions.tail;
@@ -902,7 +907,7 @@
     } else {
       reportTypeWarning(node, MessageKind.NOT_CALLABLE,
           {'elementName': elementAccess.element.name});
-      analyzeArguments(node, elementAccess.element, types.dynamicType,
+      analyzeArguments(node, elementAccess.element, const DynamicType(),
                        argumentTypes);
     }
     type = type.unalias(compiler);
@@ -910,7 +915,7 @@
       FunctionType funType = type;
       return funType.returnType;
     } else {
-      return types.dynamicType;
+      return const DynamicType();
     }
   }
 
@@ -964,11 +969,7 @@
     } else if (element.impliesType) {
       // The literal `Foo` where Foo is a class, a typedef, or a type variable.
       if (elements.isTypeLiteral(node)) {
-        assert(invariant(node, identical(compiler.typeClass,
-            elements.getType(node).element),
-            message: 'Expected type literal type: '
-              '${elements.getType(node)}'));
-        return new TypeLiteralAccess(element);
+        return new TypeLiteralAccess(elements.getTypeLiteralType(node));
       }
       return createResolvedAccess(node, name, element);
     } else if (element.isMember) {
@@ -1030,8 +1031,8 @@
   /// we suggest the use of `List<int>`, which would make promotion valid.
   DartType computeMoreSpecificType(DartType shownType,
                                    DartType knownType) {
-    if (knownType.kind == TypeKind.INTERFACE &&
-        shownType.kind == TypeKind.INTERFACE &&
+    if (knownType.isInterfaceType &&
+        shownType.isInterfaceType &&
         types.isSubtype(shownType.asRaw(), knownType)) {
       // For the comments in the block, assume the hierarchy:
       //     class A<T, V> {}
@@ -1075,7 +1076,7 @@
       }
       DartType constructorType = computeConstructorType(element, receiverType);
       analyzeArguments(node, element, constructorType);
-      return types.dynamicType;
+      return const DynamicType();
     }
 
     if (Elements.isClosureSend(node, element)) {
@@ -1235,7 +1236,7 @@
 
   /// Returns the first type in the list or [:dynamic:] if the list is empty.
   DartType firstType(Link<DartType> link) {
-    return link.isEmpty ? types.dynamicType : link.head;
+    return link.isEmpty ? const DynamicType() : link.head;
   }
 
   /**
@@ -1244,7 +1245,7 @@
    */
   DartType secondType(Link<DartType> link) {
     return link.isEmpty || link.tail.isEmpty
-        ? types.dynamicType : link.tail.head;
+        ? const DynamicType() : link.tail.head;
   }
 
   /**
@@ -1280,7 +1281,7 @@
       }
       return node.isPostfix ? getter : result;
     }
-    return types.dynamicType;
+    return const DynamicType();
   }
 
   /**
@@ -1342,7 +1343,7 @@
         return node.isPostfix ? element : result;
       }
     }
-    return types.dynamicType;
+    return const DynamicType();
   }
 
   visitSendSet(SendSet node) {
@@ -1455,7 +1456,7 @@
   }
 
   DartType visitLiteralNull(LiteralNull node) {
-    return types.dynamicType;
+    return const DynamicType();
   }
 
   DartType visitLiteralSymbol(LiteralSymbol node) {
@@ -1463,7 +1464,7 @@
   }
 
   DartType computeConstructorType(Element constructor, DartType type) {
-    if (Elements.isUnresolved(constructor)) return types.dynamicType;
+    if (Elements.isUnresolved(constructor)) return const DynamicType();
     DartType constructorType = constructor.computeType(compiler);
     if (identical(type.kind, TypeKind.INTERFACE)) {
       if (constructor.isSynthesized) {
@@ -1485,7 +1486,7 @@
 
   DartType visitNewExpression(NewExpression node) {
     Element element = elements[node.send];
-    if (Elements.isUnresolved(element)) return types.dynamicType;
+    if (Elements.isUnresolved(element)) return const DynamicType();
 
     checkPrivateAccess(node, element, element.name);
 
@@ -1579,7 +1580,7 @@
   DartType visitThrow(Throw node) {
     // TODO(johnniwinther): Handle reachability.
     analyze(node.expression);
-    return types.dynamicType;
+    return const DynamicType();
   }
 
   DartType visitTypeAnnotation(TypeAnnotation node) {
@@ -1587,10 +1588,10 @@
   }
 
   DartType visitVariableDefinitions(VariableDefinitions node) {
-    DartType type = analyzeWithDefault(node.type, types.dynamicType);
+    DartType type = analyzeWithDefault(node.type, const DynamicType());
     if (type.isVoid) {
       reportTypeWarning(node.type, MessageKind.VOID_VARIABLE);
-      type = types.dynamicType;
+      type = const DynamicType();
     }
     for (Link<Node> link = node.definitions.nodes; !link.isEmpty;
          link = link.tail) {
diff --git a/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
index 2bd0952..1a8d651 100644
--- a/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
@@ -200,8 +200,7 @@
    */
   bool containsAll(Compiler compiler) {
     if (isEmpty || isExact) return false;
-    return identical(base, compiler.objectClass)
-        || identical(base, compiler.dynamicClass);
+    return identical(base, compiler.objectClass);
   }
 
   TypeMask union(TypeMask other, Compiler compiler) {
diff --git a/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart
index e782f10..f18e96c 100644
--- a/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart
@@ -37,7 +37,6 @@
         continue;
       } else {
         FlatTypeMask flatMask = mask;
-        assert(flatMask.base == null || flatMask.base != compiler.dynamicClass);
         int inListIndex = -1;
         bool covered = false;
 
diff --git a/sdk/lib/_internal/compiler/implementation/use_unused_api.dart b/sdk/lib/_internal/compiler/implementation/use_unused_api.dart
index 259f93d..16faf1b 100644
--- a/sdk/lib/_internal/compiler/implementation/use_unused_api.dart
+++ b/sdk/lib/_internal/compiler/implementation/use_unused_api.dart
@@ -200,7 +200,7 @@
   compiler.importHelperLibrary(null);
   typeGraphInferrer.getCallersOf(null);
   dart_types.Types.sorted(null);
-  new dart_types.Types(compiler, null).copy(compiler);
+  new dart_types.Types(compiler).copy(compiler);
   new universe.TypedSelector.subclass(null, null);
   new universe.TypedSelector.subtype(null, null);
   new universe.TypedSelector.exact(null, null);
diff --git a/sdk/lib/_internal/lib/js_helper.dart b/sdk/lib/_internal/lib/js_helper.dart
index d4c7fa4..d820c22 100644
--- a/sdk/lib/_internal/lib/js_helper.dart
+++ b/sdk/lib/_internal/lib/js_helper.dart
@@ -2357,12 +2357,6 @@
 getFallThroughError() => new FallThroughErrorImplementation();
 
 /**
- * Represents the type dynamic. The compiler treats this specially.
- */
-abstract class Dynamic_ {
-}
-
-/**
  * A metadata annotation describing the types instantiated by a native element.
  *
  * The annotation is valid on a native method and a field of a native class.
diff --git a/sdk/lib/_internal/pub/lib/src/barback.dart b/sdk/lib/_internal/pub/lib/src/barback.dart
index af5e0c4..83b63de 100644
--- a/sdk/lib/_internal/pub/lib/src/barback.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback.dart
@@ -140,6 +140,9 @@
     if (configuration == null) {
       configuration = {};
     } else {
+      // Don't write to the immutable YAML map.
+      configuration = new Map.from(configuration);
+
       // Pull out the exclusions/inclusions.
       includes = parseField("\$include");
       excludes = parseField("\$exclude");
diff --git a/sdk/lib/_internal/pub/lib/src/barback/asset_environment.dart b/sdk/lib/_internal/pub/lib/src/barback/asset_environment.dart
index cea9ca2..04acfa4 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/asset_environment.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/asset_environment.dart
@@ -19,6 +19,7 @@
 import '../package_graph.dart';
 import '../sdk.dart' as sdk;
 import '../source/cached.dart';
+import '../utils.dart';
 import 'admin_server.dart';
 import 'barback_server.dart';
 import 'dart_forwarding_transformer.dart';
@@ -313,9 +314,8 @@
   /// Determines if [sourcePath] is contained within any of the directories in
   /// the root package that are visible to this build environment.
   bool containsPath(String sourcePath) {
-    var directories = ["asset", "lib"];
+    var directories = ["lib"];
     directories.addAll(_directories.keys);
-
     return directories.any((dir) => path.isWithin(dir, sourcePath));
   }
 
@@ -370,9 +370,12 @@
     // infrastructure to share code with pub proper. We provide it only during
     // the initial transformer loading process.
     var dartPath = assetPath('dart');
-    var pubSources = listDir(dartPath, recursive: true).map((library) {
-      return new AssetId('\$pub',
-          path.join('lib', path.relative(library, from: dartPath)));
+    var pubSources = listDir(dartPath, recursive: true)
+        // Don't include directories.
+        .where((file) => path.extension(file) == ".dart")
+        .map((library) {
+      var idPath = path.join('lib', path.relative(library, from: dartPath));
+      return new AssetId('\$pub', path.toUri(idPath).toString());
     });
 
     // "$sdk" is a pseudo-package that allows the dart2js transformer to find
@@ -381,67 +384,59 @@
     var libPath = path.join(sdk.rootDirectory, "lib");
     var sdkSources = listDir(libPath, recursive: true)
         .where((file) => path.extension(file) == ".dart")
-        .map((file) => new AssetId('\$sdk',
-            path.join("lib", path.relative(file, from: sdk.rootDirectory))));
+        .map((file) {
+      var idPath = path.join("lib",
+          path.relative(file, from: sdk.rootDirectory));
+      return new AssetId('\$sdk', path.toUri(idPath).toString());
+    });
 
     // Bind a server that we can use to load the transformers.
     var transformerServer;
     return BarbackServer.bind(this, _hostname, 0, null).then((server) {
       transformerServer = server;
 
-      return log.progress("Loading source assets", () {
-        barback.updateSources(pubSources);
-        barback.updateSources(sdkSources);
-        return _provideSources();
+      var errorStream = barback.errors.map((error) {
+        // Even most normally non-fatal barback errors should take down pub if
+        // they happen during the initial load process.
+        if (error is! AssetLoadException) throw error;
+
+        log.error(log.red(error.message));
+        log.fine(error.stackTrace.terse);
       });
+
+      return _withStreamErrors(() {
+        return log.progress("Loading source assets", () {
+          barback.updateSources(pubSources);
+          barback.updateSources(sdkSources);
+          return _provideSources();
+        });
+      }, [errorStream, barback.results]);
     }).then((_) {
       log.fine("Provided sources.");
       var completer = new Completer();
 
-      // If any errors get emitted either by barback or by the transformer
-      // server, including non-programmatic barback errors, they should take
-      // down the whole program.
-      var subscriptions = [
-        barback.errors.listen((error) {
-          if (error is TransformerException) {
-            var message = error.error.toString();
-            if (error.stackTrace != null) {
-              message += "\n" + error.stackTrace.terse.toString();
-            }
+      var errorStream = barback.errors.map((error) {
+        // Now that we're loading transformers, errors they log shouldn't be
+        // fatal, since we're starting to run them on real user assets which may
+        // have e.g. syntax errors. If an error would cause a transformer to
+        // fail to load, the load failure will cause us to exit.
+        if (error is! TransformerException) throw error;
 
-            _log(new LogEntry(error.transform, error.transform.primaryId,
+        var message = error.error.toString();
+        if (error.stackTrace != null) {
+          message += "\n" + error.stackTrace.terse.toString();
+        }
+
+        _log(new LogEntry(error.transform, error.transform.primaryId,
                 LogLevel.ERROR, message, null));
-          } else if (!completer.isCompleted) {
-            completer.completeError(error, new Chain.current());
-          }
-        }),
-        barback.results.listen((_) {},
-            onError: (error, stackTrace) {
-          if (completer.isCompleted) return;
-          completer.completeError(error, stackTrace);
-        }),
-        transformerServer.results.listen((_) {}, onError: (error, stackTrace) {
-          if (completer.isCompleted) return;
-          completer.completeError(error, stackTrace);
-        })
-      ];
-
-      loadAllTransformers(this, transformerServer).then((_) {
-        log.fine("Loaded transformers.");
-        return transformerServer.close();
-      }).then((_) {
-        if (!completer.isCompleted) completer.complete();
-      }).catchError((error, stackTrace) {
-        if (!completer.isCompleted) {
-          completer.completeError(error, stackTrace);
-        }
       });
 
-      return completer.future.whenComplete(() {
-        for (var subscription in subscriptions) {
-          subscription.cancel();
-        }
-      });
+      return _withStreamErrors(() {
+        return loadAllTransformers(this, transformerServer).then((_) {
+          log.fine("Loaded transformers.");
+          return transformerServer.close();
+        });
+      }, [errorStream, barback.results, transformerServer.results]);
     }).then((_) => barback.removeSources(pubSources));
   }
 
@@ -449,15 +444,11 @@
   ///
   /// If [watcherType] is not [WatcherType.NONE], enables watching on them.
   Future _provideSources() {
-    return Future.wait(graph.packages.values.map((package) {
-      // Just include the "shared" directories in each package. We'll add the
-      // other build directories in the root package by calling
-      // [serveDirectory].
-      return Future.wait([
-        _provideDirectorySources(package, "asset"),
-        _provideDirectorySources(package, "lib")
-      ]);
-    }));
+    // Just include the "lib" directory from each package. We'll add the
+    // other build directories in the root package by calling
+    // [serveDirectory].
+    return Future.wait(graph.packages.values.map(
+        (package) => _provideDirectorySources(package, "lib")));
   }
 
   /// Provides all of the source assets within [dir] in [package] to barback.
@@ -544,7 +535,7 @@
       if (relative.endsWith(".dart.js.map")) return [];
       if (relative.endsWith(".dart.precompiled.js")) return [];
 
-      return [new AssetId(package.name, relative)];
+      return [new AssetId(package.name, path.toUri(relative).toString())];
     }).toList();
   }
 
@@ -585,8 +576,8 @@
       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));
+      var idPath = path.relative(event.path, from: package.dir);
+      var id = new AssetId(package.name, path.toUri(idPath).toString());
       if (event.type == ChangeType.REMOVE) {
         if (_modifiedSources != null) {
           _modifiedSources.remove(id);
@@ -602,6 +593,31 @@
 
     return watcher.ready.then((_) => subscription);
   }
+
+  /// Returns the result of [futureCallback] unless any stream in [streams]
+  /// emits an error before it's done.
+  ///
+  /// If a stream does emit an error, that error is thrown instead.
+  /// [futureCallback] is a callback rather than a plain future to ensure that
+  /// [streams] are listened to before any code that might cause an error starts
+  /// running.
+  Future _withStreamErrors(Future futureCallback(), List<Stream> streams) {
+    var completer = new Completer.sync();
+    var subscriptions = streams.map((stream) =>
+        stream.listen((_) {}, onError: completer.complete)).toList();
+
+    syncFuture(futureCallback).then((_) {
+      if (!completer.isCompleted) completer.complete();
+    }).catchError((error, stackTrace) {
+      if (!completer.isCompleted) completer.completeError(error, stackTrace);
+    });
+
+    return completer.future.whenComplete(() {
+      for (var subscription in subscriptions) {
+        subscription.cancel();
+      }
+    });
+  }
 }
 
 /// Log [entry] using Pub's logging infrastructure.
diff --git a/sdk/lib/_internal/pub/lib/src/barback/base_server.dart b/sdk/lib/_internal/pub/lib/src/barback/base_server.dart
index 8155921..95dc355 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/base_server.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/base_server.dart
@@ -45,6 +45,7 @@
   BaseServer(this.environment, this._server) {
     shelf_io.serveRequests(Chain.track(_server), const shelf.Pipeline()
         .addMiddleware(shelf.createMiddleware(errorHandler: _handleError))
+        .addMiddleware(shelf.createMiddleware(responseHandler: _disableGzip))
         .addHandler(handleRequest));
   }
 
@@ -121,4 +122,20 @@
     close();
     return new shelf.Response.internalServerError();
   }
+
+  /// Disable GZIP responses.
+  ///
+  /// This is primarily to optimize pub's startup. Since the transformer
+  /// plug-ins are loaded over HTTP, we pay the hit to GZIP encode and decode
+  /// them. Disabling this improves startup time by about 5% on my test.
+  ///
+  // TODO(rnystrom): Remove this when #5187 is fixed and we don't have to use
+  // HTTP for isolates.
+  _disableGzip(shelf.Response response) {
+    if (!response.headers.containsKey('Content-Encoding')) {
+      return response.change(headers: {'Content-Encoding': ''});
+    }
+
+    return response;
+  }
 }
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 b3b1797..6f21c8d 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
@@ -62,9 +62,9 @@
   bool isPrimary(AssetId id) {
     if (id.extension != ".dart") return false;
 
-    // These should only contain libraries. For efficiency's sake, we don't
+    // "lib" should only contain libraries. For efficiency's sake, we don't
     // look for entrypoints in there.
-    return !["asset/", "lib/"].any(id.path.startsWith);
+    return !id.path.startsWith("lib/");
   }
 
   Future apply(Transform transform) {
@@ -292,7 +292,8 @@
     if (name == "") {
       outPath = _transform.primaryInput.id.path;
     } else {
-      outPath = path.join(path.dirname(_transform.primaryInput.id.path), name);
+      var dirname = path.url.dirname(_transform.primaryInput.id.path);
+      outPath = path.url.join(dirname, name);
     }
 
     var id = new AssetId(primaryId.package, "$outPath.$extension");
@@ -393,8 +394,8 @@
     // should be loaded directly from disk.
     var sourcePath = path.fromUri(url);
     if (_environment.containsPath(sourcePath)) {
-      var relative = path.relative(sourcePath,
-          from: _environment.rootPackage.dir);
+      var relative = path.toUri(path.relative(sourcePath,
+          from: _environment.rootPackage.dir)).toString();
 
       return new AssetId(_environment.rootPackage.name, relative);
     }
diff --git a/sdk/lib/_internal/pub/lib/src/barback/pub_package_provider.dart b/sdk/lib/_internal/pub/lib/src/barback/pub_package_provider.dart
index 1665be9..21e6fed 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/pub_package_provider.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/pub_package_provider.dart
@@ -11,6 +11,7 @@
 
 import '../io.dart';
 import '../package_graph.dart';
+import '../preprocess.dart';
 import '../sdk.dart' as sdk;
 
 /// An implementation of barback's [PackageProvider] interface so that barback
@@ -32,7 +33,18 @@
       assert(components.first == 'lib');
       components[0] = 'dart';
       var file = assetPath(path.joinAll(components));
-      return new Future.value(new Asset.fromPath(id, file));
+
+      // Barback may not be in the package graph if there are no user-defined
+      // transformers being used at all. The "$pub" sources are still provided,
+      // but will never be loaded.
+      var barback = _graph.packages['barback'];
+      if (barback == null) {
+        return new Future.value(new Asset.fromPath(id, file));
+      }
+
+      var contents = readTextFile(file);
+      contents = preprocess(contents, barback.version, path.toUri(file));
+      return new Future.value(new Asset.fromString(id, contents));
     }
 
     // "$sdk" is a pseudo-package that provides access to the Dart library
diff --git a/sdk/lib/_internal/pub/lib/src/barback/rewrite_import_transformer.dart b/sdk/lib/_internal/pub/lib/src/barback/rewrite_import_transformer.dart
index 6f454b6..8392289 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/rewrite_import_transformer.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/rewrite_import_transformer.dart
@@ -17,7 +17,7 @@
   Future apply(Transform transform) {
     return transform.primaryInput.readAsString().then((contents) {
       var collector = new _DirectiveCollector();
-      parseCompilationUnit(contents, name: transform.primaryInput.id.toString())
+      parseDirectives(contents, name: transform.primaryInput.id.toString())
           .accept(collector);
 
       var buffer = new StringBuffer();
diff --git a/sdk/lib/_internal/pub/lib/src/barback/web_socket_api.dart b/sdk/lib/_internal/pub/lib/src/barback/web_socket_api.dart
index 7952dcf..7722b94 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/web_socket_api.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/web_socket_api.dart
@@ -11,6 +11,9 @@
 import 'package:path/path.dart' as path;
 import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
 
+import '../exit_codes.dart' as exit_codes;
+import '../io.dart';
+import '../log.dart' as log;
 import '../utils.dart';
 import 'asset_environment.dart';
 
@@ -24,11 +27,22 @@
   final AssetEnvironment _environment;
   final _server = new json_rpc.Server();
 
+  /// Whether the application should exit when this connection closes.
+  bool _exitOnClose = false;
+
   WebSocketApi(this._socket, this._environment) {
     _server.registerMethod("urlToAssetId", _urlToAssetId);
     _server.registerMethod("pathToUrls", _pathToUrls);
     _server.registerMethod("serveDirectory", _serveDirectory);
     _server.registerMethod("unserveDirectory", _unserveDirectory);
+
+    /// Tells the server to exit as soon as this WebSocket connection is closed.
+    ///
+    /// This takes no arguments and returns no results. It can safely be called
+    /// as a JSON-RPC notification.
+    _server.registerMethod("exitOnClose", () {
+      _exitOnClose = true;
+    });
   }
 
   /// Listens on the socket.
@@ -41,7 +55,11 @@
       _server.parseRequest(request).then((response) {
         if (response != null) _socket.add(response);
       });
-    }, cancelOnError: true).asFuture();
+    }, cancelOnError: true).asFuture().then((_) {
+      if (!_exitOnClose) return;
+      log.message("WebSocket connection closed, terminating.");
+      flushThenExit(exit_codes.SUCCESS);
+    });
   }
 
   /// Given a URL to an asset that is served by pub, returns the ID of the
@@ -136,15 +154,14 @@
   ///
   /// The "path" key may refer to a path in another package, either by referring
   /// to its location within the top-level "packages" directory or by referring
-  /// to its location on disk. Only the "lib" and "asset" directories are
-  /// visible in other packages:
+  /// to its location on disk. Only the "lib" directory is visible in other
+  /// packages:
   ///
   ///     "params": {
   ///       "path": "packages/http/http.dart"
   ///     }
   ///
-  /// Assets in the "lib" and "asset" directories will usually have one URL for
-  /// each server:
+  /// Assets in the "lib" directory will usually have one URL for each server:
   ///
   ///     "result": {
   ///       "urls": [
diff --git a/sdk/lib/_internal/pub/lib/src/command/barback.dart b/sdk/lib/_internal/pub/lib/src/command/barback.dart
index 72a50ba..b7df78b 100644
--- a/sdk/lib/_internal/pub/lib/src/command/barback.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/barback.dart
@@ -88,10 +88,10 @@
 
     sourceDirectories.addAll(commandOptions.rest);
 
-    // Prohibit "lib" and "asset".
+    // Prohibit "lib".
     var disallowed = sourceDirectories.where((dir) {
       var parts = path.split(path.normalize(dir));
-      return parts.isNotEmpty && ["lib", "asset"].contains(parts.first);
+      return parts.isNotEmpty && parts.first == "lib";
     });
 
     if (disallowed.isNotEmpty) {
diff --git a/sdk/lib/_internal/pub/lib/src/command/build.dart b/sdk/lib/_internal/pub/lib/src/command/build.dart
index ed16ac9..353921d 100644
--- a/sdk/lib/_internal/pub/lib/src/command/build.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/build.dart
@@ -133,7 +133,7 @@
       return new Future.value();
     }
 
-    var destPath = _idtoPath(asset.id);
+    var destPath = _idToPath(asset.id);
 
     // If the asset is from a public directory, copy it into all of the
     // top-level build directories.
@@ -159,8 +159,8 @@
   ///     foo|test/main.dart     -> ERROR
   ///
   /// Throws a [FormatException] if [id] is not a valid public asset.
-  String _idtoPath(AssetId id) {
-    var parts = path.url.split(id.path);
+  String _idToPath(AssetId id) {
+    var parts = path.split(path.fromUri(id.path));
 
     if (parts.length < 2) {
       throw new FormatException(
@@ -207,7 +207,7 @@
         .map((id) => path.dirname(path.fromUri(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))
+        .where((dir) => path.split(dir).length > 1)
         .toSet();
 
     for (var dir in entrypointDirs) {
diff --git a/sdk/lib/_internal/pub/lib/src/git.dart b/sdk/lib/_internal/pub/lib/src/git.dart
index 510ca7e..d79a914 100644
--- a/sdk/lib/_internal/pub/lib/src/git.dart
+++ b/sdk/lib/_internal/pub/lib/src/git.dart
@@ -10,6 +10,7 @@
 
 import 'io.dart';
 import 'log.dart' as log;
+import 'utils.dart';
 
 /// An exception thrown because a git command failed.
 class GitException implements Exception {
@@ -41,6 +42,12 @@
 Future<List<String>> run(List<String> args,
     {String workingDir, Map<String, String> environment}) {
   return _gitCommand.then((git) {
+    if (git == null) {
+      throw new ApplicationException(
+          "Cannot find a Git executable.\n"
+          "Please ensure Git is correctly installed.");
+    }
+
     return runProcess(git, args, workingDir: workingDir,
         environment: environment);
   }).then((result) {
diff --git a/sdk/lib/_internal/pub/lib/src/io.dart b/sdk/lib/_internal/pub/lib/src/io.dart
index 09cbea8..d023350 100644
--- a/sdk/lib/_internal/pub/lib/src/io.dart
+++ b/sdk/lib/_internal/pub/lib/src/io.dart
@@ -380,7 +380,7 @@
 /// source repository.
 bool get runningFromSdk => Platform.script.path.endsWith('.snapshot');
 
-/// Resolves [target] relative to the path to pub's `resource` directory.
+/// Resolves [target] relative to the path to pub's `asset` directory.
 String assetPath(String target) {
   if (runningFromSdk) {
     return path.join(
diff --git a/sdk/lib/_internal/pub/lib/src/preprocess.dart b/sdk/lib/_internal/pub/lib/src/preprocess.dart
new file mode 100644
index 0000000..827d256
--- /dev/null
+++ b/sdk/lib/_internal/pub/lib/src/preprocess.dart
@@ -0,0 +1,142 @@
+// 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.preprocess;
+
+import 'package:string_scanner/string_scanner.dart';
+
+import 'version.dart';
+
+/// Runs a simple preprocessor over [input] to remove sections that are
+/// incompatible with the available barback version.
+///
+/// [barbackVersion] is the version of barback that's available, and [sourceUrl]
+/// is a [String] or [Uri] indicating where [input] came from. It's used for
+/// error reporting.
+///
+/// For the most part, the preprocessor leaves text in the source document
+/// alone. However, it handles two types of lines specially. Lines that begin
+/// with `//>` are uncommented by the preprocessor, and lines that begin with
+/// `//#` are operators.
+///
+/// The preprocessor currently supports one top-level operator, "if":
+///
+///     //# if barback >=0.14.1
+///       ...
+///     //# else
+///       ...
+///     //# end
+///
+/// If the current barback version matches the constraint, everything within the
+/// first block is included in the output and everything within the second block
+/// is removed; otherwise, the first block is removed and the second block is
+/// included. The `else` block is optional.
+///
+/// It's important that the preprocessor syntax also be valid Dart code, because
+/// pub loads the source files before preprocessing and runs them against the
+/// version of barback that was compiled into pub. This is why the `//>` syntax
+/// exists: so that code can be hidden from the running pub process but still be
+/// visible to the barback isolate. For example:
+///
+///     //# if barback >= 0.14.1
+///       ClassMirror get aggregateClass => reflectClass(AggregateTransformer);
+///     //# else
+///     //>   ClassMirror get aggregateClass => null;
+///     //# end
+String preprocess(String input, Version barbackVersion, sourceUrl) {
+  // Short-circuit if there are no preprocessor directives in the file.
+  if (!input.contains(new RegExp(r"^//[>#]", multiLine: true))) return input;
+  return new _Preprocessor(input, barbackVersion, sourceUrl).run();
+}
+
+/// The preprocessor class.
+class _Preprocessor {
+  /// The scanner over the input string.
+  final StringScanner _scanner;
+
+  /// The version of barback to match against.
+  final Version _barbackVersion;
+
+  /// The buffer to which the output is written.
+  final _buffer = new StringBuffer();
+
+  _Preprocessor(String input, this._barbackVersion, sourceUrl)
+      : _scanner = new StringScanner(input, sourceUrl: sourceUrl);
+
+  /// Run the preprocessor and return the processed output.
+  String run() {
+    while (!_scanner.isDone) {
+      if (_scanner.scan(new RegExp(r"//#\s*"))) {
+        _if();
+      } else {
+        _emitText();
+      }
+    }
+
+    _scanner.expectDone();
+    return _buffer.toString();
+  }
+
+  /// Emit lines of the input document directly until an operator is
+  /// encountered.
+  void _emitText() {
+    while (!_scanner.isDone && !_scanner.matches("//#")) {
+      if (_scanner.scan("//>")) {
+        if (!_scanner.matches("\n")) _scanner.expect(" ");
+      }
+
+      _scanner.scan(new RegExp(r"[^\n]*\n?"));
+      _buffer.write(_scanner.lastMatch[0]);
+    }
+  }
+
+  /// Move through lines of the input document without emitting them until an
+  /// operator is encountered.
+  void _ignoreText() {
+    while (!_scanner.isDone && !_scanner.matches("//#")) {
+      _scanner.scan(new RegExp(r"[^\n]*\n?"));
+    }
+  }
+
+  /// Handle an `if` operator.
+  void _if() {
+    _scanner.expect(new RegExp(r"if\s+"), name: "if statement");
+    _scanner.expect(new RegExp(r"[a-zA-Z0-9_]+"), name: "package name");
+    var package = _scanner.lastMatch[0];
+    if (package != 'barback') _scanner.error('Unknown package "$package".');
+
+    _scanner.scan(new RegExp(r"\s*"));
+    _scanner.expect(new RegExp(r"[^\n]+"), name: "version constraint");
+    var constraint;
+    try {
+      constraint = new VersionConstraint.parse(_scanner.lastMatch[0]);
+    } on FormatException catch (error) {
+      _scanner.error("Invalid version constraint: ${error.message}");
+    }
+    _scanner.expect("\n");
+
+    var allowed = constraint.allows(_barbackVersion);
+    if (allowed) {
+      _emitText();
+    } else {
+      _ignoreText();
+    }
+
+    _scanner.expect("//#");
+    _scanner.scan(new RegExp(r"\s*"));
+    if (_scanner.scan("else")) {
+      _scanner.expect("\n");
+      if (allowed) {
+        _ignoreText();
+      } else {
+        _emitText();
+      }
+      _scanner.expect("//#");
+      _scanner.scan(new RegExp(r"\s*"));
+    }
+
+    _scanner.expect("end");
+    if (!_scanner.isDone) _scanner.expect("\n");
+  }
+}
diff --git a/sdk/lib/_internal/pub/lib/src/pubspec.dart b/sdk/lib/_internal/pub/lib/src/pubspec.dart
index 9a4d3e3..8c29253 100644
--- a/sdk/lib/_internal/pub/lib/src/pubspec.dart
+++ b/sdk/lib/_internal/pub/lib/src/pubspec.dart
@@ -357,6 +357,9 @@
         sourceName = _sources.defaultSource.name;
         versionConstraint = _parseVersionConstraint(spec, "$field.$name");
       } else if (spec is Map) {
+        // Don't write to the immutable YAML map.
+        spec = new Map.from(spec);
+
         if (spec.containsKey('version')) {
           versionConstraint = _parseVersionConstraint(spec.remove('version'),
               "$field.$name.version");
diff --git a/sdk/lib/_internal/pub/lib/src/source/git.dart b/sdk/lib/_internal/pub/lib/src/source/git.dart
index c7329b2..b0488c4 100644
--- a/sdk/lib/_internal/pub/lib/src/source/git.dart
+++ b/sdk/lib/_internal/pub/lib/src/source/git.dart
@@ -53,7 +53,7 @@
 
     return git.isInstalled.then((installed) {
       if (!installed) {
-        throw new Exception(
+        throw new ApplicationException(
             "Cannot get ${id.name} from Git (${_getUrl(id)}).\n"
             "Please ensure Git is correctly installed.");
       }
diff --git a/sdk/lib/_internal/pub/test/barback/fails_on_disallowed_directories_test.dart b/sdk/lib/_internal/pub/test/barback/fails_on_disallowed_directories_test.dart
index 11cf657..a57d8e7 100644
--- a/sdk/lib/_internal/pub/test/barback/fails_on_disallowed_directories_test.dart
+++ b/sdk/lib/_internal/pub/test/barback/fails_on_disallowed_directories_test.dart
@@ -19,7 +19,7 @@
 
   var libSub = path.join("lib", "sub");
   pubBuildAndServeShouldFail("if given directories are not allowed",
-      args: [libSub, "asset"],
-      error: 'Directories "$libSub" and "asset" are not allowed.',
+      args: [libSub, "lib"],
+      error: 'Directories "$libSub" and "lib" are not allowed.',
       exitCode: exit_codes.USAGE);
 }
diff --git a/sdk/lib/_internal/pub/test/dart2js/ignores_entrypoints_in_lib_and_asset_test.dart b/sdk/lib/_internal/pub/test/dart2js/ignores_entrypoints_in_lib_test.dart
similarity index 74%
rename from sdk/lib/_internal/pub/test/dart2js/ignores_entrypoints_in_lib_and_asset_test.dart
rename to sdk/lib/_internal/pub/test/dart2js/ignores_entrypoints_in_lib_test.dart
index e09dd7f..73dda87 100644
--- a/sdk/lib/_internal/pub/test/dart2js/ignores_entrypoints_in_lib_and_asset_test.dart
+++ b/sdk/lib/_internal/pub/test/dart2js/ignores_entrypoints_in_lib_test.dart
@@ -13,9 +13,6 @@
   setUp(() {
     d.dir(appPath, [
       d.appPubspec(),
-      d.dir('asset', [
-        d.file('file.dart', 'void main() => print("hello");'),
-      ]),
       d.dir('lib', [
         d.file('file.dart', 'void main() => print("hello");'),
       ]),
@@ -25,21 +22,19 @@
     ]).create();
   });
 
-  integration("build ignores Dart entrypoints in lib and asset", () {
+  integration("build ignores Dart entrypoints in lib", () {
     schedulePub(args: ["build", "--all"],
         output: new RegExp(r'Built 1 file to "build".'));
 
     d.dir(appPath, [
       d.dir('build', [
-        d.nothing('asset'),
         d.nothing('lib')
       ])
     ]).validate();
   });
 
-  integration("serve ignores Dart entrypoints in lib and asset", () {
+  integration("serve ignores Dart entrypoints in lib", () {
     pubServe();
-    requestShould404("assets/myapp/main.dart.js");
     requestShould404("packages/myapp/main.dart.js");
     endPubServe();
   });
diff --git a/sdk/lib/_internal/pub/test/preprocess_test.dart b/sdk/lib/_internal/pub/test/preprocess_test.dart
new file mode 100644
index 0000000..d908f1f
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/preprocess_test.dart
@@ -0,0 +1,255 @@
+// 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.test.preprocess_test;
+
+import 'package:unittest/unittest.dart';
+
+import '../lib/src/preprocess.dart';
+import '../lib/src/version.dart';
+import 'test_pub.dart';
+
+main() {
+  initConfig();
+
+  test("does nothing on a file without preprocessor directives", () {
+    var text = '''
+some text
+// normal comment
+// #
+ //# not beginning of line
+''';
+
+    expect(_preprocess(text), equals(text));
+  });
+
+  test("allows bare insert directive", () {
+    expect(_preprocess('//> foo'), equals('foo'));
+  });
+
+  test("allows empty insert directive", () {
+    expect(_preprocess('''
+//> foo
+//>
+//> bar
+'''), equals('foo\n\nbar\n'));
+  });
+
+  group("if", () {
+    test("removes sections with non-matching versions", () {
+      expect(_preprocess('''
+before
+//# if barback <1.0.0
+inside
+//# end
+after
+'''), equals('''
+before
+after
+'''));
+    });
+
+    test("doesn't insert section with non-matching versions", () {
+      expect(_preprocess('''
+before
+//# if barback <1.0.0
+//> inside
+//# end
+after
+'''), equals('''
+before
+after
+'''));
+    });
+
+    test("doesn't remove sections with matching versions", () {
+      expect(_preprocess('''
+before
+//# if barback >1.0.0
+inside
+//# end
+after
+'''), equals('''
+before
+inside
+after
+'''));
+    });
+
+    test("inserts sections with matching versions", () {
+      expect(_preprocess('''
+before
+//# if barback >1.0.0
+//> inside
+//# end
+after
+'''), equals('''
+before
+inside
+after
+'''));
+    });
+
+    test("allows version ranges", () {
+      expect(_preprocess('''
+before
+//# if barback >=1.0.0 <2.0.0
+inside 1
+//# end
+//# if barback >=0.9.0 <1.0.0
+inside 2
+//# end
+after
+'''), equals('''
+before
+inside 1
+after
+'''));
+    });
+  });
+
+  group("else", () {
+    test("removes non-matching sections", () {
+      expect(_preprocess('''
+before
+//# if barback >1.0.0
+inside 1
+//# else
+inside 2
+//# end
+after
+'''), equals('''
+before
+inside 1
+after
+'''));
+    });
+
+    test("doesn't insert non-matching sections", () {
+      expect(_preprocess('''
+before
+//# if barback >1.0.0
+inside 1
+//# else
+//> inside 2
+//# end
+after
+'''), equals('''
+before
+inside 1
+after
+'''));
+    });
+
+    test("doesn't remove matching sections", () {
+      expect(_preprocess('''
+before
+//# if barback <1.0.0
+inside 1
+//# else
+inside 2
+//# end
+after
+'''), equals('''
+before
+inside 2
+after
+'''));
+    });
+
+    test("inserts matching sections", () {
+      expect(_preprocess('''
+before
+//# if barback <1.0.0
+inside 1
+//# else
+//> inside 2
+//# end
+after
+'''), equals('''
+before
+inside 2
+after
+'''));
+    });
+  });
+
+  group("errors", () {
+    test("disallows unknown statements", () {
+      expect(() => _preprocess('//# foo bar\n//# end'), throwsFormatException);
+    });
+
+    test("disallows insert directive without space", () {
+      expect(() => _preprocess('//>foo'), throwsFormatException);
+    });
+
+    group("if", () {
+      test("disallows if with no arguments", () {
+        expect(() => _preprocess('//# if\n//# end'), throwsFormatException);
+      });
+
+      test("disallows if with no version range", () {
+        expect(() => _preprocess('//# if barback\n//# end'),
+            throwsFormatException);
+      });
+
+      test("disallows if with no package", () {
+        expect(() => _preprocess('//# if <=1.0.0\n//# end'),
+            throwsFormatException);
+      });
+
+      test("disallows unknown package name", () {
+        expect(() => _preprocess('//# if polymer <=1.0.0\n//# end'),
+            throwsFormatException);
+      });
+
+      test("disallows invalid version constraint", () {
+        expect(() => _preprocess('//# if barback >=1.0\n//# end'),
+            throwsFormatException);
+      });
+
+      test("disallows dangling end", () {
+        expect(() => _preprocess('//# end'),
+            throwsFormatException);
+      });
+
+      test("disallows if without end", () {
+        expect(() => _preprocess('//# if barback >=1.0.0'),
+            throwsFormatException);
+      });
+
+      test("disallows nested if", () {
+        expect(() => _preprocess('''
+//# if barback >=1.0.0
+//# if barback >= 1.5.0
+//# end
+//# end
+'''),
+            throwsFormatException);
+      });
+    });
+
+    group("else", () {
+      test("disallows else without if", () {
+        expect(() => _preprocess('//# else\n//# end'), throwsFormatException);
+      });
+
+      test("disallows else without end", () {
+        expect(() => _preprocess('//# if barback >=1.0.0\n//# else'),
+            throwsFormatException);
+      });
+
+      test("disallows else with an argument", () {
+        expect(() => _preprocess('''
+//# if barback >=1.0.0
+//# else barback <0.5.0
+//# end
+'''), throwsFormatException);
+      });
+    });
+  });
+}
+
+String _preprocess(String input) =>
+    preprocess(input, new Version.parse("1.2.3"), 'source/url');
diff --git a/sdk/lib/_internal/pub/test/serve/does_not_crash_if_an_unused_dart_file_has_a_syntax_error_test.dart b/sdk/lib/_internal/pub/test/serve/does_not_crash_if_an_unused_dart_file_has_a_syntax_error_test.dart
index 01ac8f0..09d41bd 100644
--- a/sdk/lib/_internal/pub/test/serve/does_not_crash_if_an_unused_dart_file_has_a_syntax_error_test.dart
+++ b/sdk/lib/_internal/pub/test/serve/does_not_crash_if_an_unused_dart_file_has_a_syntax_error_test.dart
@@ -4,8 +4,6 @@
 
 library pub_tests;
 
-import 'package:scheduled_test/scheduled_test.dart';
-
 import '../descriptor.dart' as d;
 import '../test_pub.dart';
 import 'utils.dart';
@@ -31,8 +29,6 @@
       createLockFile('myapp', pkg: ['barback']);
 
       var server = pubServe();
-      server.stderr.expect("[RewriteImport]:");
-      server.stderr.expect(startsWith("Error in myapp|lib/src/unused.dart:"));
       requestShouldSucceed("foo.out", "foo.out");
       endPubServe();
     });
diff --git a/sdk/lib/_internal/pub/test/serve/missing_asset_test.dart b/sdk/lib/_internal/pub/test/serve/missing_asset_test.dart
index c173982..3f39054 100644
--- a/sdk/lib/_internal/pub/test/serve/missing_asset_test.dart
+++ b/sdk/lib/_internal/pub/test/serve/missing_asset_test.dart
@@ -18,9 +18,7 @@
     pubServe();
     requestShould404("index.html");
     requestShould404("packages/myapp/nope.dart");
-    requestShould404("assets/myapp/nope.png");
     requestShould404("dir/packages/myapp/nope.dart");
-    requestShould404("dir/assets/myapp/nope.png");
     endPubServe();
   });
 }
diff --git a/sdk/lib/_internal/pub/test/serve/missing_dependency_file_test.dart b/sdk/lib/_internal/pub/test/serve/missing_dependency_file_test.dart
index 7ebe99a..46821ba 100644
--- a/sdk/lib/_internal/pub/test/serve/missing_dependency_file_test.dart
+++ b/sdk/lib/_internal/pub/test/serve/missing_dependency_file_test.dart
@@ -24,9 +24,7 @@
     pubGet();
     pubServe();
     requestShould404("packages/foo/nope.dart");
-    requestShould404("assets/foo/nope.png");
     requestShould404("dir/packages/foo/nope.dart");
-    requestShould404("dir/assets/foo/nope.png");
     endPubServe();
   });
 }
diff --git a/sdk/lib/_internal/pub/test/serve/missing_file_test.dart b/sdk/lib/_internal/pub/test/serve/missing_file_test.dart
index 3b593ec..be56743 100644
--- a/sdk/lib/_internal/pub/test/serve/missing_file_test.dart
+++ b/sdk/lib/_internal/pub/test/serve/missing_file_test.dart
@@ -17,9 +17,6 @@
   integration("responds with a 404 for missing source files", () {
     d.dir(appPath, [
       d.appPubspec(),
-      d.dir("asset", [
-        d.file("nope.png", "nope")
-      ]),
       d.dir("lib", [
         d.file("nope.dart", "nope")
       ]),
@@ -34,7 +31,6 @@
 
     // Now delete them.
     schedule(() {
-      deleteEntry(path.join(sandboxDir, appPath, "asset", "nope.png"));
       deleteEntry(path.join(sandboxDir, appPath, "lib", "nope.dart"));
       deleteEntry(path.join(sandboxDir, appPath, "web", "index.html"));
     }, "delete files");
@@ -46,9 +42,7 @@
 
     requestShould404("index.html");
     requestShould404("packages/myapp/nope.dart");
-    requestShould404("assets/myapp/nope.png");
     requestShould404("dir/packages/myapp/nope.dart");
-    requestShould404("dir/assets/myapp/nope.png");
     endPubServe();
   });
 }
diff --git a/sdk/lib/_internal/pub/test/serve/serves_file_with_space_test.dart b/sdk/lib/_internal/pub/test/serve/serves_file_with_space_test.dart
new file mode 100644
index 0000000..eead808
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/serves_file_with_space_test.dart
@@ -0,0 +1,29 @@
+// 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 '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("serves a filename with a space", () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir("web", [
+        d.file("foo bar.txt", "outer contents"),
+        d.dir("sub dir", [
+          d.file("inner.txt", "inner contents"),
+        ])
+      ])
+    ]).create();
+
+    pubServe();
+    requestShouldSucceed("foo%20bar.txt", "outer contents");
+    requestShouldSucceed("sub%20dir/inner.txt", "inner contents");
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/utils.dart b/sdk/lib/_internal/pub/test/serve/utils.dart
index a1637f1..725c3b4 100644
--- a/sdk/lib/_internal/pub/test/serve/utils.dart
+++ b/sdk/lib/_internal/pub/test/serve/utils.dart
@@ -12,6 +12,7 @@
 import 'package:scheduled_test/scheduled_process.dart';
 import 'package:scheduled_test/scheduled_stream.dart';
 import 'package:scheduled_test/scheduled_test.dart';
+import 'package:stack_trace/stack_trace.dart';
 
 import '../../lib/src/utils.dart';
 import '../descriptor.dart' as d;
@@ -328,16 +329,25 @@
   });
 }
 
+/// Schedules closing the web socket connection to the currently-running pub
+/// serve.
+Future closeWebSocket() {
+  schedule(() {
+    return _ensureWebSocket().then((_) => _webSocket.close())
+        .then((_) => _webSocket = null);
+  }, "closing web socket");
+}
+
 /// Sends a JSON RPC 2.0 request to the running pub serve's web socket
 /// connection.
 ///
-/// This calls a method named [method] with the given [params]. [params] may
-/// contain Futures, in which case this will wait until they've completed before
-/// sending the request.
+/// This calls a method named [method] with the given [params] (or no
+/// parameters, if it's not passed). [params] may contain Futures, in which case
+/// this will wait until they've completed before sending the request.
 ///
 /// This schedules the request, but doesn't block the schedule on the response.
 /// It returns the response as a [Future].
-Future<Map> webSocketRequest(String method, Map params) {
+Future<Map> webSocketRequest(String method, [Map params]) {
   var completer = new Completer();
   schedule(() {
     return Future.wait([
@@ -424,17 +434,18 @@
 /// Sends a JSON-RPC 2.0 request calling [method] with [params].
 ///
 /// Returns the response object.
-Future<Map> _jsonRpcRequest(String method, Map params) {
+Future<Map> _jsonRpcRequest(String method, [Map params]) {
   var id = _rpcId++;
-  _webSocket.add(JSON.encode({
+  var message = {
     "jsonrpc": "2.0",
     "method": method,
-    "params": params,
     "id": id
-  }));
+  };
+  if (params != null) message["params"] = params;
+  _webSocket.add(JSON.encode(message));
 
-  return _webSocketBroadcastStream
-      .firstWhere((response) => response["id"] == id).then((value) {
+  return Chain.track(_webSocketBroadcastStream
+      .firstWhere((response) => response["id"] == id)).then((value) {
     currentSchedule.addDebugInfo(
         "Web Socket request $method with params $params\n"
         "Result: $value");
diff --git a/sdk/lib/_internal/pub/test/serve/web_socket/exit_on_close_test.dart b/sdk/lib/_internal/pub/test/serve/web_socket/exit_on_close_test.dart
new file mode 100644
index 0000000..3335ddf
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/web_socket/exit_on_close_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 '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+import '../utils.dart';
+
+main() {
+  initConfig();
+  integration("exits when the connection closes", () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir("web", [
+        d.file("index.html", "<body>")
+      ])
+    ]).create();
+
+    var server = pubServe();
+
+    // Make sure the web socket is active.
+    expectWebSocketResult("urlToAssetId", {
+      "url": getServerUrl("web", "index.html")
+    }, {"package": "myapp", "path": "web/index.html"});
+
+    expectWebSocketResult("exitOnClose", null, null);
+
+    // Close the web socket.
+    closeWebSocket();
+
+    server.stdout.expect("Build completed successfully");
+    server.stdout.expect("WebSocket connection closed, terminating.");
+    server.shouldExit(0);
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/web_socket/path_to_urls_errors_test.dart b/sdk/lib/_internal/pub/test/serve/web_socket/path_to_urls_errors_test.dart
index 14ed26a..61b1928 100644
--- a/sdk/lib/_internal/pub/test/serve/web_socket/path_to_urls_errors_test.dart
+++ b/sdk/lib/_internal/pub/test/serve/web_socket/path_to_urls_errors_test.dart
@@ -25,9 +25,6 @@
     d.dir(appPath, [
       d.appPubspec({"foo": {"path": "../foo"}}),
       d.file("top-level.txt", "top-level"),
-      d.dir("asset", [
-        d.file("foo.txt", "foo"),
-      ]),
       d.dir("bin", [
         d.file("foo.txt", "foo"),
       ]),
diff --git a/sdk/lib/_internal/pub/test/serve/web_socket/path_to_urls_test.dart b/sdk/lib/_internal/pub/test/serve/web_socket/path_to_urls_test.dart
index 30fdfe3..5db405c 100644
--- a/sdk/lib/_internal/pub/test/serve/web_socket/path_to_urls_test.dart
+++ b/sdk/lib/_internal/pub/test/serve/web_socket/path_to_urls_test.dart
@@ -19,10 +19,7 @@
       d.libPubspec("foo", "1.0.0"),
       d.dir("lib", [
         d.file("foo.dart", "foo() => null;")
-      ]),
-      d.dir("asset", [
-        d.file("foo.txt", "foo")
-      ]),
+      ])
     ]).create();
 
     d.dir(appPath, [
@@ -36,9 +33,6 @@
       d.dir("lib", [
         d.file("app.dart", "app() => null;")
       ]),
-      d.dir("asset", [
-        d.file("app.txt", "app")
-      ]),
       d.dir("web", [
         d.file("index.html", "<body>"),
         d.dir("sub", [
@@ -94,15 +88,6 @@
       getServerUrl("randomdir", "packages/myapp/app.dart")
     ]});
 
-    // A path in asset/.
-    expectWebSocketResult("pathToUrls", {
-      "path": p.join("asset", "app.txt")
-    }, {"urls": [
-      getServerUrl("test", "assets/myapp/app.txt"),
-      getServerUrl("web", "assets/myapp/app.txt"),
-      getServerUrl("randomdir", "assets/myapp/app.txt")
-    ]});
-
     // A path to this package in packages/.
     expectWebSocketResult("pathToUrls", {
       "path": p.join("packages", "myapp", "app.dart")
@@ -144,24 +129,6 @@
       getServerUrl("randomdir", "packages/foo/foo.dart")
     ]});
 
-    // A relative path to another package's asset/ directory.
-    expectWebSocketResult("pathToUrls", {
-      "path": p.join("..", "foo", "asset", "foo.dart")
-    }, {"urls": [
-      getServerUrl("test", "assets/foo/foo.dart"),
-      getServerUrl("web", "assets/foo/foo.dart"),
-      getServerUrl("randomdir", "assets/foo/foo.dart")
-    ]});
-
-    // An absolute path to another package's asset/ directory.
-    expectWebSocketResult("pathToUrls", {
-      "path": canonicalize(p.join(sandboxDir, "foo", "asset", "foo.dart"))
-    }, {"urls": [
-      getServerUrl("test", "assets/foo/foo.dart"),
-      getServerUrl("web", "assets/foo/foo.dart"),
-      getServerUrl("randomdir", "assets/foo/foo.dart")
-    ]});
-
     endPubServe();
   });
 }
diff --git a/sdk/lib/_internal/pub/test/transformer/does_not_run_a_transform_on_an_input_in_another_package_test.dart b/sdk/lib/_internal/pub/test/transformer/does_not_run_a_transform_on_an_input_in_another_package_test.dart
index 6fbb7ae..a464101 100644
--- a/sdk/lib/_internal/pub/test/transformer/does_not_run_a_transform_on_an_input_in_another_package_test.dart
+++ b/sdk/lib/_internal/pub/test/transformer/does_not_run_a_transform_on_an_input_in_another_package_test.dart
@@ -19,16 +19,14 @@
           "transformers": ["foo/transformer"]
         }),
         d.dir("lib", [
-          d.file("transformer.dart", REWRITE_TRANSFORMER)
-        ]),
-        d.dir("asset", [
+          d.file("transformer.dart", REWRITE_TRANSFORMER),
           d.file("foo.txt", "foo")
         ])
       ]).create();
 
       d.dir(appPath, [
         d.appPubspec({"foo": {"path": "../foo"}}),
-        d.dir("asset", [
+        d.dir("lib", [
           d.file("bar.txt", "bar")
         ])
       ]).create();
@@ -36,7 +34,7 @@
       createLockFile('myapp', sandbox: ['foo'], pkg: ['barback']);
 
       pubServe();
-      requestShould404("assets/myapp/bar.out");
+      requestShould404("packages/myapp/bar.out");
       endPubServe();
     });
   });
diff --git a/sdk/lib/_internal/pub/test/transformer/fails_to_load_a_transform_with_a_syntax_error_test.dart b/sdk/lib/_internal/pub/test/transformer/fails_to_load_a_transform_with_a_syntax_error_test.dart
index 0a61e59..ae98d66 100644
--- a/sdk/lib/_internal/pub/test/transformer/fails_to_load_a_transform_with_a_syntax_error_test.dart
+++ b/sdk/lib/_internal/pub/test/transformer/fails_to_load_a_transform_with_a_syntax_error_test.dart
@@ -31,8 +31,7 @@
       createLockFile('myapp', pkg: ['barback']);
 
       var pub = startPubServe();
-      pub.stderr.expect('[RewriteImport]:');
-      pub.stderr.expect(startsWith('Error in'));
+      pub.stderr.expect(contains("unexpected token 'syntax'"));
       pub.shouldExit(1);
       pub.stderr.expect(never(contains('This is an unexpected error')));
     });
diff --git a/sdk/lib/async/broadcast_stream_controller.dart b/sdk/lib/async/broadcast_stream_controller.dart
index 18ff654..5ec2756 100644
--- a/sdk/lib/async/broadcast_stream_controller.dart
+++ b/sdk/lib/async/broadcast_stream_controller.dart
@@ -39,7 +39,6 @@
   bool _expectsEvent(int eventId) =>
       (_eventState & _STATE_EVENT_ID) == eventId;
 
-
   void _toggleEventId() {
     _eventState ^= _STATE_EVENT_ID;
   }
@@ -181,7 +180,7 @@
 
   StreamSubscription<T> _subscribe(bool cancelOnError) {
     if (isClosed) {
-      throw new StateError("Subscribing to closed stream");
+      return new _DoneStreamSubscription<T>(_nullDoneHandler);
     }
     StreamSubscription subscription =
         new _BroadcastSubscription<T>(this, cancelOnError);
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index f953a5a..ab50c24 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -1338,11 +1338,11 @@
  * An interface that abstracts creation or handling of [Stream] events.
  */
 abstract class EventSink<T> implements Sink<T> {
-  /** Create a data event */
+  /** Send a data event to a stream. */
   void add(T event);
-  /** Create an async error. */
+  /** Send an async error to a stream. */
   void addError(errorEvent, [StackTrace stackTrace]);
-  /** Request a stream to close. */
+  /** Send a done event to a stream.*/
   void close();
 }
 
@@ -1387,6 +1387,12 @@
    */
   Future addStream(Stream<S> stream);
 
+  /**
+   * Tell the consumer that no futher streams will be added.
+   *
+   * Returns a future that is completed when the consumer is done handling
+   * events.
+   */
   Future close();
 }
 
@@ -1410,17 +1416,24 @@
  */
 abstract class StreamSink<S> implements StreamConsumer<S>, EventSink<S> {
   /**
-   * Close the [StreamSink]. It'll return the [done] Future.
+   * As [EventSink.close], but returns a future.
+   *
+   * Returns the same future as [done].
    */
   Future close();
 
   /**
-   * The [done] Future completes with the same values as [close], except
-   * for the following case:
+   * Return a future which is completed when the [StreamSink] is finished.
    *
-   * * The synchronous methods of [EventSink] were called, resulting in an
-   *   error. If there is no active future (like from an addStream call), the
-   *   [done] future will complete with that error
+   * If the `StreamSink` fails with an error,
+   * perhaps in response to adding events using [add], [addError] or [close],
+   * the [done] future will complete with that error.
+   *
+   * Otherwise, the returned future will complete when either:
+   *
+   * * all events have been processed and the sink has been closed, or
+   * * the sink has otherwise been stopped from handling more events
+   *   (for example by cancelling a stream subscription).
    */
   Future get done;
 }
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index 34582ae..5a70e94 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -382,6 +382,13 @@
     return addState.addStreamFuture;
   }
 
+  /**
+   * Returns a future that is completed when the stream is done
+   * processing events.
+   *
+   * This happens either when the done event has been sent, or if the
+   * subscriber of a single-subscription stream is cancelled.
+   */
   Future get done => _ensureDoneFuture();
 
   Future _ensureDoneFuture() {
@@ -408,15 +415,17 @@
   }
 
   /**
-   * Closes this controller.
+   * Closes this controller and sends a done event on the stream.
    *
-   * After closing, no further events may be added using [add] or [addError].
+   * The first time a controller is closed, a "done" event is added to its
+   * stream.
    *
    * You are allowed to close the controller more than once, but only the first
    * call has any effect.
    *
-   * The first time a controller is closed, a "done" event is sent to its
-   * stream.
+   * After closing, no further events may be added using [add] or [addError].
+   *
+   * The returned future is completed when the done event has been delivered.
    */
   Future close() {
     if (isClosed) {
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index 78c4087..31ae7ba 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -729,26 +729,63 @@
 typedef void _broadcastCallback(StreamSubscription subscription);
 
 /**
- * Dummy subscription that will never receive any events.
+ * Done subscription that will send one done event as soon as possible.
  */
-class _DummyStreamSubscription<T> implements StreamSubscription<T> {
-  int _pauseCounter = 0;
+class _DoneStreamSubscription<T> implements StreamSubscription<T> {
+  static const int _DONE_SENT = 1;
+  static const int _SCHEDULED = 2;
+  static const int _PAUSED = 4;
+
+  final Zone _zone;
+  int _state = 0;
+  _DoneHandler _onDone;
+
+  _DoneStreamSubscription(this._onDone) : _zone = Zone.current {
+    _schedule();
+  }
+
+  bool get _isSent => (_state & _DONE_SENT) != 0;
+  bool get _isScheduled => (_state & _SCHEDULED) != 0;
+  bool get isPaused => _state >= _PAUSED;
+
+  void _schedule() {
+    if (_isScheduled) return;
+    _zone.scheduleMicrotask(_sendDone);
+    _state |= _SCHEDULED;
+  }
 
   void onData(void handleData(T data)) {}
   void onError(Function handleError) {}
-  void onDone(void handleDone()) {}
+  void onDone(void handleDone()) { _onDone = handleDone; }
 
   void pause([Future resumeSignal]) {
-    _pauseCounter++;
-    if (resumeSignal != null) resumeSignal.then((_) { resume(); });
+    _state += _PAUSED;
+    if (resumeSignal != null) resumeSignal.whenComplete(resume);
   }
-  void resume() {
-    if (_pauseCounter > 0) _pauseCounter--;
-  }
-  Future cancel() => null;
-  bool get isPaused => _pauseCounter > 0;
 
-  Future asFuture([futureValue]) => new _Future();
+  void resume() {
+    if (isPaused) {
+      _state -= _PAUSED;
+      if (!isPaused && !_isSent) {
+        _schedule();
+      }
+    }
+  }
+
+  Future cancel() => null;
+
+  Future asFuture([futureValue]) {
+    _Future result = new _Future();
+    _onDone = () { result._completeWithValue(null); };
+    return result;
+  }
+
+  void _sendDone() {
+    _state &= ~_SCHEDULED;
+    if (isPaused) return;
+    _state |= _DONE_SENT;
+    if (_onDone != null) _zone.runGuarded(_onDone);
+  }
 }
 
 class _AsBroadcastStream<T> extends Stream<T> {
@@ -775,10 +812,10 @@
                                { Function onError,
                                  void onDone(),
                                  bool cancelOnError}) {
-    if (_controller == null) {
+    if (_controller == null || _controller.isClosed) {
       // Return a dummy subscription backed by nothing, since
-      // it won't ever receive any events.
-      return new _DummyStreamSubscription<T>();
+      // it will only ever send one done event.
+      return new _DoneStreamSubscription<T>(onDone);
     }
     if (_subscription == null) {
       _subscription = _source.listen(_controller.add,
diff --git a/sdk/lib/collection/iterable.dart b/sdk/lib/collection/iterable.dart
index 1ae7b97..36a1efd 100644
--- a/sdk/lib/collection/iterable.dart
+++ b/sdk/lib/collection/iterable.dart
@@ -418,7 +418,7 @@
   static String iterableToShortString(Iterable iterable,
                                       [String leftDelimiter = '(',
                                        String rightDelimiter = ')']) {
-    if (_toStringVisiting.contains(iterable)) {
+    if (_isToStringVisiting(iterable)) {
       if (leftDelimiter == "(" && rightDelimiter == ")") {
         // Avoid creating a new string in the "common" case.
         return "(...)";
@@ -430,7 +430,8 @@
     try {
       _iterablePartsToStrings(iterable, parts);
     } finally {
-      _toStringVisiting.remove(iterable);
+      assert(identical(_toStringVisiting.last, iterable));
+      _toStringVisiting.removeLast();
     }
     return (new StringBuffer(leftDelimiter)
                 ..writeAll(parts, ", ")
@@ -452,7 +453,7 @@
   static String iterableToFullString(Iterable iterable,
                                      [String leftDelimiter = '(',
                                       String rightDelimiter = ')']) {
-    if (_toStringVisiting.contains(iterable)) {
+    if (_isToStringVisiting(iterable)) {
       return "$leftDelimiter...$rightDelimiter";
     }
     StringBuffer buffer = new StringBuffer(leftDelimiter);
@@ -460,14 +461,23 @@
     try {
       buffer.writeAll(iterable, ", ");
     } finally {
-      _toStringVisiting.remove(iterable);
+      assert(identical(_toStringVisiting.last, iterable));
+      _toStringVisiting.removeLast();
     }
     buffer.write(rightDelimiter);
     return buffer.toString();
   }
 
   /** A set used to identify cyclic lists during toString() calls. */
-  static Set _toStringVisiting = new HashSet.identity();
+  static final List _toStringVisiting = [];
+
+  /** Check if we are currently visiting `o` in a toString call. */
+  static bool _isToStringVisiting(Object o) {
+    for (int i = 0; i < _toStringVisiting.length; i++) {
+      if (identical(o, _toStringVisiting[i])) return true;
+    }
+    return false;
+  }
 
   /**
    * Convert elments of [iterable] to strings and store them in [parts].
diff --git a/sdk/lib/collection/maps.dart b/sdk/lib/collection/maps.dart
index 28d7665..c0a411d 100644
--- a/sdk/lib/collection/maps.dart
+++ b/sdk/lib/collection/maps.dart
@@ -267,9 +267,6 @@
 
   static bool isNotEmpty(Map map) => map.keys.isNotEmpty;
 
-  // A list to identify cyclic maps during toString() calls.
-  static List _toStringList = new List();
-
   /**
    * Returns a string representing the specified map. The returned string
    * looks like this: [:'{key0: value0, key1: value1, ... keyN: valueN}':].
@@ -287,13 +284,12 @@
    * simply return the results of this method applied to the collection.
    */
   static String mapToString(Map m) {
-    for (int i = 0; i < _toStringList.length; i++) {
-      if (identical(_toStringList[i], m)) { return '{...}'; }
-    }
+    // Reuse the list in IterableBase for detecting toString cycles.
+    if (IterableBase._isToStringVisiting(m)) { return '{...}'; }
 
     var result = new StringBuffer();
     try {
-      _toStringList.add(m);
+      IterableBase._toStringVisiting.add(m);
       result.write('{');
       bool first = true;
       m.forEach((k, v) {
@@ -307,8 +303,8 @@
       });
       result.write('}');
     } finally {
-      assert(identical(_toStringList.last, m));
-      _toStringList.removeLast();
+      assert(identical(IterableBase._toStringVisiting.last, m));
+      IterableBase._toStringVisiting.removeLast();
     }
 
     return result.toString();
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 27e0f7d..050e4c0 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -2045,6 +2045,7 @@
   /** Deprecated always returns 1.0 */
   @DomName('CanvasRenderingContext2D.webkitBackingStorePixelRation')
   @Experimental()
+  @deprecated
   double get backingStorePixelRatio => 1.0;
 }
 
@@ -2807,6 +2808,7 @@
   void setProperty(String propertyName, String value, [String priority]) {
     // try/catch for IE9 which throws on unsupported values.
     try {
+      if (value == null) value = '';
       if (priority == null) {
         priority = '';
       }
@@ -4026,12 +4028,17 @@
   }
 
   /** Gets the value of "flex" */
-  String get flex =>
-    getPropertyValue('${Device.cssPrefix}flex');
+  String get flex {
+    String prefix = Device.cssPrefix;
+    if (Device.isFirefox) prefix = '';
+    return getPropertyValue('${prefix}flex');
+  }
 
   /** Sets the value of "flex" */
   void set flex(String value) {
-    setProperty('${Device.cssPrefix}flex', value, '');
+    String prefix = Device.cssPrefix;
+    if (Device.isFirefox) prefix = '';
+    setProperty('${prefix}flex', value, '');
   }
 
   /** Gets the value of "flex-basis" */
@@ -10262,59 +10269,59 @@
 
   @DomName('Element.offsetHeight')
   @DocsEditable()
-  num get offsetHeight => JS('num', '#.offsetHeight', this).round();
+  int get offsetHeight => JS('num', '#.offsetHeight', this).round();
 
   @DomName('Element.offsetLeft')
   @DocsEditable()
-  num get offsetLeft => JS('num', '#.offsetLeft', this).round();
+  int get offsetLeft => JS('num', '#.offsetLeft', this).round();
 
   @DomName('Element.offsetTop')
   @DocsEditable()
-  num get offsetTop => JS('num', '#.offsetTop', this).round();
+  int get offsetTop => JS('num', '#.offsetTop', this).round();
 
   @DomName('Element.offsetWidth')
   @DocsEditable()
-  num get offsetWidth => JS('num', '#.offsetWidth', this).round();
+  int get offsetWidth => JS('num', '#.offsetWidth', this).round();
 
   @DomName('Element.clientHeight')
   @DocsEditable()
-  num get clientHeight => JS('num', '#.clientHeight', this).round();
+  int get clientHeight => JS('num', '#.clientHeight', this).round();
 
   @DomName('Element.clientLeft')
   @DocsEditable()
-  num get clientLeft => JS('num', '#.clientLeft', this).round();
+  int get clientLeft => JS('num', '#.clientLeft', this).round();
 
   @DomName('Element.clientTop')
   @DocsEditable()
-  num get clientTop => JS('num', '#.clientTop', this).round();
+  int get clientTop => JS('num', '#.clientTop', this).round();
 
   @DomName('Element.clientWidth')
   @DocsEditable()
-  num get clientWidth => JS('num', '#.clientWidth', this).round();
+  int get clientWidth => JS('num', '#.clientWidth', this).round();
 
   @DomName('Element.scrollHeight')
   @DocsEditable()
-  num get scrollHeight => JS('num', '#.scrollHeight', this).round();
+  int get scrollHeight => JS('num', '#.scrollHeight', this).round();
 
   @DomName('Element.scrollLeft')
   @DocsEditable()
-  num get scrollLeft => JS('num', '#.scrollLeft', this).round();
+  int get scrollLeft => JS('num', '#.scrollLeft', this).round();
 
   @DomName('Element.scrollLeft')
   @DocsEditable()
-  void set scrollLeft(num value) => JS("void", "#.scrollLeft = #", this, value.round());
+  void set scrollLeft(int value) => JS("void", "#.scrollLeft = #", this, value.round());
 
   @DomName('Element.scrollTop')
   @DocsEditable()
-  num get scrollTop => JS('num', '#.scrollTop', this).round();
+  int get scrollTop => JS('num', '#.scrollTop', this).round();
 
   @DomName('Element.scrollTop')
   @DocsEditable()
-  void set scrollTop(num value) => JS("void", "#.scrollTop = #", this, value.round());
+  void set scrollTop(int value) => JS("void", "#.scrollTop = #", this, value.round());
 
   @DomName('Element.scrollWidth')
   @DocsEditable()
-  num get scrollWidth => JS('num', '#.scrollWidth', this).round();
+  int get scrollWidth => JS('num', '#.scrollWidth', this).round();
 
 
   // To suppress missing implicit constructor warnings.
@@ -14679,13 +14686,19 @@
    *
    * By default `request` will perform an HTTP GET request, but a different
    * method (`POST`, `PUT`, `DELETE`, etc) can be used by specifying the
-   * [method] parameter.
+   * [method] parameter. (See also [HttpRequest.postFormData] for `POST` 
+   * requests only.
    *
    * The Future is completed when the response is available.
    *
    * If specified, `sendData` will send data in the form of a [ByteBuffer],
    * [Blob], [Document], [String], or [FormData] along with the HttpRequest.
    *
+   * If specified, [responseType] sets the desired response format for the
+   * request. By default it is [String], but can also be 'arraybuffer', 'blob', 
+   * 'document', 'json', or 'text'. See also [HttpRequest.responseType] 
+   * for more information.
+   *
    * The [withCredentials] parameter specified that credentials such as a cookie
    * (already) set in the header or
    * [authorization headers](http://tools.ietf.org/html/rfc1945#section-10.2)
@@ -15557,6 +15570,23 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
+@DocsEditable()
+@DomName('InjectedScriptHost')
+@Experimental() // untriaged
+class InjectedScriptHost extends Interceptor native "InjectedScriptHost" {
+  // To suppress missing implicit constructor warnings.
+  factory InjectedScriptHost._() { throw new UnsupportedError("Not supported"); }
+
+  @DomName('InjectedScriptHost.inspect')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void inspect(Object objectId, Object hints) 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.
+
+
 @DomName('HTMLInputElement')
 class InputElement extends HtmlElement implements
     HiddenInputElement,
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 35910da..c93a3d7 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -301,6 +301,7 @@
   'History': History,
   'ImageBitmap': ImageBitmap,
   'ImageData': ImageData,
+  'InjectedScriptHost': InjectedScriptHost,
   'InputMethodContext': InputMethodContext,
   'InstallEvent': InstallEvent,
   'InstallPhaseEvent': InstallPhaseEvent,
@@ -2558,6 +2559,7 @@
   /** Deprecated always returns 1.0 */
   @DomName('CanvasRenderingContext2D.webkitBackingStorePixelRation')
   @Experimental()
+  @deprecated
   double get backingStorePixelRatio => 1.0;
 }
 
@@ -4637,12 +4639,17 @@
   }
 
   /** Gets the value of "flex" */
-  String get flex =>
-    getPropertyValue('${Device.cssPrefix}flex');
+  String get flex {
+    String prefix = Device.cssPrefix;
+    if (Device.isFirefox) prefix = '';
+    return getPropertyValue('${prefix}flex');
+  }
 
   /** Sets the value of "flex" */
   void set flex(String value) {
-    setProperty('${Device.cssPrefix}flex', value, '');
+    String prefix = Device.cssPrefix;
+    if (Device.isFirefox) prefix = '';
+    setProperty('${prefix}flex', value, '');
   }
 
   /** Gets the value of "flex-basis" */
@@ -10589,59 +10596,59 @@
 
   @DomName('Element.offsetHeight')
   @DocsEditable()
-  num get offsetHeight => _blink.Native_Element_offsetHeight_Getter(this).round();
+  int get offsetHeight => _blink.Native_Element_offsetHeight_Getter(this).round();
 
   @DomName('Element.offsetLeft')
   @DocsEditable()
-  num get offsetLeft => _blink.Native_Element_offsetLeft_Getter(this).round();
+  int get offsetLeft => _blink.Native_Element_offsetLeft_Getter(this).round();
 
   @DomName('Element.offsetTop')
   @DocsEditable()
-  num get offsetTop => _blink.Native_Element_offsetTop_Getter(this).round();
+  int get offsetTop => _blink.Native_Element_offsetTop_Getter(this).round();
 
   @DomName('Element.offsetWidth')
   @DocsEditable()
-  num get offsetWidth => _blink.Native_Element_offsetWidth_Getter(this).round();
+  int get offsetWidth => _blink.Native_Element_offsetWidth_Getter(this).round();
 
   @DomName('Element.clientHeight')
   @DocsEditable()
-  num get clientHeight => _blink.Native_Element_clientHeight_Getter(this).round();
+  int get clientHeight => _blink.Native_Element_clientHeight_Getter(this).round();
 
   @DomName('Element.clientLeft')
   @DocsEditable()
-  num get clientLeft => _blink.Native_Element_clientLeft_Getter(this).round();
+  int get clientLeft => _blink.Native_Element_clientLeft_Getter(this).round();
 
   @DomName('Element.clientTop')
   @DocsEditable()
-  num get clientTop => _blink.Native_Element_clientTop_Getter(this).round();
+  int get clientTop => _blink.Native_Element_clientTop_Getter(this).round();
 
   @DomName('Element.clientWidth')
   @DocsEditable()
-  num get clientWidth => _blink.Native_Element_clientWidth_Getter(this).round();
+  int get clientWidth => _blink.Native_Element_clientWidth_Getter(this).round();
 
   @DomName('Element.scrollHeight')
   @DocsEditable()
-  num get scrollHeight => _blink.Native_Element_scrollHeight_Getter(this).round();
+  int get scrollHeight => _blink.Native_Element_scrollHeight_Getter(this).round();
 
   @DomName('Element.scrollLeft')
   @DocsEditable()
-  num get scrollLeft => _blink.Native_Element_scrollLeft_Getter(this).round();
+  int get scrollLeft => _blink.Native_Element_scrollLeft_Getter(this).round();
 
   @DomName('Element.scrollLeft')
   @DocsEditable()
-  void set scrollLeft(num value) => _blink.Native_Element_scrollLeft_Setter(this, value.round());
+  void set scrollLeft(int value) => _blink.Native_Element_scrollLeft_Setter(this, value.round());
 
   @DomName('Element.scrollTop')
   @DocsEditable()
-  num get scrollTop => _blink.Native_Element_scrollTop_Getter(this).round();
+  int get scrollTop => _blink.Native_Element_scrollTop_Getter(this).round();
 
   @DomName('Element.scrollTop')
   @DocsEditable()
-  void set scrollTop(num value) => _blink.Native_Element_scrollTop_Setter(this, value.round());
+  void set scrollTop(int value) => _blink.Native_Element_scrollTop_Setter(this, value.round());
 
   @DomName('Element.scrollWidth')
   @DocsEditable()
-  num get scrollWidth => _blink.Native_Element_scrollWidth_Getter(this).round();
+  int get scrollWidth => _blink.Native_Element_scrollWidth_Getter(this).round();
 
   // To suppress missing implicit constructor warnings.
   factory Element._() { throw new UnsupportedError("Not supported"); }
@@ -15603,13 +15610,19 @@
    *
    * By default `request` will perform an HTTP GET request, but a different
    * method (`POST`, `PUT`, `DELETE`, etc) can be used by specifying the
-   * [method] parameter.
+   * [method] parameter. (See also [HttpRequest.postFormData] for `POST` 
+   * requests only.
    *
    * The Future is completed when the response is available.
    *
    * If specified, `sendData` will send data in the form of a [ByteBuffer],
    * [Blob], [Document], [String], or [FormData] along with the HttpRequest.
    *
+   * If specified, [responseType] sets the desired response format for the
+   * request. By default it is [String], but can also be 'arraybuffer', 'blob', 
+   * 'document', 'json', or 'text'. See also [HttpRequest.responseType] 
+   * for more information.
+   *
    * The [withCredentials] parameter specified that credentials such as a cookie
    * (already) set in the header or
    * [authorization headers](http://tools.ietf.org/html/rfc1945#section-10.2)
@@ -16545,6 +16558,26 @@
 // for 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('InjectedScriptHost')
+@Experimental() // untriaged
+class InjectedScriptHost extends NativeFieldWrapperClass2 {
+  // To suppress missing implicit constructor warnings.
+  factory InjectedScriptHost._() { throw new UnsupportedError("Not supported"); }
+
+  @DomName('InjectedScriptHost.inspect')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void inspect(Object objectId, Object hints) => _blink.Native_InjectedScriptHost_inspect_Callback(this, objectId, hints);
+
+}
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
 
 @DomName('HTMLInputElement')
 class InputElement extends HtmlElement implements
@@ -37061,8 +37094,7 @@
     if (element.runtimeType != _nativeType) {
       throw new UnsupportedError('Element is incorrect type');
     }
-    _Utils.changeElementWrapper(element, _type);
-    return null;
+    return _Utils.changeElementWrapper(element, _type);
   }
 }
 
@@ -37463,6 +37495,32 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
+class _Property {
+  _Property(this.name) :
+      _hasValue = false,
+      writable = false,
+      isMethod = false,
+      isOwn = true,
+      wasThrown = false;
+
+  bool get hasValue => _hasValue;
+  get value => _value;
+  set value(v) {
+    _value = v;
+    _hasValue = true;
+  }
+
+  final String name;
+  Function setter;
+  Function getter;
+  var _value;
+  bool _hasValue;
+  bool writable;
+  bool isMethod;
+  bool isOwn;
+  bool wasThrown;
+}
+
 class _ConsoleVariables {
   Map<String, Object> _data = new Map<String, Object>();
 
@@ -37478,7 +37536,8 @@
       member = member.substring(0, member.length - 1);
       _data[member] = invocation.positionalArguments[0];
     } else {
-      return Function.apply(_data[member], invocation.positionalArguments, invocation.namedArguments);
+      return Function.apply(_data[member], invocation.positionalArguments,
+          invocation.namedArguments);
     }
   }
 
@@ -37487,7 +37546,60 @@
   /**
    * List all variables currently defined.
    */
-  List variables() => _data.keys.toList(growable: false);
+  List variables() => _data.keys.toList();
+
+  void setVariable(String name, value) {
+    _data[name] = value;
+  }
+}
+
+/**
+ * Base class for invocation trampolines used to closurize methods, getters
+ * and setters.
+ */
+abstract class _Trampoline implements Function {
+  final ObjectMirror _receiver;
+  final MethodMirror _methodMirror;
+  final Symbol _selector;
+
+  _Trampoline(this._receiver, this._methodMirror, this._selector);
+}
+
+class _MethodTrampoline extends _Trampoline {
+  _MethodTrampoline(ObjectMirror receiver, MethodMirror methodMirror,
+      Symbol selector) :
+      super(receiver, methodMirror, selector);
+
+  noSuchMethod(Invocation msg) {
+    if (msg.memberName != #call) return super.noSuchMethod(msg);
+    return _receiver.invoke(_selector,
+                            msg.positionalArguments,
+                            msg.namedArguments).reflectee;
+  }
+}
+
+/**
+ * Invocation trampoline class used to closurize getters.
+ */
+class _GetterTrampoline extends _Trampoline {
+  _GetterTrampoline(ObjectMirror receiver, MethodMirror methodMirror,
+      Symbol selector) :
+      super(receiver, methodMirror, selector);
+
+  call() => _receiver.getField(_selector).reflectee;
+}
+
+/**
+ * Invocation trampoline class used to closurize setters.
+ */
+class _SetterTrampoline extends _Trampoline {
+  _SetterTrampoline(ObjectMirror receiver, MethodMirror methodMirror,
+      Symbol selector) :
+      super(receiver, methodMirror, selector);
+
+  call(value) {
+    _receiver.setField(_selector, value);
+  }
 }
 
 class _Utils {
@@ -37603,27 +37715,6 @@
   static _ConsoleVariables _consoleTempVariables = new _ConsoleVariables();
 
   /**
-   * Header passed in from the Dartium Developer Tools when an expression is
-   * evaluated in the console as opposed to the watch window or another context
-   * that does not expect REPL support in Dartium 34.
-   */
-  static const _CONSOLE_API_SUPPORT_HEADER_34 =
-      'with ((console && console._commandLineAPI) || { __proto__: null }) {\n';
-  /**
-   * Header passed in from the Dartium Developer Tools when an expression is
-   * evaluated in the console as opposed to the watch window or another context
-   * that does not expect REPL support in Dartium 35.
-   */
-  static const _CONSOLE_API_SUPPORT_HEADER_35 =
-      'with (__commandLineAPI || { __proto__: null }) {\n';
-
-
-  static bool expectsConsoleApi(String expression) {
-    return expression.indexOf(_CONSOLE_API_SUPPORT_HEADER_34) == 0 ||
-        expression.indexOf(_CONSOLE_API_SUPPORT_HEADER_35) == 0;
-  }
-
-  /**
    * Takes an [expression] and a list of [local] variable and returns an
    * expression for a closure with a body matching the original expression
    * where locals are passed in as arguments. Returns a list containing the
@@ -37635,8 +37726,7 @@
    * For example:
    * <code>
    * _consoleTempVariables = {'a' : someValue, 'b': someOtherValue}
-   * wrapExpressionAsClosure("${_CONSOLE_API_SUPPORT_HEADER35}foo + bar + a",
-   *                         ["bar", 40, "foo", 2])
+   * wrapExpressionAsClosure("foo + bar + a", ["bar", 40, "foo", 2], true)
    * </code>
    * will return:
    * <code>
@@ -37646,9 +37736,8 @@
    * [_consoleTempVariables, 40, 2, someValue, someOtherValue]]
    * </code>
    */
-  static List wrapExpressionAsClosure(String expression, List locals) {
-    // FIXME: dartbug.com/10434 find a less fragile way to determine whether
-    // we need to strip off console API support added by InjectedScript.
+  static List wrapExpressionAsClosure(String expression, List locals,
+      bool includeCommandLineAPI) {
     var args = {};
     var sb = new StringBuffer("(");
     addArg(arg, value) {
@@ -37667,10 +37756,7 @@
       args[arg] = value;
     }
 
-    if (expectsConsoleApi(expression)) {
-      expression = expression.substring(expression.indexOf('\n') + 1);
-      expression = expression.substring(0, expression.lastIndexOf('\n'));
-
+    if (includeCommandLineAPI) {
       addArg("\$consoleVariables", _consoleTempVariables);
 
       // FIXME: use a real Dart tokenizer. The following regular expressions
@@ -37727,13 +37813,19 @@
     return [sb.toString(), args.values.toList(growable: false)];
   }
 
-  /**
-   * TODO(jacobr): this is a big hack to get around the fact that we are still
-   * passing some JS expression to the evaluate method even when in a Dart
-   * context.
-   */
-  static bool isJsExpression(String expression) =>
-    expression.startsWith("(function getCompletions");
+  static String _getShortSymbolName(Symbol symbol,
+                                    DeclarationMirror declaration) {
+    var name = MirrorSystem.getName(symbol);
+    if (declaration is MethodMirror) {
+      if (declaration.isSetter && name[name.length-1] == "=") {
+        return name.substring(0, name.length-1);
+      }
+      if (declaration.isConstructor) {
+        return name.substring(name.indexOf('.') + 1);
+      }
+    }
+    return name;
+  }
 
   /**
    * Returns a list of completions to use if the receiver is o.
@@ -37772,97 +37864,409 @@
   }
 
   /**
-   * Convenience helper to get the keys of a [Map] as a [List].
+   * Adds all candidate String completitions from [declarations] to [output]
+   * filtering based on [staticContext] and [includePrivate].
    */
-  static List getMapKeyList(Map map) => map.keys.toList();
-
- /**
-   * Returns the keys of an arbitrary Dart Map encoded as unique Strings.
-   * Keys that are strings are left unchanged except that the prefix ":" is
-   * added to disambiguate keys from other Dart members.
-   * Keys that are not strings have # followed by the index of the key in the map
-   * prepended to disambuguate. This scheme is simplistic but easy to encode and
-   * decode. The use case for this method is displaying all map keys in a human
-   * readable way in debugging tools.
-   */
-  static List<String> getEncodedMapKeyList(dynamic obj) {
-    if (obj is! Map) return null;
-
-    var ret = new List<String>();
-    int i = 0;
-    return obj.keys.map((key) {
-      var encodedKey;
-      if (key is String) {
-        encodedKey = ':$key';
-      } else {
-        // If the key isn't a string, return a guaranteed unique for this map
-        // string representation of the key that is still somewhat human
-        // readable.
-        encodedKey = '#${i}:$key';
+  static void _getCompletionsHelper(ClassMirror classMirror,
+      bool staticContext, LibraryMirror libraryMirror, Set<String> output) {
+    bool includePrivate = libraryMirror == classMirror.owner;
+    classMirror.declarations.forEach((symbol, declaration) {
+      if (!includePrivate && declaration.isPrivate) return;
+      if (declaration is VariableMirror) {
+        if (staticContext != declaration.isStatic) return;
+      } else if (declaration is MethodMirror) {
+        if (declaration.isOperator) return;
+        if (declaration.isConstructor) {
+          if (!staticContext) return;
+          var name = MirrorSystem.getName(declaration.constructorName);
+          if (name.isNotEmpty) output.add(name);
+          return;
+        }
+        if (staticContext != declaration.isStatic) return;
+      } else if (declaration is TypeMirror) {
+        return;
       }
-      i++;
-      return encodedKey;
-    }).toList(growable: false);
+      output.add(_getShortSymbolName(symbol, declaration));
+    });
+
+    if (!staticContext) {
+      for (var interface in classMirror.superinterfaces) {
+        _getCompletionsHelper(interface, staticContext,
+            libraryMirror, output);
+      }
+      if (classMirror.superclass != null) {
+        _getCompletionsHelper(classMirror.superclass, staticContext,
+            libraryMirror, output);
+      }
+    }
   }
 
-  static final RegExp _NON_STRING_KEY_REGEXP = new RegExp("^#(\\d+):(.+)\$");
+  static void _getLibraryCompletionsHelper(
+      LibraryMirror library, bool includePrivate, Set<String> output) {
+    library.declarations.forEach((symbol, declaration) {
+      if (!includePrivate && declaration.isPrivate) return;
+      output.add(_getShortSymbolName(symbol, declaration));
+    });
+  }
 
-  static _decodeKey(Map map, String key) {
-    // The key is a regular old String.
-    if (key.startsWith(':')) return key.substring(1);
+  static LibraryMirror getLibraryMirror(String url) =>
+      currentMirrorSystem().libraries[Uri.parse(url)];
 
-    var match = _NON_STRING_KEY_REGEXP.firstMatch(key);
-    if (match != null) {
-      int index = int.parse(match.group(1));
-      var iter = map.keys.skip(index);
-      if (iter.isNotEmpty) {
-        var ret = iter.first;
-        // Validate that the toString representation of the key matches what we
-        // expect. FIXME: throw an error if it does not.
-        assert(match.group(2) == '$ret');
-        return ret;
+  /**
+   * Get code completions for [o] only showing privates from [libraryUrl].
+   */
+  static List<String> getObjectCompletions(o, String libraryUrl) {
+    var classMirror;
+    bool staticContext;
+    if (o is Type) {
+      classMirror = reflectClass(o);
+      staticContext = true;
+    } else {
+      classMirror = reflect(o).type;
+      staticContext = false;
+    }
+    var names = new Set<String>();
+    getClassCompletions(classMirror, names, staticContext, libraryUrl);
+    return names.toList()..sort();
+  }
+
+  static void getClassCompletions(ClassMirror classMirror, Set<String> names,
+      bool staticContext, String libraryUrl) {
+    LibraryMirror libraryMirror = getLibraryMirror(libraryUrl);
+    _getCompletionsHelper(classMirror, staticContext, libraryMirror, names);
+  }
+
+  static List<String> getLibraryCompletions(String url) {
+    var names = new Set<String>();
+    _getLibraryCompletionsHelper(getLibraryMirror(url), true, names);
+    return names.toList();
+  }
+
+  /**
+   * Get valid code completitions from within a library and all libraries
+   * imported by that library.
+   */
+  static List<String> getLibraryCompletionsIncludingImports(String url) {
+    var names = new Set<String>();
+    var libraryMirror = getLibraryMirror(url);
+    _getLibraryCompletionsHelper(libraryMirror, true, names);
+    for (var dependency in libraryMirror.libraryDependencies) {
+      if (dependency.isImport) {
+        if (dependency.prefix == null) {
+          _getLibraryCompletionsHelper(dependency.targetLibrary, false, names);
+        } else {
+          names.add(MirrorSystem.getName(dependency.prefix));
+        }
       }
     }
+    return names.toList();
+  }
+
+  static final SIDE_EFFECT_FREE_LIBRARIES = new Set<String>()
+      ..add('dart:html')
+      ..add('dart:indexed_db')
+      ..add('dart:svg')
+      ..add('dart:typed_data')
+      ..add('dart:web_audio')
+      ..add('dart:web_gl')
+      ..add('dart:web_sql');
+
+  static LibraryMirror _getLibrary(MethodMirror methodMirror) {
+    var owner = methodMirror.owner;
+    if (owner is ClassMirror) {
+      return owner;
+    } else if (owner is LibraryMirror) {
+      return owner;
+    }
     return null;
   }
 
   /**
-   * Converts keys encoded with [getEncodedMapKeyList] to their actual keys.
+   * For parity with the JavaScript debugger, we treat some getters as if
+   * they are fields so that users can see their values immediately.
+   * This matches JavaScript's behavior for getters on DOM objects.
+   * In the future we should consider adding an annotation to tag getters
+   * in user libraries as side effect free.
    */
-  static lookupValueForEncodedMapKey(Map obj, String key) => obj[_decodeKey(obj, key)];
-
+  static bool _isSideEffectFreeGetter(MethodMirror methodMirror,
+      LibraryMirror libraryMirror) {
+    // This matches JavaScript behavior. We should consider displaying
+    // getters for all dart platform libraries rather than just the DOM
+    // libraries.
+    return libraryMirror.uri.scheme == 'dart' &&
+        SIDE_EFFECT_FREE_LIBRARIES.contains(libraryMirror.uri.toString());
+  }
+  
   /**
-   * Builds a constructor name with the form expected by the C Dart mirrors API.
+   * Whether we should treat a property as a field for the purposes of the
+   * debugger.
    */
-  static String buildConstructorName(String className, String constructorName) => '$className.$constructorName';
+  static bool treatPropertyAsField(MethodMirror methodMirror,
+      LibraryMirror libraryMirror) {
+    return (methodMirror.isGetter || methodMirror.isSetter) &&
+          (methodMirror.isSynthetic ||
+              _isSideEffectFreeGetter(methodMirror,libraryMirror));
+  }
 
-  /**
-   * Strips the class name from an expression of the form "className.someName".
-   */
-  static String stripClassName(String str, String className) {
-    if (str.length > className.length + 1 &&
-        str.startsWith(className) && str[className.length] == '.') {
-      return str.substring(className.length + 1);
-    } else {
-      return str;
+  // TODO(jacobr): generate more concise function descriptions instead of
+  // dumping the entire function source.
+  static String describeFunction(function) {
+    if (function is _Trampoline) return function._methodMirror.source;
+    try {
+      var mirror = reflect(function);
+      return mirror.function.source;
+    } catch (e) {
+      return function.toString();
+    }
+  }
+
+  static List getInvocationTrampolineDetails(_Trampoline method) {
+    var loc = method._methodMirror.location;
+    return [loc.line, loc.column, loc.sourceUri.toString(),
+        MirrorSystem.getName(method._selector)];
+  }
+
+  static List getLibraryProperties(String libraryUrl, bool ownProperties,
+      bool accessorPropertiesOnly) {
+    var properties = new Map<String, _Property>();
+    var libraryMirror = getLibraryMirror(libraryUrl);
+    _addInstanceMirrors(libraryMirror, libraryMirror,
+        libraryMirror.declarations,
+        ownProperties, accessorPropertiesOnly, false, false,
+        properties);
+    if (!accessorPropertiesOnly) {
+      // We need to add class properties for all classes in the library.
+      libraryMirror.declarations.forEach((symbol, declarationMirror) {
+        if (declarationMirror is ClassMirror) {
+          var name = MirrorSystem.getName(symbol);
+          if (declarationMirror.hasReflectedType
+              && !properties.containsKey(name)) {
+            properties[name] = new _Property(name)
+                ..value = declarationMirror.reflectedType;
+          }
+        }
+      });
+    }
+    return packageProperties(properties);
+  }
+
+  static List getObjectProperties(o, bool ownProperties,
+      bool accessorPropertiesOnly) {
+    var properties = new Map<String, _Property>();
+    var names = new Set<String>();
+    var objectMirror = reflect(o);
+    var classMirror = objectMirror.type;
+    _addInstanceMirrors(objectMirror, classMirror.owner,
+        classMirror.instanceMembers,
+        ownProperties, accessorPropertiesOnly, false, true,
+        properties);
+    return packageProperties(properties);
+  }
+
+  static List getObjectClassProperties(o, bool ownProperties,
+      bool accessorPropertiesOnly) {
+    var properties = new Map<String, _Property>();
+    var objectMirror = reflect(o);
+    var classMirror = objectMirror.type;
+    _addInstanceMirrors(objectMirror, classMirror.owner,
+        classMirror.instanceMembers,
+        ownProperties, accessorPropertiesOnly, true, false,
+        properties);
+    _addStatics(classMirror, properties, accessorPropertiesOnly);
+    return packageProperties(properties);
+  }
+
+  static List getClassProperties(Type t, bool ownProperties,
+      bool accessorPropertiesOnly) {
+    var properties = new Map<String, _Property>();
+    var classMirror = reflectClass(t);
+    _addStatics(classMirror, properties, accessorPropertiesOnly);
+    return packageProperties(properties);
+  }
+
+  static void _addStatics(ClassMirror classMirror,
+                          Map<String, _Property> properties,
+                          bool accessorPropertiesOnly) {
+    var libraryMirror = classMirror.owner;
+    classMirror.declarations.forEach((symbol, declaration) {
+      var name = _getShortSymbolName(symbol, declaration);
+      if (name.isEmpty) return;
+      if (declaration is VariableMirror) {
+        if (accessorPropertiesOnly) return;
+        if (!declaration.isStatic) return;
+        properties.putIfAbsent(name, () => new _Property(name))
+            ..value = classMirror.getField(symbol).reflectee
+            ..writable = !declaration.isFinal && !declaration.isConst;
+      } else if (declaration is MethodMirror) {
+        MethodMirror methodMirror = declaration;
+        // FIXMEDART: should we display constructors?
+        if (methodMirror.isConstructor) return;
+        if (!methodMirror.isStatic) return;
+        if (accessorPropertiesOnly) {
+          if (methodMirror.isRegularMethod ||
+              treatPropertyAsField(methodMirror, libraryMirror)) {
+            return;
+          }
+        } else if (!methodMirror.isRegularMethod &&
+            !treatPropertyAsField(methodMirror, libraryMirror)) {
+          return;
+        }
+        var property = properties.putIfAbsent(name, () => new _Property(name));
+        _fillMethodMirrorProperty(libraryMirror, classMirror, methodMirror,
+            symbol, accessorPropertiesOnly, property);
+      }
+    });
+  }
+
+  static void _fillMethodMirrorProperty(LibraryMirror libraryMirror,
+        methodOwner, MethodMirror methodMirror, Symbol symbol,
+        bool accessorPropertiesOnly, _Property property) {
+    if (methodMirror.isRegularMethod) {
+      property
+          ..value = new _MethodTrampoline(methodOwner, methodMirror, symbol)
+          ..isMethod = true;
+    } else if (methodMirror.isGetter) {
+      if (treatPropertyAsField(methodMirror, libraryMirror)) {
+        try {
+          property.value = methodOwner.getField(symbol).reflectee;
+        } catch (e) {
+          property
+              ..wasThrown = true
+              ..value = e;
+        }
+      } else if (accessorPropertiesOnly) {
+        property.getter = new _GetterTrampoline(methodOwner,
+            methodMirror, symbol);
+      }
+    } else if (methodMirror.isSetter) {
+      if (accessorPropertiesOnly &&
+          !treatPropertyAsField(methodMirror, libraryMirror)) {
+        property.setter = new _SetterTrampoline(methodOwner,
+            methodMirror, MirrorSystem.getSymbol(property.name, libraryMirror));
+      }
+      property.writable = true;
     }
   }
 
   /**
-   * Removes the trailing dot from an expression ending in a dot.
-   * This method is used as Library prefixes include a trailing dot when using
-   * the C Dart debugger API.
+   * Helper method that handles collecting up properties from classes
+   * or libraries using the filters [ownProperties], [accessorPropertiesOnly],
+   * [hideFields], and [hideMethods] to determine which properties are
+   * collected. [accessorPropertiesOnly] specifies whether all properties
+   * should be returned or just accessors. [hideFields] specifies whether
+   * fields should be hidden. hideMethods specifies whether methods should be
+   * shown or hidden. [ownProperties] is not currently used but is part of the
+   * Blink devtools API for enumerating properties.
    */
-  static String stripTrailingDot(String str) =>
-    (str != null && str[str.length - 1] == '.') ? str.substring(0, str.length - 1) : str;
-
-  static String addTrailingDot(String str) => '${str}.';
-
-  static String demangle(String str) {
-    var atPos = str.indexOf('@');
-    return atPos == -1 ? str : str.substring(0, atPos);
+  static void _addInstanceMirrors(
+      ObjectMirror objectMirror,
+      LibraryMirror libraryMirror,
+      Map<Symbol, Mirror> declarations,
+      bool ownProperties, bool accessorPropertiesOnly,
+      bool hideFields, bool hideMethods,
+      Map<String, _Property> properties) {
+    declarations.forEach((symbol, declaration) {
+      if (declaration is TypedefMirror || declaration is ClassMirror) return;
+      var name = _getShortSymbolName(symbol, declaration);
+      if (name.isEmpty) return;
+      bool isField = declaration is VariableMirror ||
+          (declaration is MethodMirror &&
+              treatPropertyAsField(declaration, libraryMirror));
+      if ((isField && hideFields) || (hideMethods && !isField)) return;
+      if (accessorPropertiesOnly) {
+        if (declaration is VariableMirror || declaration.isRegularMethod ||
+            isField) {
+          return;
+        }
+      } else if (declaration is MethodMirror &&
+          (declaration.isGetter || declaration.isSetter) &&
+          !treatPropertyAsField(declaration, libraryMirror)) {
+        return;
+      }
+      var property = properties.putIfAbsent(name, () => new _Property(name));
+      if (declaration is VariableMirror) {
+        property
+            ..value = objectMirror.getField(symbol).reflectee
+            ..writable = !declaration.isFinal && !declaration.isConst;
+        return;
+      }
+      _fillMethodMirrorProperty(libraryMirror, objectMirror, declaration,
+          symbol, accessorPropertiesOnly, property);
+    });
   }
 
+  /**
+   * Flatten down the properties data structure into a List that is easy to
+   * access from native code.
+   */
+  static List packageProperties(Map<String, _Property> properties) {
+    var ret = [];
+    for (var property in properties.values) {
+      ret.addAll([property.name,
+                  property.setter,
+                  property.getter,
+                  property.value,
+                  property.hasValue,
+                  property.writable,
+                  property.isMethod,
+                  property.isOwn,
+                  property.wasThrown]);
+    }
+    return ret;
+  }
+  
+  /**
+   * Get a property, returning null if the property does not exist.
+   * For private property names, we attempt to resolve the property in the
+   * context of each library that the property name could be associated with.
+   */
+  static getObjectPropertySafe(o, String propertyName) {
+    var objectMirror = reflect(o);
+    var classMirror = objectMirror.type;
+    if (propertyName.startsWith("_")) {
+      var attemptedLibraries = new Set<LibraryMirror>(); 
+      while (classMirror != null) {
+        LibraryMirror library = classMirror.owner;
+        if (!attemptedLibraries.contains(library)) {
+          try {
+            return objectMirror.getField(
+                MirrorSystem.getSymbol(propertyName, library)).reflectee;
+          } catch (e) { }
+          attemptedLibraries.add(library);
+        }
+        classMirror = classMirror.superclass;
+      }
+      return null;     
+    }
+    try {
+      return objectMirror.getField(
+          MirrorSystem.getSymbol(propertyName)).reflectee;
+    } catch (e) {
+      return null;
+    }
+  }
+
+  /**
+   * Helper to wrap the inspect method on InjectedScriptHost to provide the
+   * inspect method required for the 
+   */
+  static List consoleApi(host) {
+    return [
+        "inspect",
+        (o) {
+          host.inspect(o, null);
+          return o;
+        },
+        "dir",
+        window().console.dir,
+        "dirxml",
+        window().console.dirxml
+        // FIXME: add copy method.
+        ];
+  }
+
+  static List getMapKeyList(Map map) => map.keys.toList();
+
   static bool isNoSuchMethodError(obj) => obj is NoSuchMethodError;
 
   static void register(Document document, String tag, Type type,
@@ -37888,7 +38292,7 @@
   static void initializeCustomElement(HtmlElement element) =>
     _blink.Native_Utils_initializeCustomElement(element);
 
-  static void changeElementWrapper(HtmlElement element, Type type) =>
+  static Element changeElementWrapper(HtmlElement element, Type type) =>
     _blink.Native_Utils_changeElementWrapper(element, type);
 }
 
@@ -37971,7 +38375,7 @@
   }
 }
 
-final _printClosure = window.console.log;
+final _printClosure = (s) => window.console.log(s);
 final _pureIsolatePrintClosure = (s) {
   throw new UnimplementedError("Printing from a background isolate "
                                "is not supported in the browser");
diff --git a/sdk/lib/io/http.dart b/sdk/lib/io/http.dart
index 21b177d..b995137b 100644
--- a/sdk/lib/io/http.dart
+++ b/sdk/lib/io/http.dart
@@ -1225,6 +1225,18 @@
   Duration idleTimeout;
 
   /**
+   * Get and set the maximum number of live connections, to a single host.
+   *
+   * Increasing this number may lower performance and take up unwanted
+   * system resources.
+   *
+   * To disable, set to `null`.
+   *
+   * Default is `null`.
+   */
+  int maxConnectionsPerHost;
+
+  /**
    * Set and get the default value of the `User-Agent` header for all requests
    * generated by this [HttpClient]. The default value is
    * `Dart/<version> (dart:io)`.
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index 2af9f6c..5d1d535 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -262,6 +262,13 @@
                                        {Function onError,
                                         void onDone(),
                                         bool cancelOnError}) {
+    if (_incoming.upgraded) {
+      // If upgraded, the connection is already 'removed' form the client.
+      // Since listening to upgraded data is 'bogus', simply close and
+      // return empty stream subscription.
+      _httpRequest._httpClientConnection.destroy();
+      return new Stream.fromIterable([]).listen(null, onDone: onDone);
+    }
     var stream = _incoming;
     if (headers.value(HttpHeaders.CONTENT_ENCODING) == "gzip") {
       stream = stream.transform(GZIP.decoder);
@@ -1359,6 +1366,11 @@
               .then((incoming) {
                 _currentUri = null;
                 incoming.dataDone.then((closing) {
+                  if (incoming.upgraded) {
+                    _httpClient._connectionClosed(this);
+                    startTimer();
+                    return;
+                  }
                   if (closed) return;
                   if (!closing &&
                       !_dispose &&
@@ -1494,27 +1506,32 @@
   }
 }
 
-class _ConnnectionInfo {
+class _ConnectionInfo {
   final _HttpClientConnection connection;
   final _Proxy proxy;
 
-  _ConnnectionInfo(this.connection, this.proxy);
+  _ConnectionInfo(this.connection, this.proxy);
 }
 
 
 class _ConnectionTarget {
   // Unique key for this connection target.
   final String key;
+  final String host;
+  final int port;
+  final bool isSecure;
   final Set<_HttpClientConnection> _idle = new HashSet();
   final Set<_HttpClientConnection> _active = new HashSet();
+  final Queue _pending = new ListQueue();
+  int _connecting = 0;
 
-  _ConnectionTarget(this.key);
+  _ConnectionTarget(this.key, this.host, this.port, this.isSecure);
 
-  bool get isEmpty => _idle.isEmpty && _active.isEmpty;
+  bool get isEmpty => _idle.isEmpty && _active.isEmpty && _connecting == 0;
 
   bool get hasIdle => _idle.isNotEmpty;
 
-  bool get hasActive => _active.isNotEmpty;
+  bool get hasActive => _active.isNotEmpty || _connecting > 0;
 
   _HttpClientConnection takeIdle() {
     assert(hasIdle);
@@ -1525,6 +1542,12 @@
     return connection;
   }
 
+  _checkPending() {
+    if (_pending.isNotEmpty) {
+      _pending.removeFirst()();
+    }
+  }
+
   void addNewActive(_HttpClientConnection connection) {
     _active.add(connection);
   }
@@ -1533,12 +1556,15 @@
     assert(_active.contains(connection));
     _active.remove(connection);
     _idle.add(connection);
+    connection.startTimer();
+    _checkPending();
   }
 
   void connectionClosed(_HttpClientConnection connection) {
     assert(!_active.contains(connection) || !_idle.contains(connection));
     _active.remove(connection);
     _idle.remove(connection);
+    _checkPending();
   }
 
   void close(bool force) {
@@ -1551,6 +1577,58 @@
       }
     }
   }
+
+  Future<_ConnectionInfo> connect(String uriHost,
+                                   int uriPort,
+                                   _Proxy proxy,
+                                   _HttpClient client) {
+    if (hasIdle) {
+      var connection = takeIdle();
+      client._updateTimers();
+      return new Future.value(new _ConnectionInfo(connection, proxy));
+    }
+    if (client.maxConnectionsPerHost != null &&
+        _active.length + _connecting >= client.maxConnectionsPerHost) {
+      var completer = new Completer();
+      _pending.add(() {
+        connect(uriHost, uriPort, proxy, client)
+            .then(completer.complete, onError: completer.completeError);
+      });
+      return completer.future;
+    }
+    var currentBadCertificateCallback = client._badCertificateCallback;
+    bool callback(X509Certificate certificate) =>
+        currentBadCertificateCallback == null ? false :
+        currentBadCertificateCallback(certificate, uriHost, uriPort);
+    Future socketFuture = (isSecure && proxy.isDirect
+        ? SecureSocket.connect(host,
+                               port,
+                               sendClientCertificate: true,
+                               onBadCertificate: callback)
+        : Socket.connect(host, port));
+    _connecting++;
+    return socketFuture.then((socket) {
+        _connecting--;
+        socket.setOption(SocketOption.TCP_NODELAY, true);
+        var connection = new _HttpClientConnection(key, socket, client);
+        if (isSecure && !proxy.isDirect) {
+          connection._dispose = true;
+          return connection.createProxyTunnel(uriHost, uriPort, proxy, callback)
+              .then((tunnel) {
+                client._getConnectionTarget(uriHost, uriPort, true)
+                    .addNewActive(tunnel);
+                return new _ConnectionInfo(tunnel, proxy);
+              });
+        } else {
+          addNewActive(connection);
+          return new _ConnectionInfo(connection, proxy);
+        }
+      }, onError: (error) {
+        _connecting--;
+        _checkPending();
+        throw error;
+      });
+  }
 }
 
 
@@ -1570,6 +1648,8 @@
 
   Duration get idleTimeout => _idleTimeout;
 
+  int maxConnectionsPerHost;
+
   String userAgent = _getHttpVersion();
 
   void set idleTimeout(Duration timeout) {
@@ -1638,7 +1718,8 @@
     _closing = true;
     _connectionTargets.values.toList().forEach((c) => c.close(force));
     assert(!_connectionTargets.values.any((s) => s.hasIdle));
-    assert(!force || _connectionTargets.isEmpty);
+    assert(!force ||
+        !_connectionTargets.values.any((s) => s._active.isNotEmpty));
   }
 
   set authenticate(Future<bool> f(Uri url, String scheme, String realm)) {
@@ -1738,7 +1819,6 @@
   // Return a live connection to the idle pool.
   void _returnConnection(_HttpClientConnection connection) {
     _connectionTargets[connection.key].returnConnection(connection);
-    connection.startTimer();
     _updateTimers();
   }
 
@@ -1776,60 +1856,28 @@
     }
   }
 
-  // Get a new _HttpClientConnection, either from the idle pool or created from
-  // a new Socket.
-  Future<_ConnnectionInfo> _getConnection(String uriHost,
+  _ConnectionTarget _getConnectionTarget(String host, int port, bool isSecure) {
+    String key = _HttpClientConnection.makeKey(isSecure, host, port);
+    return _connectionTargets.putIfAbsent(
+        key, () => new _ConnectionTarget(key, host, port, isSecure));
+  }
+
+  // Get a new _HttpClientConnection, from the matching _ConnectionTarget.
+  Future<_ConnectionInfo> _getConnection(String uriHost,
                                           int uriPort,
                                           _ProxyConfiguration proxyConf,
                                           bool isSecure) {
     Iterator<_Proxy> proxies = proxyConf.proxies.iterator;
 
-    Future<_ConnnectionInfo> connect(error) {
+    Future<_ConnectionInfo> connect(error) {
       if (!proxies.moveNext()) return new Future.error(error);
       _Proxy proxy = proxies.current;
       String host = proxy.isDirect ? uriHost: proxy.host;
       int port = proxy.isDirect ? uriPort: proxy.port;
-      String key = _HttpClientConnection.makeKey(isSecure, host, port);
-      var connectionTarget = _connectionTargets[key];
-      if (connectionTarget != null && connectionTarget.hasIdle) {
-        var connection = connectionTarget.takeIdle();
-        _updateTimers();
-        return new Future.value(new _ConnnectionInfo(connection, proxy));
-      }
-      var currentBadCertificateCallback = _badCertificateCallback;
-      bool callback(X509Certificate certificate) =>
-          currentBadCertificateCallback == null ? false :
-          currentBadCertificateCallback(certificate, uriHost, uriPort);
-      Future socketFuture = (isSecure && proxy.isDirect
-          ? SecureSocket.connect(host,
-                                 port,
-                                 sendClientCertificate: true,
-                                 onBadCertificate: callback)
-          : Socket.connect(host, port));
-      return socketFuture.then((socket) {
-          socket.setOption(SocketOption.TCP_NODELAY, true);
-          var connection = new _HttpClientConnection(key, socket, this);
-          if (isSecure && !proxy.isDirect) {
-            connection._dispose = true;
-            return connection.createProxyTunnel(
-                uriHost, uriPort, proxy, callback)
-                .then((tunnel) {
-                  var connectionTarget = _connectionTargets
-                      .putIfAbsent(tunnel.key,
-                                   () => new _ConnectionTarget(tunnel.key));
-                  connectionTarget.addNewActive(tunnel);
-                  return new _ConnnectionInfo(tunnel, proxy);
-                });
-          } else {
-            var connectionTarget = _connectionTargets
-                .putIfAbsent(key, () => new _ConnectionTarget(key));
-            connectionTarget.addNewActive(connection);
-            return new _ConnnectionInfo(connection, proxy);
-          }
-        }, onError: (error) {
-          // Continue with next proxy.
-          return connect(error);
-        });
+      return _getConnectionTarget(host, port, isSecure)
+          .connect(uriHost, uriPort, proxy, this)
+          // On error, continue with next proxy.
+          .catchError(connect);
     }
     return connect(new HttpException("No proxies given"));
   }
diff --git a/sdk/lib/io/io.dart b/sdk/lib/io/io.dart
index 4cd9e3c..4a9300a 100644
--- a/sdk/lib/io/io.dart
+++ b/sdk/lib/io/io.dart
@@ -200,6 +200,8 @@
 import 'dart:_internal';
 import 'dart:collection' show HashMap,
                               HashSet,
+                              Queue,
+                              ListQueue,
                               LinkedList,
                               LinkedListEntry,
                               UnmodifiableMapView;
diff --git a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
index f9ff6005..a94c162 100644
--- a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
+++ b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
@@ -2234,7 +2234,7 @@
   /**
    * Buffers the specified data.
    *
-   * This specific method is provided for WebGL API compatibility reasons, but
+   * The [bufferData] method is provided for WebGL API compatibility reasons, but
    * it is highly recommended that you use [bufferDataTyped] or [bufferByteData]
    * depending on your purposes.
    */
@@ -2245,7 +2245,7 @@
   /**
    * Buffers the specified data.
    *
-   * This specific method is provided for WebGL API compatibility reasons, but
+   * The [bufferData] method is provided for WebGL API compatibility reasons, but
    * it is highly recommended that you use [bufferDataTyped] or [bufferByteData]
    * depending on your purposes.
    */
@@ -2257,7 +2257,7 @@
   /**
    * Buffers the specified data.
    *
-   * This specific method is provided for WebGL API compatibility reasons, but
+   * The [bufferData] method is provided for WebGL API compatibility reasons, but
    * it is highly recommended that you use [bufferDataTyped] or [bufferByteData]
    * depending on your purposes.
    */
@@ -2269,7 +2269,7 @@
   /**
    * Buffers the specified subset of data.
    *
-   * This specific method is provided for WebGL API compatibility reasons, but
+   * The [bufferSubData] method is provided for WebGL API compatibility reasons, but
    * it is highly recommended that you use [bufferSubDataTyped] or [bufferSubByteData]
    * depending on your purposes.
    */
@@ -2280,7 +2280,7 @@
   /**
    * Buffers the specified subset of data.
    *
-   * This specific method is provided for WebGL API compatibility reasons, but
+   * The [bufferSubData] method is provided for WebGL API compatibility reasons, but
    * it is highly recommended that you use [bufferSubDataTyped] or [bufferSubByteData]
    * depending on your purposes.
    */
@@ -2292,7 +2292,7 @@
   /**
    * Buffers the specified subset of data.
    *
-   * This specific method is provided for WebGL API compatibility reasons, but
+   * The [bufferSubData] method is provided for WebGL API compatibility reasons, but
    * it is highly recommended that you use [bufferSubDataTyped] or [bufferSubByteData]
    * depending on your purposes.
    */
@@ -2677,7 +2677,7 @@
   /**
    * Updates the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
    * (or for more specificity, the more specialized [texImage2DImageData],
    * [texImage2DCanvas], [texImage2DVideo]).
@@ -2712,7 +2712,7 @@
   /**
    * Updates the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
    * (or for more specificity, the more specialized [texImage2DImageData],
    * [texImage2DCanvas], [texImage2DVideo]).
@@ -2724,7 +2724,7 @@
   /**
    * Updates the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
    * (or for more specificity, the more specialized [texImage2DImageData],
    * [texImage2DCanvas], [texImage2DVideo]).
@@ -2736,7 +2736,7 @@
   /**
    * Updates the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
    * (or for more specificity, the more specialized [texImage2DImageData],
    * [texImage2DCanvas], [texImage2DVideo]).
@@ -2748,7 +2748,7 @@
   /**
    * Updates the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
    * (or for more specificity, the more specialized [texImage2DImageData],
    * [texImage2DCanvas], [texImage2DVideo]).
@@ -2760,7 +2760,7 @@
   /**
    * Updates the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
    * (or for more specificity, the more specialized [texImage2DImageData],
    * [texImage2DCanvas], [texImage2DVideo]).
@@ -2773,7 +2773,7 @@
   /**
    * Updates the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
    * (or for more specificity, the more specialized [texImage2DImageData],
    * [texImage2DCanvas], [texImage2DVideo]).
@@ -2786,7 +2786,7 @@
   /**
    * Updates the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
    * (or for more specificity, the more specialized [texImage2DImageData],
    * [texImage2DCanvas], [texImage2DVideo]).
@@ -2798,7 +2798,7 @@
   /**
    * Updates the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
    * (or for more specificity, the more specialized [texImage2DImageData],
    * [texImage2DCanvas], [texImage2DVideo]).
@@ -2814,7 +2814,7 @@
   /**
    * Updates the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
    * (or for more specificity, the more specialized [texImage2DImageData],
    * [texImage2DCanvas], [texImage2DVideo]).
@@ -2827,7 +2827,7 @@
   /**
    * Updates the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]
    * (or for more specificity, the more specialized [texImage2DImageData],
    * [texImage2DCanvas], [texImage2DVideo]).
@@ -2847,7 +2847,7 @@
   /**
    * Updates a sub-rectangle of the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texSubImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
    * (or for more specificity, the more specialized [texSubImage2DImageData],
    * [texSubImage2DCanvas], [texSubImage2DVideo]).
@@ -2882,7 +2882,7 @@
   /**
    * Updates a sub-rectangle of the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texSubImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
    * (or for more specificity, the more specialized [texSubImage2DImageData],
    * [texSubImage2DCanvas], [texSubImage2DVideo]).
@@ -2894,7 +2894,7 @@
   /**
    * Updates a sub-rectangle of the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texSubImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
    * (or for more specificity, the more specialized [texSubImage2DImageData],
    * [texSubImage2DCanvas], [texSubImage2DVideo]).
@@ -2906,7 +2906,7 @@
   /**
    * Updates a sub-rectangle of the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texSubImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
    * (or for more specificity, the more specialized [texSubImage2DImageData],
    * [texSubImage2DCanvas], [texSubImage2DVideo]).
@@ -2918,7 +2918,7 @@
   /**
    * Updates a sub-rectangle of the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texSubImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
    * (or for more specificity, the more specialized [texSubImage2DImageData],
    * [texSubImage2DCanvas], [texSubImage2DVideo]).
@@ -2930,7 +2930,7 @@
   /**
    * Updates a sub-rectangle of the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texSubImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
    * (or for more specificity, the more specialized [texSubImage2DImageData],
    * [texSubImage2DCanvas], [texSubImage2DVideo]).
@@ -2943,7 +2943,7 @@
   /**
    * Updates a sub-rectangle of the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texSubImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
    * (or for more specificity, the more specialized [texSubImage2DImageData],
    * [texSubImage2DCanvas], [texSubImage2DVideo]).
@@ -2956,7 +2956,7 @@
   /**
    * Updates a sub-rectangle of the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texSubImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
    * (or for more specificity, the more specialized [texSubImage2DImageData],
    * [texSubImage2DCanvas], [texSubImage2DVideo]).
@@ -2968,7 +2968,7 @@
   /**
    * Updates a sub-rectangle of the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texSubImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
    * (or for more specificity, the more specialized [texSubImage2DImageData],
    * [texSubImage2DCanvas], [texSubImage2DVideo]).
@@ -2984,7 +2984,7 @@
   /**
    * Updates a sub-rectangle of the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texSubImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
    * (or for more specificity, the more specialized [texSubImage2DImageData],
    * [texSubImage2DCanvas], [texSubImage2DVideo]).
@@ -2997,7 +2997,7 @@
   /**
    * Updates a sub-rectangle of the currently bound texture to [data].
    *
-   * This specific method is provided for WebGL API compatibility reasons, but it
+   * The [texSubImage2D] method is provided for WebGL API compatibility reasons, but it
    * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]
    * (or for more specificity, the more specialized [texSubImage2DImageData],
    * [texSubImage2DCanvas], [texSubImage2DVideo]).
diff --git a/tests/co19/co19-dartium.status b/tests/co19/co19-dartium.status
index 1a1c9a2..49bbb13 100644
--- a/tests/co19/co19-dartium.status
+++ b/tests/co19/co19-dartium.status
@@ -391,3 +391,4 @@
 
 [ $compiler == none && $runtime == ContentShellOnAndroid ]
 LibTest/math/log_A01_t01: Pass, Fail # co19 issue 44.
+LibTest/html/Element/getBoundingClientRect_A01_t02: RuntimeError # Issue 19127.
diff --git a/tests/compiler/dart2js/members_test.dart b/tests/compiler/dart2js/members_test.dart
index 6d697a9..6b1679c 100644
--- a/tests/compiler/dart2js/members_test.dart
+++ b/tests/compiler/dart2js/members_test.dart
@@ -188,7 +188,7 @@
     InterfaceType String_ = env['String'];
     InterfaceType num_ = env['num'];
     InterfaceType int_ = env['int'];
-    InterfaceType dynamic_ = env['dynamic'];
+    DynamicType dynamic_ = env['dynamic'];
     VoidType void_ = env['void'];
     InterfaceType Type_ = env['Type'];
     InterfaceType Invocation_ = env['Invocation'];
@@ -400,7 +400,7 @@
     abstract class D implements A, B, C {}
     """).then((env) {
 
-    InterfaceType dynamic_ = env['dynamic'];
+    DynamicType dynamic_ = env['dynamic'];
     VoidType void_ = env['void'];
     InterfaceType num_ = env['num'];
     InterfaceType int_ = env['int'];
@@ -566,7 +566,7 @@
     abstract class C extends A implements B {}
     """).then((env) {
 
-    InterfaceType dynamic_ = env['dynamic'];
+    DynamicType dynamic_ = env['dynamic'];
     VoidType void_ = env['void'];
     InterfaceType num_ = env['num'];
     InterfaceType int_ = env['int'];
@@ -619,7 +619,7 @@
     abstract class C<U, V> extends Object with A<U> implements B<V> {}
     """).then((env) {
 
-    InterfaceType dynamic_ = env['dynamic'];
+    DynamicType dynamic_ = env['dynamic'];
     VoidType void_ = env['void'];
     InterfaceType num_ = env['num'];
     InterfaceType int_ = env['int'];
diff --git a/tests/compiler/dart2js/type_test_helper.dart b/tests/compiler/dart2js/type_test_helper.dart
index daeae99..dd7c322 100644
--- a/tests/compiler/dart2js/type_test_helper.dart
+++ b/tests/compiler/dart2js/type_test_helper.dart
@@ -93,7 +93,7 @@
   }
 
   DartType operator[] (String name) {
-    if (name == 'dynamic') return compiler.types.dynamicType;
+    if (name == 'dynamic') return const DynamicType();
     if (name == 'void') return const VoidType();
     return getElementType(name);
   }
diff --git a/tests/html/cssstyledeclaration_test.dart b/tests/html/cssstyledeclaration_test.dart
index 38bdbf3..f506c5c 100644
--- a/tests/html/cssstyledeclaration_test.dart
+++ b/tests/html/cssstyledeclaration_test.dart
@@ -55,6 +55,10 @@
     style.border = "1px solid blue";
     style.border = "";
     expect(style.border, equals(""));
+
+    style.border = "1px solid blue";
+    style.border = null;
+    expect(style.border, equals(""));
   });
 
   test('CSS property getters and setters', () {
diff --git a/tests/html/custom/template_wrappers_test.dart b/tests/html/custom/template_wrappers_test.dart
deleted file mode 100644
index 0828c97..0000000
--- a/tests/html/custom/template_wrappers_test.dart
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library template_wrappers_test;
-
-import 'dart:async';
-import 'dart:html';
-import 'dart:js' as js;
-import 'package:unittest/html_config.dart';
-import 'package:unittest/unittest.dart';
-import '../utils.dart';
-
-int createdCount = 0;
-
-class CustomElement extends HtmlElement {
-  CustomElement.created() : super.created() {
-    ++createdCount;
-  }
-
-  void checkCreated() {
-  }
-}
-
-main() {
-  useHtmlConfiguration();
-
-  setUp(() => customElementsReady);
-
-  test('element is upgraded once', () {
-
-    expect(createdCount, 0);
-    document.registerElement('x-custom', CustomElement);
-    expect(createdCount, 0);
-
-    var element = document.createElement('x-custom');
-    expect(createdCount, 1);
-
-    forceGC();
-
-    return new Future.delayed(new Duration(milliseconds: 50)).then((_) {
-      var t = document.querySelector('.t1');
-
-      var fragment = t.content;
-
-      fragment.querySelector('x-custom').attributes['foo'] = 'true';
-      expect(createdCount, 1);
-    });
-  });
-/*
-  test('old wrappers do not cause multiple upgrades', () {
-    createdCount = 0;
-    var d1 = document.querySelector('x-custom-two');
-    d1.attributes['foo'] = 'bar';
-    d1 = null;
-
-    document.registerElement('x-custom-two', CustomElement);
-
-    expect(createdCount, 1);
-
-    forceGC();
-
-    return new Future.delayed(new Duration(milliseconds: 50)).then((_) {
-      var d = document.querySelector('x-custom-two');
-      expect(createdCount, 1);
-    });
-  });
-*/
-}
-
-
-void forceGC() {
-  var N = 1000000;
-  var M = 100;
-  for (var i = 0; i < M; ++i) {
-    var l = new List(N);
-  }
-}
diff --git a/tests/html/custom/template_wrappers_test.html b/tests/html/custom/template_wrappers_test.html
deleted file mode 100644
index 1b22431..0000000
--- a/tests/html/custom/template_wrappers_test.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta http-equiv="X-UA-Compatible" content="IE=edge">
-  <meta name="dart.unittest" content="full-stack-traces">
-  <title> template_wrappers_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 template_wrappers_test </h1>
-  <template class='t1'>
-    <x-custom></x-custom>
-  </template>
-  <x-custom-two></x-custom-two>
-  <script type="text/javascript"
-      src="/root_dart/tools/testing/dart/test_controller.js"></script>
-  %TEST_SCRIPTS%
-</body>
-</html>
diff --git a/tests/html/html.status b/tests/html/html.status
index 6992f91..782d633 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -5,11 +5,8 @@
 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)
-[ $runtime == drt || $runtime == dartium ]
-custom/template_wrappers_test: Pass # Issue 16656 Override others
 
-[ $compiler == none && ($runtime == drt || $runtime == dartium) ]
+[ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 form_data_test/functional: Fail # Issue 18931 (Disabled for Chrome 35 roll)
 indexeddb_5_test: Fail # Issue 18931 (Disabled for Chrome 35 roll)
 custom/attribute_changed_callback_test/unsupported_on_polyfill: Fail # Issue 18931 (Disabled for Chrome 35 roll)
@@ -34,7 +31,7 @@
 [ $compiler == none && $runtime == dartium && $system == macos]
 canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Pass,Fail # Issue 11834
 
-[ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellInAndroid) ]
+[ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 # postMessage in dartium always transfers the typed array buffer, never a view
 postmessage_structured_test/typed_arrays: Fail
 xhr_test/json: Fail # Issue 13069
@@ -43,18 +40,21 @@
 isolates_test: Fail # Issue 13921
 custom/element_upgrade_test: Skip # Issue 17298
 
-[ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellInAndroid) && $mode == debug ]
+[ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) && $mode == debug ]
 websocket_test/websocket: Skip # Issue 17666
 canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Skip #Issue 17666
 
-[ $compiler == none && $runtime == ContentShellInAndroid ]
-element_offset_test/offset: Pass, Fail # Issue 13296
+[ $compiler == none && $runtime == ContentShellOnAndroid ]
+element_offset_test/offset: Pass, Fail # Issue 17550
+mouse_event_test: Skip # Times out. Issue 19127
+css_test/supportsPointConversions: Skip # Times out. Issue 19127
+canvasrenderingcontext2d_test/drawImage_video_element: RuntimeError # Issue 19127
+canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: RuntimeError # Issue 19127
 
 [ $compiler == none && $runtime == drt && $system == windows ]
 worker_test/functional: Pass, Crash # Issue 9929.
 touchevent_test/supported: Pass, Fail # Issue 17061
 
-
 [ $compiler == dart2js && $runtime == chromeOnAndroid ]
 crypto_test/functional: Pass, Slow # TODO(dart2js-team): Please triage this failure.
 input_element_test/supported_datetime-local: Pass, Slow # TODO(dart2js-team): Please triage this failure.
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index 08ba971..fae13ca 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -74,21 +74,18 @@
 unresolved_ports_test: Pass, Timeout # Issue 15610
 
 [ $compiler == none && $runtime == drt ]
-isolate_stress_test: Skip # Issue 14463
 spawn_uri_nested_vm_test: Skip # Issue 14463
 
 [ $jscl || $runtime == ie9 ]
 spawn_uri_multi_test/none: RuntimeError # http://dartbug.com/13544
 
-[ $compiler == none && $runtime == dartium ]
+[ $compiler == none && ($runtime == dartium || $runtime == ContentShellOnAndroid) ]
 spawn_uri_nested_vm_test: Skip # Issue 14479: This test is timing out.
 
-[ $compiler == none && $runtime == dartium ]
-isolate_stress_test: Skip # Issue 14463
-
-[ $compiler == none && ( $runtime == dartium || $runtime == drt ) ]
+[ $compiler == none && ( $runtime == dartium || $runtime == drt || $runtime == ContentShellOnAndroid) ]
 compile_time_error_test/none: Fail, OK # Issue 13921 Dom isolates don't support spawnFunction
 isolate_import_test/none: Fail, OK # Issue 13921 Dom isolates don't support spawnFunction
+isolate_stress_test: Skip # Issue 13921 Dom isolates don't support spawnFunction
 simple_message_test/none: Fail, OK # Issue 13921 Dom isolates don't support spawnFunction
 spawn_uri_missing_from_isolate_test: RuntimeError # http://dartbug.com/17649
 spawn_uri_missing_test: Skip # Times out.
diff --git a/tests/language/language.status b/tests/language/language.status
index 13e902c..0b9bc88 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -93,24 +93,24 @@
 [ $compiler == dart2js && $runtime == ie9 ]
 lazy_static3_test: Fail # Issue 13469
 
-[ $compiler == none && $runtime == dartium && $unchecked ]
+[ $compiler == none && ($runtime == dartium || $runtime == ContentShellOnAndroid) && $unchecked ]
+assertion_test: Fail # Issue 13719: Please triage this failure.
+generic_test: Fail # Issue 13719: Please triage this failure.
+list_literal4_test: Fail # Issue 13719: Please triage this failure.
+map_literal4_test: Fail # Issue 13719: Please triage this failure.
 named_parameters_type_test/01: Fail # Issue 13719: Please triage this failure.
 named_parameters_type_test/02: Fail # Issue 13719: Please triage this failure.
 named_parameters_type_test/03: Fail # Issue 13719: Please triage this failure.
 positional_parameters_type_test/01: Fail # Issue 13719: Please triage this failure.
 positional_parameters_type_test/02: Fail # Issue 13719: Please triage this failure.
-assertion_test: Fail # Issue 13719: Please triage this failure.
-generic_test: Fail # Issue 13719: Please triage this failure.
-list_literal4_test: Fail # Issue 13719: Please triage this failure.
-map_literal4_test: Fail # Issue 13719: Please triage this failure.
 type_checks_in_factory_method_test: Fail # Issue 13719: Please triage this failure.
 vm/type_vm_test: Fail # Issue 13719: Please triage this failure.
 
 [ $compiler == none && $runtime == dartium ]
 first_class_types_literals_test: Pass, Fail # Issue 13719: Please triage this failure.
-issue13474_test: Pass, Fail # Issue 14651.
 
-[ $compiler == none && ( $runtime == dartium || $runtime == drt ) ]
+[ $compiler == none && ( $runtime == dartium || $runtime == drt || $runtime == ContentShellOnAndroid) ]
+issue13474_test: Pass, Fail # Issue 14651.
 typed_message_test: Crash, Fail # Issue 13921, 14400
 vm/optimized_guarded_field_isolates_test: Fail # Issue 13921.
 
diff --git a/tests/language/switch_try_catch_test.dart b/tests/language/switch_try_catch_test.dart
new file mode 100644
index 0000000..d362a14
--- /dev/null
+++ b/tests/language/switch_try_catch_test.dart
@@ -0,0 +1,33 @@
+// 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.
+
+// Regression test for issue 18869: Check that try-catch is working correctly
+// inside switch-case clauses.
+
+
+import "package:expect/expect.dart";
+
+test_switch() {
+  switch(0) {
+    _0: case 0:
+      print("_0");
+      continue _5;
+    _1: case 1:
+      try {
+        print("bunny");
+        continue _6;
+      } catch(e) { }
+      break;
+    _5: case 5:
+      print("_5");
+      continue _6;
+    _6: case 6:
+      print("_6");
+     throw 555;
+  }
+}
+
+main() {
+  Expect.throws(() => test_switch(), (e) => e == 555);
+}
diff --git a/tests/lib/async/stream_controller_async_test.dart b/tests/lib/async/stream_controller_async_test.dart
index 77e1919..43a7ca7 100644
--- a/tests/lib/async/stream_controller_async_test.dart
+++ b/tests/lib/async/stream_controller_async_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// Test the basic StreamController and StreamController.singleSubscription.
+// Test the basic StreamController and StreamController.broadcast.
 library stream_controller_async_test;
 
 import 'dart:async';
diff --git a/tests/lib/async/stream_controller_test.dart b/tests/lib/async/stream_controller_test.dart
index 6cb1e69..3407614 100644
--- a/tests/lib/async/stream_controller_test.dart
+++ b/tests/lib/async/stream_controller_test.dart
@@ -10,6 +10,8 @@
 import 'dart:async';
 import 'event_helper.dart';
 
+const MS = const Duration(milliseconds: 1);
+
 fail(e) { Expect.fail("Unexepected error: $e"); }
 
 void testMultiController() {
@@ -419,6 +421,60 @@
   Expect.isTrue(c.isClosed);
 }
 
+void testCloseFuture() {
+  asyncStart();
+  asyncStart();
+  var c = new StreamController();
+  var f = c.close();
+  Expect.isTrue(c.isClosed);
+  bool doneSeen = false;
+  f.then((_) {
+    Expect.isTrue(doneSeen);
+    asyncEnd();
+  });
+  // Only listen after a while.
+  new Timer(MS * 250, () {
+    c.stream.listen(null, onDone: () {
+      asyncEnd();
+      doneSeen = true;
+    });
+  });
+}
+
+void testCloseFuture2() {
+  asyncStart();
+  asyncStart();
+  var c = new StreamController.broadcast();
+  var f = c.close();
+  Expect.isTrue(c.isClosed);
+  bool doneSeen = false;
+  f.then((_) {
+    // Done future on broadcast stream can happen
+    // before a listener is added.
+    Expect.isFalse(doneSeen);
+    asyncEnd();
+  });
+  // Only listen after a while.
+  new Timer(MS * 250, () {
+    c.stream.listen(null, onDone: () {
+      doneSeen = true;
+      asyncEnd();
+    });
+  });
+}
+
+void testCloseFuture3() {
+  asyncStart();
+  var c = new StreamController.broadcast();
+  c..add(1)..add(2)..add(3)..add(4);
+  c.stream.listen(null).cancel();
+  var f = c.close();
+  Expect.isTrue(c.isClosed);
+  f.then((_) {
+    asyncEnd();
+  });
+}
+
 void testStreamEquals() {
   StreamController c;
   c = new StreamController(sync: false);
@@ -531,15 +587,92 @@
   c.done.catchError(fail).whenComplete(asyncEnd); // Error must not go here.
 }
 
+void testBroadcastListenAfterClose() {
+  asyncStart();
+  StreamController c = new StreamController.broadcast();
+  var f = c.close();
+  f.then((_) {
+    // Listening after close is allowed. The listener gets a done event.
+    c.stream.listen(null, onDone: asyncEnd);
+  });
+}
+
+void testBroadcastListenAfterClosePaused() {
+  asyncStart();
+  StreamController c = new StreamController.broadcast();
+  var f = c.close();
+  f.then((_) {
+    // Listening after close is allowed. The listener gets a done event.
+    var sub = c.stream.listen(null, onDone: () {
+      Expect.fail("wrong done");
+    });
+    sub.pause();
+    sub.pause();
+    new Timer(MS * 100, () {
+      sub.asFuture().whenComplete(() { Expect.fail("Bad complete"); });
+      sub.resume();
+      new Timer(MS * 100, () {
+        sub.onDone(asyncEnd);
+        sub.resume();
+      });
+    });
+  });
+}
+
+void testAsBroadcastListenAfterClose() {
+  asyncStart();
+  asyncStart();
+  StreamController c = new StreamController();
+  Stream s = c.stream.asBroadcastStream();
+  s.listen(null, onDone: asyncEnd);
+  var f = c.close();
+  f.then((_) {
+    // Listening after close is allowed. The listener gets a done event.
+    s.listen(null, onDone: asyncEnd);
+  });
+}
+
+void testAsBroadcastListenAfterClosePaused() {
+  asyncStart();
+  asyncStart();
+  StreamController c = new StreamController();
+  Stream s = c.stream.asBroadcastStream();
+  s.listen(null, onDone: asyncEnd);
+  var f = c.close();
+  f.then((_) {
+    // Listening after close is allowed. The listener gets a done event.
+    var sub = s.listen(null, onDone: () {
+      Expect.fail("wrong done");
+    });
+    sub.pause();
+    sub.pause();
+    new Timer(MS * 100, () {
+      sub.asFuture().whenComplete(() { Expect.fail("Bad complete"); });
+      sub.resume();
+      new Timer(MS * 100, () {
+        sub.onDone(asyncEnd);
+        sub.resume();
+      });
+    });
+  });
+}
+
 main() {
   asyncStart();
   testMultiController();
   testSingleController();
   testExtraMethods();
   testClosed();
+  testCloseFuture();
+  testCloseFuture2();
+  testCloseFuture3();
   testStreamEquals();
   testCancelThrow();
   testCancelThrow2();
   testCancelThrow3();
+  testBroadcastListenAfterClose();
+  testBroadcastListenAfterClosePaused();
+  testAsBroadcastListenAfterClose();
+  testAsBroadcastListenAfterClosePaused();
   asyncEnd();
 }
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 09c9c46..5176cbf 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -173,6 +173,7 @@
 async/stream_asyncexpand_test: RuntimeError # Timer interface not supported: dartbug.com/7728.
 async/stream_asyncmap_test: RuntimeError # Timer interface not supported: dartbug.com/7728.
 async/stream_transformation_broadcast_test: RuntimeError # Timer interface not supported: dartbug.com/7728.
+async/stream_controller_test: Fail # Timer interface not supported: dartbug.com/7728.
 
 [ $compiler == dart2js && $checked ]
 convert/utf85_test: Pass, Slow # Issue 12029.
diff --git a/tests/standalone/io/http_client_connect_test.dart b/tests/standalone/io/http_client_connect_test.dart
index 8e18325..841944c 100644
--- a/tests/standalone/io/http_client_connect_test.dart
+++ b/tests/standalone/io/http_client_connect_test.dart
@@ -248,6 +248,35 @@
   });
 }
 
+void testMaxConnectionsPerHost(int connectionCap, int connections) {
+  asyncStart();
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    int handled = 0;
+    server.listen((request) {
+      Expect.isTrue(server.connectionsInfo().total <= connectionCap);
+      request.response.close();
+      handled++;
+      if (handled == connections) {
+        asyncEnd();
+        server.close();
+      }
+    });
+
+    var client = new HttpClient();
+    client.maxConnectionsPerHost = connectionCap;
+    for (int i = 0; i < connections; i++) {
+      asyncStart();
+      client.get("127.0.0.1", server.port, "/")
+        .then((request) => request.close())
+        .then((response) {
+          response.listen(null, onDone: () {
+            asyncEnd();
+          });
+        });
+    }
+  });
+}
+
 
 void main() {
   testGetEmptyRequest();
@@ -260,4 +289,8 @@
   testOpenEmptyRequest();
   testOpenUrlEmptyRequest();
   testNoBuffer();
+  testMaxConnectionsPerHost(1, 1);
+  testMaxConnectionsPerHost(1, 10);
+  testMaxConnectionsPerHost(5, 10);
+  testMaxConnectionsPerHost(10, 50);
 }
diff --git a/tests/standalone/io/http_detach_socket_test.dart b/tests/standalone/io/http_detach_socket_test.dart
index e5669d6..033a474 100644
--- a/tests/standalone/io/http_detach_socket_test.dart
+++ b/tests/standalone/io/http_detach_socket_test.dart
@@ -8,6 +8,7 @@
 // VMOptions=--short_socket_read --short_socket_write
 
 import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
 import "dart:io";
 import "dart:isolate";
 
@@ -145,9 +146,60 @@
   });
 }
 
+void testUpgradedConnection() {
+  asyncStart();
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      request.response.headers.set('connection', 'upgrade');
+      if (request.headers.value('upgrade') == 'mine') {
+        asyncStart();
+        request.response.detachSocket().then((socket) {
+          socket.pipe(socket).then((_) {
+            asyncEnd();
+          });
+        });
+      } else {
+        request.response.close();
+      }
+    });
+
+    var client = new HttpClient();
+    client.userAgent = null;
+    client.get("127.0.0.1", server.port, "/")
+      .then((request) {
+        request.headers.set('upgrade', 'mine');
+        return request.close();
+      })
+      .then((response) {
+        client.get("127.0.0.1", server.port, "/")
+            .then((request) {
+              response.detachSocket().then((socket) {
+                // We are testing that we can detach the socket, even though
+                // we made a new connection (testing it was not reused).
+                request.close().then((response) {
+                  asyncStart();
+                  response.listen(null, onDone: () {
+                    server.close();
+                    asyncEnd();
+                  });
+                  socket.add([0]);
+                  socket.close();
+                  socket.fold([], (l, d) => l..addAll(d))
+                    .then((data) {
+                      asyncEnd();
+                      Expect.listEquals([0], data);
+                    });
+                });
+              });
+            });
+      });
+  });
+}
+
 void main() {
   testServerDetachSocket();
   testServerDetachSocketNoWriteHeaders();
   testBadServerDetachSocket();
   testClientDetachSocket();
+  testUpgradedConnection();
 }
diff --git a/tests/standalone/io/http_response_deadline_test.dart b/tests/standalone/io/http_response_deadline_test.dart
index e10913a..5ec6a32 100644
--- a/tests/standalone/io/http_response_deadline_test.dart
+++ b/tests/standalone/io/http_response_deadline_test.dart
@@ -59,6 +59,7 @@
     server.listen((request) {
       request.response.deadline = const Duration(milliseconds: 0);
       request.response.contentLength = 5;
+      request.response.persistentConnection = false;
       request.response.detachSocket().then((socket) {
         new Timer(const Duration(milliseconds: 100), () {
           socket.write('stuff');
diff --git a/tests/standalone/io/http_shutdown_test.dart b/tests/standalone/io/http_shutdown_test.dart
index dd5b622..f00468b 100644
--- a/tests/standalone/io/http_shutdown_test.dart
+++ b/tests/standalone/io/http_shutdown_test.dart
@@ -162,6 +162,7 @@
     // close the client and wait for the server to lose all active
     // connections.
     var client= new HttpClient();
+    client.maxConnectionsPerHost = totalConnections;
     for (int i = 0; i < totalConnections; i++) {
       client.post("127.0.0.1", server.port, "/")
         .then((request) {
diff --git a/tests/standalone/typed_data_test.dart b/tests/standalone/typed_data_test.dart
index 99ab2a3..4429765 100644
--- a/tests/standalone/typed_data_test.dart
+++ b/tests/standalone/typed_data_test.dart
@@ -60,6 +60,9 @@
       typed_data[1] = 1.2;
     });
   }
+  Expect.throws(() => typed_data[-1]);
+  Expect.throws(() => typed_data[100]);
+  Expect.throws(() => typed_data[2.0]);
 }
 
 void testUnsignedTypedDataRange(bool check_throws) {
@@ -87,6 +90,9 @@
       typed_data[1] = 1.2;
     });
   }
+  Expect.throws(() => typed_data[-1]);
+  Expect.throws(() => typed_data[100]);
+  Expect.throws(() => typed_data[2.0]);
 }
 
 void testClampedUnsignedTypedDataRangeHelper(Uint8ClampedList typed_data,
diff --git a/tests/standalone/vmservice/test_helper.dart b/tests/standalone/vmservice/test_helper.dart
index fde93e0..9591647 100644
--- a/tests/standalone/vmservice/test_helper.dart
+++ b/tests/standalone/vmservice/test_helper.dart
@@ -39,10 +39,10 @@
   void onResponse(var seq, Map response);
   void runTest();
 
-  Future sendMessage(var seq, List<String> path) {
+  Future sendMessage(var seq, String request) {
     var map = {
       'seq': seq,
-      'path': path
+      'request': request
     };
     var message = JSON.encode(map);
     _socket.add(message);
diff --git a/tests/standalone/vmservice/websocket_client_test.dart b/tests/standalone/vmservice/websocket_client_test.dart
index bf8fac1..ebf75b3 100644
--- a/tests/standalone/vmservice/websocket_client_test.dart
+++ b/tests/standalone/vmservice/websocket_client_test.dart
@@ -30,9 +30,9 @@
 
   runTest() {
     // Send a request for clients with 'cli' sequence id.
-    sendMessage('cli', ['clients']);
+    sendMessage('cli', 'clients');
     // Send a request for vm info with 'vm' sequence id.
-    sendMessage('vm', ['vm']);
+    sendMessage('vm', 'vm');
   }
 }
 
diff --git a/tools/FAKE_COMMITS b/tools/FAKE_COMMITS
index add01e9..6cd6034 100644
--- a/tools/FAKE_COMMITS
+++ b/tools/FAKE_COMMITS
@@ -5,3 +5,4 @@
 File for landing text only commits in the dart repo.
 
 Tracer update
+Force build after chrome-bot messup
diff --git a/tools/VERSION b/tools/VERSION
index b0d624a..3bf5b0d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 5
 PATCH 0
-PRERELEASE 3
-PRERELEASE_PATCH 4
+PRERELEASE 4
+PRERELEASE_PATCH 0
diff --git a/tools/bots/functional_testing.py b/tools/bots/functional_testing.py
index b746bf6..80756f6 100644
--- a/tools/bots/functional_testing.py
+++ b/tools/bots/functional_testing.py
@@ -8,5 +8,88 @@
 Buildbot steps for functional testing master and slaves
 """
 
+import os
+import re
+import shutil
+import sys
+
+import bot
+import bot_utils
+
+utils = bot_utils.GetUtils()
+
+FT_BUILDER = r'ft-slave-(linux|mac)'
+FT_MASTER = r'ft-master'
+
+HOST_OS = utils.GuessOS()
+
+def SrcConfig(name, is_buildbot):
+  """Returns info for the current buildbot based on the name of the builder.
+
+  - mode: always "release"
+  - system: always "linux" or "mac"
+  """
+  pattern = re.match(FT_BUILDER, name)
+  master_pattern = re.match(FT_MASTER, name)
+  if not pattern and not master_pattern:
+    return None
+  if master_pattern:
+    tag = 'master'
+    system = 'linux'
+  else:
+    tag = 'slave'
+    system = pattern.group(1)
+  return bot.BuildInfo('none', 'none', 'release', system,
+                       builder_tag=tag)
+
+def Run(args):
+  print "Running: %s" % ' '.join(args)
+  sys.stdout.flush()
+  bot.RunProcess(args)
+
+def FTSlave(config):
+  with bot.BuildStep('Fetching editor'):
+    revision = int(os.environ['BUILDBOT_GOT_REVISION'])
+    bot_name, _ = bot.GetBotName()
+    print bot_name
+    channel = bot_utils.GetChannelFromName(bot_name)
+    namer = bot_utils.GCSNamer(channel=channel)
+    system = config.system
+    if system == 'mac':
+      system = 'macos'
+    editor_path = namer.editor_zipfilepath(revision, system, 'x64')
+    gsutils = bot_utils.GSUtil()
+    editor_location='/home/chrome-bot/Desktop'
+    if system == 'macos':
+      editor_location='/Users/chrome-bot/Desktop'
+    local_path = os.path.join(editor_location, 'editor.zip')
+    if os.path.exists(local_path):
+      os.remove(local_path)
+    local_extracted = os.path.join(editor_location, 'dart')
+    shutil.rmtree(local_extracted, ignore_errors=True)
+    gsutils.execute(['cp', editor_path, local_path])
+    Run(['unzip', local_path, '-d', editor_location])
+
+def FTMaster(config):
+  run = int(os.environ['BUILDBOT_ANNOTATED_STEPS_RUN'])
+  with bot.BuildStep('Master run %s' % run):
+    if run == 1:
+      print 'Not doing anything on master before the triggers'
+      return
+    else:
+      builddir = os.path.join(bot_utils.DART_DIR,
+                              utils.GetBuildDir(HOST_OS, HOST_OS),
+                              'functional_testing')
+      shutil.rmtree(builddir, ignore_errors=True)
+      os.makedirs(builddir)
+      script_locations = os.path.join(bot_utils.DART_DIR, 'editor', 'ft')
+      Run(['/home/chrome-bot/func-test/bot-run', builddir, script_locations])
+
+def FTSteps(config):
+  if config.builder_tag == 'master':
+    FTMaster(config)
+  else:
+    FTSlave(config)
+  
 if __name__ == '__main__':
-  print "Functional testing placeholder"
+  bot.RunBot(SrcConfig, FTSteps, build_step=None)
diff --git a/tools/dom/docs/docs.json b/tools/dom/docs/docs.json
index 447fa51..04839df 100644
--- a/tools/dom/docs/docs.json
+++ b/tools/dom/docs/docs.json
@@ -5189,7 +5189,7 @@
           "/**",
           "   * Buffers the specified data.",
           "   *",
-          "   * This specific method is provided for WebGL API compatibility reasons, but",
+          "   * The [bufferData] method is provided for WebGL API compatibility reasons, but",
           "   * it is highly recommended that you use [bufferDataTyped] or [bufferByteData]",
           "   * depending on your purposes.",
           "   */"
@@ -5198,7 +5198,7 @@
           "/**",
           "   * Buffers the specified subset of data.",
           "   *",
-          "   * This specific method is provided for WebGL API compatibility reasons, but",
+          "   * The [bufferSubData] method is provided for WebGL API compatibility reasons, but",
           "   * it is highly recommended that you use [bufferSubDataTyped] or [bufferSubByteData]",
           "   * depending on your purposes.",
           "   */"
@@ -5207,7 +5207,7 @@
           "/**",
           "   * Updates the currently bound texture to [data].",
           "   *",
-          "   * This specific method is provided for WebGL API compatibility reasons, but it",
+          "   * The [texImage2D] method is provided for WebGL API compatibility reasons, but it",
           "   * is highly recommended that you use [texImage2DUntyped] or [texImage2DTyped]",
           "   * (or for more specificity, the more specialized [texImage2DImageData],",
           "   * [texImage2DCanvas], [texImage2DVideo]).",
@@ -5217,7 +5217,7 @@
           "/**",
           "   * Updates a sub-rectangle of the currently bound texture to [data].",
           "   *",
-          "   * This specific method is provided for WebGL API compatibility reasons, but it",
+          "   * The [texSubImage2D] method is provided for WebGL API compatibility reasons, but it",
           "   * is highly recommended that you use [texSubImage2DUntyped] or [texSubImage2DTyped]",
           "   * (or for more specificity, the more specialized [texSubImage2DImageData],",
           "   * [texSubImage2DCanvas], [texSubImage2DVideo]).",
diff --git a/tools/dom/dom.json b/tools/dom/dom.json
index 0c3954e..4311e7d 100644
--- a/tools/dom/dom.json
+++ b/tools/dom/dom.json
@@ -5873,6 +5873,14 @@
     },
     "support_level": "stable"
   },
+  "InjectedScriptHost": {
+    "members": {
+      "inspect": {
+        "support_level": "untriaged"
+      }
+    },
+    "support_level": "untriaged"
+  },
   "InputMethodContext": {
     "comment": "http://www.w3.org/TR/ime-api/#idl-def-InputMethodContext",
     "members": {
diff --git a/tools/dom/idl/dart/dart.idl b/tools/dom/idl/dart/dart.idl
index d4353b3..cdf46f3 100644
--- a/tools/dom/idl/dart/dart.idl
+++ b/tools/dom/idl/dart/dart.idl
@@ -324,8 +324,24 @@
 interface AbstractView {};
 
 
-[Suppressed]
-interface InjectedScriptHost {};
+interface InjectedScriptHost {
+    [Custom] void inspect(any objectId, any hints);
+    [Suppressed, Custom] any inspectedObject(long num);
+    [Suppressed, Custom] any internalConstructorName(any obj);
+    [Suppressed, Custom] boolean isHTMLAllCollection(any obj);
+    [Suppressed, Custom] DOMString type(any obj);
+    [Suppressed, Custom] any functionDetails(any obj);
+    [Suppressed, Custom] any[] getInternalProperties(any obj);
+    [Suppressed, Custom] EventListener[] getEventListeners(EventTarget target);
+    [Suppressed, Custom] any evaluate(DOMString text);
+    [Suppressed, Custom] void debugFunction(any fn);
+    [Suppressed, Custom] void undebugFunction(any fn);
+    [Suppressed, Custom] void monitorFunction(any fn);
+    [Suppressed, Custom] void unmonitorFunction(any fn);
+
+    // Only declarative scope (local, with and catch) is accepted. Returns undefined.
+    [Suppressed, Custom] any setFunctionVariableValue(any functionObject, long scopeIndex, DOMString variableName, any newValue);
+};
 
 
 [Suppressed]
diff --git a/tools/dom/src/dartium_CustomElementSupport.dart b/tools/dom/src/dartium_CustomElementSupport.dart
index 37baa55..3afc56a 100644
--- a/tools/dom/src/dartium_CustomElementSupport.dart
+++ b/tools/dom/src/dartium_CustomElementSupport.dart
@@ -30,8 +30,7 @@
     if (element.runtimeType != _nativeType) {
       throw new UnsupportedError('Element is incorrect type');
     }
-    _Utils.changeElementWrapper(element, _type);
-    return null;
+    return _Utils.changeElementWrapper(element, _type);
   }
 }
 
diff --git a/tools/dom/src/html_native_DOMImplementation.dart b/tools/dom/src/html_native_DOMImplementation.dart
index 304c474..4ac5eff 100644
--- a/tools/dom/src/html_native_DOMImplementation.dart
+++ b/tools/dom/src/html_native_DOMImplementation.dart
@@ -4,6 +4,32 @@
 
 part of html;
 
+class _Property {
+  _Property(this.name) :
+      _hasValue = false,
+      writable = false,
+      isMethod = false,
+      isOwn = true,
+      wasThrown = false;
+
+  bool get hasValue => _hasValue;
+  get value => _value;
+  set value(v) {
+    _value = v;
+    _hasValue = true;
+  }
+
+  final String name;
+  Function setter;
+  Function getter;
+  var _value;
+  bool _hasValue;
+  bool writable;
+  bool isMethod;
+  bool isOwn;
+  bool wasThrown;
+}
+
 class _ConsoleVariables {
   Map<String, Object> _data = new Map<String, Object>();
 
@@ -19,7 +45,8 @@
       member = member.substring(0, member.length - 1);
       _data[member] = invocation.positionalArguments[0];
     } else {
-      return Function.apply(_data[member], invocation.positionalArguments, invocation.namedArguments);
+      return Function.apply(_data[member], invocation.positionalArguments,
+          invocation.namedArguments);
     }
   }
 
@@ -28,7 +55,60 @@
   /**
    * List all variables currently defined.
    */
-  List variables() => _data.keys.toList(growable: false);
+  List variables() => _data.keys.toList();
+
+  void setVariable(String name, value) {
+    _data[name] = value;
+  }
+}
+
+/**
+ * Base class for invocation trampolines used to closurize methods, getters
+ * and setters.
+ */
+abstract class _Trampoline implements Function {
+  final ObjectMirror _receiver;
+  final MethodMirror _methodMirror;
+  final Symbol _selector;
+
+  _Trampoline(this._receiver, this._methodMirror, this._selector);
+}
+
+class _MethodTrampoline extends _Trampoline {
+  _MethodTrampoline(ObjectMirror receiver, MethodMirror methodMirror,
+      Symbol selector) :
+      super(receiver, methodMirror, selector);
+
+  noSuchMethod(Invocation msg) {
+    if (msg.memberName != #call) return super.noSuchMethod(msg);
+    return _receiver.invoke(_selector,
+                            msg.positionalArguments,
+                            msg.namedArguments).reflectee;
+  }
+}
+
+/**
+ * Invocation trampoline class used to closurize getters.
+ */
+class _GetterTrampoline extends _Trampoline {
+  _GetterTrampoline(ObjectMirror receiver, MethodMirror methodMirror,
+      Symbol selector) :
+      super(receiver, methodMirror, selector);
+
+  call() => _receiver.getField(_selector).reflectee;
+}
+
+/**
+ * Invocation trampoline class used to closurize setters.
+ */
+class _SetterTrampoline extends _Trampoline {
+  _SetterTrampoline(ObjectMirror receiver, MethodMirror methodMirror,
+      Symbol selector) :
+      super(receiver, methodMirror, selector);
+
+  call(value) {
+    _receiver.setField(_selector, value);
+  }
 }
 
 class _Utils {
@@ -144,27 +224,6 @@
   static _ConsoleVariables _consoleTempVariables = new _ConsoleVariables();
 
   /**
-   * Header passed in from the Dartium Developer Tools when an expression is
-   * evaluated in the console as opposed to the watch window or another context
-   * that does not expect REPL support in Dartium 34.
-   */
-  static const _CONSOLE_API_SUPPORT_HEADER_34 =
-      'with ((console && console._commandLineAPI) || { __proto__: null }) {\n';
-  /**
-   * Header passed in from the Dartium Developer Tools when an expression is
-   * evaluated in the console as opposed to the watch window or another context
-   * that does not expect REPL support in Dartium 35.
-   */
-  static const _CONSOLE_API_SUPPORT_HEADER_35 =
-      'with (__commandLineAPI || { __proto__: null }) {\n';
-
-
-  static bool expectsConsoleApi(String expression) {
-    return expression.indexOf(_CONSOLE_API_SUPPORT_HEADER_34) == 0 ||
-        expression.indexOf(_CONSOLE_API_SUPPORT_HEADER_35) == 0;
-  }
-
-  /**
    * Takes an [expression] and a list of [local] variable and returns an
    * expression for a closure with a body matching the original expression
    * where locals are passed in as arguments. Returns a list containing the
@@ -176,8 +235,7 @@
    * For example:
    * <code>
    * _consoleTempVariables = {'a' : someValue, 'b': someOtherValue}
-   * wrapExpressionAsClosure("${_CONSOLE_API_SUPPORT_HEADER35}foo + bar + a",
-   *                         ["bar", 40, "foo", 2])
+   * wrapExpressionAsClosure("foo + bar + a", ["bar", 40, "foo", 2], true)
    * </code>
    * will return:
    * <code>
@@ -187,9 +245,8 @@
    * [_consoleTempVariables, 40, 2, someValue, someOtherValue]]
    * </code>
    */
-  static List wrapExpressionAsClosure(String expression, List locals) {
-    // FIXME: dartbug.com/10434 find a less fragile way to determine whether
-    // we need to strip off console API support added by InjectedScript.
+  static List wrapExpressionAsClosure(String expression, List locals,
+      bool includeCommandLineAPI) {
     var args = {};
     var sb = new StringBuffer("(");
     addArg(arg, value) {
@@ -208,10 +265,7 @@
       args[arg] = value;
     }
 
-    if (expectsConsoleApi(expression)) {
-      expression = expression.substring(expression.indexOf('\n') + 1);
-      expression = expression.substring(0, expression.lastIndexOf('\n'));
-
+    if (includeCommandLineAPI) {
       addArg("\$consoleVariables", _consoleTempVariables);
 
       // FIXME: use a real Dart tokenizer. The following regular expressions
@@ -268,13 +322,19 @@
     return [sb.toString(), args.values.toList(growable: false)];
   }
 
-  /**
-   * TODO(jacobr): this is a big hack to get around the fact that we are still
-   * passing some JS expression to the evaluate method even when in a Dart
-   * context.
-   */
-  static bool isJsExpression(String expression) =>
-    expression.startsWith("(function getCompletions");
+  static String _getShortSymbolName(Symbol symbol,
+                                    DeclarationMirror declaration) {
+    var name = MirrorSystem.getName(symbol);
+    if (declaration is MethodMirror) {
+      if (declaration.isSetter && name[name.length-1] == "=") {
+        return name.substring(0, name.length-1);
+      }
+      if (declaration.isConstructor) {
+        return name.substring(name.indexOf('.') + 1);
+      }
+    }
+    return name;
+  }
 
   /**
    * Returns a list of completions to use if the receiver is o.
@@ -313,97 +373,409 @@
   }
 
   /**
-   * Convenience helper to get the keys of a [Map] as a [List].
+   * Adds all candidate String completitions from [declarations] to [output]
+   * filtering based on [staticContext] and [includePrivate].
    */
-  static List getMapKeyList(Map map) => map.keys.toList();
-
- /**
-   * Returns the keys of an arbitrary Dart Map encoded as unique Strings.
-   * Keys that are strings are left unchanged except that the prefix ":" is
-   * added to disambiguate keys from other Dart members.
-   * Keys that are not strings have # followed by the index of the key in the map
-   * prepended to disambuguate. This scheme is simplistic but easy to encode and
-   * decode. The use case for this method is displaying all map keys in a human
-   * readable way in debugging tools.
-   */
-  static List<String> getEncodedMapKeyList(dynamic obj) {
-    if (obj is! Map) return null;
-
-    var ret = new List<String>();
-    int i = 0;
-    return obj.keys.map((key) {
-      var encodedKey;
-      if (key is String) {
-        encodedKey = ':$key';
-      } else {
-        // If the key isn't a string, return a guaranteed unique for this map
-        // string representation of the key that is still somewhat human
-        // readable.
-        encodedKey = '#${i}:$key';
+  static void _getCompletionsHelper(ClassMirror classMirror,
+      bool staticContext, LibraryMirror libraryMirror, Set<String> output) {
+    bool includePrivate = libraryMirror == classMirror.owner;
+    classMirror.declarations.forEach((symbol, declaration) {
+      if (!includePrivate && declaration.isPrivate) return;
+      if (declaration is VariableMirror) {
+        if (staticContext != declaration.isStatic) return;
+      } else if (declaration is MethodMirror) {
+        if (declaration.isOperator) return;
+        if (declaration.isConstructor) {
+          if (!staticContext) return;
+          var name = MirrorSystem.getName(declaration.constructorName);
+          if (name.isNotEmpty) output.add(name);
+          return;
+        }
+        if (staticContext != declaration.isStatic) return;
+      } else if (declaration is TypeMirror) {
+        return;
       }
-      i++;
-      return encodedKey;
-    }).toList(growable: false);
+      output.add(_getShortSymbolName(symbol, declaration));
+    });
+
+    if (!staticContext) {
+      for (var interface in classMirror.superinterfaces) {
+        _getCompletionsHelper(interface, staticContext,
+            libraryMirror, output);
+      }
+      if (classMirror.superclass != null) {
+        _getCompletionsHelper(classMirror.superclass, staticContext,
+            libraryMirror, output);
+      }
+    }
   }
 
-  static final RegExp _NON_STRING_KEY_REGEXP = new RegExp("^#(\\d+):(.+)\$");
+  static void _getLibraryCompletionsHelper(
+      LibraryMirror library, bool includePrivate, Set<String> output) {
+    library.declarations.forEach((symbol, declaration) {
+      if (!includePrivate && declaration.isPrivate) return;
+      output.add(_getShortSymbolName(symbol, declaration));
+    });
+  }
 
-  static _decodeKey(Map map, String key) {
-    // The key is a regular old String.
-    if (key.startsWith(':')) return key.substring(1);
+  static LibraryMirror getLibraryMirror(String url) =>
+      currentMirrorSystem().libraries[Uri.parse(url)];
 
-    var match = _NON_STRING_KEY_REGEXP.firstMatch(key);
-    if (match != null) {
-      int index = int.parse(match.group(1));
-      var iter = map.keys.skip(index);
-      if (iter.isNotEmpty) {
-        var ret = iter.first;
-        // Validate that the toString representation of the key matches what we
-        // expect. FIXME: throw an error if it does not.
-        assert(match.group(2) == '$ret');
-        return ret;
+  /**
+   * Get code completions for [o] only showing privates from [libraryUrl].
+   */
+  static List<String> getObjectCompletions(o, String libraryUrl) {
+    var classMirror;
+    bool staticContext;
+    if (o is Type) {
+      classMirror = reflectClass(o);
+      staticContext = true;
+    } else {
+      classMirror = reflect(o).type;
+      staticContext = false;
+    }
+    var names = new Set<String>();
+    getClassCompletions(classMirror, names, staticContext, libraryUrl);
+    return names.toList()..sort();
+  }
+
+  static void getClassCompletions(ClassMirror classMirror, Set<String> names,
+      bool staticContext, String libraryUrl) {
+    LibraryMirror libraryMirror = getLibraryMirror(libraryUrl);
+    _getCompletionsHelper(classMirror, staticContext, libraryMirror, names);
+  }
+
+  static List<String> getLibraryCompletions(String url) {
+    var names = new Set<String>();
+    _getLibraryCompletionsHelper(getLibraryMirror(url), true, names);
+    return names.toList();
+  }
+
+  /**
+   * Get valid code completitions from within a library and all libraries
+   * imported by that library.
+   */
+  static List<String> getLibraryCompletionsIncludingImports(String url) {
+    var names = new Set<String>();
+    var libraryMirror = getLibraryMirror(url);
+    _getLibraryCompletionsHelper(libraryMirror, true, names);
+    for (var dependency in libraryMirror.libraryDependencies) {
+      if (dependency.isImport) {
+        if (dependency.prefix == null) {
+          _getLibraryCompletionsHelper(dependency.targetLibrary, false, names);
+        } else {
+          names.add(MirrorSystem.getName(dependency.prefix));
+        }
       }
     }
+    return names.toList();
+  }
+
+  static final SIDE_EFFECT_FREE_LIBRARIES = new Set<String>()
+      ..add('dart:html')
+      ..add('dart:indexed_db')
+      ..add('dart:svg')
+      ..add('dart:typed_data')
+      ..add('dart:web_audio')
+      ..add('dart:web_gl')
+      ..add('dart:web_sql');
+
+  static LibraryMirror _getLibrary(MethodMirror methodMirror) {
+    var owner = methodMirror.owner;
+    if (owner is ClassMirror) {
+      return owner;
+    } else if (owner is LibraryMirror) {
+      return owner;
+    }
     return null;
   }
 
   /**
-   * Converts keys encoded with [getEncodedMapKeyList] to their actual keys.
+   * For parity with the JavaScript debugger, we treat some getters as if
+   * they are fields so that users can see their values immediately.
+   * This matches JavaScript's behavior for getters on DOM objects.
+   * In the future we should consider adding an annotation to tag getters
+   * in user libraries as side effect free.
    */
-  static lookupValueForEncodedMapKey(Map obj, String key) => obj[_decodeKey(obj, key)];
-
+  static bool _isSideEffectFreeGetter(MethodMirror methodMirror,
+      LibraryMirror libraryMirror) {
+    // This matches JavaScript behavior. We should consider displaying
+    // getters for all dart platform libraries rather than just the DOM
+    // libraries.
+    return libraryMirror.uri.scheme == 'dart' &&
+        SIDE_EFFECT_FREE_LIBRARIES.contains(libraryMirror.uri.toString());
+  }
+  
   /**
-   * Builds a constructor name with the form expected by the C Dart mirrors API.
+   * Whether we should treat a property as a field for the purposes of the
+   * debugger.
    */
-  static String buildConstructorName(String className, String constructorName) => '$className.$constructorName';
+  static bool treatPropertyAsField(MethodMirror methodMirror,
+      LibraryMirror libraryMirror) {
+    return (methodMirror.isGetter || methodMirror.isSetter) &&
+          (methodMirror.isSynthetic ||
+              _isSideEffectFreeGetter(methodMirror,libraryMirror));
+  }
 
-  /**
-   * Strips the class name from an expression of the form "className.someName".
-   */
-  static String stripClassName(String str, String className) {
-    if (str.length > className.length + 1 &&
-        str.startsWith(className) && str[className.length] == '.') {
-      return str.substring(className.length + 1);
-    } else {
-      return str;
+  // TODO(jacobr): generate more concise function descriptions instead of
+  // dumping the entire function source.
+  static String describeFunction(function) {
+    if (function is _Trampoline) return function._methodMirror.source;
+    try {
+      var mirror = reflect(function);
+      return mirror.function.source;
+    } catch (e) {
+      return function.toString();
+    }
+  }
+
+  static List getInvocationTrampolineDetails(_Trampoline method) {
+    var loc = method._methodMirror.location;
+    return [loc.line, loc.column, loc.sourceUri.toString(),
+        MirrorSystem.getName(method._selector)];
+  }
+
+  static List getLibraryProperties(String libraryUrl, bool ownProperties,
+      bool accessorPropertiesOnly) {
+    var properties = new Map<String, _Property>();
+    var libraryMirror = getLibraryMirror(libraryUrl);
+    _addInstanceMirrors(libraryMirror, libraryMirror,
+        libraryMirror.declarations,
+        ownProperties, accessorPropertiesOnly, false, false,
+        properties);
+    if (!accessorPropertiesOnly) {
+      // We need to add class properties for all classes in the library.
+      libraryMirror.declarations.forEach((symbol, declarationMirror) {
+        if (declarationMirror is ClassMirror) {
+          var name = MirrorSystem.getName(symbol);
+          if (declarationMirror.hasReflectedType
+              && !properties.containsKey(name)) {
+            properties[name] = new _Property(name)
+                ..value = declarationMirror.reflectedType;
+          }
+        }
+      });
+    }
+    return packageProperties(properties);
+  }
+
+  static List getObjectProperties(o, bool ownProperties,
+      bool accessorPropertiesOnly) {
+    var properties = new Map<String, _Property>();
+    var names = new Set<String>();
+    var objectMirror = reflect(o);
+    var classMirror = objectMirror.type;
+    _addInstanceMirrors(objectMirror, classMirror.owner,
+        classMirror.instanceMembers,
+        ownProperties, accessorPropertiesOnly, false, true,
+        properties);
+    return packageProperties(properties);
+  }
+
+  static List getObjectClassProperties(o, bool ownProperties,
+      bool accessorPropertiesOnly) {
+    var properties = new Map<String, _Property>();
+    var objectMirror = reflect(o);
+    var classMirror = objectMirror.type;
+    _addInstanceMirrors(objectMirror, classMirror.owner,
+        classMirror.instanceMembers,
+        ownProperties, accessorPropertiesOnly, true, false,
+        properties);
+    _addStatics(classMirror, properties, accessorPropertiesOnly);
+    return packageProperties(properties);
+  }
+
+  static List getClassProperties(Type t, bool ownProperties,
+      bool accessorPropertiesOnly) {
+    var properties = new Map<String, _Property>();
+    var classMirror = reflectClass(t);
+    _addStatics(classMirror, properties, accessorPropertiesOnly);
+    return packageProperties(properties);
+  }
+
+  static void _addStatics(ClassMirror classMirror,
+                          Map<String, _Property> properties,
+                          bool accessorPropertiesOnly) {
+    var libraryMirror = classMirror.owner;
+    classMirror.declarations.forEach((symbol, declaration) {
+      var name = _getShortSymbolName(symbol, declaration);
+      if (name.isEmpty) return;
+      if (declaration is VariableMirror) {
+        if (accessorPropertiesOnly) return;
+        if (!declaration.isStatic) return;
+        properties.putIfAbsent(name, () => new _Property(name))
+            ..value = classMirror.getField(symbol).reflectee
+            ..writable = !declaration.isFinal && !declaration.isConst;
+      } else if (declaration is MethodMirror) {
+        MethodMirror methodMirror = declaration;
+        // FIXMEDART: should we display constructors?
+        if (methodMirror.isConstructor) return;
+        if (!methodMirror.isStatic) return;
+        if (accessorPropertiesOnly) {
+          if (methodMirror.isRegularMethod ||
+              treatPropertyAsField(methodMirror, libraryMirror)) {
+            return;
+          }
+        } else if (!methodMirror.isRegularMethod &&
+            !treatPropertyAsField(methodMirror, libraryMirror)) {
+          return;
+        }
+        var property = properties.putIfAbsent(name, () => new _Property(name));
+        _fillMethodMirrorProperty(libraryMirror, classMirror, methodMirror,
+            symbol, accessorPropertiesOnly, property);
+      }
+    });
+  }
+
+  static void _fillMethodMirrorProperty(LibraryMirror libraryMirror,
+        methodOwner, MethodMirror methodMirror, Symbol symbol,
+        bool accessorPropertiesOnly, _Property property) {
+    if (methodMirror.isRegularMethod) {
+      property
+          ..value = new _MethodTrampoline(methodOwner, methodMirror, symbol)
+          ..isMethod = true;
+    } else if (methodMirror.isGetter) {
+      if (treatPropertyAsField(methodMirror, libraryMirror)) {
+        try {
+          property.value = methodOwner.getField(symbol).reflectee;
+        } catch (e) {
+          property
+              ..wasThrown = true
+              ..value = e;
+        }
+      } else if (accessorPropertiesOnly) {
+        property.getter = new _GetterTrampoline(methodOwner,
+            methodMirror, symbol);
+      }
+    } else if (methodMirror.isSetter) {
+      if (accessorPropertiesOnly &&
+          !treatPropertyAsField(methodMirror, libraryMirror)) {
+        property.setter = new _SetterTrampoline(methodOwner,
+            methodMirror, MirrorSystem.getSymbol(property.name, libraryMirror));
+      }
+      property.writable = true;
     }
   }
 
   /**
-   * Removes the trailing dot from an expression ending in a dot.
-   * This method is used as Library prefixes include a trailing dot when using
-   * the C Dart debugger API.
+   * Helper method that handles collecting up properties from classes
+   * or libraries using the filters [ownProperties], [accessorPropertiesOnly],
+   * [hideFields], and [hideMethods] to determine which properties are
+   * collected. [accessorPropertiesOnly] specifies whether all properties
+   * should be returned or just accessors. [hideFields] specifies whether
+   * fields should be hidden. hideMethods specifies whether methods should be
+   * shown or hidden. [ownProperties] is not currently used but is part of the
+   * Blink devtools API for enumerating properties.
    */
-  static String stripTrailingDot(String str) =>
-    (str != null && str[str.length - 1] == '.') ? str.substring(0, str.length - 1) : str;
-
-  static String addTrailingDot(String str) => '${str}.';
-
-  static String demangle(String str) {
-    var atPos = str.indexOf('@');
-    return atPos == -1 ? str : str.substring(0, atPos);
+  static void _addInstanceMirrors(
+      ObjectMirror objectMirror,
+      LibraryMirror libraryMirror,
+      Map<Symbol, Mirror> declarations,
+      bool ownProperties, bool accessorPropertiesOnly,
+      bool hideFields, bool hideMethods,
+      Map<String, _Property> properties) {
+    declarations.forEach((symbol, declaration) {
+      if (declaration is TypedefMirror || declaration is ClassMirror) return;
+      var name = _getShortSymbolName(symbol, declaration);
+      if (name.isEmpty) return;
+      bool isField = declaration is VariableMirror ||
+          (declaration is MethodMirror &&
+              treatPropertyAsField(declaration, libraryMirror));
+      if ((isField && hideFields) || (hideMethods && !isField)) return;
+      if (accessorPropertiesOnly) {
+        if (declaration is VariableMirror || declaration.isRegularMethod ||
+            isField) {
+          return;
+        }
+      } else if (declaration is MethodMirror &&
+          (declaration.isGetter || declaration.isSetter) &&
+          !treatPropertyAsField(declaration, libraryMirror)) {
+        return;
+      }
+      var property = properties.putIfAbsent(name, () => new _Property(name));
+      if (declaration is VariableMirror) {
+        property
+            ..value = objectMirror.getField(symbol).reflectee
+            ..writable = !declaration.isFinal && !declaration.isConst;
+        return;
+      }
+      _fillMethodMirrorProperty(libraryMirror, objectMirror, declaration,
+          symbol, accessorPropertiesOnly, property);
+    });
   }
 
+  /**
+   * Flatten down the properties data structure into a List that is easy to
+   * access from native code.
+   */
+  static List packageProperties(Map<String, _Property> properties) {
+    var ret = [];
+    for (var property in properties.values) {
+      ret.addAll([property.name,
+                  property.setter,
+                  property.getter,
+                  property.value,
+                  property.hasValue,
+                  property.writable,
+                  property.isMethod,
+                  property.isOwn,
+                  property.wasThrown]);
+    }
+    return ret;
+  }
+  
+  /**
+   * Get a property, returning null if the property does not exist.
+   * For private property names, we attempt to resolve the property in the
+   * context of each library that the property name could be associated with.
+   */
+  static getObjectPropertySafe(o, String propertyName) {
+    var objectMirror = reflect(o);
+    var classMirror = objectMirror.type;
+    if (propertyName.startsWith("_")) {
+      var attemptedLibraries = new Set<LibraryMirror>(); 
+      while (classMirror != null) {
+        LibraryMirror library = classMirror.owner;
+        if (!attemptedLibraries.contains(library)) {
+          try {
+            return objectMirror.getField(
+                MirrorSystem.getSymbol(propertyName, library)).reflectee;
+          } catch (e) { }
+          attemptedLibraries.add(library);
+        }
+        classMirror = classMirror.superclass;
+      }
+      return null;     
+    }
+    try {
+      return objectMirror.getField(
+          MirrorSystem.getSymbol(propertyName)).reflectee;
+    } catch (e) {
+      return null;
+    }
+  }
+
+  /**
+   * Helper to wrap the inspect method on InjectedScriptHost to provide the
+   * inspect method required for the 
+   */
+  static List consoleApi(host) {
+    return [
+        "inspect",
+        (o) {
+          host.inspect(o, null);
+          return o;
+        },
+        "dir",
+        window().console.dir,
+        "dirxml",
+        window().console.dirxml
+        // FIXME: add copy method.
+        ];
+  }
+
+  static List getMapKeyList(Map map) => map.keys.toList();
+
   static bool isNoSuchMethodError(obj) => obj is NoSuchMethodError;
 
   static void register(Document document, String tag, Type type,
@@ -429,7 +801,7 @@
   static void initializeCustomElement(HtmlElement element) =>
     _blink.Native_Utils_initializeCustomElement(element);
 
-  static void changeElementWrapper(HtmlElement element, Type type) =>
+  static Element changeElementWrapper(HtmlElement element, Type type) =>
     _blink.Native_Utils_changeElementWrapper(element, type);
 }
 
@@ -512,7 +884,7 @@
   }
 }
 
-final _printClosure = window.console.log;
+final _printClosure = (s) => window.console.log(s);
 final _pureIsolatePrintClosure = (s) {
   throw new UnimplementedError("Printing from a background isolate "
                                "is not supported in the browser");
diff --git a/tools/dom/src/native_DOMImplementation.dart b/tools/dom/src/native_DOMImplementation.dart
index 490dd14..d8d603b 100644
--- a/tools/dom/src/native_DOMImplementation.dart
+++ b/tools/dom/src/native_DOMImplementation.dart
@@ -499,7 +499,7 @@
   }
 }
 
-final _printClosure = window.console.log;
+final _printClosure = (s) => window.console.log(s);
 final _pureIsolatePrintClosure = (s) {
   throw new UnimplementedError("Printing from a background isolate "
                                "is not supported in the browser");
diff --git a/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate b/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
index c0120c2..c7d1075 100644
--- a/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
+++ b/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
@@ -24,6 +24,7 @@
   void setProperty(String propertyName, String value, [String priority]) {
     // try/catch for IE9 which throws on unsupported values.
     try {
+      if (value == null) value = '';
       if (priority == null) {
         priority = '';
       }
@@ -1222,12 +1223,17 @@
   }
 
   /** Gets the value of "flex" */
-  String get flex =>
-    getPropertyValue('${Device.cssPrefix}flex');
+  String get flex {
+    String prefix = Device.cssPrefix;
+    if (Device.isFirefox) prefix = '';
+    return getPropertyValue('${prefix}flex');
+  }
 
   /** Sets the value of "flex" */
   void set flex(String value) {
-    setProperty('${Device.cssPrefix}flex', value, '');
+    String prefix = Device.cssPrefix;
+    if (Device.isFirefox) prefix = '';
+    setProperty('${prefix}flex', value, '');
   }
 
   /** Gets the value of "flex-basis" */
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 225b31d..3266c6c 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -1328,116 +1328,116 @@
 $if DART2JS
   @DomName('Element.offsetHeight')
   @DocsEditable()
-  num get offsetHeight => JS('num', '#.offsetHeight', this).round();
+  int get offsetHeight => JS('num', '#.offsetHeight', this).round();
 
   @DomName('Element.offsetLeft')
   @DocsEditable()
-  num get offsetLeft => JS('num', '#.offsetLeft', this).round();
+  int get offsetLeft => JS('num', '#.offsetLeft', this).round();
 
   @DomName('Element.offsetTop')
   @DocsEditable()
-  num get offsetTop => JS('num', '#.offsetTop', this).round();
+  int get offsetTop => JS('num', '#.offsetTop', this).round();
 
   @DomName('Element.offsetWidth')
   @DocsEditable()
-  num get offsetWidth => JS('num', '#.offsetWidth', this).round();
+  int get offsetWidth => JS('num', '#.offsetWidth', this).round();
 
   @DomName('Element.clientHeight')
   @DocsEditable()
-  num get clientHeight => JS('num', '#.clientHeight', this).round();
+  int get clientHeight => JS('num', '#.clientHeight', this).round();
 
   @DomName('Element.clientLeft')
   @DocsEditable()
-  num get clientLeft => JS('num', '#.clientLeft', this).round();
+  int get clientLeft => JS('num', '#.clientLeft', this).round();
 
   @DomName('Element.clientTop')
   @DocsEditable()
-  num get clientTop => JS('num', '#.clientTop', this).round();
+  int get clientTop => JS('num', '#.clientTop', this).round();
 
   @DomName('Element.clientWidth')
   @DocsEditable()
-  num get clientWidth => JS('num', '#.clientWidth', this).round();
+  int get clientWidth => JS('num', '#.clientWidth', this).round();
 
   @DomName('Element.scrollHeight')
   @DocsEditable()
-  num get scrollHeight => JS('num', '#.scrollHeight', this).round();
+  int get scrollHeight => JS('num', '#.scrollHeight', this).round();
 
   @DomName('Element.scrollLeft')
   @DocsEditable()
-  num get scrollLeft => JS('num', '#.scrollLeft', this).round();
+  int get scrollLeft => JS('num', '#.scrollLeft', this).round();
 
   @DomName('Element.scrollLeft')
   @DocsEditable()
-  void set scrollLeft(num value) => JS("void", "#.scrollLeft = #", this, value.round());
+  void set scrollLeft(int value) => JS("void", "#.scrollLeft = #", this, value.round());
 
   @DomName('Element.scrollTop')
   @DocsEditable()
-  num get scrollTop => JS('num', '#.scrollTop', this).round();
+  int get scrollTop => JS('num', '#.scrollTop', this).round();
 
   @DomName('Element.scrollTop')
   @DocsEditable()
-  void set scrollTop(num value) => JS("void", "#.scrollTop = #", this, value.round());
+  void set scrollTop(int value) => JS("void", "#.scrollTop = #", this, value.round());
 
   @DomName('Element.scrollWidth')
   @DocsEditable()
-  num get scrollWidth => JS('num', '#.scrollWidth', this).round();
+  int get scrollWidth => JS('num', '#.scrollWidth', this).round();
 
 $else
   @DomName('Element.offsetHeight')
   @DocsEditable()
-  num get offsetHeight => _blink.Native_Element_offsetHeight_Getter(this).round();
+  int get offsetHeight => _blink.Native_Element_offsetHeight_Getter(this).round();
 
   @DomName('Element.offsetLeft')
   @DocsEditable()
-  num get offsetLeft => _blink.Native_Element_offsetLeft_Getter(this).round();
+  int get offsetLeft => _blink.Native_Element_offsetLeft_Getter(this).round();
 
   @DomName('Element.offsetTop')
   @DocsEditable()
-  num get offsetTop => _blink.Native_Element_offsetTop_Getter(this).round();
+  int get offsetTop => _blink.Native_Element_offsetTop_Getter(this).round();
 
   @DomName('Element.offsetWidth')
   @DocsEditable()
-  num get offsetWidth => _blink.Native_Element_offsetWidth_Getter(this).round();
+  int get offsetWidth => _blink.Native_Element_offsetWidth_Getter(this).round();
 
   @DomName('Element.clientHeight')
   @DocsEditable()
-  num get clientHeight => _blink.Native_Element_clientHeight_Getter(this).round();
+  int get clientHeight => _blink.Native_Element_clientHeight_Getter(this).round();
 
   @DomName('Element.clientLeft')
   @DocsEditable()
-  num get clientLeft => _blink.Native_Element_clientLeft_Getter(this).round();
+  int get clientLeft => _blink.Native_Element_clientLeft_Getter(this).round();
 
   @DomName('Element.clientTop')
   @DocsEditable()
-  num get clientTop => _blink.Native_Element_clientTop_Getter(this).round();
+  int get clientTop => _blink.Native_Element_clientTop_Getter(this).round();
 
   @DomName('Element.clientWidth')
   @DocsEditable()
-  num get clientWidth => _blink.Native_Element_clientWidth_Getter(this).round();
+  int get clientWidth => _blink.Native_Element_clientWidth_Getter(this).round();
 
   @DomName('Element.scrollHeight')
   @DocsEditable()
-  num get scrollHeight => _blink.Native_Element_scrollHeight_Getter(this).round();
+  int get scrollHeight => _blink.Native_Element_scrollHeight_Getter(this).round();
 
   @DomName('Element.scrollLeft')
   @DocsEditable()
-  num get scrollLeft => _blink.Native_Element_scrollLeft_Getter(this).round();
+  int get scrollLeft => _blink.Native_Element_scrollLeft_Getter(this).round();
 
   @DomName('Element.scrollLeft')
   @DocsEditable()
-  void set scrollLeft(num value) => _blink.Native_Element_scrollLeft_Setter(this, value.round());
+  void set scrollLeft(int value) => _blink.Native_Element_scrollLeft_Setter(this, value.round());
 
   @DomName('Element.scrollTop')
   @DocsEditable()
-  num get scrollTop => _blink.Native_Element_scrollTop_Getter(this).round();
+  int get scrollTop => _blink.Native_Element_scrollTop_Getter(this).round();
 
   @DomName('Element.scrollTop')
   @DocsEditable()
-  void set scrollTop(num value) => _blink.Native_Element_scrollTop_Setter(this, value.round());
+  void set scrollTop(int value) => _blink.Native_Element_scrollTop_Setter(this, value.round());
 
   @DomName('Element.scrollWidth')
   @DocsEditable()
-  num get scrollWidth => _blink.Native_Element_scrollWidth_Getter(this).round();
+  int get scrollWidth => _blink.Native_Element_scrollWidth_Getter(this).round();
 $endif
 
 $!MEMBERS
diff --git a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
index 539e645..e8f64d5 100644
--- a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
+++ b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
@@ -137,13 +137,19 @@
    *
    * By default `request` will perform an HTTP GET request, but a different
    * method (`POST`, `PUT`, `DELETE`, etc) can be used by specifying the
-   * [method] parameter.
+   * [method] parameter. (See also [HttpRequest.postFormData] for `POST` 
+   * requests only.
    *
    * The Future is completed when the response is available.
    *
    * If specified, `sendData` will send data in the form of a [ByteBuffer],
    * [Blob], [Document], [String], or [FormData] along with the HttpRequest.
    *
+   * If specified, [responseType] sets the desired response format for the
+   * request. By default it is [String], but can also be 'arraybuffer', 'blob', 
+   * 'document', 'json', or 'text'. See also [HttpRequest.responseType] 
+   * for more information.
+   *
    * The [withCredentials] parameter specified that credentials such as a cookie
    * (already) set in the header or
    * [authorization headers](http://tools.ietf.org/html/rfc1945#section-10.2)
diff --git a/tools/task_kill.py b/tools/task_kill.py
index 05cf4fa..b13dba5 100755
--- a/tools/task_kill.py
+++ b/tools/task_kill.py
@@ -27,6 +27,7 @@
     'chrome': 'chrome.exe',
     'content_shell': 'content_shell.exe',
     'dart': 'dart.exe',
+    'editor': 'DartEditor.exe',
     'iexplore': 'iexplore.exe',
     'firefox': 'firefox.exe',
     'git': 'git.exe',
@@ -36,6 +37,8 @@
     'chrome': 'chrome',
     'content_shell': 'content_shell',
     'dart': 'dart',
+    'editor': 'DartEditor',
+    'eggplant': 'Eggplant',
     'firefox': 'firefox.exe',
     'git': 'git',
     'svn': 'svn'
@@ -44,6 +47,7 @@
     'chrome': 'Chrome',
     'content_shell': 'Content Shell',
     'dart': 'dart',
+    'editor': 'DartEditor',
     'firefox': 'firefox',
     'safari': 'Safari',
     'git': 'git',
@@ -65,6 +69,8 @@
                     help="Kill all git and svn processes")
   parser.add_option("--kill_browsers", default=False,
                      help="Kill all browser processes")
+  parser.add_option("--kill_editor", default=True,
+                     help="Kill all editor processes")
   (options, args) = parser.parse_args()
   return options
 
@@ -187,6 +193,12 @@
   status = Kill("dart")
   return status
 
+def KillEditor():
+  status = Kill("editor")
+  if os_name == "linux":
+    status += Kill("eggplant")
+  return status
+
 def Main():
   options = GetOptions()
   status = 0
@@ -196,6 +208,8 @@
     status += KillVCSystems();
   if (options.kill_browsers):
     status += KillBrowsers()
+  if (options.kill_editor):
+    status += KillEditor()
   return status
 
 if __name__ == '__main__':