Home | History | Annotate | Download | only in webcomponentsjs
      1 /**
      2  * @license
      3  * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
      4  * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
      5  * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
      6  * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
      7  * Code distributed by Google as part of the polymer project is also
      8  * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
      9  */
     10 // @version 0.6.1
     11 if (typeof WeakMap === "undefined") {
     12   (function() {
     13     var defineProperty = Object.defineProperty;
     14     var counter = Date.now() % 1e9;
     15     var WeakMap = function() {
     16       this.name = "__st" + (Math.random() * 1e9 >>> 0) + (counter++ + "__");
     17     };
     18     WeakMap.prototype = {
     19       set: function(key, value) {
     20         var entry = key[this.name];
     21         if (entry && entry[0] === key) entry[1] = value; else defineProperty(key, this.name, {
     22           value: [ key, value ],
     23           writable: true
     24         });
     25         return this;
     26       },
     27       get: function(key) {
     28         var entry;
     29         return (entry = key[this.name]) && entry[0] === key ? entry[1] : undefined;
     30       },
     31       "delete": function(key) {
     32         var entry = key[this.name];
     33         if (!entry || entry[0] !== key) return false;
     34         entry[0] = entry[1] = undefined;
     35         return true;
     36       },
     37       has: function(key) {
     38         var entry = key[this.name];
     39         if (!entry) return false;
     40         return entry[0] === key;
     41       }
     42     };
     43     window.WeakMap = WeakMap;
     44   })();
     45 }
     46 
     47 (function(global) {
     48   var registrationsTable = new WeakMap();
     49   var setImmediate;
     50   if (/Trident|Edge/.test(navigator.userAgent)) {
     51     setImmediate = setTimeout;
     52   } else if (window.setImmediate) {
     53     setImmediate = window.setImmediate;
     54   } else {
     55     var setImmediateQueue = [];
     56     var sentinel = String(Math.random());
     57     window.addEventListener("message", function(e) {
     58       if (e.data === sentinel) {
     59         var queue = setImmediateQueue;
     60         setImmediateQueue = [];
     61         queue.forEach(function(func) {
     62           func();
     63         });
     64       }
     65     });
     66     setImmediate = function(func) {
     67       setImmediateQueue.push(func);
     68       window.postMessage(sentinel, "*");
     69     };
     70   }
     71   var isScheduled = false;
     72   var scheduledObservers = [];
     73   function scheduleCallback(observer) {
     74     scheduledObservers.push(observer);
     75     if (!isScheduled) {
     76       isScheduled = true;
     77       setImmediate(dispatchCallbacks);
     78     }
     79   }
     80   function wrapIfNeeded(node) {
     81     return window.ShadowDOMPolyfill && window.ShadowDOMPolyfill.wrapIfNeeded(node) || node;
     82   }
     83   function dispatchCallbacks() {
     84     isScheduled = false;
     85     var observers = scheduledObservers;
     86     scheduledObservers = [];
     87     observers.sort(function(o1, o2) {
     88       return o1.uid_ - o2.uid_;
     89     });
     90     var anyNonEmpty = false;
     91     observers.forEach(function(observer) {
     92       var queue = observer.takeRecords();
     93       removeTransientObserversFor(observer);
     94       if (queue.length) {
     95         observer.callback_(queue, observer);
     96         anyNonEmpty = true;
     97       }
     98     });
     99     if (anyNonEmpty) dispatchCallbacks();
    100   }
    101   function removeTransientObserversFor(observer) {
    102     observer.nodes_.forEach(function(node) {
    103       var registrations = registrationsTable.get(node);
    104       if (!registrations) return;
    105       registrations.forEach(function(registration) {
    106         if (registration.observer === observer) registration.removeTransientObservers();
    107       });
    108     });
    109   }
    110   function forEachAncestorAndObserverEnqueueRecord(target, callback) {
    111     for (var node = target; node; node = node.parentNode) {
    112       var registrations = registrationsTable.get(node);
    113       if (registrations) {
    114         for (var j = 0; j < registrations.length; j++) {
    115           var registration = registrations[j];
    116           var options = registration.options;
    117           if (node !== target && !options.subtree) continue;
    118           var record = callback(options);
    119           if (record) registration.enqueue(record);
    120         }
    121       }
    122     }
    123   }
    124   var uidCounter = 0;
    125   function JsMutationObserver(callback) {
    126     this.callback_ = callback;
    127     this.nodes_ = [];
    128     this.records_ = [];
    129     this.uid_ = ++uidCounter;
    130   }
    131   JsMutationObserver.prototype = {
    132     observe: function(target, options) {
    133       target = wrapIfNeeded(target);
    134       if (!options.childList && !options.attributes && !options.characterData || options.attributeOldValue && !options.attributes || options.attributeFilter && options.attributeFilter.length && !options.attributes || options.characterDataOldValue && !options.characterData) {
    135         throw new SyntaxError();
    136       }
    137       var registrations = registrationsTable.get(target);
    138       if (!registrations) registrationsTable.set(target, registrations = []);
    139       var registration;
    140       for (var i = 0; i < registrations.length; i++) {
    141         if (registrations[i].observer === this) {
    142           registration = registrations[i];
    143           registration.removeListeners();
    144           registration.options = options;
    145           break;
    146         }
    147       }
    148       if (!registration) {
    149         registration = new Registration(this, target, options);
    150         registrations.push(registration);
    151         this.nodes_.push(target);
    152       }
    153       registration.addListeners();
    154     },
    155     disconnect: function() {
    156       this.nodes_.forEach(function(node) {
    157         var registrations = registrationsTable.get(node);
    158         for (var i = 0; i < registrations.length; i++) {
    159           var registration = registrations[i];
    160           if (registration.observer === this) {
    161             registration.removeListeners();
    162             registrations.splice(i, 1);
    163             break;
    164           }
    165         }
    166       }, this);
    167       this.records_ = [];
    168     },
    169     takeRecords: function() {
    170       var copyOfRecords = this.records_;
    171       this.records_ = [];
    172       return copyOfRecords;
    173     }
    174   };
    175   function MutationRecord(type, target) {
    176     this.type = type;
    177     this.target = target;
    178     this.addedNodes = [];
    179     this.removedNodes = [];
    180     this.previousSibling = null;
    181     this.nextSibling = null;
    182     this.attributeName = null;
    183     this.attributeNamespace = null;
    184     this.oldValue = null;
    185   }
    186   function copyMutationRecord(original) {
    187     var record = new MutationRecord(original.type, original.target);
    188     record.addedNodes = original.addedNodes.slice();
    189     record.removedNodes = original.removedNodes.slice();
    190     record.previousSibling = original.previousSibling;
    191     record.nextSibling = original.nextSibling;
    192     record.attributeName = original.attributeName;
    193     record.attributeNamespace = original.attributeNamespace;
    194     record.oldValue = original.oldValue;
    195     return record;
    196   }
    197   var currentRecord, recordWithOldValue;
    198   function getRecord(type, target) {
    199     return currentRecord = new MutationRecord(type, target);
    200   }
    201   function getRecordWithOldValue(oldValue) {
    202     if (recordWithOldValue) return recordWithOldValue;
    203     recordWithOldValue = copyMutationRecord(currentRecord);
    204     recordWithOldValue.oldValue = oldValue;
    205     return recordWithOldValue;
    206   }
    207   function clearRecords() {
    208     currentRecord = recordWithOldValue = undefined;
    209   }
    210   function recordRepresentsCurrentMutation(record) {
    211     return record === recordWithOldValue || record === currentRecord;
    212   }
    213   function selectRecord(lastRecord, newRecord) {
    214     if (lastRecord === newRecord) return lastRecord;
    215     if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord)) return recordWithOldValue;
    216     return null;
    217   }
    218   function Registration(observer, target, options) {
    219     this.observer = observer;
    220     this.target = target;
    221     this.options = options;
    222     this.transientObservedNodes = [];
    223   }
    224   Registration.prototype = {
    225     enqueue: function(record) {
    226       var records = this.observer.records_;
    227       var length = records.length;
    228       if (records.length > 0) {
    229         var lastRecord = records[length - 1];
    230         var recordToReplaceLast = selectRecord(lastRecord, record);
    231         if (recordToReplaceLast) {
    232           records[length - 1] = recordToReplaceLast;
    233           return;
    234         }
    235       } else {
    236         scheduleCallback(this.observer);
    237       }
    238       records[length] = record;
    239     },
    240     addListeners: function() {
    241       this.addListeners_(this.target);
    242     },
    243     addListeners_: function(node) {
    244       var options = this.options;
    245       if (options.attributes) node.addEventListener("DOMAttrModified", this, true);
    246       if (options.characterData) node.addEventListener("DOMCharacterDataModified", this, true);
    247       if (options.childList) node.addEventListener("DOMNodeInserted", this, true);
    248       if (options.childList || options.subtree) node.addEventListener("DOMNodeRemoved", this, true);
    249     },
    250     removeListeners: function() {
    251       this.removeListeners_(this.target);
    252     },
    253     removeListeners_: function(node) {
    254       var options = this.options;
    255       if (options.attributes) node.removeEventListener("DOMAttrModified", this, true);
    256       if (options.characterData) node.removeEventListener("DOMCharacterDataModified", this, true);
    257       if (options.childList) node.removeEventListener("DOMNodeInserted", this, true);
    258       if (options.childList || options.subtree) node.removeEventListener("DOMNodeRemoved", this, true);
    259     },
    260     addTransientObserver: function(node) {
    261       if (node === this.target) return;
    262       this.addListeners_(node);
    263       this.transientObservedNodes.push(node);
    264       var registrations = registrationsTable.get(node);
    265       if (!registrations) registrationsTable.set(node, registrations = []);
    266       registrations.push(this);
    267     },
    268     removeTransientObservers: function() {
    269       var transientObservedNodes = this.transientObservedNodes;
    270       this.transientObservedNodes = [];
    271       transientObservedNodes.forEach(function(node) {
    272         this.removeListeners_(node);
    273         var registrations = registrationsTable.get(node);
    274         for (var i = 0; i < registrations.length; i++) {
    275           if (registrations[i] === this) {
    276             registrations.splice(i, 1);
    277             break;
    278           }
    279         }
    280       }, this);
    281     },
    282     handleEvent: function(e) {
    283       e.stopImmediatePropagation();
    284       switch (e.type) {
    285        case "DOMAttrModified":
    286         var name = e.attrName;
    287         var namespace = e.relatedNode.namespaceURI;
    288         var target = e.target;
    289         var record = new getRecord("attributes", target);
    290         record.attributeName = name;
    291         record.attributeNamespace = namespace;
    292         var oldValue = e.attrChange === MutationEvent.ADDITION ? null : e.prevValue;
    293         forEachAncestorAndObserverEnqueueRecord(target, function(options) {
    294           if (!options.attributes) return;
    295           if (options.attributeFilter && options.attributeFilter.length && options.attributeFilter.indexOf(name) === -1 && options.attributeFilter.indexOf(namespace) === -1) {
    296             return;
    297           }
    298           if (options.attributeOldValue) return getRecordWithOldValue(oldValue);
    299           return record;
    300         });
    301         break;
    302 
    303        case "DOMCharacterDataModified":
    304         var target = e.target;
    305         var record = getRecord("characterData", target);
    306         var oldValue = e.prevValue;
    307         forEachAncestorAndObserverEnqueueRecord(target, function(options) {
    308           if (!options.characterData) return;
    309           if (options.characterDataOldValue) return getRecordWithOldValue(oldValue);
    310           return record;
    311         });
    312         break;
    313 
    314        case "DOMNodeRemoved":
    315         this.addTransientObserver(e.target);
    316 
    317        case "DOMNodeInserted":
    318         var changedNode = e.target;
    319         var addedNodes, removedNodes;
    320         if (e.type === "DOMNodeInserted") {
    321           addedNodes = [ changedNode ];
    322           removedNodes = [];
    323         } else {
    324           addedNodes = [];
    325           removedNodes = [ changedNode ];
    326         }
    327         var previousSibling = changedNode.previousSibling;
    328         var nextSibling = changedNode.nextSibling;
    329         var record = getRecord("childList", e.target.parentNode);
    330         record.addedNodes = addedNodes;
    331         record.removedNodes = removedNodes;
    332         record.previousSibling = previousSibling;
    333         record.nextSibling = nextSibling;
    334         forEachAncestorAndObserverEnqueueRecord(e.relatedNode, function(options) {
    335           if (!options.childList) return;
    336           return record;
    337         });
    338       }
    339       clearRecords();
    340     }
    341   };
    342   global.JsMutationObserver = JsMutationObserver;
    343   if (!global.MutationObserver) global.MutationObserver = JsMutationObserver;
    344 })(this);
    345 
    346 window.CustomElements = window.CustomElements || {
    347   flags: {}
    348 };
    349 
    350 (function(scope) {
    351   var flags = scope.flags;
    352   var modules = [];
    353   var addModule = function(module) {
    354     modules.push(module);
    355   };
    356   var initializeModules = function() {
    357     modules.forEach(function(module) {
    358       module(scope);
    359     });
    360   };
    361   scope.addModule = addModule;
    362   scope.initializeModules = initializeModules;
    363   scope.hasNative = Boolean(document.registerElement);
    364   scope.useNative = !flags.register && scope.hasNative && !window.ShadowDOMPolyfill && (!window.HTMLImports || HTMLImports.useNative);
    365 })(CustomElements);
    366 
    367 CustomElements.addModule(function(scope) {
    368   var IMPORT_LINK_TYPE = window.HTMLImports ? HTMLImports.IMPORT_LINK_TYPE : "none";
    369   function forSubtree(node, cb) {
    370     findAllElements(node, function(e) {
    371       if (cb(e)) {
    372         return true;
    373       }
    374       forRoots(e, cb);
    375     });
    376     forRoots(node, cb);
    377   }
    378   function findAllElements(node, find, data) {
    379     var e = node.firstElementChild;
    380     if (!e) {
    381       e = node.firstChild;
    382       while (e && e.nodeType !== Node.ELEMENT_NODE) {
    383         e = e.nextSibling;
    384       }
    385     }
    386     while (e) {
    387       if (find(e, data) !== true) {
    388         findAllElements(e, find, data);
    389       }
    390       e = e.nextElementSibling;
    391     }
    392     return null;
    393   }
    394   function forRoots(node, cb) {
    395     var root = node.shadowRoot;
    396     while (root) {
    397       forSubtree(root, cb);
    398       root = root.olderShadowRoot;
    399     }
    400   }
    401   function forDocumentTree(doc, cb) {
    402     _forDocumentTree(doc, cb, []);
    403   }
    404   function _forDocumentTree(doc, cb, processingDocuments) {
    405     doc = wrap(doc);
    406     if (processingDocuments.indexOf(doc) >= 0) {
    407       return;
    408     }
    409     processingDocuments.push(doc);
    410     var imports = doc.querySelectorAll("link[rel=" + IMPORT_LINK_TYPE + "]");
    411     for (var i = 0, l = imports.length, n; i < l && (n = imports[i]); i++) {
    412       if (n.import) {
    413         _forDocumentTree(n.import, cb, processingDocuments);
    414       }
    415     }
    416     cb(doc);
    417   }
    418   scope.forDocumentTree = forDocumentTree;
    419   scope.forSubtree = forSubtree;
    420 });
    421 
    422 CustomElements.addModule(function(scope) {
    423   var flags = scope.flags;
    424   var forSubtree = scope.forSubtree;
    425   var forDocumentTree = scope.forDocumentTree;
    426   function addedNode(node) {
    427     return added(node) || addedSubtree(node);
    428   }
    429   function added(node) {
    430     if (scope.upgrade(node)) {
    431       return true;
    432     }
    433     attached(node);
    434   }
    435   function addedSubtree(node) {
    436     forSubtree(node, function(e) {
    437       if (added(e)) {
    438         return true;
    439       }
    440     });
    441   }
    442   function attachedNode(node) {
    443     attached(node);
    444     if (inDocument(node)) {
    445       forSubtree(node, function(e) {
    446         attached(e);
    447       });
    448     }
    449   }
    450   var hasPolyfillMutations = !window.MutationObserver || window.MutationObserver === window.JsMutationObserver;
    451   scope.hasPolyfillMutations = hasPolyfillMutations;
    452   var isPendingMutations = false;
    453   var pendingMutations = [];
    454   function deferMutation(fn) {
    455     pendingMutations.push(fn);
    456     if (!isPendingMutations) {
    457       isPendingMutations = true;
    458       setTimeout(takeMutations);
    459     }
    460   }
    461   function takeMutations() {
    462     isPendingMutations = false;
    463     var $p = pendingMutations;
    464     for (var i = 0, l = $p.length, p; i < l && (p = $p[i]); i++) {
    465       p();
    466     }
    467     pendingMutations = [];
    468   }
    469   function attached(element) {
    470     if (hasPolyfillMutations) {
    471       deferMutation(function() {
    472         _attached(element);
    473       });
    474     } else {
    475       _attached(element);
    476     }
    477   }
    478   function _attached(element) {
    479     if (element.__upgraded__ && (element.attachedCallback || element.detachedCallback)) {
    480       if (!element.__attached && inDocument(element)) {
    481         element.__attached = true;
    482         if (element.attachedCallback) {
    483           element.attachedCallback();
    484         }
    485       }
    486     }
    487   }
    488   function detachedNode(node) {
    489     detached(node);
    490     forSubtree(node, function(e) {
    491       detached(e);
    492     });
    493   }
    494   function detached(element) {
    495     if (hasPolyfillMutations) {
    496       deferMutation(function() {
    497         _detached(element);
    498       });
    499     } else {
    500       _detached(element);
    501     }
    502   }
    503   function _detached(element) {
    504     if (element.__upgraded__ && (element.attachedCallback || element.detachedCallback)) {
    505       if (element.__attached && !inDocument(element)) {
    506         element.__attached = false;
    507         if (element.detachedCallback) {
    508           element.detachedCallback();
    509         }
    510       }
    511     }
    512   }
    513   function inDocument(element) {
    514     var p = element;
    515     var doc = wrap(document);
    516     while (p) {
    517       if (p == doc) {
    518         return true;
    519       }
    520       p = p.parentNode || p.nodeType === Node.DOCUMENT_FRAGMENT_NODE && p.host;
    521     }
    522   }
    523   function watchShadow(node) {
    524     if (node.shadowRoot && !node.shadowRoot.__watched) {
    525       flags.dom && console.log("watching shadow-root for: ", node.localName);
    526       var root = node.shadowRoot;
    527       while (root) {
    528         observe(root);
    529         root = root.olderShadowRoot;
    530       }
    531     }
    532   }
    533   function handler(mutations) {
    534     if (flags.dom) {
    535       var mx = mutations[0];
    536       if (mx && mx.type === "childList" && mx.addedNodes) {
    537         if (mx.addedNodes) {
    538           var d = mx.addedNodes[0];
    539           while (d && d !== document && !d.host) {
    540             d = d.parentNode;
    541           }
    542           var u = d && (d.URL || d._URL || d.host && d.host.localName) || "";
    543           u = u.split("/?").shift().split("/").pop();
    544         }
    545       }
    546       console.group("mutations (%d) [%s]", mutations.length, u || "");
    547     }
    548     mutations.forEach(function(mx) {
    549       if (mx.type === "childList") {
    550         forEach(mx.addedNodes, function(n) {
    551           if (!n.localName) {
    552             return;
    553           }
    554           addedNode(n);
    555         });
    556         forEach(mx.removedNodes, function(n) {
    557           if (!n.localName) {
    558             return;
    559           }
    560           detachedNode(n);
    561         });
    562       }
    563     });
    564     flags.dom && console.groupEnd();
    565   }
    566   function takeRecords(node) {
    567     node = wrap(node);
    568     if (!node) {
    569       node = wrap(document);
    570     }
    571     while (node.parentNode) {
    572       node = node.parentNode;
    573     }
    574     var observer = node.__observer;
    575     if (observer) {
    576       handler(observer.takeRecords());
    577       takeMutations();
    578     }
    579   }
    580   var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
    581   function observe(inRoot) {
    582     if (inRoot.__observer) {
    583       return;
    584     }
    585     var observer = new MutationObserver(handler);
    586     observer.observe(inRoot, {
    587       childList: true,
    588       subtree: true
    589     });
    590     inRoot.__observer = observer;
    591   }
    592   function upgradeDocument(doc) {
    593     doc = wrap(doc);
    594     flags.dom && console.group("upgradeDocument: ", doc.baseURI.split("/").pop());
    595     addedNode(doc);
    596     observe(doc);
    597     flags.dom && console.groupEnd();
    598   }
    599   function upgradeDocumentTree(doc) {
    600     forDocumentTree(doc, upgradeDocument);
    601   }
    602   var originalCreateShadowRoot = Element.prototype.createShadowRoot;
    603   if (originalCreateShadowRoot) {
    604     Element.prototype.createShadowRoot = function() {
    605       var root = originalCreateShadowRoot.call(this);
    606       CustomElements.watchShadow(this);
    607       return root;
    608     };
    609   }
    610   scope.watchShadow = watchShadow;
    611   scope.upgradeDocumentTree = upgradeDocumentTree;
    612   scope.upgradeSubtree = addedSubtree;
    613   scope.upgradeAll = addedNode;
    614   scope.attachedNode = attachedNode;
    615   scope.takeRecords = takeRecords;
    616 });
    617 
    618 CustomElements.addModule(function(scope) {
    619   var flags = scope.flags;
    620   function upgrade(node) {
    621     if (!node.__upgraded__ && node.nodeType === Node.ELEMENT_NODE) {
    622       var is = node.getAttribute("is");
    623       var definition = scope.getRegisteredDefinition(is || node.localName);
    624       if (definition) {
    625         if (is && definition.tag == node.localName) {
    626           return upgradeWithDefinition(node, definition);
    627         } else if (!is && !definition.extends) {
    628           return upgradeWithDefinition(node, definition);
    629         }
    630       }
    631     }
    632   }
    633   function upgradeWithDefinition(element, definition) {
    634     flags.upgrade && console.group("upgrade:", element.localName);
    635     if (definition.is) {
    636       element.setAttribute("is", definition.is);
    637     }
    638     implementPrototype(element, definition);
    639     element.__upgraded__ = true;
    640     created(element);
    641     scope.attachedNode(element);
    642     scope.upgradeSubtree(element);
    643     flags.upgrade && console.groupEnd();
    644     return element;
    645   }
    646   function implementPrototype(element, definition) {
    647     if (Object.__proto__) {
    648       element.__proto__ = definition.prototype;
    649     } else {
    650       customMixin(element, definition.prototype, definition.native);
    651       element.__proto__ = definition.prototype;
    652     }
    653   }
    654   function customMixin(inTarget, inSrc, inNative) {
    655     var used = {};
    656     var p = inSrc;
    657     while (p !== inNative && p !== HTMLElement.prototype) {
    658       var keys = Object.getOwnPropertyNames(p);
    659       for (var i = 0, k; k = keys[i]; i++) {
    660         if (!used[k]) {
    661           Object.defineProperty(inTarget, k, Object.getOwnPropertyDescriptor(p, k));
    662           used[k] = 1;
    663         }
    664       }
    665       p = Object.getPrototypeOf(p);
    666     }
    667   }
    668   function created(element) {
    669     if (element.createdCallback) {
    670       element.createdCallback();
    671     }
    672   }
    673   scope.upgrade = upgrade;
    674   scope.upgradeWithDefinition = upgradeWithDefinition;
    675   scope.implementPrototype = implementPrototype;
    676 });
    677 
    678 CustomElements.addModule(function(scope) {
    679   var isIE11OrOlder = scope.isIE11OrOlder;
    680   var upgradeDocumentTree = scope.upgradeDocumentTree;
    681   var upgradeAll = scope.upgradeAll;
    682   var upgradeWithDefinition = scope.upgradeWithDefinition;
    683   var implementPrototype = scope.implementPrototype;
    684   var useNative = scope.useNative;
    685   function register(name, options) {
    686     var definition = options || {};
    687     if (!name) {
    688       throw new Error("document.registerElement: first argument `name` must not be empty");
    689     }
    690     if (name.indexOf("-") < 0) {
    691       throw new Error("document.registerElement: first argument ('name') must contain a dash ('-'). Argument provided was '" + String(name) + "'.");
    692     }
    693     if (isReservedTag(name)) {
    694       throw new Error("Failed to execute 'registerElement' on 'Document': Registration failed for type '" + String(name) + "'. The type name is invalid.");
    695     }
    696     if (getRegisteredDefinition(name)) {
    697       throw new Error("DuplicateDefinitionError: a type with name '" + String(name) + "' is already registered");
    698     }
    699     if (!definition.prototype) {
    700       definition.prototype = Object.create(HTMLElement.prototype);
    701     }
    702     definition.__name = name.toLowerCase();
    703     definition.lifecycle = definition.lifecycle || {};
    704     definition.ancestry = ancestry(definition.extends);
    705     resolveTagName(definition);
    706     resolvePrototypeChain(definition);
    707     overrideAttributeApi(definition.prototype);
    708     registerDefinition(definition.__name, definition);
    709     definition.ctor = generateConstructor(definition);
    710     definition.ctor.prototype = definition.prototype;
    711     definition.prototype.constructor = definition.ctor;
    712     if (scope.ready) {
    713       upgradeDocumentTree(document);
    714     }
    715     return definition.ctor;
    716   }
    717   function overrideAttributeApi(prototype) {
    718     if (prototype.setAttribute._polyfilled) {
    719       return;
    720     }
    721     var setAttribute = prototype.setAttribute;
    722     prototype.setAttribute = function(name, value) {
    723       changeAttribute.call(this, name, value, setAttribute);
    724     };
    725     var removeAttribute = prototype.removeAttribute;
    726     prototype.removeAttribute = function(name) {
    727       changeAttribute.call(this, name, null, removeAttribute);
    728     };
    729     prototype.setAttribute._polyfilled = true;
    730   }
    731   function changeAttribute(name, value, operation) {
    732     name = name.toLowerCase();
    733     var oldValue = this.getAttribute(name);
    734     operation.apply(this, arguments);
    735     var newValue = this.getAttribute(name);
    736     if (this.attributeChangedCallback && newValue !== oldValue) {
    737       this.attributeChangedCallback(name, oldValue, newValue);
    738     }
    739   }
    740   function isReservedTag(name) {
    741     for (var i = 0; i < reservedTagList.length; i++) {
    742       if (name === reservedTagList[i]) {
    743         return true;
    744       }
    745     }
    746   }
    747   var reservedTagList = [ "annotation-xml", "color-profile", "font-face", "font-face-src", "font-face-uri", "font-face-format", "font-face-name", "missing-glyph" ];
    748   function ancestry(extnds) {
    749     var extendee = getRegisteredDefinition(extnds);
    750     if (extendee) {
    751       return ancestry(extendee.extends).concat([ extendee ]);
    752     }
    753     return [];
    754   }
    755   function resolveTagName(definition) {
    756     var baseTag = definition.extends;
    757     for (var i = 0, a; a = definition.ancestry[i]; i++) {
    758       baseTag = a.is && a.tag;
    759     }
    760     definition.tag = baseTag || definition.__name;
    761     if (baseTag) {
    762       definition.is = definition.__name;
    763     }
    764   }
    765   function resolvePrototypeChain(definition) {
    766     if (!Object.__proto__) {
    767       var nativePrototype = HTMLElement.prototype;
    768       if (definition.is) {
    769         var inst = document.createElement(definition.tag);
    770         var expectedPrototype = Object.getPrototypeOf(inst);
    771         if (expectedPrototype === definition.prototype) {
    772           nativePrototype = expectedPrototype;
    773         }
    774       }
    775       var proto = definition.prototype, ancestor;
    776       while (proto && proto !== nativePrototype) {
    777         ancestor = Object.getPrototypeOf(proto);
    778         proto.__proto__ = ancestor;
    779         proto = ancestor;
    780       }
    781       definition.native = nativePrototype;
    782     }
    783   }
    784   function instantiate(definition) {
    785     return upgradeWithDefinition(domCreateElement(definition.tag), definition);
    786   }
    787   var registry = {};
    788   function getRegisteredDefinition(name) {
    789     if (name) {
    790       return registry[name.toLowerCase()];
    791     }
    792   }
    793   function registerDefinition(name, definition) {
    794     registry[name] = definition;
    795   }
    796   function generateConstructor(definition) {
    797     return function() {
    798       return instantiate(definition);
    799     };
    800   }
    801   var HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
    802   function createElementNS(namespace, tag, typeExtension) {
    803     if (namespace === HTML_NAMESPACE) {
    804       return createElement(tag, typeExtension);
    805     } else {
    806       return domCreateElementNS(namespace, tag);
    807     }
    808   }
    809   function createElement(tag, typeExtension) {
    810     var definition = getRegisteredDefinition(typeExtension || tag);
    811     if (definition) {
    812       if (tag == definition.tag && typeExtension == definition.is) {
    813         return new definition.ctor();
    814       }
    815       if (!typeExtension && !definition.is) {
    816         return new definition.ctor();
    817       }
    818     }
    819     var element;
    820     if (typeExtension) {
    821       element = createElement(tag);
    822       element.setAttribute("is", typeExtension);
    823       return element;
    824     }
    825     element = domCreateElement(tag);
    826     if (tag.indexOf("-") >= 0) {
    827       implementPrototype(element, HTMLElement);
    828     }
    829     return element;
    830   }
    831   var domCreateElement = document.createElement.bind(document);
    832   var domCreateElementNS = document.createElementNS.bind(document);
    833   var isInstance;
    834   if (!Object.__proto__ && !useNative) {
    835     isInstance = function(obj, ctor) {
    836       var p = obj;
    837       while (p) {
    838         if (p === ctor.prototype) {
    839           return true;
    840         }
    841         p = p.__proto__;
    842       }
    843       return false;
    844     };
    845   } else {
    846     isInstance = function(obj, base) {
    847       return obj instanceof base;
    848     };
    849   }
    850   function wrapDomMethodToForceUpgrade(obj, methodName) {
    851     var orig = obj[methodName];
    852     obj[methodName] = function() {
    853       var n = orig.apply(this, arguments);
    854       upgradeAll(n);
    855       return n;
    856     };
    857   }
    858   wrapDomMethodToForceUpgrade(Node.prototype, "cloneNode");
    859   wrapDomMethodToForceUpgrade(document, "importNode");
    860   if (isIE11OrOlder) {
    861     (function() {
    862       var importNode = document.importNode;
    863       document.importNode = function() {
    864         var n = importNode.apply(document, arguments);
    865         if (n.nodeType == n.DOCUMENT_FRAGMENT_NODE) {
    866           var f = document.createDocumentFragment();
    867           f.appendChild(n);
    868           return f;
    869         } else {
    870           return n;
    871         }
    872       };
    873     })();
    874   }
    875   document.registerElement = register;
    876   document.createElement = createElement;
    877   document.createElementNS = createElementNS;
    878   scope.registry = registry;
    879   scope.instanceof = isInstance;
    880   scope.reservedTagList = reservedTagList;
    881   scope.getRegisteredDefinition = getRegisteredDefinition;
    882   document.register = document.registerElement;
    883 });
    884 
    885 (function(scope) {
    886   var useNative = scope.useNative;
    887   var initializeModules = scope.initializeModules;
    888   var isIE11OrOlder = /Trident/.test(navigator.userAgent);
    889   if (useNative) {
    890     var nop = function() {};
    891     scope.watchShadow = nop;
    892     scope.upgrade = nop;
    893     scope.upgradeAll = nop;
    894     scope.upgradeDocumentTree = nop;
    895     scope.upgradeSubtree = nop;
    896     scope.takeRecords = nop;
    897     scope.instanceof = function(obj, base) {
    898       return obj instanceof base;
    899     };
    900   } else {
    901     initializeModules();
    902   }
    903   var upgradeDocumentTree = scope.upgradeDocumentTree;
    904   if (!window.wrap) {
    905     if (window.ShadowDOMPolyfill) {
    906       window.wrap = ShadowDOMPolyfill.wrapIfNeeded;
    907       window.unwrap = ShadowDOMPolyfill.unwrapIfNeeded;
    908     } else {
    909       window.wrap = window.unwrap = function(node) {
    910         return node;
    911       };
    912     }
    913   }
    914   function bootstrap() {
    915     upgradeDocumentTree(wrap(document));
    916     if (window.HTMLImports) {
    917       HTMLImports.__importsParsingHook = function(elt) {
    918         upgradeDocumentTree(wrap(elt.import));
    919       };
    920     }
    921     CustomElements.ready = true;
    922     setTimeout(function() {
    923       CustomElements.readyTime = Date.now();
    924       if (window.HTMLImports) {
    925         CustomElements.elapsed = CustomElements.readyTime - HTMLImports.readyTime;
    926       }
    927       document.dispatchEvent(new CustomEvent("WebComponentsReady", {
    928         bubbles: true
    929       }));
    930     });
    931   }
    932   if (isIE11OrOlder && typeof window.CustomEvent !== "function") {
    933     window.CustomEvent = function(inType, params) {
    934       params = params || {};
    935       var e = document.createEvent("CustomEvent");
    936       e.initCustomEvent(inType, Boolean(params.bubbles), Boolean(params.cancelable), params.detail);
    937       return e;
    938     };
    939     window.CustomEvent.prototype = window.Event.prototype;
    940   }
    941   if (document.readyState === "complete" || scope.flags.eager) {
    942     bootstrap();
    943   } else if (document.readyState === "interactive" && !window.attachEvent && (!window.HTMLImports || window.HTMLImports.ready)) {
    944     bootstrap();
    945   } else {
    946     var loadEvent = window.HTMLImports && !HTMLImports.ready ? "HTMLImportsLoaded" : "DOMContentLoaded";
    947     window.addEventListener(loadEvent, bootstrap);
    948   }
    949   scope.isIE11OrOlder = isIE11OrOlder;
    950 })(window.CustomElements);