cmd/heapview: dowgrade to customelements v0

I've had too many issues with customelements v1. The interface for v0
isn't as nice, and v0 will eventually be deprecated. But v1's polyfill
library is better supported, and it will be easy to upgrade later.

Change-Id: I87b376376b750167a0464c6c249930edecbd59db
Reviewed-on: https://go-review.googlesource.com/25545
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/cmd/heapview/client/main.ts b/cmd/heapview/client/main.ts
index 787c569..045e069 100644
--- a/cmd/heapview/client/main.ts
+++ b/cmd/heapview/client/main.ts
@@ -6,17 +6,17 @@
  * A hamburger menu element.
  */
 class HamburgerElement extends HTMLElement {
-  connectedCallback() {
+  attachedCallback() {
     this.innerHTML = '&#9776';  // Unicode character for hamburger menu.
   }
 }
-window.customElements.define('heap-hamburger', HamburgerElement);
+document.registerElement('heap-hamburger', HamburgerElement);
 
 /**
  * A heading for the page with a hamburger menu and a title.
  */
 export class HeadingElement extends HTMLElement {
-  connectedCallback() {
+  attachedCallback() {
     this.style.display = 'block';
     this.style.backgroundColor = '#2196F3';
     this.style.webkitUserSelect = 'none';
@@ -28,8 +28,7 @@
     `;
   }
 }
-window.customElements.define('heap-heading', HeadingElement);
-
+document.registerElement('heap-heading', HeadingElement);
 
 /**
  * Reset body's margin and padding, and set font.
@@ -46,5 +45,5 @@
 export function main() {
   document.title = 'Go Heap Viewer';
   clearStyle();
-  document.body.appendChild(new HeadingElement());
+  document.body.appendChild(document.createElement("heap-heading"));
 }
diff --git a/third_party/webcomponents/customelements.js b/third_party/webcomponents/customelements.js
index aec587f..931f6c2 100644
--- a/third_party/webcomponents/customelements.js
+++ b/third_party/webcomponents/customelements.js
@@ -1,597 +1,1029 @@
 /**
  * @license
- * Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
+ * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
  * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  * Code distributed by Google as part of the polymer project is also
  * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  */
-
-/**
- * 2.3
- * http://w3c.github.io/webcomponents/spec/custom/#dfn-element-definition
- * @typedef {{
- *  name: string,
- *  localName: string,
- *  constructor: Function,
- *  connectedCallback: Function,
- *  disconnectedCallback: Function,
- *  attributeChangedCallback: Function,
- *  observedAttributes: Array<string>,
- * }}
- */
-var CustomElementDefinition;
-
-(function() {
-  'use strict';
-
-  var doc = document;
-  var win = window;
-
-  // name validation
-  // https://html.spec.whatwg.org/multipage/scripting.html#valid-custom-element-name
-
-  /**
-   * @const
-   * @type {Array<string>}
-   */
-  var reservedTagList = [
-    'annotation-xml',
-    'color-profile',
-    'font-face',
-    'font-face-src',
-    'font-face-uri',
-    'font-face-format',
-    'font-face-name',
-    'missing-glyph',
-  ];
-
-  /** @const */
-  var customNameValidation = /^[a-z][.0-9_a-z]*-[\-.0-9_a-z]*$/;
-  function isValidCustomElementName(name) {
-    return customNameValidation.test(name) && reservedTagList.indexOf(name) === -1;
-  }
-
-  function createTreeWalker(root) {
-    // IE 11 requires the third and fourth arguments be present. If the third
-    // arg is null, it applies the default behaviour. However IE also requires
-    // the fourth argument be present even though the other browsers ignore it.
-    return doc.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, null, false);
-  }
-
-  function isElement(node) {
-    return node.nodeType === Node.ELEMENT_NODE
-  }
-
-  /**
-   * A registry of custom element definitions.
-   *
-   * See https://html.spec.whatwg.org/multipage/scripting.html#customelementsregistry
-   *
-   * @constructor
-   * @property {boolean} polyfilled Whether this registry is polyfilled
-   * @property {boolean} enableFlush Set to true to enable the flush() method
-   *   to work. This should only be done for tests, as it causes a memory leak.
-   */
-  function CustomElementsRegistry() {
-    /** @private {Map<string, CustomElementDefinition>} **/
-    this._definitions = new Map();
-
-    /** @private {Map<Function, CustomElementDefinition>} **/
-    this._constructors = new Map();
-
-    this._whenDefinedMap = new Map();
-
-    /** @private {Set<MutationObserver>} **/
-    this._observers = new Set();
-
-    /** @private {MutationObserver} **/
-    this._attributeObserver =
-        new MutationObserver(this._handleAttributeChange.bind(this));
-
-    /** @private {HTMLElement} **/
-    this._newInstance = null;
-
-    this.polyfilled = true;
-    this.enableFlush = false;
-
-    this._observeRoot(document);
-  }
-
-  CustomElementsRegistry.prototype = {
-
-    // HTML spec part 4.13.4
-    // https://html.spec.whatwg.org/multipage/scripting.html#dom-customelementsregistry-define
-    define: function(name, constructor, options) {
-      name = name.toString().toLowerCase();
-
-      // 1:
-      if (typeof constructor !== 'function') {
-        throw new TypeError('constructor must be a Constructor');
-      }
-
-      // 2. If constructor is an interface object whose corresponding interface
-      //    either is HTMLElement or has HTMLElement in its set of inherited
-      //    interfaces, throw a TypeError and abort these steps.
-      //
-      // It doesn't appear possible to check this condition from script
-
-      // 3:
-      if (!isValidCustomElementName(name)) {
-        throw new SyntaxError(`The element name '${name}' is not valid.`);
-      }
-
-      // 4, 5:
-      // Note: we don't track being-defined names and constructors because
-      // define() isn't normally reentrant. The only time user code can run
-      // during define() is when getting callbacks off the prototype, which
-      // would be highly-unusual. We can make define() reentrant-safe if needed.
-      if (this._definitions.has(name)) {
-        throw new Error(`An element with name '${name}' is already defined`);
-      }
-
-      // 6, 7:
-      if (this._constructors.has(constructor)) {
-        throw new Error(`Definition failed for '${name}': ` +
-            `The constructor is already used.`);
-      }
-
-      // 8:
-      var localName = name;
-
-      // 9, 10: We do not support extends currently.
-
-      // 11, 12, 13: Our define() isn't rentrant-safe
-
-      // 14.1:
-      var prototype = constructor.prototype;
-
-      // 14.2:
-      if (typeof prototype !== 'object') {
-        throw new TypeError(`Definition failed for '${name}': ` +
-            `constructor.prototype must be an object`);
-      }
-
-      function getCallback(calllbackName) {
-        var callback = prototype[calllbackName];
-        if (callback !== undefined && typeof callback !== 'function') {
-          throw new Error(`${localName} '${calllbackName}' is not a Function`);
-        }
-        return callback;
-      }
-
-      // 3, 4:
-      var connectedCallback = getCallback('connectedCallback');
-
-      // 5, 6:
-      var disconnectedCallback = getCallback('disconnectedCallback');
-
-      // Divergence from spec: we always throw if attributeChangedCallback is
-      // not a function, and always get observedAttributes.
-
-      // 7, 9.1:
-      var attributeChangedCallback = getCallback('attributeChangedCallback');
-
-      // 8, 9.2, 9.3:
-      var observedAttributes = constructor['observedAttributes'] || [];
-
-      // 15:
-      // @type {CustomElementDefinition}
-      var definition = {
-        name: name,
-        localName: localName,
-        constructor: constructor,
-        connectedCallback: connectedCallback,
-        disconnectedCallback: disconnectedCallback,
-        attributeChangedCallback: attributeChangedCallback,
-        observedAttributes: observedAttributes,
-      };
-
-      // 16:
-      this._definitions.set(localName, definition);
-      this._constructors.set(constructor, localName);
-
-      // 17, 18, 19:
-      this._addNodes(doc.childNodes);
-
-      // 20:
-      var deferred = this._whenDefinedMap.get(localName);
-      if (deferred) {
-        deferred.resolve(undefined);
-        this._whenDefinedMap.delete(localName);
-      }
-    },
-
-    /**
-     * Returns the constructor defined for `name`, or `null`.
-     *
-     * @param {string} name
-     * @return {Function|undefined}
-     */
-    get: function(name) {
-      // https://html.spec.whatwg.org/multipage/scripting.html#custom-elements-api
-      var def = this._definitions.get(name);
-      return def ? def.constructor : undefined;
-    },
-
-    /**
-     * Returns a `Promise` that resolves when a custom element for `name` has
-     * been defined.
-     *
-     * @param {string} name
-     * @return {Promise}
-     */
-    whenDefined: function(name) {
-      // https://html.spec.whatwg.org/multipage/scripting.html#dom-customelementsregistry-whendefined
-      if (!customNameValidation.test(name)) {
-        return Promise.reject(
-          new SyntaxError(`The element name '${name}' is not valid.`));
-      }
-      if (this._definitions.has(name)) {
-        return Promise.resolve();
-      }
-      var deferred = {
-        promise: null,
-      };
-      deferred.promise = new Promise(function(resolve, _) {
-       deferred.resolve = resolve;
-      });
-      this._whenDefinedMap.set(name, deferred);
-      return deferred.promise;
-    },
-
-    /**
-     * Causes all pending mutation records to be processed, and thus all
-     * customization, upgrades and custom element reactions to be called.
-     * `enableFlush` must be true for this to work. Only use during tests!
-     */
-    flush: function() {
-      if (this.enableFlush) {
-        console.warn("flush!!!");
-        this._observers.forEach(function(observer) {
-          this._handleMutations(observer.takeRecords());
-        }, this);
-      }
-    },
-
-    _setNewInstance: function(instance) {
-      this._newInstance = instance;
-    },
-
-    /**
-     * Observes a DOM root for mutations that trigger upgrades and reactions.
-     * @private
-     */
-    _observeRoot: function(root) {
-      root.__observer = new MutationObserver(this._handleMutations.bind(this));
-      root.__observer.observe(root, {childList: true, subtree: true});
-      if (this.enableFlush) {
-        // this is memory leak, only use in tests
-        this._observers.add(root.__observer);
-      }
-    },
-
-    /**
-     * @private
-     */
-    _unobserveRoot: function(root) {
-      if (root.__observer) {
-        root.__observer.disconnect();
-        root.__observer = null;
-        if (this.enableFlush) {
-          this._observers.delete(root.__observer);
-        }
-      }
-    },
-
-    /**
-     * @private
-     */
-    _handleMutations: function(mutations) {
-      for (var i = 0; i < mutations.length; i++) {
-        var mutation = mutations[i];
-        if (mutation.type === 'childList') {
-          // Note: we can't get an ordering between additions and removals, and
-          // so might diverge from spec reaction ordering
-          this._addNodes(mutation.addedNodes);
-          this._removeNodes(mutation.removedNodes);
-        }
-      }
-    },
-
-    /**
-     * @param {NodeList} nodeList
-     * @private
-     */
-    _addNodes: function(nodeList) {
-      for (var i = 0; i < nodeList.length; i++) {
-        var root = nodeList[i];
-
-        if (!isElement(root)) {
-          continue;
-        }
-
-        // Since we're adding this node to an observed tree, we can unobserve
-        this._unobserveRoot(root);
-
-        var walker = createTreeWalker(root);
-        do {
-          var node = /** @type {HTMLElement} */ (walker.currentNode);
-          var definition = this._definitions.get(node.localName);
-          if (definition) {
-            if (!node.__upgraded) {
-              this._upgradeElement(node, definition, true);
-            }
-            if (node.__upgraded && !node.__attached) {
-              node.__attached = true;
-              if (definition && definition.connectedCallback) {
-                definition.connectedCallback.call(node);
-              }
-            }
-          }
-          if (node.shadowRoot) {
-            // TODO(justinfagnani): do we need to check that the shadowRoot
-            // is observed?
-            this._addNodes(node.shadowRoot.childNodes);
-          }
-          if (node.tagName === 'LINK') {
-            var onLoad = (function() {
-              var link = node;
-              return function() {
-                link.removeEventListener('load', onLoad);
-                this._observeRoot(link.import);
-                this._addNodes(link.import.childNodes);
-              }.bind(this);
-            }).bind(this)();
-            if (node.import) {
-              onLoad();
-            } else {
-              node.addEventListener('load', onLoad);
-            }
-          }
-        } while (walker.nextNode())
-      }
-    },
-
-    /**
-     * @param {NodeList} nodeList
-     * @private
-     */
-    _removeNodes: function(nodeList) {
-      for (var i = 0; i < nodeList.length; i++) {
-        var root = nodeList[i];
-
-        if (!isElement(root)) {
-          continue;
-        }
-
-        // Since we're detatching this element from an observed root, we need to
-        // reobserve it.
-        // TODO(justinfagnani): can we do this in a microtask so we don't thrash
-        // on creating and destroying MutationObservers on batch DOM mutations?
-        this._observeRoot(root);
-
-        var walker = createTreeWalker(root);
-        do {
-          var node = walker.currentNode;
-          if (node.__upgraded && node.__attached) {
-            node.__attached = false;
-            var definition = this._definitions.get(node.localName);
-            if (definition && definition.disconnectedCallback) {
-              definition.disconnectedCallback.call(node);
-            }
-          }
-        } while (walker.nextNode())
-      }
-    },
-
-    /**
-     * Upgrades or customizes a custom element.
-     *
-     * @param {HTMLElement} element
-     * @param {CustomElementDefinition} definition
-     * @param {boolean} callConstructor
-     * @private
-     */
-    _upgradeElement: function(element, definition, callConstructor) {
-      var prototype = definition.constructor.prototype;
-      element.__proto__ = prototype;
-      if (callConstructor) {
-        this._setNewInstance(element);
-        element.__upgraded = true;
-        new (definition.constructor)();
-        console.assert(this._newInstance == null);
-      }
-
-      var observedAttributes = definition.observedAttributes;
-      if (definition.attributeChangedCallback && observedAttributes.length > 0) {
-        this._attributeObserver.observe(element, {
-          attributes: true,
-          attributeOldValue: true,
-          attributeFilter: observedAttributes,
+// @version 0.7.22
+if (typeof WeakMap === "undefined") {
+  (function() {
+    var defineProperty = Object.defineProperty;
+    var counter = Date.now() % 1e9;
+    var WeakMap = function() {
+      this.name = "__st" + (Math.random() * 1e9 >>> 0) + (counter++ + "__");
+    };
+    WeakMap.prototype = {
+      set: function(key, value) {
+        var entry = key[this.name];
+        if (entry && entry[0] === key) entry[1] = value; else defineProperty(key, this.name, {
+          value: [ key, value ],
+          writable: true
         });
-
-        // Trigger attributeChangedCallback for existing attributes.
-        // https://html.spec.whatwg.org/multipage/scripting.html#upgrades
-        for (var i = 0; i < observedAttributes.length; i++) {
-          var name = observedAttributes[i];
-          if (element.hasAttribute(name)) {
-            var value = element.getAttribute(name);
-            element.attributeChangedCallback(name, null, value);
-          }
-        }
-      }
-    },
-
-    /**
-     * @private
-     */
-    _handleAttributeChange: function(mutations) {
-      for (var i = 0; i < mutations.length; i++) {
-        var mutation = mutations[i];
-        if (mutation.type === 'attributes') {
-          var name = mutation.attributeName;
-          var oldValue = mutation.oldValue;
-          var target = mutation.target;
-          var newValue = target.getAttribute(name);
-          var namespace = mutation.attributeNamespace;
-          target['attributeChangedCallback'](name, oldValue, newValue, namespace);
-        }
-      }
-    },
-  }
-
-  // Closure Compiler Exports
-  window['CustomElementsRegistry'] = CustomElementsRegistry;
-  CustomElementsRegistry.prototype['define'] = CustomElementsRegistry.prototype.define;
-  CustomElementsRegistry.prototype['get'] = CustomElementsRegistry.prototype.get;
-  CustomElementsRegistry.prototype['whenDefined'] = CustomElementsRegistry.prototype.whenDefined;
-  CustomElementsRegistry.prototype['flush'] = CustomElementsRegistry.prototype.flush;
-  CustomElementsRegistry.prototype['polyfilled'] = CustomElementsRegistry.prototype.polyfilled;
-  CustomElementsRegistry.prototype['enableFlush'] = CustomElementsRegistry.prototype.enableFlush;
-
-  // patch window.HTMLElement
-
-  var origHTMLElement = win.HTMLElement;
-  win.HTMLElement = function HTMLElement() {
-    var customElements = win['customElements'];
-    if (customElements._newInstance) {
-      var i = customElements._newInstance;
-      customElements._newInstance = null;
-      return i;
-    }
-    if (this.constructor) {
-      var tagName = customElements._constructors.get(this.constructor);
-      return doc._createElement(tagName, false);
-    }
-    throw new Error('unknown constructor. Did you call customElements.define()?');
-  }
-  win.HTMLElement.prototype = Object.create(origHTMLElement.prototype);
-  Object.defineProperty(win.HTMLElement.prototype, 'constructor', {value: win.HTMLElement});
-
-  // patch all built-in subclasses of HTMLElement to inherit from the new HTMLElement
-  // See https://html.spec.whatwg.org/multipage/indices.html#element-interfaces
-
-  /** @const */
-  var htmlElementSubclasses = [
-  	'Button',
-  	'Canvas',
-  	'Data',
-  	'Head',
-  	'Mod',
-  	'TableCell',
-  	'TableCol',
-    'Anchor',
-    'Area',
-    'Base',
-    'Body',
-    'BR',
-    'DataList',
-    'Details',
-    'Dialog',
-    'Div',
-    'DList',
-    'Embed',
-    'FieldSet',
-    'Form',
-    'Heading',
-    'HR',
-    'Html',
-    'IFrame',
-    'Image',
-    'Input',
-    'Keygen',
-    'Label',
-    'Legend',
-    'LI',
-    'Link',
-    'Map',
-    'Media',
-    'Menu',
-    'MenuItem',
-    'Meta',
-    'Meter',
-    'Object',
-    'OList',
-    'OptGroup',
-    'Option',
-    'Output',
-    'Paragraph',
-    'Param',
-    'Picture',
-    'Pre',
-    'Progress',
-    'Quote',
-    'Script',
-    'Select',
-    'Slot',
-    'Source',
-    'Span',
-    'Style',
-    'TableCaption',
-    'Table',
-    'TableRow',
-    'TableSection',
-    'Template',
-    'TextArea',
-    'Time',
-    'Title',
-    'Track',
-    'UList',
-    'Unknown',
-  ];
-
-  for (var i = 0; i < htmlElementSubclasses.length; i++) {
-    var ctor = window['HTML' + htmlElementSubclasses[i] + 'Element'];
-    if (ctor) {
-      ctor.prototype.__proto__ = win.HTMLElement.prototype;
-    }
-  }
-
-  // patch doc.createElement
-
-  var rawCreateElement = doc.createElement;
-  doc._createElement = function(tagName, callConstructor) {
-    var customElements = win['customElements'];
-    var element = rawCreateElement.call(doc, tagName);
-    var definition = customElements._definitions.get(tagName.toLowerCase());
-    if (definition) {
-      customElements._upgradeElement(element, definition, callConstructor);
-    }
-    customElements._observeRoot(element);
-    return element;
-  };
-  doc.createElement = function(tagName) {
-    return doc._createElement(tagName, true);
-  }
-
-  // patch doc.createElementNS
-
-  var HTMLNS = 'http://www.w3.org/1999/xhtml';
-  var _origCreateElementNS = doc.createElementNS;
-  doc.createElementNS = function(namespaceURI, qualifiedName) {
-    if (namespaceURI === 'http://www.w3.org/1999/xhtml') {
-      return doc.createElement(qualifiedName);
-    } else {
-      return _origCreateElementNS.call(document, namespaceURI, qualifiedName);
-    }
-  };
-
-  // patch Element.attachShadow
-
-  var _origAttachShadow = Element.prototype['attachShadow'];
-  if (_origAttachShadow) {
-    Object.defineProperty(Element.prototype, 'attachShadow', {
-      value: function(options) {
-        var root = _origAttachShadow.call(this, options);
-        var customElements = win['customElements'];
-        customElements._observeRoot(root);
-        return root;
+        return this;
       },
+      get: function(key) {
+        var entry;
+        return (entry = key[this.name]) && entry[0] === key ? entry[1] : undefined;
+      },
+      "delete": function(key) {
+        var entry = key[this.name];
+        if (!entry || entry[0] !== key) return false;
+        entry[0] = entry[1] = undefined;
+        return true;
+      },
+      has: function(key) {
+        var entry = key[this.name];
+        if (!entry) return false;
+        return entry[0] === key;
+      }
+    };
+    window.WeakMap = WeakMap;
+  })();
+}
+
+(function(global) {
+  if (global.JsMutationObserver) {
+    return;
+  }
+  var registrationsTable = new WeakMap();
+  var setImmediate;
+  if (/Trident|Edge/.test(navigator.userAgent)) {
+    setImmediate = setTimeout;
+  } else if (window.setImmediate) {
+    setImmediate = window.setImmediate;
+  } else {
+    var setImmediateQueue = [];
+    var sentinel = String(Math.random());
+    window.addEventListener("message", function(e) {
+      if (e.data === sentinel) {
+        var queue = setImmediateQueue;
+        setImmediateQueue = [];
+        queue.forEach(function(func) {
+          func();
+        });
+      }
+    });
+    setImmediate = function(func) {
+      setImmediateQueue.push(func);
+      window.postMessage(sentinel, "*");
+    };
+  }
+  var isScheduled = false;
+  var scheduledObservers = [];
+  function scheduleCallback(observer) {
+    scheduledObservers.push(observer);
+    if (!isScheduled) {
+      isScheduled = true;
+      setImmediate(dispatchCallbacks);
+    }
+  }
+  function wrapIfNeeded(node) {
+    return window.ShadowDOMPolyfill && window.ShadowDOMPolyfill.wrapIfNeeded(node) || node;
+  }
+  function dispatchCallbacks() {
+    isScheduled = false;
+    var observers = scheduledObservers;
+    scheduledObservers = [];
+    observers.sort(function(o1, o2) {
+      return o1.uid_ - o2.uid_;
+    });
+    var anyNonEmpty = false;
+    observers.forEach(function(observer) {
+      var queue = observer.takeRecords();
+      removeTransientObserversFor(observer);
+      if (queue.length) {
+        observer.callback_(queue, observer);
+        anyNonEmpty = true;
+      }
+    });
+    if (anyNonEmpty) dispatchCallbacks();
+  }
+  function removeTransientObserversFor(observer) {
+    observer.nodes_.forEach(function(node) {
+      var registrations = registrationsTable.get(node);
+      if (!registrations) return;
+      registrations.forEach(function(registration) {
+        if (registration.observer === observer) registration.removeTransientObservers();
+      });
     });
   }
+  function forEachAncestorAndObserverEnqueueRecord(target, callback) {
+    for (var node = target; node; node = node.parentNode) {
+      var registrations = registrationsTable.get(node);
+      if (registrations) {
+        for (var j = 0; j < registrations.length; j++) {
+          var registration = registrations[j];
+          var options = registration.options;
+          if (node !== target && !options.subtree) continue;
+          var record = callback(options);
+          if (record) registration.enqueue(record);
+        }
+      }
+    }
+  }
+  var uidCounter = 0;
+  function JsMutationObserver(callback) {
+    this.callback_ = callback;
+    this.nodes_ = [];
+    this.records_ = [];
+    this.uid_ = ++uidCounter;
+  }
+  JsMutationObserver.prototype = {
+    observe: function(target, options) {
+      target = wrapIfNeeded(target);
+      if (!options.childList && !options.attributes && !options.characterData || options.attributeOldValue && !options.attributes || options.attributeFilter && options.attributeFilter.length && !options.attributes || options.characterDataOldValue && !options.characterData) {
+        throw new SyntaxError();
+      }
+      var registrations = registrationsTable.get(target);
+      if (!registrations) registrationsTable.set(target, registrations = []);
+      var registration;
+      for (var i = 0; i < registrations.length; i++) {
+        if (registrations[i].observer === this) {
+          registration = registrations[i];
+          registration.removeListeners();
+          registration.options = options;
+          break;
+        }
+      }
+      if (!registration) {
+        registration = new Registration(this, target, options);
+        registrations.push(registration);
+        this.nodes_.push(target);
+      }
+      registration.addListeners();
+    },
+    disconnect: function() {
+      this.nodes_.forEach(function(node) {
+        var registrations = registrationsTable.get(node);
+        for (var i = 0; i < registrations.length; i++) {
+          var registration = registrations[i];
+          if (registration.observer === this) {
+            registration.removeListeners();
+            registrations.splice(i, 1);
+            break;
+          }
+        }
+      }, this);
+      this.records_ = [];
+    },
+    takeRecords: function() {
+      var copyOfRecords = this.records_;
+      this.records_ = [];
+      return copyOfRecords;
+    }
+  };
+  function MutationRecord(type, target) {
+    this.type = type;
+    this.target = target;
+    this.addedNodes = [];
+    this.removedNodes = [];
+    this.previousSibling = null;
+    this.nextSibling = null;
+    this.attributeName = null;
+    this.attributeNamespace = null;
+    this.oldValue = null;
+  }
+  function copyMutationRecord(original) {
+    var record = new MutationRecord(original.type, original.target);
+    record.addedNodes = original.addedNodes.slice();
+    record.removedNodes = original.removedNodes.slice();
+    record.previousSibling = original.previousSibling;
+    record.nextSibling = original.nextSibling;
+    record.attributeName = original.attributeName;
+    record.attributeNamespace = original.attributeNamespace;
+    record.oldValue = original.oldValue;
+    return record;
+  }
+  var currentRecord, recordWithOldValue;
+  function getRecord(type, target) {
+    return currentRecord = new MutationRecord(type, target);
+  }
+  function getRecordWithOldValue(oldValue) {
+    if (recordWithOldValue) return recordWithOldValue;
+    recordWithOldValue = copyMutationRecord(currentRecord);
+    recordWithOldValue.oldValue = oldValue;
+    return recordWithOldValue;
+  }
+  function clearRecords() {
+    currentRecord = recordWithOldValue = undefined;
+  }
+  function recordRepresentsCurrentMutation(record) {
+    return record === recordWithOldValue || record === currentRecord;
+  }
+  function selectRecord(lastRecord, newRecord) {
+    if (lastRecord === newRecord) return lastRecord;
+    if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord)) return recordWithOldValue;
+    return null;
+  }
+  function Registration(observer, target, options) {
+    this.observer = observer;
+    this.target = target;
+    this.options = options;
+    this.transientObservedNodes = [];
+  }
+  Registration.prototype = {
+    enqueue: function(record) {
+      var records = this.observer.records_;
+      var length = records.length;
+      if (records.length > 0) {
+        var lastRecord = records[length - 1];
+        var recordToReplaceLast = selectRecord(lastRecord, record);
+        if (recordToReplaceLast) {
+          records[length - 1] = recordToReplaceLast;
+          return;
+        }
+      } else {
+        scheduleCallback(this.observer);
+      }
+      records[length] = record;
+    },
+    addListeners: function() {
+      this.addListeners_(this.target);
+    },
+    addListeners_: function(node) {
+      var options = this.options;
+      if (options.attributes) node.addEventListener("DOMAttrModified", this, true);
+      if (options.characterData) node.addEventListener("DOMCharacterDataModified", this, true);
+      if (options.childList) node.addEventListener("DOMNodeInserted", this, true);
+      if (options.childList || options.subtree) node.addEventListener("DOMNodeRemoved", this, true);
+    },
+    removeListeners: function() {
+      this.removeListeners_(this.target);
+    },
+    removeListeners_: function(node) {
+      var options = this.options;
+      if (options.attributes) node.removeEventListener("DOMAttrModified", this, true);
+      if (options.characterData) node.removeEventListener("DOMCharacterDataModified", this, true);
+      if (options.childList) node.removeEventListener("DOMNodeInserted", this, true);
+      if (options.childList || options.subtree) node.removeEventListener("DOMNodeRemoved", this, true);
+    },
+    addTransientObserver: function(node) {
+      if (node === this.target) return;
+      this.addListeners_(node);
+      this.transientObservedNodes.push(node);
+      var registrations = registrationsTable.get(node);
+      if (!registrations) registrationsTable.set(node, registrations = []);
+      registrations.push(this);
+    },
+    removeTransientObservers: function() {
+      var transientObservedNodes = this.transientObservedNodes;
+      this.transientObservedNodes = [];
+      transientObservedNodes.forEach(function(node) {
+        this.removeListeners_(node);
+        var registrations = registrationsTable.get(node);
+        for (var i = 0; i < registrations.length; i++) {
+          if (registrations[i] === this) {
+            registrations.splice(i, 1);
+            break;
+          }
+        }
+      }, this);
+    },
+    handleEvent: function(e) {
+      e.stopImmediatePropagation();
+      switch (e.type) {
+       case "DOMAttrModified":
+        var name = e.attrName;
+        var namespace = e.relatedNode.namespaceURI;
+        var target = e.target;
+        var record = new getRecord("attributes", target);
+        record.attributeName = name;
+        record.attributeNamespace = namespace;
+        var oldValue = e.attrChange === MutationEvent.ADDITION ? null : e.prevValue;
+        forEachAncestorAndObserverEnqueueRecord(target, function(options) {
+          if (!options.attributes) return;
+          if (options.attributeFilter && options.attributeFilter.length && options.attributeFilter.indexOf(name) === -1 && options.attributeFilter.indexOf(namespace) === -1) {
+            return;
+          }
+          if (options.attributeOldValue) return getRecordWithOldValue(oldValue);
+          return record;
+        });
+        break;
 
-  /** @type {CustomElementsRegistry} */
-  window['customElements'] = new CustomElementsRegistry();
-})();
+       case "DOMCharacterDataModified":
+        var target = e.target;
+        var record = getRecord("characterData", target);
+        var oldValue = e.prevValue;
+        forEachAncestorAndObserverEnqueueRecord(target, function(options) {
+          if (!options.characterData) return;
+          if (options.characterDataOldValue) return getRecordWithOldValue(oldValue);
+          return record;
+        });
+        break;
+
+       case "DOMNodeRemoved":
+        this.addTransientObserver(e.target);
+
+       case "DOMNodeInserted":
+        var changedNode = e.target;
+        var addedNodes, removedNodes;
+        if (e.type === "DOMNodeInserted") {
+          addedNodes = [ changedNode ];
+          removedNodes = [];
+        } else {
+          addedNodes = [];
+          removedNodes = [ changedNode ];
+        }
+        var previousSibling = changedNode.previousSibling;
+        var nextSibling = changedNode.nextSibling;
+        var record = getRecord("childList", e.target.parentNode);
+        record.addedNodes = addedNodes;
+        record.removedNodes = removedNodes;
+        record.previousSibling = previousSibling;
+        record.nextSibling = nextSibling;
+        forEachAncestorAndObserverEnqueueRecord(e.relatedNode, function(options) {
+          if (!options.childList) return;
+          return record;
+        });
+      }
+      clearRecords();
+    }
+  };
+  global.JsMutationObserver = JsMutationObserver;
+  if (!global.MutationObserver) {
+    global.MutationObserver = JsMutationObserver;
+    JsMutationObserver._isPolyfilled = true;
+  }
+})(self);
+
+(function(scope) {
+  "use strict";
+  if (!window.performance) {
+    var start = Date.now();
+    window.performance = {
+      now: function() {
+        return Date.now() - start;
+      }
+    };
+  }
+  if (!window.requestAnimationFrame) {
+    window.requestAnimationFrame = function() {
+      var nativeRaf = window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
+      return nativeRaf ? function(callback) {
+        return nativeRaf(function() {
+          callback(performance.now());
+        });
+      } : function(callback) {
+        return window.setTimeout(callback, 1e3 / 60);
+      };
+    }();
+  }
+  if (!window.cancelAnimationFrame) {
+    window.cancelAnimationFrame = function() {
+      return window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || function(id) {
+        clearTimeout(id);
+      };
+    }();
+  }
+  var workingDefaultPrevented = function() {
+    var e = document.createEvent("Event");
+    e.initEvent("foo", true, true);
+    e.preventDefault();
+    return e.defaultPrevented;
+  }();
+  if (!workingDefaultPrevented) {
+    var origPreventDefault = Event.prototype.preventDefault;
+    Event.prototype.preventDefault = function() {
+      if (!this.cancelable) {
+        return;
+      }
+      origPreventDefault.call(this);
+      Object.defineProperty(this, "defaultPrevented", {
+        get: function() {
+          return true;
+        },
+        configurable: true
+      });
+    };
+  }
+  var isIE = /Trident/.test(navigator.userAgent);
+  if (!window.CustomEvent || isIE && typeof window.CustomEvent !== "function") {
+    window.CustomEvent = function(inType, params) {
+      params = params || {};
+      var e = document.createEvent("CustomEvent");
+      e.initCustomEvent(inType, Boolean(params.bubbles), Boolean(params.cancelable), params.detail);
+      return e;
+    };
+    window.CustomEvent.prototype = window.Event.prototype;
+  }
+  if (!window.Event || isIE && typeof window.Event !== "function") {
+    var origEvent = window.Event;
+    window.Event = function(inType, params) {
+      params = params || {};
+      var e = document.createEvent("Event");
+      e.initEvent(inType, Boolean(params.bubbles), Boolean(params.cancelable));
+      return e;
+    };
+    window.Event.prototype = origEvent.prototype;
+  }
+})(window.WebComponents);
+
+window.CustomElements = window.CustomElements || {
+  flags: {}
+};
+
+(function(scope) {
+  var flags = scope.flags;
+  var modules = [];
+  var addModule = function(module) {
+    modules.push(module);
+  };
+  var initializeModules = function() {
+    modules.forEach(function(module) {
+      module(scope);
+    });
+  };
+  scope.addModule = addModule;
+  scope.initializeModules = initializeModules;
+  scope.hasNative = Boolean(document.registerElement);
+  scope.isIE = /Trident/.test(navigator.userAgent);
+  scope.useNative = !flags.register && scope.hasNative && !window.ShadowDOMPolyfill && (!window.HTMLImports || window.HTMLImports.useNative);
+})(window.CustomElements);
+
+window.CustomElements.addModule(function(scope) {
+  var IMPORT_LINK_TYPE = window.HTMLImports ? window.HTMLImports.IMPORT_LINK_TYPE : "none";
+  function forSubtree(node, cb) {
+    findAllElements(node, function(e) {
+      if (cb(e)) {
+        return true;
+      }
+      forRoots(e, cb);
+    });
+    forRoots(node, cb);
+  }
+  function findAllElements(node, find, data) {
+    var e = node.firstElementChild;
+    if (!e) {
+      e = node.firstChild;
+      while (e && e.nodeType !== Node.ELEMENT_NODE) {
+        e = e.nextSibling;
+      }
+    }
+    while (e) {
+      if (find(e, data) !== true) {
+        findAllElements(e, find, data);
+      }
+      e = e.nextElementSibling;
+    }
+    return null;
+  }
+  function forRoots(node, cb) {
+    var root = node.shadowRoot;
+    while (root) {
+      forSubtree(root, cb);
+      root = root.olderShadowRoot;
+    }
+  }
+  function forDocumentTree(doc, cb) {
+    _forDocumentTree(doc, cb, []);
+  }
+  function _forDocumentTree(doc, cb, processingDocuments) {
+    doc = window.wrap(doc);
+    if (processingDocuments.indexOf(doc) >= 0) {
+      return;
+    }
+    processingDocuments.push(doc);
+    var imports = doc.querySelectorAll("link[rel=" + IMPORT_LINK_TYPE + "]");
+    for (var i = 0, l = imports.length, n; i < l && (n = imports[i]); i++) {
+      if (n.import) {
+        _forDocumentTree(n.import, cb, processingDocuments);
+      }
+    }
+    cb(doc);
+  }
+  scope.forDocumentTree = forDocumentTree;
+  scope.forSubtree = forSubtree;
+});
+
+window.CustomElements.addModule(function(scope) {
+  var flags = scope.flags;
+  var forSubtree = scope.forSubtree;
+  var forDocumentTree = scope.forDocumentTree;
+  function addedNode(node, isAttached) {
+    return added(node, isAttached) || addedSubtree(node, isAttached);
+  }
+  function added(node, isAttached) {
+    if (scope.upgrade(node, isAttached)) {
+      return true;
+    }
+    if (isAttached) {
+      attached(node);
+    }
+  }
+  function addedSubtree(node, isAttached) {
+    forSubtree(node, function(e) {
+      if (added(e, isAttached)) {
+        return true;
+      }
+    });
+  }
+  var hasThrottledAttached = window.MutationObserver._isPolyfilled && flags["throttle-attached"];
+  scope.hasPolyfillMutations = hasThrottledAttached;
+  scope.hasThrottledAttached = hasThrottledAttached;
+  var isPendingMutations = false;
+  var pendingMutations = [];
+  function deferMutation(fn) {
+    pendingMutations.push(fn);
+    if (!isPendingMutations) {
+      isPendingMutations = true;
+      setTimeout(takeMutations);
+    }
+  }
+  function takeMutations() {
+    isPendingMutations = false;
+    var $p = pendingMutations;
+    for (var i = 0, l = $p.length, p; i < l && (p = $p[i]); i++) {
+      p();
+    }
+    pendingMutations = [];
+  }
+  function attached(element) {
+    if (hasThrottledAttached) {
+      deferMutation(function() {
+        _attached(element);
+      });
+    } else {
+      _attached(element);
+    }
+  }
+  function _attached(element) {
+    if (element.__upgraded__ && !element.__attached) {
+      element.__attached = true;
+      if (element.attachedCallback) {
+        element.attachedCallback();
+      }
+    }
+  }
+  function detachedNode(node) {
+    detached(node);
+    forSubtree(node, function(e) {
+      detached(e);
+    });
+  }
+  function detached(element) {
+    if (hasThrottledAttached) {
+      deferMutation(function() {
+        _detached(element);
+      });
+    } else {
+      _detached(element);
+    }
+  }
+  function _detached(element) {
+    if (element.__upgraded__ && element.__attached) {
+      element.__attached = false;
+      if (element.detachedCallback) {
+        element.detachedCallback();
+      }
+    }
+  }
+  function inDocument(element) {
+    var p = element;
+    var doc = window.wrap(document);
+    while (p) {
+      if (p == doc) {
+        return true;
+      }
+      p = p.parentNode || p.nodeType === Node.DOCUMENT_FRAGMENT_NODE && p.host;
+    }
+  }
+  function watchShadow(node) {
+    if (node.shadowRoot && !node.shadowRoot.__watched) {
+      flags.dom && console.log("watching shadow-root for: ", node.localName);
+      var root = node.shadowRoot;
+      while (root) {
+        observe(root);
+        root = root.olderShadowRoot;
+      }
+    }
+  }
+  function handler(root, mutations) {
+    if (flags.dom) {
+      var mx = mutations[0];
+      if (mx && mx.type === "childList" && mx.addedNodes) {
+        if (mx.addedNodes) {
+          var d = mx.addedNodes[0];
+          while (d && d !== document && !d.host) {
+            d = d.parentNode;
+          }
+          var u = d && (d.URL || d._URL || d.host && d.host.localName) || "";
+          u = u.split("/?").shift().split("/").pop();
+        }
+      }
+      console.group("mutations (%d) [%s]", mutations.length, u || "");
+    }
+    var isAttached = inDocument(root);
+    mutations.forEach(function(mx) {
+      if (mx.type === "childList") {
+        forEach(mx.addedNodes, function(n) {
+          if (!n.localName) {
+            return;
+          }
+          addedNode(n, isAttached);
+        });
+        forEach(mx.removedNodes, function(n) {
+          if (!n.localName) {
+            return;
+          }
+          detachedNode(n);
+        });
+      }
+    });
+    flags.dom && console.groupEnd();
+  }
+  function takeRecords(node) {
+    node = window.wrap(node);
+    if (!node) {
+      node = window.wrap(document);
+    }
+    while (node.parentNode) {
+      node = node.parentNode;
+    }
+    var observer = node.__observer;
+    if (observer) {
+      handler(node, observer.takeRecords());
+      takeMutations();
+    }
+  }
+  var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
+  function observe(inRoot) {
+    if (inRoot.__observer) {
+      return;
+    }
+    var observer = new MutationObserver(handler.bind(this, inRoot));
+    observer.observe(inRoot, {
+      childList: true,
+      subtree: true
+    });
+    inRoot.__observer = observer;
+  }
+  function upgradeDocument(doc) {
+    doc = window.wrap(doc);
+    flags.dom && console.group("upgradeDocument: ", doc.baseURI.split("/").pop());
+    var isMainDocument = doc === window.wrap(document);
+    addedNode(doc, isMainDocument);
+    observe(doc);
+    flags.dom && console.groupEnd();
+  }
+  function upgradeDocumentTree(doc) {
+    forDocumentTree(doc, upgradeDocument);
+  }
+  var originalCreateShadowRoot = Element.prototype.createShadowRoot;
+  if (originalCreateShadowRoot) {
+    Element.prototype.createShadowRoot = function() {
+      var root = originalCreateShadowRoot.call(this);
+      window.CustomElements.watchShadow(this);
+      return root;
+    };
+  }
+  scope.watchShadow = watchShadow;
+  scope.upgradeDocumentTree = upgradeDocumentTree;
+  scope.upgradeDocument = upgradeDocument;
+  scope.upgradeSubtree = addedSubtree;
+  scope.upgradeAll = addedNode;
+  scope.attached = attached;
+  scope.takeRecords = takeRecords;
+});
+
+window.CustomElements.addModule(function(scope) {
+  var flags = scope.flags;
+  function upgrade(node, isAttached) {
+    if (node.localName === "template") {
+      if (window.HTMLTemplateElement && HTMLTemplateElement.decorate) {
+        HTMLTemplateElement.decorate(node);
+      }
+    }
+    if (!node.__upgraded__ && node.nodeType === Node.ELEMENT_NODE) {
+      var is = node.getAttribute("is");
+      var definition = scope.getRegisteredDefinition(node.localName) || scope.getRegisteredDefinition(is);
+      if (definition) {
+        if (is && definition.tag == node.localName || !is && !definition.extends) {
+          return upgradeWithDefinition(node, definition, isAttached);
+        }
+      }
+    }
+  }
+  function upgradeWithDefinition(element, definition, isAttached) {
+    flags.upgrade && console.group("upgrade:", element.localName);
+    if (definition.is) {
+      element.setAttribute("is", definition.is);
+    }
+    implementPrototype(element, definition);
+    element.__upgraded__ = true;
+    created(element);
+    if (isAttached) {
+      scope.attached(element);
+    }
+    scope.upgradeSubtree(element, isAttached);
+    flags.upgrade && console.groupEnd();
+    return element;
+  }
+  function implementPrototype(element, definition) {
+    if (Object.__proto__) {
+      element.__proto__ = definition.prototype;
+    } else {
+      customMixin(element, definition.prototype, definition.native);
+      element.__proto__ = definition.prototype;
+    }
+  }
+  function customMixin(inTarget, inSrc, inNative) {
+    var used = {};
+    var p = inSrc;
+    while (p !== inNative && p !== HTMLElement.prototype) {
+      var keys = Object.getOwnPropertyNames(p);
+      for (var i = 0, k; k = keys[i]; i++) {
+        if (!used[k]) {
+          Object.defineProperty(inTarget, k, Object.getOwnPropertyDescriptor(p, k));
+          used[k] = 1;
+        }
+      }
+      p = Object.getPrototypeOf(p);
+    }
+  }
+  function created(element) {
+    if (element.createdCallback) {
+      element.createdCallback();
+    }
+  }
+  scope.upgrade = upgrade;
+  scope.upgradeWithDefinition = upgradeWithDefinition;
+  scope.implementPrototype = implementPrototype;
+});
+
+window.CustomElements.addModule(function(scope) {
+  var isIE = scope.isIE;
+  var upgradeDocumentTree = scope.upgradeDocumentTree;
+  var upgradeAll = scope.upgradeAll;
+  var upgradeWithDefinition = scope.upgradeWithDefinition;
+  var implementPrototype = scope.implementPrototype;
+  var useNative = scope.useNative;
+  function register(name, options) {
+    var definition = options || {};
+    if (!name) {
+      throw new Error("document.registerElement: first argument `name` must not be empty");
+    }
+    if (name.indexOf("-") < 0) {
+      throw new Error("document.registerElement: first argument ('name') must contain a dash ('-'). Argument provided was '" + String(name) + "'.");
+    }
+    if (isReservedTag(name)) {
+      throw new Error("Failed to execute 'registerElement' on 'Document': Registration failed for type '" + String(name) + "'. The type name is invalid.");
+    }
+    if (getRegisteredDefinition(name)) {
+      throw new Error("DuplicateDefinitionError: a type with name '" + String(name) + "' is already registered");
+    }
+    if (!definition.prototype) {
+      definition.prototype = Object.create(HTMLElement.prototype);
+    }
+    definition.__name = name.toLowerCase();
+    if (definition.extends) {
+      definition.extends = definition.extends.toLowerCase();
+    }
+    definition.lifecycle = definition.lifecycle || {};
+    definition.ancestry = ancestry(definition.extends);
+    resolveTagName(definition);
+    resolvePrototypeChain(definition);
+    overrideAttributeApi(definition.prototype);
+    registerDefinition(definition.__name, definition);
+    definition.ctor = generateConstructor(definition);
+    definition.ctor.prototype = definition.prototype;
+    definition.prototype.constructor = definition.ctor;
+    if (scope.ready) {
+      upgradeDocumentTree(document);
+    }
+    return definition.ctor;
+  }
+  function overrideAttributeApi(prototype) {
+    if (prototype.setAttribute._polyfilled) {
+      return;
+    }
+    var setAttribute = prototype.setAttribute;
+    prototype.setAttribute = function(name, value) {
+      changeAttribute.call(this, name, value, setAttribute);
+    };
+    var removeAttribute = prototype.removeAttribute;
+    prototype.removeAttribute = function(name) {
+      changeAttribute.call(this, name, null, removeAttribute);
+    };
+    prototype.setAttribute._polyfilled = true;
+  }
+  function changeAttribute(name, value, operation) {
+    name = name.toLowerCase();
+    var oldValue = this.getAttribute(name);
+    operation.apply(this, arguments);
+    var newValue = this.getAttribute(name);
+    if (this.attributeChangedCallback && newValue !== oldValue) {
+      this.attributeChangedCallback(name, oldValue, newValue);
+    }
+  }
+  function isReservedTag(name) {
+    for (var i = 0; i < reservedTagList.length; i++) {
+      if (name === reservedTagList[i]) {
+        return true;
+      }
+    }
+  }
+  var reservedTagList = [ "annotation-xml", "color-profile", "font-face", "font-face-src", "font-face-uri", "font-face-format", "font-face-name", "missing-glyph" ];
+  function ancestry(extnds) {
+    var extendee = getRegisteredDefinition(extnds);
+    if (extendee) {
+      return ancestry(extendee.extends).concat([ extendee ]);
+    }
+    return [];
+  }
+  function resolveTagName(definition) {
+    var baseTag = definition.extends;
+    for (var i = 0, a; a = definition.ancestry[i]; i++) {
+      baseTag = a.is && a.tag;
+    }
+    definition.tag = baseTag || definition.__name;
+    if (baseTag) {
+      definition.is = definition.__name;
+    }
+  }
+  function resolvePrototypeChain(definition) {
+    if (!Object.__proto__) {
+      var nativePrototype = HTMLElement.prototype;
+      if (definition.is) {
+        var inst = document.createElement(definition.tag);
+        nativePrototype = Object.getPrototypeOf(inst);
+      }
+      var proto = definition.prototype, ancestor;
+      var foundPrototype = false;
+      while (proto) {
+        if (proto == nativePrototype) {
+          foundPrototype = true;
+        }
+        ancestor = Object.getPrototypeOf(proto);
+        if (ancestor) {
+          proto.__proto__ = ancestor;
+        }
+        proto = ancestor;
+      }
+      if (!foundPrototype) {
+        console.warn(definition.tag + " prototype not found in prototype chain for " + definition.is);
+      }
+      definition.native = nativePrototype;
+    }
+  }
+  function instantiate(definition) {
+    return upgradeWithDefinition(domCreateElement(definition.tag), definition);
+  }
+  var registry = {};
+  function getRegisteredDefinition(name) {
+    if (name) {
+      return registry[name.toLowerCase()];
+    }
+  }
+  function registerDefinition(name, definition) {
+    registry[name] = definition;
+  }
+  function generateConstructor(definition) {
+    return function() {
+      return instantiate(definition);
+    };
+  }
+  var HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
+  function createElementNS(namespace, tag, typeExtension) {
+    if (namespace === HTML_NAMESPACE) {
+      return createElement(tag, typeExtension);
+    } else {
+      return domCreateElementNS(namespace, tag);
+    }
+  }
+  function createElement(tag, typeExtension) {
+    if (tag) {
+      tag = tag.toLowerCase();
+    }
+    if (typeExtension) {
+      typeExtension = typeExtension.toLowerCase();
+    }
+    var definition = getRegisteredDefinition(typeExtension || tag);
+    if (definition) {
+      if (tag == definition.tag && typeExtension == definition.is) {
+        return new definition.ctor();
+      }
+      if (!typeExtension && !definition.is) {
+        return new definition.ctor();
+      }
+    }
+    var element;
+    if (typeExtension) {
+      element = createElement(tag);
+      element.setAttribute("is", typeExtension);
+      return element;
+    }
+    element = domCreateElement(tag);
+    if (tag.indexOf("-") >= 0) {
+      implementPrototype(element, HTMLElement);
+    }
+    return element;
+  }
+  var domCreateElement = document.createElement.bind(document);
+  var domCreateElementNS = document.createElementNS.bind(document);
+  var isInstance;
+  if (!Object.__proto__ && !useNative) {
+    isInstance = function(obj, ctor) {
+      if (obj instanceof ctor) {
+        return true;
+      }
+      var p = obj;
+      while (p) {
+        if (p === ctor.prototype) {
+          return true;
+        }
+        p = p.__proto__;
+      }
+      return false;
+    };
+  } else {
+    isInstance = function(obj, base) {
+      return obj instanceof base;
+    };
+  }
+  function wrapDomMethodToForceUpgrade(obj, methodName) {
+    var orig = obj[methodName];
+    obj[methodName] = function() {
+      var n = orig.apply(this, arguments);
+      upgradeAll(n);
+      return n;
+    };
+  }
+  wrapDomMethodToForceUpgrade(Node.prototype, "cloneNode");
+  wrapDomMethodToForceUpgrade(document, "importNode");
+  document.registerElement = register;
+  document.createElement = createElement;
+  document.createElementNS = createElementNS;
+  scope.registry = registry;
+  scope.instanceof = isInstance;
+  scope.reservedTagList = reservedTagList;
+  scope.getRegisteredDefinition = getRegisteredDefinition;
+  document.register = document.registerElement;
+});
+
+(function(scope) {
+  var useNative = scope.useNative;
+  var initializeModules = scope.initializeModules;
+  var isIE = scope.isIE;
+  if (useNative) {
+    var nop = function() {};
+    scope.watchShadow = nop;
+    scope.upgrade = nop;
+    scope.upgradeAll = nop;
+    scope.upgradeDocumentTree = nop;
+    scope.upgradeSubtree = nop;
+    scope.takeRecords = nop;
+    scope.instanceof = function(obj, base) {
+      return obj instanceof base;
+    };
+  } else {
+    initializeModules();
+  }
+  var upgradeDocumentTree = scope.upgradeDocumentTree;
+  var upgradeDocument = scope.upgradeDocument;
+  if (!window.wrap) {
+    if (window.ShadowDOMPolyfill) {
+      window.wrap = window.ShadowDOMPolyfill.wrapIfNeeded;
+      window.unwrap = window.ShadowDOMPolyfill.unwrapIfNeeded;
+    } else {
+      window.wrap = window.unwrap = function(node) {
+        return node;
+      };
+    }
+  }
+  if (window.HTMLImports) {
+    window.HTMLImports.__importsParsingHook = function(elt) {
+      if (elt.import) {
+        upgradeDocument(wrap(elt.import));
+      }
+    };
+  }
+  function bootstrap() {
+    upgradeDocumentTree(window.wrap(document));
+    window.CustomElements.ready = true;
+    var requestAnimationFrame = window.requestAnimationFrame || function(f) {
+      setTimeout(f, 16);
+    };
+    requestAnimationFrame(function() {
+      setTimeout(function() {
+        window.CustomElements.readyTime = Date.now();
+        if (window.HTMLImports) {
+          window.CustomElements.elapsed = window.CustomElements.readyTime - window.HTMLImports.readyTime;
+        }
+        document.dispatchEvent(new CustomEvent("WebComponentsReady", {
+          bubbles: true
+        }));
+      });
+    });
+  }
+  if (document.readyState === "complete" || scope.flags.eager) {
+    bootstrap();
+  } else if (document.readyState === "interactive" && !window.attachEvent && (!window.HTMLImports || window.HTMLImports.ready)) {
+    bootstrap();
+  } else {
+    var loadEvent = window.HTMLImports && !window.HTMLImports.ready ? "HTMLImportsLoaded" : "DOMContentLoaded";
+    window.addEventListener(loadEvent, bootstrap);
+  }
+})(window.CustomElements);
\ No newline at end of file