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.5.5
     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 window.HTMLImports = window.HTMLImports || {
     48   flags: {}
     49 };
     50 
     51 (function(scope) {
     52   var IMPORT_LINK_TYPE = "import";
     53   var useNative = Boolean(IMPORT_LINK_TYPE in document.createElement("link"));
     54   var hasShadowDOMPolyfill = Boolean(window.ShadowDOMPolyfill);
     55   var wrap = function(node) {
     56     return hasShadowDOMPolyfill ? ShadowDOMPolyfill.wrapIfNeeded(node) : node;
     57   };
     58   var rootDocument = wrap(document);
     59   var currentScriptDescriptor = {
     60     get: function() {
     61       var script = HTMLImports.currentScript || document.currentScript || (document.readyState !== "complete" ? document.scripts[document.scripts.length - 1] : null);
     62       return wrap(script);
     63     },
     64     configurable: true
     65   };
     66   Object.defineProperty(document, "_currentScript", currentScriptDescriptor);
     67   Object.defineProperty(rootDocument, "_currentScript", currentScriptDescriptor);
     68   var isIE = /Trident|Edge/.test(navigator.userAgent);
     69   function whenReady(callback, doc) {
     70     doc = doc || rootDocument;
     71     whenDocumentReady(function() {
     72       watchImportsLoad(callback, doc);
     73     }, doc);
     74   }
     75   var requiredReadyState = isIE ? "complete" : "interactive";
     76   var READY_EVENT = "readystatechange";
     77   function isDocumentReady(doc) {
     78     return doc.readyState === "complete" || doc.readyState === requiredReadyState;
     79   }
     80   function whenDocumentReady(callback, doc) {
     81     if (!isDocumentReady(doc)) {
     82       var checkReady = function() {
     83         if (doc.readyState === "complete" || doc.readyState === requiredReadyState) {
     84           doc.removeEventListener(READY_EVENT, checkReady);
     85           whenDocumentReady(callback, doc);
     86         }
     87       };
     88       doc.addEventListener(READY_EVENT, checkReady);
     89     } else if (callback) {
     90       callback();
     91     }
     92   }
     93   function markTargetLoaded(event) {
     94     event.target.__loaded = true;
     95   }
     96   function watchImportsLoad(callback, doc) {
     97     var imports = doc.querySelectorAll("link[rel=import]");
     98     var loaded = 0, l = imports.length;
     99     function checkDone(d) {
    100       if (loaded == l && callback) {
    101         callback();
    102       }
    103     }
    104     function loadedImport(e) {
    105       markTargetLoaded(e);
    106       loaded++;
    107       checkDone();
    108     }
    109     if (l) {
    110       for (var i = 0, imp; i < l && (imp = imports[i]); i++) {
    111         if (isImportLoaded(imp)) {
    112           loadedImport.call(imp, {
    113             target: imp
    114           });
    115         } else {
    116           imp.addEventListener("load", loadedImport);
    117           imp.addEventListener("error", loadedImport);
    118         }
    119       }
    120     } else {
    121       checkDone();
    122     }
    123   }
    124   function isImportLoaded(link) {
    125     return useNative ? link.__loaded || link.import && link.import.readyState !== "loading" : link.__importParsed;
    126   }
    127   if (useNative) {
    128     new MutationObserver(function(mxns) {
    129       for (var i = 0, l = mxns.length, m; i < l && (m = mxns[i]); i++) {
    130         if (m.addedNodes) {
    131           handleImports(m.addedNodes);
    132         }
    133       }
    134     }).observe(document.head, {
    135       childList: true
    136     });
    137     function handleImports(nodes) {
    138       for (var i = 0, l = nodes.length, n; i < l && (n = nodes[i]); i++) {
    139         if (isImport(n)) {
    140           handleImport(n);
    141         }
    142       }
    143     }
    144     function isImport(element) {
    145       return element.localName === "link" && element.rel === "import";
    146     }
    147     function handleImport(element) {
    148       var loaded = element.import;
    149       if (loaded) {
    150         markTargetLoaded({
    151           target: element
    152         });
    153       } else {
    154         element.addEventListener("load", markTargetLoaded);
    155         element.addEventListener("error", markTargetLoaded);
    156       }
    157     }
    158     (function() {
    159       if (document.readyState === "loading") {
    160         var imports = document.querySelectorAll("link[rel=import]");
    161         for (var i = 0, l = imports.length, imp; i < l && (imp = imports[i]); i++) {
    162           handleImport(imp);
    163         }
    164       }
    165     })();
    166   }
    167   whenReady(function() {
    168     HTMLImports.ready = true;
    169     HTMLImports.readyTime = new Date().getTime();
    170     var evt = rootDocument.createEvent("CustomEvent");
    171     evt.initCustomEvent("HTMLImportsLoaded", true, true, {});
    172     rootDocument.dispatchEvent(evt);
    173   });
    174   scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;
    175   scope.useNative = useNative;
    176   scope.rootDocument = rootDocument;
    177   scope.whenReady = whenReady;
    178   scope.isIE = isIE;
    179 })(HTMLImports);
    180 
    181 (function(scope) {
    182   var modules = [];
    183   var addModule = function(module) {
    184     modules.push(module);
    185   };
    186   var initializeModules = function() {
    187     modules.forEach(function(module) {
    188       module(scope);
    189     });
    190   };
    191   scope.addModule = addModule;
    192   scope.initializeModules = initializeModules;
    193 })(HTMLImports);
    194 
    195 HTMLImports.addModule(function(scope) {
    196   var CSS_URL_REGEXP = /(url\()([^)]*)(\))/g;
    197   var CSS_IMPORT_REGEXP = /(@import[\s]+(?!url\())([^;]*)(;)/g;
    198   var path = {
    199     resolveUrlsInStyle: function(style) {
    200       var doc = style.ownerDocument;
    201       var resolver = doc.createElement("a");
    202       style.textContent = this.resolveUrlsInCssText(style.textContent, resolver);
    203       return style;
    204     },
    205     resolveUrlsInCssText: function(cssText, urlObj) {
    206       var r = this.replaceUrls(cssText, urlObj, CSS_URL_REGEXP);
    207       r = this.replaceUrls(r, urlObj, CSS_IMPORT_REGEXP);
    208       return r;
    209     },
    210     replaceUrls: function(text, urlObj, regexp) {
    211       return text.replace(regexp, function(m, pre, url, post) {
    212         var urlPath = url.replace(/["']/g, "");
    213         urlObj.href = urlPath;
    214         urlPath = urlObj.href;
    215         return pre + "'" + urlPath + "'" + post;
    216       });
    217     }
    218   };
    219   scope.path = path;
    220 });
    221 
    222 HTMLImports.addModule(function(scope) {
    223   var xhr = {
    224     async: true,
    225     ok: function(request) {
    226       return request.status >= 200 && request.status < 300 || request.status === 304 || request.status === 0;
    227     },
    228     load: function(url, next, nextContext) {
    229       var request = new XMLHttpRequest();
    230       if (scope.flags.debug || scope.flags.bust) {
    231         url += "?" + Math.random();
    232       }
    233       request.open("GET", url, xhr.async);
    234       request.addEventListener("readystatechange", function(e) {
    235         if (request.readyState === 4) {
    236           var locationHeader = request.getResponseHeader("Location");
    237           var redirectedUrl = null;
    238           if (locationHeader) {
    239             var redirectedUrl = locationHeader.substr(0, 1) === "/" ? location.origin + locationHeader : locationHeader;
    240           }
    241           next.call(nextContext, !xhr.ok(request) && request, request.response || request.responseText, redirectedUrl);
    242         }
    243       });
    244       request.send();
    245       return request;
    246     },
    247     loadDocument: function(url, next, nextContext) {
    248       this.load(url, next, nextContext).responseType = "document";
    249     }
    250   };
    251   scope.xhr = xhr;
    252 });
    253 
    254 HTMLImports.addModule(function(scope) {
    255   var xhr = scope.xhr;
    256   var flags = scope.flags;
    257   var Loader = function(onLoad, onComplete) {
    258     this.cache = {};
    259     this.onload = onLoad;
    260     this.oncomplete = onComplete;
    261     this.inflight = 0;
    262     this.pending = {};
    263   };
    264   Loader.prototype = {
    265     addNodes: function(nodes) {
    266       this.inflight += nodes.length;
    267       for (var i = 0, l = nodes.length, n; i < l && (n = nodes[i]); i++) {
    268         this.require(n);
    269       }
    270       this.checkDone();
    271     },
    272     addNode: function(node) {
    273       this.inflight++;
    274       this.require(node);
    275       this.checkDone();
    276     },
    277     require: function(elt) {
    278       var url = elt.src || elt.href;
    279       elt.__nodeUrl = url;
    280       if (!this.dedupe(url, elt)) {
    281         this.fetch(url, elt);
    282       }
    283     },
    284     dedupe: function(url, elt) {
    285       if (this.pending[url]) {
    286         this.pending[url].push(elt);
    287         return true;
    288       }
    289       var resource;
    290       if (this.cache[url]) {
    291         this.onload(url, elt, this.cache[url]);
    292         this.tail();
    293         return true;
    294       }
    295       this.pending[url] = [ elt ];
    296       return false;
    297     },
    298     fetch: function(url, elt) {
    299       flags.load && console.log("fetch", url, elt);
    300       if (!url) {
    301         setTimeout(function() {
    302           this.receive(url, elt, {
    303             error: "href must be specified"
    304           }, null);
    305         }.bind(this), 0);
    306       } else if (url.match(/^data:/)) {
    307         var pieces = url.split(",");
    308         var header = pieces[0];
    309         var body = pieces[1];
    310         if (header.indexOf(";base64") > -1) {
    311           body = atob(body);
    312         } else {
    313           body = decodeURIComponent(body);
    314         }
    315         setTimeout(function() {
    316           this.receive(url, elt, null, body);
    317         }.bind(this), 0);
    318       } else {
    319         var receiveXhr = function(err, resource, redirectedUrl) {
    320           this.receive(url, elt, err, resource, redirectedUrl);
    321         }.bind(this);
    322         xhr.load(url, receiveXhr);
    323       }
    324     },
    325     receive: function(url, elt, err, resource, redirectedUrl) {
    326       this.cache[url] = resource;
    327       var $p = this.pending[url];
    328       for (var i = 0, l = $p.length, p; i < l && (p = $p[i]); i++) {
    329         this.onload(url, p, resource, err, redirectedUrl);
    330         this.tail();
    331       }
    332       this.pending[url] = null;
    333     },
    334     tail: function() {
    335       --this.inflight;
    336       this.checkDone();
    337     },
    338     checkDone: function() {
    339       if (!this.inflight) {
    340         this.oncomplete();
    341       }
    342     }
    343   };
    344   scope.Loader = Loader;
    345 });
    346 
    347 HTMLImports.addModule(function(scope) {
    348   var Observer = function(addCallback) {
    349     this.addCallback = addCallback;
    350     this.mo = new MutationObserver(this.handler.bind(this));
    351   };
    352   Observer.prototype = {
    353     handler: function(mutations) {
    354       for (var i = 0, l = mutations.length, m; i < l && (m = mutations[i]); i++) {
    355         if (m.type === "childList" && m.addedNodes.length) {
    356           this.addedNodes(m.addedNodes);
    357         }
    358       }
    359     },
    360     addedNodes: function(nodes) {
    361       if (this.addCallback) {
    362         this.addCallback(nodes);
    363       }
    364       for (var i = 0, l = nodes.length, n, loading; i < l && (n = nodes[i]); i++) {
    365         if (n.children && n.children.length) {
    366           this.addedNodes(n.children);
    367         }
    368       }
    369     },
    370     observe: function(root) {
    371       this.mo.observe(root, {
    372         childList: true,
    373         subtree: true
    374       });
    375     }
    376   };
    377   scope.Observer = Observer;
    378 });
    379 
    380 HTMLImports.addModule(function(scope) {
    381   var path = scope.path;
    382   var rootDocument = scope.rootDocument;
    383   var flags = scope.flags;
    384   var isIE = scope.isIE;
    385   var IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;
    386   var IMPORT_SELECTOR = "link[rel=" + IMPORT_LINK_TYPE + "]";
    387   var importParser = {
    388     documentSelectors: IMPORT_SELECTOR,
    389     importsSelectors: [ IMPORT_SELECTOR, "link[rel=stylesheet]", "style", "script:not([type])", 'script[type="text/javascript"]' ].join(","),
    390     map: {
    391       link: "parseLink",
    392       script: "parseScript",
    393       style: "parseStyle"
    394     },
    395     dynamicElements: [],
    396     parseNext: function() {
    397       var next = this.nextToParse();
    398       if (next) {
    399         this.parse(next);
    400       }
    401     },
    402     parse: function(elt) {
    403       if (this.isParsed(elt)) {
    404         flags.parse && console.log("[%s] is already parsed", elt.localName);
    405         return;
    406       }
    407       var fn = this[this.map[elt.localName]];
    408       if (fn) {
    409         this.markParsing(elt);
    410         fn.call(this, elt);
    411       }
    412     },
    413     parseDynamic: function(elt, quiet) {
    414       this.dynamicElements.push(elt);
    415       if (!quiet) {
    416         this.parseNext();
    417       }
    418     },
    419     markParsing: function(elt) {
    420       flags.parse && console.log("parsing", elt);
    421       this.parsingElement = elt;
    422     },
    423     markParsingComplete: function(elt) {
    424       elt.__importParsed = true;
    425       this.markDynamicParsingComplete(elt);
    426       if (elt.__importElement) {
    427         elt.__importElement.__importParsed = true;
    428         this.markDynamicParsingComplete(elt.__importElement);
    429       }
    430       this.parsingElement = null;
    431       flags.parse && console.log("completed", elt);
    432     },
    433     markDynamicParsingComplete: function(elt) {
    434       var i = this.dynamicElements.indexOf(elt);
    435       if (i >= 0) {
    436         this.dynamicElements.splice(i, 1);
    437       }
    438     },
    439     parseImport: function(elt) {
    440       if (HTMLImports.__importsParsingHook) {
    441         HTMLImports.__importsParsingHook(elt);
    442       }
    443       if (elt.import) {
    444         elt.import.__importParsed = true;
    445       }
    446       this.markParsingComplete(elt);
    447       if (elt.__resource && !elt.__error) {
    448         elt.dispatchEvent(new CustomEvent("load", {
    449           bubbles: false
    450         }));
    451       } else {
    452         elt.dispatchEvent(new CustomEvent("error", {
    453           bubbles: false
    454         }));
    455       }
    456       if (elt.__pending) {
    457         var fn;
    458         while (elt.__pending.length) {
    459           fn = elt.__pending.shift();
    460           if (fn) {
    461             fn({
    462               target: elt
    463             });
    464           }
    465         }
    466       }
    467       this.parseNext();
    468     },
    469     parseLink: function(linkElt) {
    470       if (nodeIsImport(linkElt)) {
    471         this.parseImport(linkElt);
    472       } else {
    473         linkElt.href = linkElt.href;
    474         this.parseGeneric(linkElt);
    475       }
    476     },
    477     parseStyle: function(elt) {
    478       var src = elt;
    479       elt = cloneStyle(elt);
    480       elt.__importElement = src;
    481       this.parseGeneric(elt);
    482     },
    483     parseGeneric: function(elt) {
    484       this.trackElement(elt);
    485       this.addElementToDocument(elt);
    486     },
    487     rootImportForElement: function(elt) {
    488       var n = elt;
    489       while (n.ownerDocument.__importLink) {
    490         n = n.ownerDocument.__importLink;
    491       }
    492       return n;
    493     },
    494     addElementToDocument: function(elt) {
    495       var port = this.rootImportForElement(elt.__importElement || elt);
    496       port.parentNode.insertBefore(elt, port);
    497     },
    498     trackElement: function(elt, callback) {
    499       var self = this;
    500       var done = function(e) {
    501         if (callback) {
    502           callback(e);
    503         }
    504         self.markParsingComplete(elt);
    505         self.parseNext();
    506       };
    507       elt.addEventListener("load", done);
    508       elt.addEventListener("error", done);
    509       if (isIE && elt.localName === "style") {
    510         var fakeLoad = false;
    511         if (elt.textContent.indexOf("@import") == -1) {
    512           fakeLoad = true;
    513         } else if (elt.sheet) {
    514           fakeLoad = true;
    515           var csr = elt.sheet.cssRules;
    516           var len = csr ? csr.length : 0;
    517           for (var i = 0, r; i < len && (r = csr[i]); i++) {
    518             if (r.type === CSSRule.IMPORT_RULE) {
    519               fakeLoad = fakeLoad && Boolean(r.styleSheet);
    520             }
    521           }
    522         }
    523         if (fakeLoad) {
    524           elt.dispatchEvent(new CustomEvent("load", {
    525             bubbles: false
    526           }));
    527         }
    528       }
    529     },
    530     parseScript: function(scriptElt) {
    531       var script = document.createElement("script");
    532       script.__importElement = scriptElt;
    533       script.src = scriptElt.src ? scriptElt.src : generateScriptDataUrl(scriptElt);
    534       scope.currentScript = scriptElt;
    535       this.trackElement(script, function(e) {
    536         script.parentNode.removeChild(script);
    537         scope.currentScript = null;
    538       });
    539       this.addElementToDocument(script);
    540     },
    541     nextToParse: function() {
    542       this._mayParse = [];
    543       return !this.parsingElement && (this.nextToParseInDoc(rootDocument) || this.nextToParseDynamic());
    544     },
    545     nextToParseInDoc: function(doc, link) {
    546       if (doc && this._mayParse.indexOf(doc) < 0) {
    547         this._mayParse.push(doc);
    548         var nodes = doc.querySelectorAll(this.parseSelectorsForNode(doc));
    549         for (var i = 0, l = nodes.length, p = 0, n; i < l && (n = nodes[i]); i++) {
    550           if (!this.isParsed(n)) {
    551             if (this.hasResource(n)) {
    552               return nodeIsImport(n) ? this.nextToParseInDoc(n.import, n) : n;
    553             } else {
    554               return;
    555             }
    556           }
    557         }
    558       }
    559       return link;
    560     },
    561     nextToParseDynamic: function() {
    562       return this.dynamicElements[0];
    563     },
    564     parseSelectorsForNode: function(node) {
    565       var doc = node.ownerDocument || node;
    566       return doc === rootDocument ? this.documentSelectors : this.importsSelectors;
    567     },
    568     isParsed: function(node) {
    569       return node.__importParsed;
    570     },
    571     needsDynamicParsing: function(elt) {
    572       return this.dynamicElements.indexOf(elt) >= 0;
    573     },
    574     hasResource: function(node) {
    575       if (nodeIsImport(node) && node.import === undefined) {
    576         return false;
    577       }
    578       return true;
    579     }
    580   };
    581   function nodeIsImport(elt) {
    582     return elt.localName === "link" && elt.rel === IMPORT_LINK_TYPE;
    583   }
    584   function generateScriptDataUrl(script) {
    585     var scriptContent = generateScriptContent(script);
    586     return "data:text/javascript;charset=utf-8," + encodeURIComponent(scriptContent);
    587   }
    588   function generateScriptContent(script) {
    589     return script.textContent + generateSourceMapHint(script);
    590   }
    591   function generateSourceMapHint(script) {
    592     var owner = script.ownerDocument;
    593     owner.__importedScripts = owner.__importedScripts || 0;
    594     var moniker = script.ownerDocument.baseURI;
    595     var num = owner.__importedScripts ? "-" + owner.__importedScripts : "";
    596     owner.__importedScripts++;
    597     return "\n//# sourceURL=" + moniker + num + ".js\n";
    598   }
    599   function cloneStyle(style) {
    600     var clone = style.ownerDocument.createElement("style");
    601     clone.textContent = style.textContent;
    602     path.resolveUrlsInStyle(clone);
    603     return clone;
    604   }
    605   scope.parser = importParser;
    606   scope.IMPORT_SELECTOR = IMPORT_SELECTOR;
    607 });
    608 
    609 HTMLImports.addModule(function(scope) {
    610   var flags = scope.flags;
    611   var IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;
    612   var IMPORT_SELECTOR = scope.IMPORT_SELECTOR;
    613   var rootDocument = scope.rootDocument;
    614   var Loader = scope.Loader;
    615   var Observer = scope.Observer;
    616   var parser = scope.parser;
    617   var importer = {
    618     documents: {},
    619     documentPreloadSelectors: IMPORT_SELECTOR,
    620     importsPreloadSelectors: [ IMPORT_SELECTOR ].join(","),
    621     loadNode: function(node) {
    622       importLoader.addNode(node);
    623     },
    624     loadSubtree: function(parent) {
    625       var nodes = this.marshalNodes(parent);
    626       importLoader.addNodes(nodes);
    627     },
    628     marshalNodes: function(parent) {
    629       return parent.querySelectorAll(this.loadSelectorsForNode(parent));
    630     },
    631     loadSelectorsForNode: function(node) {
    632       var doc = node.ownerDocument || node;
    633       return doc === rootDocument ? this.documentPreloadSelectors : this.importsPreloadSelectors;
    634     },
    635     loaded: function(url, elt, resource, err, redirectedUrl) {
    636       flags.load && console.log("loaded", url, elt);
    637       elt.__resource = resource;
    638       elt.__error = err;
    639       if (isImportLink(elt)) {
    640         var doc = this.documents[url];
    641         if (doc === undefined) {
    642           doc = err ? null : makeDocument(resource, redirectedUrl || url);
    643           if (doc) {
    644             doc.__importLink = elt;
    645             this.bootDocument(doc);
    646           }
    647           this.documents[url] = doc;
    648         }
    649         elt.import = doc;
    650       }
    651       parser.parseNext();
    652     },
    653     bootDocument: function(doc) {
    654       this.loadSubtree(doc);
    655       this.observer.observe(doc);
    656       parser.parseNext();
    657     },
    658     loadedAll: function() {
    659       parser.parseNext();
    660     }
    661   };
    662   var importLoader = new Loader(importer.loaded.bind(importer), importer.loadedAll.bind(importer));
    663   importer.observer = new Observer();
    664   function isImportLink(elt) {
    665     return isLinkRel(elt, IMPORT_LINK_TYPE);
    666   }
    667   function isLinkRel(elt, rel) {
    668     return elt.localName === "link" && elt.getAttribute("rel") === rel;
    669   }
    670   function hasBaseURIAccessor(doc) {
    671     return !!Object.getOwnPropertyDescriptor(doc, "baseURI");
    672   }
    673   function makeDocument(resource, url) {
    674     var doc = document.implementation.createHTMLDocument(IMPORT_LINK_TYPE);
    675     doc._URL = url;
    676     var base = doc.createElement("base");
    677     base.setAttribute("href", url);
    678     if (!doc.baseURI && !hasBaseURIAccessor(doc)) {
    679       Object.defineProperty(doc, "baseURI", {
    680         value: url
    681       });
    682     }
    683     var meta = doc.createElement("meta");
    684     meta.setAttribute("charset", "utf-8");
    685     doc.head.appendChild(meta);
    686     doc.head.appendChild(base);
    687     doc.body.innerHTML = resource;
    688     if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) {
    689       HTMLTemplateElement.bootstrap(doc);
    690     }
    691     return doc;
    692   }
    693   if (!document.baseURI) {
    694     var baseURIDescriptor = {
    695       get: function() {
    696         var base = document.querySelector("base");
    697         return base ? base.href : window.location.href;
    698       },
    699       configurable: true
    700     };
    701     Object.defineProperty(document, "baseURI", baseURIDescriptor);
    702     Object.defineProperty(rootDocument, "baseURI", baseURIDescriptor);
    703   }
    704   scope.importer = importer;
    705   scope.importLoader = importLoader;
    706 });
    707 
    708 HTMLImports.addModule(function(scope) {
    709   var parser = scope.parser;
    710   var importer = scope.importer;
    711   var dynamic = {
    712     added: function(nodes) {
    713       var owner, parsed, loading;
    714       for (var i = 0, l = nodes.length, n; i < l && (n = nodes[i]); i++) {
    715         if (!owner) {
    716           owner = n.ownerDocument;
    717           parsed = parser.isParsed(owner);
    718         }
    719         loading = this.shouldLoadNode(n);
    720         if (loading) {
    721           importer.loadNode(n);
    722         }
    723         if (this.shouldParseNode(n) && parsed) {
    724           parser.parseDynamic(n, loading);
    725         }
    726       }
    727     },
    728     shouldLoadNode: function(node) {
    729       return node.nodeType === 1 && matches.call(node, importer.loadSelectorsForNode(node));
    730     },
    731     shouldParseNode: function(node) {
    732       return node.nodeType === 1 && matches.call(node, parser.parseSelectorsForNode(node));
    733     }
    734   };
    735   importer.observer.addCallback = dynamic.added.bind(dynamic);
    736   var matches = HTMLElement.prototype.matches || HTMLElement.prototype.matchesSelector || HTMLElement.prototype.webkitMatchesSelector || HTMLElement.prototype.mozMatchesSelector || HTMLElement.prototype.msMatchesSelector;
    737 });
    738 
    739 (function(scope) {
    740   var initializeModules = scope.initializeModules;
    741   var isIE = scope.isIE;
    742   if (scope.useNative) {
    743     return;
    744   }
    745   if (isIE && typeof window.CustomEvent !== "function") {
    746     window.CustomEvent = function(inType, params) {
    747       params = params || {};
    748       var e = document.createEvent("CustomEvent");
    749       e.initCustomEvent(inType, Boolean(params.bubbles), Boolean(params.cancelable), params.detail);
    750       return e;
    751     };
    752     window.CustomEvent.prototype = window.Event.prototype;
    753   }
    754   initializeModules();
    755   var rootDocument = scope.rootDocument;
    756   function bootstrap() {
    757     HTMLImports.importer.bootDocument(rootDocument);
    758   }
    759   if (document.readyState === "complete" || document.readyState === "interactive" && !window.attachEvent) {
    760     bootstrap();
    761   } else {
    762     document.addEventListener("DOMContentLoaded", bootstrap);
    763   }
    764 })(HTMLImports);