| Index: pkg/web_components/lib/platform.concat.js
|
| diff --git a/pkg/web_components/lib/platform.concat.js b/pkg/web_components/lib/platform.concat.js
|
| index 449be75909a04336153634aebcadeda141e6e05c..f6ebf1541bbbcf21c42d0e8aba7b5f867c0060e9 100644
|
| --- a/pkg/web_components/lib/platform.concat.js
|
| +++ b/pkg/web_components/lib/platform.concat.js
|
| @@ -46,7 +46,7 @@ window.logFlags = window.logFlags || {};
|
| }
|
|
|
| if (flags.shadow && document.querySelectorAll('script').length > 1) {
|
| - console.warn('platform.js is not the first script on the page. ' +
|
| + console.log('Warning: platform.js is not the first script on the page. ' +
|
| 'See http://www.polymer-project.org/docs/start/platform.html#setup ' +
|
| 'for details.');
|
| }
|
| @@ -88,6 +88,7 @@ if (typeof WeakMap === 'undefined') {
|
| entry[1] = value;
|
| else
|
| defineProperty(key, this.name, {value: [key, value], writable: true});
|
| + return this;
|
| },
|
| get: function(key) {
|
| var entry;
|
| @@ -4509,6 +4510,7 @@ window.ShadowDOMPolyfill = {};
|
| return s;
|
| },
|
| set textContent(textContent) {
|
| + if (textContent == null) textContent = '';
|
| var removedNodes = snapshotNodeList(this.childNodes);
|
|
|
| if (this.invalidateShadowRenderer()) {
|
| @@ -9513,6 +9515,30 @@ scope.ShadowCSS = ShadowCSS;
|
| if ('#' == hash[0])
|
| hash = hash.slice(1);
|
| parse.call(this, hash, 'fragment');
|
| + },
|
| +
|
| + get origin() {
|
| + var host;
|
| + if (this._isInvalid || !this._scheme) {
|
| + return '';
|
| + }
|
| + // javascript: Gecko returns String(""), WebKit/Blink String("null")
|
| + // Gecko throws error for "data://"
|
| + // data: Gecko returns "", Blink returns "data://", WebKit returns "null"
|
| + // Gecko returns String("") for file: mailto:
|
| + // WebKit/Blink returns String("SCHEME://") for file: mailto:
|
| + switch (this._scheme) {
|
| + case 'data':
|
| + case 'file':
|
| + case 'javascript':
|
| + case 'mailto':
|
| + return 'null';
|
| + }
|
| + host = this.host;
|
| + if (!host) {
|
| + return '';
|
| + }
|
| + return this._scheme + '://' + host;
|
| }
|
| };
|
|
|
| @@ -10127,17 +10153,18 @@ window.HTMLImports = window.HTMLImports || {flags:{}};
|
|
|
| (function(scope) {
|
|
|
| -var hasNative = ('import' in document.createElement('link'));
|
| +var IMPORT_LINK_TYPE = 'import';
|
| +var hasNative = (IMPORT_LINK_TYPE in document.createElement('link'));
|
| var useNative = hasNative;
|
| -
|
| -isIE = /Trident/.test(navigator.userAgent);
|
| +var isIE = /Trident/.test(navigator.userAgent);
|
|
|
| // TODO(sorvell): SD polyfill intrusion
|
| var hasShadowDOMPolyfill = Boolean(window.ShadowDOMPolyfill);
|
| var wrap = function(node) {
|
| return hasShadowDOMPolyfill ? ShadowDOMPolyfill.wrapIfNeeded(node) : node;
|
| };
|
| -var mainDoc = wrap(document);
|
| +
|
| +var rootDocument = wrap(document);
|
|
|
| // NOTE: We cannot polyfill document.currentScript because it's not possible
|
| // both to override and maintain the ability to capture the native value;
|
| @@ -10157,14 +10184,14 @@ var currentScriptDescriptor = {
|
| };
|
|
|
| Object.defineProperty(document, '_currentScript', currentScriptDescriptor);
|
| -Object.defineProperty(mainDoc, '_currentScript', currentScriptDescriptor);
|
| +Object.defineProperty(rootDocument, '_currentScript', currentScriptDescriptor);
|
|
|
| // call a callback when all HTMLImports in the document at call (or at least
|
| // document ready) time have loaded.
|
| // 1. ensure the document is in a ready state (has dom), then
|
| // 2. watch for loading of imports and call callback when done
|
| -function whenImportsReady(callback, doc) {
|
| - doc = doc || mainDoc;
|
| +function whenReady(callback, doc) {
|
| + doc = doc || rootDocument;
|
| // if document is loading, wait and try again
|
| whenDocumentReady(function() {
|
| watchImportsLoad(callback, doc);
|
| @@ -10204,8 +10231,8 @@ function watchImportsLoad(callback, doc) {
|
| var imports = doc.querySelectorAll('link[rel=import]');
|
| var loaded = 0, l = imports.length;
|
| function checkDone(d) {
|
| - if (loaded == l) {
|
| - callback && callback();
|
| + if ((loaded == l) && callback) {
|
| + callback();
|
| }
|
| }
|
| function loadedImport(e) {
|
| @@ -10298,10 +10325,10 @@ if (useNative) {
|
| // have loaded. This event is required to simulate the script blocking
|
| // behavior of native imports. A main document script that needs to be sure
|
| // imports have loaded should wait for this event.
|
| -whenImportsReady(function() {
|
| +whenReady(function() {
|
| HTMLImports.ready = true;
|
| HTMLImports.readyTime = new Date().getTime();
|
| - mainDoc.dispatchEvent(
|
| + rootDocument.dispatchEvent(
|
| new CustomEvent('HTMLImportsLoaded', {bubbles: true})
|
| );
|
| });
|
| @@ -10309,12 +10336,11 @@ whenImportsReady(function() {
|
| // exports
|
| scope.useNative = useNative;
|
| scope.isImportLoaded = isImportLoaded;
|
| -scope.whenReady = whenImportsReady;
|
| +scope.whenReady = whenReady;
|
| +scope.rootDocument = rootDocument;
|
| +scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;
|
| scope.isIE = isIE;
|
|
|
| -// deprecated
|
| -scope.whenImportsReady = whenImportsReady;
|
| -
|
| })(window.HTMLImports);
|
| /*
|
| * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
| @@ -10344,6 +10370,7 @@ scope.whenImportsReady = whenImportsReady;
|
| };
|
|
|
| Loader.prototype = {
|
| +
|
| addNodes: function(nodes) {
|
| // number of transactions to complete
|
| this.inflight += nodes.length;
|
| @@ -10354,6 +10381,7 @@ scope.whenImportsReady = whenImportsReady;
|
| // anything to do?
|
| this.checkDone();
|
| },
|
| +
|
| addNode: function(node) {
|
| // number of transactions to complete
|
| this.inflight++;
|
| @@ -10362,6 +10390,7 @@ scope.whenImportsReady = whenImportsReady;
|
| // anything to do?
|
| this.checkDone();
|
| },
|
| +
|
| require: function(elt) {
|
| var url = elt.src || elt.href;
|
| // ensure we have a standard url that can be used
|
| @@ -10374,6 +10403,7 @@ scope.whenImportsReady = whenImportsReady;
|
| this.fetch(url, elt);
|
| }
|
| },
|
| +
|
| dedupe: function(url, elt) {
|
| if (this.pending[url]) {
|
| // add to list of nodes waiting for inUrl
|
| @@ -10394,6 +10424,7 @@ scope.whenImportsReady = whenImportsReady;
|
| // need fetch (not a dupe)
|
| return false;
|
| },
|
| +
|
| fetch: function(url, elt) {
|
| flags.load && console.log('fetch', url, elt);
|
| if (url.match(/^data:/)) {
|
| @@ -10429,6 +10460,7 @@ scope.whenImportsReady = whenImportsReady;
|
| */
|
| }
|
| },
|
| +
|
| receive: function(url, elt, err, resource, redirectedUrl) {
|
| this.cache[url] = resource;
|
| var $p = this.pending[url];
|
| @@ -10440,24 +10472,29 @@ scope.whenImportsReady = whenImportsReady;
|
| }
|
| this.pending[url] = null;
|
| },
|
| +
|
| tail: function() {
|
| --this.inflight;
|
| this.checkDone();
|
| },
|
| +
|
| checkDone: function() {
|
| if (!this.inflight) {
|
| this.oncomplete();
|
| }
|
| }
|
| +
|
| };
|
|
|
| xhr = xhr || {
|
| async: true,
|
| +
|
| ok: function(request) {
|
| return (request.status >= 200 && request.status < 300)
|
| || (request.status === 304)
|
| || (request.status === 0);
|
| },
|
| +
|
| load: function(url, next, nextContext) {
|
| var request = new XMLHttpRequest();
|
| if (scope.flags.debug || scope.flags.bust) {
|
| @@ -10482,9 +10519,11 @@ scope.whenImportsReady = whenImportsReady;
|
| request.send();
|
| return request;
|
| },
|
| +
|
| loadDocument: function(url, next, nextContext) {
|
| this.load(url, next, nextContext).responseType = 'document';
|
| }
|
| +
|
| };
|
|
|
| // exports
|
| @@ -10503,12 +10542,11 @@ scope.whenImportsReady = whenImportsReady;
|
| */
|
| (function(scope) {
|
|
|
| -var IMPORT_LINK_TYPE = 'import';
|
| +// imports
|
| +var rootDocument = scope.rootDocument;
|
| var flags = scope.flags;
|
| var isIE = scope.isIE;
|
| -// TODO(sorvell): SD polyfill intrusion
|
| -var mainDoc = window.ShadowDOMPolyfill ?
|
| - window.ShadowDOMPolyfill.wrapIfNeeded(document) : document;
|
| +var IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;
|
|
|
| // importParser
|
| // highlander object to manage parsing of imports
|
| @@ -10519,8 +10557,10 @@ var mainDoc = window.ShadowDOMPolyfill ?
|
|
|
| // highlander object for parsing a document tree
|
| var importParser = {
|
| +
|
| // parse selectors for main document elements
|
| documentSelectors: 'link[rel=' + IMPORT_LINK_TYPE + ']',
|
| +
|
| // parse selectors for import document elements
|
| importsSelectors: [
|
| 'link[rel=' + IMPORT_LINK_TYPE + ']',
|
| @@ -10529,11 +10569,15 @@ var importParser = {
|
| 'script:not([type])',
|
| 'script[type="text/javascript"]'
|
| ].join(','),
|
| +
|
| map: {
|
| link: 'parseLink',
|
| script: 'parseScript',
|
| style: 'parseStyle'
|
| },
|
| +
|
| + dynamicElements: [],
|
| +
|
| // try to parse the next import in the tree
|
| parseNext: function() {
|
| var next = this.nextToParse();
|
| @@ -10541,6 +10585,7 @@ var importParser = {
|
| this.parse(next);
|
| }
|
| },
|
| +
|
| parse: function(elt) {
|
| if (this.isParsed(elt)) {
|
| flags.parse && console.log('[%s] is already parsed', elt.localName);
|
| @@ -10552,6 +10597,14 @@ var importParser = {
|
| fn.call(this, elt);
|
| }
|
| },
|
| +
|
| + parseDynamic: function(elt, quiet) {
|
| + this.dynamicElements.push(elt);
|
| + if (!quiet) {
|
| + this.parseNext();
|
| + }
|
| + },
|
| +
|
| // only 1 element may be parsed at a time; parsing is async so each
|
| // parsing implementation must inform the system that parsing is complete
|
| // via markParsingComplete.
|
| @@ -10564,29 +10617,25 @@ var importParser = {
|
| flags.parse && console.log('parsing', elt);
|
| this.parsingElement = elt;
|
| },
|
| +
|
| markParsingComplete: function(elt) {
|
| elt.__importParsed = true;
|
| + this.markDynamicParsingComplete(elt);
|
| if (elt.__importElement) {
|
| elt.__importElement.__importParsed = true;
|
| + this.markDynamicParsingComplete(elt.__importElement);
|
| }
|
| this.parsingElement = null;
|
| flags.parse && console.log('completed', elt);
|
| },
|
| - invalidateParse: function(doc) {
|
| - if (doc && doc.__importLink) {
|
| - doc.__importParsed = doc.__importLink.__importParsed = false;
|
| - this.parseSoon();
|
| - }
|
| - },
|
| - parseSoon: function() {
|
| - if (this._parseSoon) {
|
| - cancelAnimationFrame(this._parseDelay);
|
| +
|
| + markDynamicParsingComplete: function(elt) {
|
| + var i = this.dynamicElements.indexOf(elt);
|
| + if (i >= 0) {
|
| + this.dynamicElements.splice(i, 1);
|
| }
|
| - var parser = this;
|
| - this._parseSoon = requestAnimationFrame(function() {
|
| - parser.parseNext();
|
| - });
|
| },
|
| +
|
| parseImport: function(elt) {
|
| // TODO(sorvell): consider if there's a better way to do this;
|
| // expose an imports parsing hook; this is needed, for example, by the
|
| @@ -10617,6 +10666,7 @@ var importParser = {
|
| }
|
| this.parseNext();
|
| },
|
| +
|
| parseLink: function(linkElt) {
|
| if (nodeIsImport(linkElt)) {
|
| this.parseImport(linkElt);
|
| @@ -10626,6 +10676,7 @@ var importParser = {
|
| this.parseGeneric(linkElt);
|
| }
|
| },
|
| +
|
| parseStyle: function(elt) {
|
| // TODO(sorvell): style element load event can just not fire so clone styles
|
| var src = elt;
|
| @@ -10633,10 +10684,12 @@ var importParser = {
|
| elt.__importElement = src;
|
| this.parseGeneric(elt);
|
| },
|
| +
|
| parseGeneric: function(elt) {
|
| this.trackElement(elt);
|
| this.addElementToDocument(elt);
|
| },
|
| +
|
| rootImportForElement: function(elt) {
|
| var n = elt;
|
| while (n.ownerDocument.__importLink) {
|
| @@ -10644,6 +10697,7 @@ var importParser = {
|
| }
|
| return n;
|
| },
|
| +
|
| addElementToDocument: function(elt) {
|
| var port = this.rootImportForElement(elt.__importElement || elt);
|
| var l = port.__insertedElements = port.__insertedElements || 0;
|
| @@ -10653,6 +10707,7 @@ var importParser = {
|
| }
|
| port.parentNode.insertBefore(elt, refNode);
|
| },
|
| +
|
| // tracks when a loadable element has loaded
|
| trackElement: function(elt, callback) {
|
| var self = this;
|
| @@ -10692,6 +10747,7 @@ var importParser = {
|
| }
|
| }
|
| },
|
| +
|
| // NOTE: execute scripts by injecting them and watching for the load/error
|
| // event. Inline scripts are handled via dataURL's because browsers tend to
|
| // provide correct parsing errors in this case. If this has any compatibility
|
| @@ -10710,11 +10766,14 @@ var importParser = {
|
| });
|
| this.addElementToDocument(script);
|
| },
|
| +
|
| // determine the next element in the tree which should be parsed
|
| nextToParse: function() {
|
| this._mayParse = [];
|
| - return !this.parsingElement && this.nextToParseInDoc(mainDoc);
|
| + return !this.parsingElement && (this.nextToParseInDoc(rootDocument) ||
|
| + this.nextToParseDynamic());
|
| },
|
| +
|
| nextToParseInDoc: function(doc, link) {
|
| // use `marParse` list to avoid looping into the same document again
|
| // since it could cause an iloop.
|
| @@ -10734,20 +10793,33 @@ var importParser = {
|
| // all nodes have been parsed, ready to parse import, if any
|
| return link;
|
| },
|
| +
|
| + nextToParseDynamic: function() {
|
| + return this.dynamicElements[0];
|
| + },
|
| +
|
| // return the set of parse selectors relevant for this node.
|
| parseSelectorsForNode: function(node) {
|
| var doc = node.ownerDocument || node;
|
| - return doc === mainDoc ? this.documentSelectors : this.importsSelectors;
|
| + return doc === rootDocument ? this.documentSelectors :
|
| + this.importsSelectors;
|
| },
|
| +
|
| isParsed: function(node) {
|
| return node.__importParsed;
|
| },
|
| +
|
| + needsDynamicParsing: function(elt) {
|
| + return (this.dynamicElements.indexOf(elt) >= 0);
|
| + },
|
| +
|
| hasResource: function(node) {
|
| if (nodeIsImport(node) && (node.import === undefined)) {
|
| return false;
|
| }
|
| return true;
|
| }
|
| +
|
| };
|
|
|
| function nodeIsImport(elt) {
|
| @@ -10797,17 +10869,20 @@ var CSS_URL_REGEXP = /(url\()([^)]*)(\))/g;
|
| var CSS_IMPORT_REGEXP = /(@import[\s]+(?!url\())([^;]*)(;)/g;
|
|
|
| var path = {
|
| +
|
| resolveUrlsInStyle: function(style) {
|
| var doc = style.ownerDocument;
|
| var resolver = doc.createElement('a');
|
| style.textContent = this.resolveUrlsInCssText(style.textContent, resolver);
|
| return style;
|
| },
|
| +
|
| resolveUrlsInCssText: function(cssText, urlObj) {
|
| var r = this.replaceUrls(cssText, urlObj, CSS_URL_REGEXP);
|
| r = this.replaceUrls(r, urlObj, CSS_IMPORT_REGEXP);
|
| return r;
|
| },
|
| +
|
| replaceUrls: function(text, urlObj, regexp) {
|
| return text.replace(regexp, function(m, pre, url, post) {
|
| var urlPath = url.replace(/["']/g, '');
|
| @@ -10816,7 +10891,8 @@ var path = {
|
| return pre + '\'' + urlPath + '\'' + post;
|
| });
|
| }
|
| -}
|
| +
|
| +};
|
|
|
| // exports
|
| scope.parser = importParser;
|
| @@ -10834,17 +10910,15 @@ scope.path = path;
|
| */
|
| (function(scope) {
|
|
|
| +// imports
|
| var useNative = scope.useNative;
|
| var flags = scope.flags;
|
| -var IMPORT_LINK_TYPE = 'import';
|
| -
|
| -// TODO(sorvell): SD polyfill intrusion
|
| -var mainDoc = window.ShadowDOMPolyfill ?
|
| - ShadowDOMPolyfill.wrapIfNeeded(document) : document;
|
| +var IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;
|
|
|
| if (!useNative) {
|
|
|
| // imports
|
| + var rootDocument = scope.rootDocument;
|
| var xhr = scope.xhr;
|
| var Loader = scope.Loader;
|
| var parser = scope.parser;
|
| @@ -10856,32 +10930,40 @@ if (!useNative) {
|
| // - loads any linked import documents (with deduping)
|
|
|
| var importer = {
|
| +
|
| documents: {},
|
| +
|
| // nodes to load in the mian document
|
| documentPreloadSelectors: 'link[rel=' + IMPORT_LINK_TYPE + ']',
|
| +
|
| // nodes to load in imports
|
| importsPreloadSelectors: [
|
| 'link[rel=' + IMPORT_LINK_TYPE + ']'
|
| ].join(','),
|
| +
|
| loadNode: function(node) {
|
| importLoader.addNode(node);
|
| },
|
| +
|
| // load all loadable elements within the parent element
|
| loadSubtree: function(parent) {
|
| var nodes = this.marshalNodes(parent);
|
| // add these nodes to loader's queue
|
| importLoader.addNodes(nodes);
|
| },
|
| +
|
| marshalNodes: function(parent) {
|
| // all preloadable nodes in inDocument
|
| return parent.querySelectorAll(this.loadSelectorsForNode(parent));
|
| },
|
| +
|
| // find the proper set of load selectors for a given node
|
| loadSelectorsForNode: function(node) {
|
| var doc = node.ownerDocument || node;
|
| - return doc === mainDoc ? this.documentPreloadSelectors :
|
| + return doc === rootDocument ? this.documentPreloadSelectors :
|
| this.importsPreloadSelectors;
|
| },
|
| +
|
| loaded: function(url, elt, resource, err, redirectedUrl) {
|
| flags.load && console.log('loaded', url, elt);
|
| // store generic resource
|
| @@ -10910,14 +10992,17 @@ if (!useNative) {
|
| }
|
| parser.parseNext();
|
| },
|
| +
|
| bootDocument: function(doc) {
|
| this.loadSubtree(doc);
|
| this.observe(doc);
|
| parser.parseNext();
|
| },
|
| +
|
| loadedAll: function() {
|
| parser.parseNext();
|
| }
|
| +
|
| };
|
|
|
| // loader singleton
|
| @@ -10985,7 +11070,7 @@ if (!useNative) {
|
| };
|
|
|
| Object.defineProperty(document, 'baseURI', baseURIDescriptor);
|
| - Object.defineProperty(mainDoc, 'baseURI', baseURIDescriptor);
|
| + Object.defineProperty(rootDocument, 'baseURI', baseURIDescriptor);
|
| }
|
|
|
| // IE shim for CustomEvent
|
| @@ -11010,7 +11095,6 @@ scope.importer = importer;
|
| scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;
|
| scope.importLoader = importLoader;
|
|
|
| -
|
| })(window.HTMLImports);
|
|
|
| /*
|
| @@ -11023,11 +11107,14 @@ scope.importLoader = importLoader;
|
| */
|
| (function(scope){
|
|
|
| +// imports
|
| var IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;
|
| -var importSelector = 'link[rel=' + IMPORT_LINK_TYPE + ']';
|
| var importer = scope.importer;
|
| var parser = scope.parser;
|
|
|
| +var importSelector = 'link[rel=' + IMPORT_LINK_TYPE + ']';
|
| +
|
| +
|
| // we track mutations for addedNodes, looking for imports
|
| function handler(mutations) {
|
| for (var i=0, l=mutations.length, m; (i<l) && (m=mutations[i]); i++) {
|
| @@ -11038,25 +11125,28 @@ function handler(mutations) {
|
| }
|
|
|
| // find loadable elements and add them to the importer
|
| +// IFF the owning document has already parsed, then parsable elements
|
| +// need to be marked for dynamic parsing.
|
| function addedNodes(nodes) {
|
| - var owner;
|
| - for (var i=0, l=nodes.length, n; (i<l) && (n=nodes[i]); i++) {
|
| - owner = owner || n.ownerDocument;
|
| - if (shouldLoadNode(n)) {
|
| + var owner, parsed;
|
| + for (var i=0, l=nodes.length, n, loading; (i<l) && (n=nodes[i]); i++) {
|
| + if (!owner) {
|
| + owner = n.ownerDocument;
|
| + parsed = parser.isParsed(owner);
|
| + }
|
| + // note: the act of loading kicks the parser, so we use parseDynamic's
|
| + // 2nd argument to control if this added node needs to kick the parser.
|
| + loading = shouldLoadNode(n);
|
| + if (loading) {
|
| importer.loadNode(n);
|
| }
|
| + if (shouldParseNode(n) && parsed) {
|
| + parser.parseDynamic(n, loading);
|
| + }
|
| if (n.children && n.children.length) {
|
| addedNodes(n.children);
|
| }
|
| }
|
| - // TODO(sorvell): This is not the right approach here. We shouldn't need to
|
| - // invalidate parsing when an element is added. Disabling this code
|
| - // until a better approach is found.
|
| - /*
|
| - if (owner) {
|
| - parser.invalidateParse(owner);
|
| - }
|
| - */
|
| }
|
|
|
| function shouldLoadNode(node) {
|
| @@ -11064,6 +11154,11 @@ function shouldLoadNode(node) {
|
| importer.loadSelectorsForNode(node));
|
| }
|
|
|
| +function shouldParseNode(node) {
|
| + return (node.nodeType === 1) && matches.call(node,
|
| + parser.parseSelectorsForNode(node));
|
| +}
|
| +
|
| // x-plat matches
|
| var matches = HTMLElement.prototype.matches ||
|
| HTMLElement.prototype.matchesSelector ||
|
|
|