siesta-lite
Version:
Stress-free JavaScript unit testing and functional testing tool, works in NodeJS and browsers
1,302 lines (1,206 loc) • 777 kB
JavaScript
(function(){/*
Copyright (c) 2017 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
*/
'use strict';var k={};function n(){this.end=this.start=0;this.rules=this.parent=this.previous=null;this.cssText=this.parsedCssText="";this.atRule=!1;this.type=0;this.parsedSelector=this.selector=this.keyframesName=""}
function p(a){a=a.replace(aa,"").replace(ba,"");var b=q,c=a,d=new n;d.start=0;d.end=c.length;for(var e=d,f=0,h=c.length;f<h;f++)if("{"===c[f]){e.rules||(e.rules=[]);var g=e,m=g.rules[g.rules.length-1]||null,e=new n;e.start=f+1;e.parent=g;e.previous=m;g.rules.push(e)}else"}"===c[f]&&(e.end=f+1,e=e.parent||d);return b(d,a)}
function q(a,b){var c=b.substring(a.start,a.end-1);a.parsedCssText=a.cssText=c.trim();a.parent&&((c=b.substring(a.previous?a.previous.end:a.parent.start,a.start-1),c=ca(c),c=c.replace(r," "),c=c.substring(c.lastIndexOf(";")+1),c=a.parsedSelector=a.selector=c.trim(),a.atRule=!c.indexOf("@"),a.atRule)?c.indexOf("@media")?c.match(da)&&(a.type=u,a.keyframesName=a.selector.split(r).pop()):a.type=t:a.type=c.indexOf("--")?v:x);if(c=a.rules)for(var d=0,e=c.length,f;d<e&&(f=c[d]);d++)q(f,b);return a}
function ca(a){return a.replace(/\\([0-9a-f]{1,6})\s/gi,function(a,c){a=c;for(c=6-a.length;c--;)a="0"+a;return"\\"+a})}
function y(a,b,c){c=void 0===c?"":c;var d="";if(a.cssText||a.rules){var e=a.rules,f;if(f=e)f=e[0],f=!(f&&f.selector&&0===f.selector.indexOf("--"));if(f){f=0;for(var h=e.length,g;f<h&&(g=e[f]);f++)d=y(g,b,d)}else b?b=a.cssText:(b=a.cssText,b=b.replace(ea,"").replace(fa,""),b=b.replace(ga,"").replace(ha,"")),(d=b.trim())&&(d=" "+d+"\n")}d&&(a.selector&&(c+=a.selector+" {\n"),c+=d,a.selector&&(c+="}\n\n"));return c}
var v=1,u=7,t=4,x=1E3,aa=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,ba=/@import[^;]*;/gim,ea=/(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?(?:[;\n]|$)/gim,fa=/(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?{[^}]*?}(?:[;\n]|$)?/gim,ga=/@apply\s*\(?[^);]*\)?\s*(?:[;\n]|$)?/gim,ha=/[^;:]*?:[^;]*?var\([^;]*\)(?:[;\n]|$)?/gim,da=/^@[^\s]*keyframes/,r=/\s+/g;var ia=Promise.resolve();function ja(a){if(a=k[a])a._applyShimCurrentVersion=a._applyShimCurrentVersion||0,a._applyShimValidatingVersion=a._applyShimValidatingVersion||0,a._applyShimNextVersion=(a._applyShimNextVersion||0)+1}function z(a){return a._applyShimCurrentVersion===a._applyShimNextVersion}function ka(a){a._applyShimValidatingVersion=a._applyShimNextVersion;a.a||(a.a=!0,ia.then(function(){a._applyShimCurrentVersion=a._applyShimNextVersion;a.a=!1}))};var A=/(?:^|[;\s{]\s*)(--[\w-]*?)\s*:\s*(?:((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^)]*?\)|[^};{])+)|\{([^}]*)\}(?:(?=[;\s}])|$))/gi,B=/(?:^|\W+)@apply\s*\(?([^);\n]*)\)?/gi,la=/@media\s(.*)/;var C=!(window.ShadyDOM&&window.ShadyDOM.inUse),E;function F(a){E=a&&a.shimcssproperties?!1:C||!(navigator.userAgent.match(/AppleWebKit\/601|Edge\/15/)||!window.CSS||!CSS.supports||!CSS.supports("box-shadow","0 0 0 var(--foo)"))}window.ShadyCSS&&void 0!==window.ShadyCSS.nativeCss?E=window.ShadyCSS.nativeCss:window.ShadyCSS?(F(window.ShadyCSS),window.ShadyCSS=void 0):F(window.WebComponents&&window.WebComponents.flags);var G=E;function H(a){if(!a)return"";"string"===typeof a&&(a=p(a));return y(a,G)}function I(a){!a.__cssRules&&a.textContent&&(a.__cssRules=p(a.textContent));return a.__cssRules||null}function J(a,b,c,d){if(a){var e=!1,f=a.type;if(d&&f===t){var h=a.selector.match(la);h&&(window.matchMedia(h[1]).matches||(e=!0))}f===v?b(a):c&&f===u?c(a):f===x&&(e=!0);if((a=a.rules)&&!e)for(var e=0,f=a.length,g;e<f&&(g=a[e]);e++)J(g,b,c,d)}}
function K(a,b){var c=a.indexOf("var(");if(-1===c)return b(a,"","","");a:{var d=0;var e=c+3;for(var f=a.length;e<f;e++)if("("===a[e])d++;else if(")"===a[e]&&!--d)break a;e=-1}d=a.substring(c+4,e);c=a.substring(0,c);a=K(a.substring(e+1),b);e=d.indexOf(",");return-1===e?b(c,d.trim(),"",a):b(c,d.substring(0,e).trim(),d.substring(e+1).trim(),a)};var ma=/;\s*/m,na=/^\s*(initial)|(inherit)\s*$/;function L(){this.a={}}L.prototype.set=function(a,b){a=a.trim();this.a[a]={h:b,i:{}}};L.prototype.get=function(a){a=a.trim();return this.a[a]||null};var M=null;function N(){this.b=this.c=null;this.a=new L}N.prototype.o=function(a){a=B.test(a)||A.test(a);B.lastIndex=0;A.lastIndex=0;return a};N.prototype.m=function(a,b){a=a.content.querySelector("style");var c=null;a&&(c=this.j(a,b));return c};
N.prototype.j=function(a,b){b=void 0===b?"":b;var c=I(a);this.l(c,b);a.textContent=H(c);return c};N.prototype.f=function(a){var b=this,c=I(a);J(c,function(a){":root"===a.selector&&(a.selector="html");b.g(a)});a.textContent=H(c);return c};N.prototype.l=function(a,b){var c=this;this.c=b;J(a,function(a){c.g(a)});this.c=null};N.prototype.g=function(a){a.cssText=oa(this,a.parsedCssText);":root"===a.selector&&(a.selector=":host > *")};
function oa(a,b){b=b.replace(A,function(b,d,e,f){return pa(a,b,d,e,f)});return O(a,b)}function O(a,b){for(var c;c=B.exec(b);){var d=c[0],e=c[1];c=c.index;var f=b.slice(0,c+d.indexOf("@apply"));b=b.slice(c+d.length);var h=P(a,f),d=void 0;var g=a;var e=e.replace(ma,""),m=[];var l=g.a.get(e);l||(g.a.set(e,{}),l=g.a.get(e));if(l)for(d in g.c&&(l.i[g.c]=!0),l.h)g=h&&h[d],l=[d,": var(",e,"_-_",d],g&&l.push(",",g),l.push(")"),m.push(l.join(""));d=m.join("; ");b=""+f+d+b;B.lastIndex=c+d.length}return b}
function P(a,b){b=b.split(";");for(var c,d,e={},f=0,h;f<b.length;f++)if(c=b[f])if(h=c.split(":"),1<h.length){c=h[0].trim();var g=a;d=c;h=h.slice(1).join(":");var m=na.exec(h);m&&(m[1]?(g.b||(g.b=document.createElement("meta"),g.b.setAttribute("apply-shim-measure",""),g.b.style.all="initial",document.head.appendChild(g.b)),d=window.getComputedStyle(g.b).getPropertyValue(d)):d="apply-shim-inherit",h=d);d=h;e[c]=d}return e}function qa(a,b){if(M)for(var c in b.i)c!==a.c&&M(c)}
function pa(a,b,c,d,e){d&&K(d,function(b,c){c&&a.a.get(c)&&(e="@apply "+c+";")});if(!e)return b;var f=O(a,e),h=b.slice(0,b.indexOf("--")),g=f=P(a,f),m=a.a.get(c),l=m&&m.h;l?g=Object.assign(Object.create(l),f):a.a.set(c,g);var X=[],w,Y=!1;for(w in g){var D=f[w];void 0===D&&(D="initial");!l||w in l||(Y=!0);X.push(""+c+"_-_"+w+": "+D)}Y&&qa(a,m);m&&(m.h=g);d&&(h=b+";"+h);return""+h+X.join("; ")+";"}N.prototype.detectMixin=N.prototype.o;N.prototype.transformStyle=N.prototype.j;
N.prototype.transformCustomStyle=N.prototype.f;N.prototype.transformRules=N.prototype.l;N.prototype.transformRule=N.prototype.g;N.prototype.transformTemplate=N.prototype.m;N.prototype._separator="_-_";Object.defineProperty(N.prototype,"invalidCallback",{get:function(){return M},set:function(a){M=a}});var Q=null,R=window.HTMLImports&&window.HTMLImports.whenReady||null,S;function ra(a){requestAnimationFrame(function(){R?R(a):(Q||(Q=new Promise(function(a){S=a}),"complete"===document.readyState?S():document.addEventListener("readystatechange",function(){"complete"===document.readyState&&S()})),Q.then(function(){a&&a()}))})};var T=new N;function U(){var a=this;this.a=null;ra(function(){V(a)});T.invalidCallback=ja}function V(a){a.a||(a.a=window.ShadyCSS.CustomStyleInterface,a.a&&(a.a.transformCallback=function(a){T.f(a)},a.a.validateCallback=function(){requestAnimationFrame(function(){a.a.enqueued&&W(a)})}))}U.prototype.prepareTemplate=function(a,b){V(this);k[b]=a;b=T.m(a,b);a._styleAst=b};
function W(a){V(a);if(a.a){var b=a.a.processStyles();if(a.a.enqueued){for(var c=0;c<b.length;c++){var d=a.a.getStyleForCustomStyle(b[c]);d&&T.f(d)}a.a.enqueued=!1}}}U.prototype.styleSubtree=function(a,b){V(this);if(b)for(var c in b)null===c?a.style.removeProperty(c):a.style.setProperty(c,b[c]);if(a.shadowRoot)for(this.styleElement(a),a=a.shadowRoot.children||a.shadowRoot.childNodes,b=0;b<a.length;b++)this.styleSubtree(a[b]);else for(a=a.children||a.childNodes,b=0;b<a.length;b++)this.styleSubtree(a[b])};
U.prototype.styleElement=function(a){V(this);var b=a.localName,c;b?-1<b.indexOf("-")?c=b:c=a.getAttribute&&a.getAttribute("is")||"":c=a.is;if((b=k[c])&&!z(b)){if(z(b)||b._applyShimValidatingVersion!==b._applyShimNextVersion)this.prepareTemplate(b,c),ka(b);if(a=a.shadowRoot)if(a=a.querySelector("style"))a.__cssRules=b._styleAst,a.textContent=H(b._styleAst)}};U.prototype.styleDocument=function(a){V(this);this.styleSubtree(document.body,a)};
if(!window.ShadyCSS||!window.ShadyCSS.ScopingShim){var Z=new U,sa=window.ShadyCSS&&window.ShadyCSS.CustomStyleInterface;window.ShadyCSS={prepareTemplate:function(a,b){W(Z);Z.prepareTemplate(a,b)},styleSubtree:function(a,b){W(Z);Z.styleSubtree(a,b)},styleElement:function(a){W(Z);Z.styleElement(a)},styleDocument:function(a){W(Z);Z.styleDocument(a)},getComputedStyleValue:function(a,b){return(a=window.getComputedStyle(a).getPropertyValue(b))?a.trim():""},nativeCss:G,nativeShadow:C};sa&&(window.ShadyCSS.CustomStyleInterface=
sa)}window.ShadyCSS.ApplyShim=T;}).call(this);
//# sourceMappingURL=apply-shim.min.js.map
(function() {
'use strict';
const userPolymer = window.Polymer;
/**
* @namespace Polymer
* @summary Polymer is a lightweight library built on top of the web
* standards-based Web Components API's, and makes it easy to build your
* own custom HTML elements.
* @param {!PolymerInit} info Prototype for the custom element. It must contain
* an `is` property to specify the element name. Other properties populate
* the element prototype. The `properties`, `observers`, `hostAttributes`,
* and `listeners` properties are processed to create element features.
* @return {!Object} Returns a custom element class for the given provided
* prototype `info` object. The name of the element if given by `info.is`.
*/
window.Polymer = function(info) {
return window.Polymer._polymerFn(info);
}
// support user settings on the Polymer object
if (userPolymer) {
Object.assign(Polymer, userPolymer);
}
// To be plugged by legacy implementation if loaded
/* eslint-disable valid-jsdoc */
/**
* @param {!PolymerInit} info Prototype for the custom element. It must contain
* an `is` property to specify the element name. Other properties populate
* the element prototype. The `properties`, `observers`, `hostAttributes`,
* and `listeners` properties are processed to create element features.
* @return {!Object} Returns a custom element class for the given provided
* prototype `info` object. The name of the element if given by `info.is`.
*/
window.Polymer._polymerFn = function(info) { // eslint-disable-line no-unused-vars
throw new Error('Load polymer.html to use the Polymer() function.');
}
/* eslint-enable */
window.Polymer.version = '2.0.1';
/* eslint-disable no-unused-vars */
/*
When using Closure Compiler, JSCompiler_renameProperty(property, object) is replaced by the munged name for object[property]
We cannot alias this function, so we have to use a small shim that has the same behavior when not compiling.
*/
window.JSCompiler_renameProperty = function(prop, obj) {
return prop;
}
/* eslint-enable */
})();
(function() {
'use strict';
let CSS_URL_RX = /(url\()([^)]*)(\))/g;
let ABS_URL = /(^\/)|(^#)|(^[\w-\d]*:)/;
let workingURL;
let resolveDoc;
/**
* Resolves the given URL against the provided `baseUri'.
*
* @memberof Polymer.ResolveUrl
* @param {string} url Input URL to resolve
* @param {?string=} baseURI Base URI to resolve the URL against
* @return {string} resolved URL
*/
function resolveUrl(url, baseURI) {
if (url && ABS_URL.test(url)) {
return url;
}
// Lazy feature detection.
if (workingURL === undefined) {
workingURL = false;
try {
const u = new URL('b', 'http://a');
u.pathname = 'c%20d';
workingURL = (u.href === 'http://a/c%20d');
} catch (e) {
// silently fail
}
}
if (!baseURI) {
baseURI = document.baseURI || window.location.href;
}
if (workingURL) {
return (new URL(url, baseURI)).href;
}
// Fallback to creating an anchor into a disconnected document.
if (!resolveDoc) {
resolveDoc = document.implementation.createHTMLDocument('temp');
resolveDoc.base = resolveDoc.createElement('base');
resolveDoc.head.appendChild(resolveDoc.base);
resolveDoc.anchor = resolveDoc.createElement('a');
resolveDoc.body.appendChild(resolveDoc.anchor);
}
resolveDoc.base.href = baseURI;
resolveDoc.anchor.href = url;
return resolveDoc.anchor.href || url;
}
/**
* Resolves any relative URL's in the given CSS text against the provided
* `ownerDocument`'s `baseURI`.
*
* @memberof Polymer.ResolveUrl
* @param {string} cssText CSS text to process
* @param {string} baseURI Base URI to resolve the URL against
* @return {string} Processed CSS text with resolved URL's
*/
function resolveCss(cssText, baseURI) {
return cssText.replace(CSS_URL_RX, function(m, pre, url, post) {
return pre + '\'' +
resolveUrl(url.replace(/["']/g, ''), baseURI) +
'\'' + post;
});
}
/**
* Returns a path from a given `url`. The path includes the trailing
* `/` from the url.
*
* @memberof Polymer.ResolveUrl
* @param {string} url Input URL to transform
* @return {string} resolved path
*/
function pathFromUrl(url) {
return url.substring(0, url.lastIndexOf('/') + 1);
}
/**
* Module with utilities for resolving relative URL's.
*
* @namespace
* @memberof Polymer
* @summary Module with utilities for resolving relative URL's.
*/
Polymer.ResolveUrl = {
resolveCss: resolveCss,
resolveUrl: resolveUrl,
pathFromUrl: pathFromUrl
};
})();
/** @suppress {deprecated} */
(function() {
'use strict';
/**
* Legacy settings.
* @namespace
* @memberof Polymer
*/
const settings = Polymer.Settings || {};
settings.useShadow = !(window.ShadyDOM);
settings.useNativeCSSProperties =
Boolean(!window.ShadyCSS || window.ShadyCSS.nativeCss);
settings.useNativeCustomElements =
!(window.customElements.polyfillWrapFlushCallback);
/**
* Sets the global, legacy settings.
*
* @deprecated
* @memberof Polymer
*/
Polymer.Settings = settings;
/**
* Globally settable property that is automatically assigned to
* `Polymer.ElementMixin` instances, useful for binding in templates to
* make URL's relative to an application's root. Defaults to the main
* document URL, but can be overridden by users. It may be useful to set
* `Polymer.rootPath` to provide a stable application mount path when
* using client side routing.
*
* @memberof Polymer
*/
let rootPath = Polymer.rootPath ||
Polymer.ResolveUrl.pathFromUrl(document.baseURI || window.location.href);
Polymer.rootPath = rootPath;
/**
* Sets the global rootPath property used by `Polymer.ElementMixin` and
* available via `Polymer.rootPath`.
*
* @memberof Polymer
* @param {string} path The new root path
*/
Polymer.setRootPath = function(path) {
Polymer.rootPath = path;
}
})();
(function() {
'use strict';
// unique global id for deduping mixins.
let dedupeId = 0;
/**
* @constructor
* @extends {Function}
*/
function MixinFunction(){}
/** @type {(WeakMap | undefined)} */
MixinFunction.prototype.__mixinApplications;
/** @type {(Object | undefined)} */
MixinFunction.prototype.__mixinSet;
/* eslint-disable valid-jsdoc */
/**
* Wraps an ES6 class expression mixin such that the mixin is only applied
* if it has not already been applied its base argument. Also memoizes mixin
* applications.
*
* @memberof Polymer
* @template T
* @param {T} mixin ES6 class expression mixin to wrap
* @suppress {invalidCasts}
*/
Polymer.dedupingMixin = function(mixin) {
let mixinApplications = /** @type {!MixinFunction} */(mixin).__mixinApplications;
if (!mixinApplications) {
mixinApplications = new WeakMap();
/** @type {!MixinFunction} */(mixin).__mixinApplications = mixinApplications;
}
// maintain a unique id for each mixin
let mixinDedupeId = dedupeId++;
function dedupingMixin(base) {
let baseSet = /** @type {!MixinFunction} */(base).__mixinSet;
if (baseSet && baseSet[mixinDedupeId]) {
return base;
}
let map = mixinApplications;
let extended = map.get(base);
if (!extended) {
extended = /** @type {!Function} */(mixin)(base);
map.set(base, extended);
}
// copy inherited mixin set from the extended class, or the base class
// NOTE: we avoid use of Set here because some browser (IE11)
// cannot extend a base Set via the constructor.
let mixinSet = Object.create(/** @type {!MixinFunction} */(extended).__mixinSet || baseSet || null);
mixinSet[mixinDedupeId] = true;
/** @type {!MixinFunction} */(extended).__mixinSet = mixinSet;
return extended;
}
return dedupingMixin;
};
/* eslint-enable valid-jsdoc */
})();
(function() {
'use strict';
const caseMap = {};
const DASH_TO_CAMEL = /-[a-z]/g;
const CAMEL_TO_DASH = /([A-Z])/g;
/**
* Module with utilities for converting between "dash-case" and "camelCase"
* identifiers.
*
* @namespace
* @memberof Polymer
* @summary Module that provides utilities for converting between "dash-case"
* and "camelCase".
*/
const CaseMap = {
/**
* Converts "dash-case" identifier (e.g. `foo-bar-baz`) to "camelCase"
* (e.g. `fooBarBaz`).
*
* @memberof Polymer.CaseMap
* @param {string} dash Dash-case identifier
* @return {string} Camel-case representation of the identifier
*/
dashToCamelCase(dash) {
return caseMap[dash] || (
caseMap[dash] = dash.indexOf('-') < 0 ? dash : dash.replace(DASH_TO_CAMEL,
(m) => m[1].toUpperCase()
)
);
},
/**
* Converts "camelCase" identifier (e.g. `fooBarBaz`) to "dash-case"
* (e.g. `foo-bar-baz`).
*
* @memberof Polymer.CaseMap
* @param {string} camel Camel-case identifier
* @return {string} Dash-case representation of the identifier
*/
camelToDashCase(camel) {
return caseMap[camel] || (
caseMap[camel] = camel.replace(CAMEL_TO_DASH, '-$1').toLowerCase()
);
}
};
Polymer.CaseMap = CaseMap;
})();
(function() {
'use strict';
const MODULE_STYLE_LINK_SELECTOR = 'link[rel=import][type~=css]';
const INCLUDE_ATTR = 'include';
function importModule(moduleId) {
if (!Polymer.DomModule) {
return null;
}
return Polymer.DomModule.import(moduleId);
}
/** @typedef {{assetpath: string}} */
let templateWithAssetPath; // eslint-disable-line no-unused-vars
/**
* Module with utilities for collection CSS text from `<templates>`, external
* stylesheets, and `dom-module`s.
*
* @namespace
* @memberof Polymer
* @summary Module with utilities for collection CSS text from various sources.
*/
const StyleGather = {
/**
* Returns CSS text of styles in a space-separated list of `dom-module`s.
*
* @memberof Polymer.StyleGather
* @param {string} moduleIds List of dom-module id's within which to
* search for css.
* @return {string} Concatenated CSS content from specified `dom-module`s
* @this {StyleGather}
*/
cssFromModules(moduleIds) {
let modules = moduleIds.trim().split(' ');
let cssText = '';
for (let i=0; i < modules.length; i++) {
cssText += this.cssFromModule(modules[i]);
}
return cssText;
},
/**
* Returns CSS text of styles in a given `dom-module`. CSS in a `dom-module`
* can come either from `<style>`s within the first `<template>`, or else
* from one or more `<link rel="import" type="css">` links outside the
* template.
*
* Any `<styles>` processed are removed from their original location.
*
* @memberof Polymer.StyleGather
* @param {string} moduleId dom-module id to gather styles from
* @return {string} Concatenated CSS content from specified `dom-module`
* @this {StyleGather}
*/
cssFromModule(moduleId) {
let m = importModule(moduleId);
if (m && m._cssText === undefined) {
let cssText = '';
// include css from the first template in the module
let t = m.querySelector('template');
if (t) {
cssText += this.cssFromTemplate(t, /** @type {templateWithAssetPath }*/(m).assetpath);
}
// module imports: <link rel="import" type="css">
cssText += this.cssFromModuleImports(moduleId);
m._cssText = cssText || null;
}
if (!m) {
console.warn('Could not find style data in module named', moduleId);
}
return m && m._cssText || '';
},
/**
* Returns CSS text of `<styles>` within a given template.
*
* Any `<styles>` processed are removed from their original location.
*
* @memberof Polymer.StyleGather
* @param {HTMLTemplateElement} template Template to gather styles from
* @param {string} baseURI Base URI to resolve the URL against
* @return {string} Concatenated CSS content from specified template
* @this {StyleGather}
*/
cssFromTemplate(template, baseURI) {
let cssText = '';
// if element is a template, get content from its .content
let e$ = template.content.querySelectorAll('style');
for (let i=0; i < e$.length; i++) {
let e = e$[i];
// support style sharing by allowing styles to "include"
// other dom-modules that contain styling
let include = e.getAttribute(INCLUDE_ATTR);
if (include) {
cssText += this.cssFromModules(include);
}
e.parentNode.removeChild(e);
cssText += baseURI ?
Polymer.ResolveUrl.resolveCss(e.textContent, baseURI) : e.textContent;
}
return cssText;
},
/**
* Returns CSS text from stylsheets loaded via `<link rel="import" type="css">`
* links within the specified `dom-module`.
*
* @memberof Polymer.StyleGather
* @param {string} moduleId Id of `dom-module` to gather CSS from
* @return {string} Concatenated CSS content from links in specified `dom-module`
* @this {StyleGather}
*/
cssFromModuleImports(moduleId) {
let cssText = '';
let m = importModule(moduleId);
if (!m) {
return cssText;
}
let p$ = m.querySelectorAll(MODULE_STYLE_LINK_SELECTOR);
for (let i=0; i < p$.length; i++) {
let p = p$[i];
if (p.import) {
let importDoc = p.import;
// NOTE: polyfill affordance.
// under the HTMLImports polyfill, there will be no 'body',
// but the import pseudo-doc can be used directly.
let container = importDoc.body ? importDoc.body : importDoc;
cssText +=
Polymer.ResolveUrl.resolveCss(container.textContent,
importDoc.baseURI);
}
}
return cssText;
}
};
Polymer.StyleGather = StyleGather;
})();
(function() {
'use strict';
let modules = {};
let lcModules = {};
function findModule(id) {
return modules[id] || lcModules[id.toLowerCase()];
}
function styleOutsideTemplateCheck(inst) {
if (inst.querySelector('style')) {
console.warn('dom-module %s has style outside template', inst.id);
}
}
/**
* The `dom-module` element registers the dom it contains to the name given
* by the module's id attribute. It provides a unified database of dom
* accessible via its static `import` API.
*
* A key use case of `dom-module` is for providing custom element `<template>`s
* via HTML imports that are parsed by the native HTML parser, that can be
* relocated during a bundling pass and still looked up by `id`.
*
* Example:
*
* <dom-module id="foo">
* <img src="stuff.png">
* </dom-module>
*
* Then in code in some other location that cannot access the dom-module above
*
* let img = document.createElement('dom-module').import('foo', 'img');
*
* @customElement
* @extends HTMLElement
* @memberof Polymer
* @summary Custom element that provides a registry of relocatable DOM content
* by `id` that is agnostic to bundling.
* @unrestricted
*/
class DomModule extends HTMLElement {
static get observedAttributes() { return ['id'] }
/**
* Retrieves the element specified by the css `selector` in the module
* registered by `id`. For example, this.import('foo', 'img');
* @param {string} id The id of the dom-module in which to search.
* @param {string=} selector The css selector by which to find the element.
* @return {Element} Returns the element which matches `selector` in the
* module registered at the specified `id`.
*/
static import(id, selector) {
if (id) {
let m = findModule(id);
if (m && selector) {
return m.querySelector(selector);
}
return m;
}
return null;
}
attributeChangedCallback(name, old, value) {
if (old !== value) {
this.register();
}
}
/**
* The absolute URL of the original location of this `dom-module`.
*
* This value will differ from this element's `ownerDocument` in the
* following ways:
* - Takes into account any `assetpath` attribute added during bundling
* to indicate the original location relative to the bundled location
* - Uses the HTMLImports polyfill's `importForElement` API to ensure
* the path is relative to the import document's location since
* `ownerDocument` is not currently polyfilled
*/
get assetpath() {
// Don't override existing assetpath.
if (!this.__assetpath) {
// note: assetpath set via an attribute must be relative to this
// element's location; accomodate polyfilled HTMLImports
const owner = window.HTMLImports && HTMLImports.importForElement ?
HTMLImports.importForElement(this) || document : this.ownerDocument;
const url = Polymer.ResolveUrl.resolveUrl(
this.getAttribute('assetpath') || '', owner.baseURI);
this.__assetpath = Polymer.ResolveUrl.pathFromUrl(url);
}
return this.__assetpath;
}
/**
* Registers the dom-module at a given id. This method should only be called
* when a dom-module is imperatively created. For
* example, `document.createElement('dom-module').register('foo')`.
* @param {string=} id The id at which to register the dom-module.
*/
register(id) {
id = id || this.id;
if (id) {
this.id = id;
// store id separate from lowercased id so that
// in all cases mixedCase id will stored distinctly
// and lowercase version is a fallback
modules[id] = this;
lcModules[id.toLowerCase()] = this;
styleOutsideTemplateCheck(this);
}
}
}
DomModule.prototype['modules'] = modules;
customElements.define('dom-module', DomModule);
// export
Polymer.DomModule = DomModule;
})();
(function() {
'use strict';
/**
* Module with utilities for manipulating structured data path strings.
*
* @namespace
* @memberof Polymer
* @summary Module with utilities for manipulating structured data path strings.
*/
const Path = {
/**
* Returns true if the given string is a structured data path (has dots).
*
* Example:
*
* ```
* Polymer.Path.isPath('foo.bar.baz') // true
* Polymer.Path.isPath('foo') // false
* ```
*
* @memberof Polymer.Path
* @param {string} path Path string
* @return {boolean} True if the string contained one or more dots
*/
isPath: function(path) {
return path.indexOf('.') >= 0;
},
/**
* Returns the root property name for the given path.
*
* Example:
*
* ```
* Polymer.Path.root('foo.bar.baz') // 'foo'
* Polymer.Path.root('foo') // 'foo'
* ```
*
* @memberof Polymer.Path
* @param {string} path Path string
* @return {string} Root property name
*/
root: function(path) {
let dotIndex = path.indexOf('.');
if (dotIndex === -1) {
return path;
}
return path.slice(0, dotIndex);
},
/**
* Given `base` is `foo.bar`, `foo` is an ancestor, `foo.bar` is not
* Returns true if the given path is an ancestor of the base path.
*
* Example:
*
* ```
* Polymer.Path.isAncestor('foo.bar', 'foo') // true
* Polymer.Path.isAncestor('foo.bar', 'foo.bar') // false
* Polymer.Path.isAncestor('foo.bar', 'foo.bar.baz') // false
* ```
*
* @memberof Polymer.Path
* @param {string} base Path string to test against.
* @param {string} path Path string to test.
* @return {boolean} True if `path` is an ancestor of `base`.
*/
isAncestor: function(base, path) {
// base.startsWith(path + '.');
return base.indexOf(path + '.') === 0;
},
/**
* Given `base` is `foo.bar`, `foo.bar.baz` is an descendant
*
* Example:
*
* ```
* Polymer.Path.isDescendant('foo.bar', 'foo.bar.baz') // true
* Polymer.Path.isDescendant('foo.bar', 'foo.bar') // false
* Polymer.Path.isDescendant('foo.bar', 'foo') // false
* ```
*
* @memberof Polymer.Path
* @param {string} base Path string to test against.
* @param {string} path Path string to test.
* @return {boolean} True if `path` is a descendant of `base`.
*/
isDescendant: function(base, path) {
// path.startsWith(base + '.');
return path.indexOf(base + '.') === 0;
},
/**
* Replaces a previous base path with a new base path, preserving the
* remainder of the path.
*
* User must ensure `path` has a prefix of `base`.
*
* Example:
*
* ```
* Polymer.Path.translate('foo.bar', 'zot' 'foo.bar.baz') // 'zot.baz'
* ```
*
* @memberof Polymer.Path
* @param {string} base Current base string to remove
* @param {string} newBase New base string to replace with
* @param {string} path Path to translate
* @return {string} Translated string
*/
translate: function(base, newBase, path) {
return newBase + path.slice(base.length);
},
/**
* @param {string} base Path string to test against
* @param {string} path Path string to test
* @return {boolean} True if `path` is equal to `base`
* @this {Path}
*/
matches: function(base, path) {
return (base === path) ||
this.isAncestor(base, path) ||
this.isDescendant(base, path);
},
/**
* Converts array-based paths to flattened path. String-based paths
* are returned as-is.
*
* Example:
*
* ```
* Polymer.Path.normalize(['foo.bar', 0, 'baz']) // 'foo.bar.0.baz'
* Polymer.Path.normalize('foo.bar.0.baz') // 'foo.bar.0.baz'
* ```
*
* @memberof Polymer.Path
* @param {string | !Array<string|number>} path Input path
* @return {string} Flattened path
*/
normalize: function(path) {
if (Array.isArray(path)) {
let parts = [];
for (let i=0; i<path.length; i++) {
let args = path[i].toString().split('.');
for (let j=0; j<args.length; j++) {
parts.push(args[j]);
}
}
return parts.join('.');
} else {
return path;
}
},
/**
* Splits a path into an array of property names. Accepts either arrays
* of path parts or strings.
*
* Example:
*
* ```
* Polymer.Path.split(['foo.bar', 0, 'baz']) // ['foo', 'bar', '0', 'baz']
* Polymer.Path.split('foo.bar.0.baz') // ['foo', 'bar', '0', 'baz']
* ```
*
* @memberof Polymer.Path
* @param {string | !Array<string|number>} path Input path
* @return {!Array<string>} Array of path parts
* @this {Path}
* @suppress {checkTypes}
*/
split: function(path) {
if (Array.isArray(path)) {
return this.normalize(path).split('.');
}
return path.toString().split('.');
},
/**
* Reads a value from a path. If any sub-property in the path is `undefined`,
* this method returns `undefined` (will never throw.
*
* @memberof Polymer.Path
* @param {Object} root Object from which to dereference path from
* @param {string | !Array<string|number>} path Path to read
* @param {Object=} info If an object is provided to `info`, the normalized
* (flattened) path will be set to `info.path`.
* @return {*} Value at path, or `undefined` if the path could not be
* fully dereferenced.
* @this {Path}
*/
get: function(root, path, info) {
let prop = root;
let parts = this.split(path);
// Loop over path parts[0..n-1] and dereference
for (let i=0; i<parts.length; i++) {
if (!prop) {
return;
}
let part = parts[i];
prop = prop[part];
}
if (info) {
info.path = parts.join('.');
}
return prop;
},
/**
* Sets a value to a path. If any sub-property in the path is `undefined`,
* this method will no-op.
*
* @memberof Polymer.Path
* @param {Object} root Object from which to dereference path from
* @param {string | !Array<string|number>} path Path to set
* @param {*} value Value to set to path
* @return {string | undefined} The normalized version of the input path
* @this {Path}
*/
set: function(root, path, value) {
let prop = root;
let parts = this.split(path);
let last = parts[parts.length-1];
if (parts.length > 1) {
// Loop over path parts[0..n-2] and dereference
for (let i=0; i<parts.length-1; i++) {
let part = parts[i];
prop = prop[part];
if (!prop) {
return;
}
}
// Set value to object at end of path
prop[last] = value;
} else {
// Simple property set
prop[path] = value;
}
return parts.join('.');
}
};
/**
* Returns true if the given string is a structured data path (has dots).
*
* This function is deprecated. Use `Polymer.Path.isPath` instead.
*
* Example:
*
* ```
* Polymer.Path.isDeep('foo.bar.baz') // true
* Polymer.Path.isDeep('foo') // false
* ```
*
* @deprecated
* @memberof Polymer.Path
* @param {string} path Path string
* @return {boolean} True if the string contained one or more dots
*/
Path.isDeep = Path.isPath;
Polymer.Path = Path;
})();
(function() {
'use strict';
/** @typedef {{run: function(function(), number=):number, cancel: function(number)}} */
let AsyncInterface; // eslint-disable-line no-unused-vars
// Microtask implemented using Mutation Observer
let microtaskCurrHandle = 0;
let microtaskLastHandle = 0;
let microtaskCallbacks = [];
let microtaskNodeContent = 0;
let microtaskNode = document.createTextNode('');
new window.MutationObserver(microtaskFlush).observe(microtaskNode, {characterData: true});
function microtaskFlush() {
const len = microtaskCallbacks.length;
for (let i = 0; i < len; i++) {
let cb = microtaskCallbacks[i];
if (cb) {
try {
cb();
} catch (e) {
setTimeout(() => { throw e });
}
}
}
microtaskCallbacks.splice(0, len);
microtaskLastHandle += len;
}
/**
* Module that provides a number of strategies for enqueuing asynchronous
* tasks. Each sub-module provides a standard `run(fn)` interface that returns a
* handle, and a `cancel(handle)` interface for canceling async tasks before
* they run.
*
* @namespace
* @memberof Polymer
* @summary Module that provides a number of strategies for enqueuing asynchronous
* tasks.
*/
Polymer.Async = {
/**
* Async interface wrapper around `setTimeout`.
*
* @namespace
* @memberof Polymer.Async
* @summary Async interface wrapper around `setTimeout`.
*/
timeOut: {
/**
* Returns a sub-module with the async interface providing the provided
* delay.
*
* @memberof Polymer.Async.timeOut
* @param {number} delay Time to wait before calling callbacks in ms
* @return {AsyncInterface} An async timeout interface
*/
after(delay) {
return {
run(fn) { return setTimeout(fn, delay) },
cancel: window.clearTimeout.bind(window)
}
},
/**
* Enqueues a function called in the next task.
*
* @memberof Polymer.Async.timeOut
* @param {Function} fn Callback to run
* @return {number} Handle used for canceling task
*/
run: window.setTimeout.bind(window),
/**
* Cancels a previously enqueued `timeOut` callback.
*
* @memberof Polymer.Async.timeOut
* @param {number} handle Handle returned from `run` of callback to cancel
*/
cancel: window.clearTimeout.bind(window)
},
/**
* Async interface wrapper around `requestAnimationFrame`.
*
* @namespace
* @memberof Polymer.Async
* @summary Async interface wrapper around `requestAnimationFrame`.
*/
animationFrame: {
/**
* Enqueues a function called at `requestAnimationFrame` timing.
*
* @memberof Polymer.Async.animationFrame
* @param {Function} fn Callback to run
* @return {number} Handle used for canceling task
*/
run: window.requestAnimationFrame.bind(window),
/**
* Cancels a previously enqueued `animationFrame` callback.
*
* @memberof Polymer.Async.timeOut
* @param {number} handle Handle returned from `run` of callback to cancel
*/
cancel: window.cancelAnimationFrame.bind(window)
},
/**
* Async interface wrapper around `requestIdleCallback`. Falls back to
* `setTimeout` on browsers that do not support `requestIdleCallback`.
*
* @namespace
* @memberof Polymer.Async
* @summary Async interface wrapper around `requestIdleCallback`.
*/
idlePeriod: {
/**
* Enqueues a function called at `requestIdleCallback` timing.
*
* @memberof Polymer.Async.idlePeriod
* @param {function(IdleDeadline)} fn Callback to run
* @return {number} Handle used for canceling task
*/
run(fn) {
return window.requestIdleCallback ?
window.requestIdleCallback(fn) :
window.setTimeout(fn, 16);
},
/**
* Cancels a previously enqueued `idlePeriod` callback.
*
* @memberof Polymer.Async.idlePeriod
* @param {number} handle Handle returned from `run` of callback to cancel
*/
cancel(handle) {
window.cancelIdleCallback ?
window.cancelIdleCallback(handle) :
window.clearTimeout(handle);
}
},
/**
* Async interface for enqueueing callbacks that run at microtask timing.
*
* Note that microtask timing is achieved via a single `MutationObserver`,
* and thus callbacks enqueued with this API will all run in a single
* batch, and not interleaved with other microtasks such as promises.
* Promises are avoided as an implementation choice for the time being
* due to Safari bugs that cause Promises to lack microtask guarantees.
*
* @namespace
* @memberof Polymer.Async
* @summary Async interface for enqueueing callbacks that run at microtask
* timing.
*/
microTask: {
/**
* Enqueues a function called at microtask timing.
*
* @memberof Polymer.Async.microTask
* @param {Function} callback Callback to run
* @return {number} Handle used for canceling task
*/
run(callback) {
microtaskNode.textContent = microtaskNodeContent++;
microtaskCallbacks.push(callback);
return microtaskCurrHandle++;
},
/**
* Cancels a previously enqueued `microTask` callback.
*
* @memberof Polymer.Async.microTask
* @param {number} handle Handle returned from `run` of callback to cancel
*/
cancel(handle) {
const idx = handle - microtaskLastHandle;
if (idx >= 0) {
if (!microtaskCallbacks[idx]) {
throw new Error('invalid async handle: ' + handle);
}
microtaskCallbacks[idx] = null;
}
}
}
};
})();
(function() {
'use strict';
let caseMap = Polymer.CaseMap;
let microtask = Polymer.Async.microTask;
// Save map of native properties; this forms a blacklist or properties
// that won't have their values "saved" by `saveAccessorValue`, since
// reading from an HTMLElement accessor from the context of a prototype throws
const nativeProperties = {};
let proto = HTMLElement.prototype;
while (proto) {
let props = Object.getOwnPropertyNames(proto);
for (let i=0; i<props.length; i++) {
nativeProperties[props[i]] = true;
}
proto = Object.getPrototypeOf(proto);
}
/**
* Used to save the value of a property that will be overridden with
* an accessor. If the `model` is a prototype, the values will be saved
* in `__dataProto`, and it's up to the user (or downstream mixin) to
* decide how/when to set these values back into the accessors.
* If `model` is already an instance (it has a `__data` property), then
* the value will be set as a pending property, meaning the user should
* call `_invalidateProperties` or `_flushProperties` to take effect
*
* @param {Object} model Prototype or instance
* @param {string} property Name of property
* @private
*/
function saveAccessorValue(model, property) {
// Don't read/store value for any native properties since they could throw
if (!nativeProperties[property]) {
let value = model[property];
if (value !== undefined) {
if (model.__data) {
// Adding accessor to instance; update the property
// It is the user's responsibility to call _flushProperties
model._setPendingProperty(property, value);
} else {
// Adding accessor to proto; save proto's value for instance-time use
if (!model.__dataProto) {
model.__dataProto = {};
} else if (!model.hasOwnProperty(JSCompiler_renameProperty('__dataProto', model))) {
model.__dataProto = Object.create(model.__dataProto);
}
model.__dataProto[property] = value;
}
}
}
}
/**
* Element class mixin that provides basic meta-programming for creating one
* or more property accessors (getter/setter pair) that enqueue an async
* (batched) `_propertiesChanged` callback.
*
* For basic usage of this mixin, simply declare attributes to observe via
* the standard `static get observedAttributes()`, implement `_propertiesChanged`
* on the class, and then call `MyClass.createPropertiesForAttributes()` once
* on the class to generate property accessors for each observed attribute
* prior to instancing. Last, call `this._flushProperties()` once to enable
* the accessors.
*
* Any `observedAttributes` will automatically be
* deserialized via `attributeChangedCallback` and set to the associated
* property using `dash-case`-to-`camelCase` convention.
*
* @mixinFunction
* @polymer
* @memberof Polymer
* @summary Element class mixin for reacting to property changes from
* generated property accessors.
*/
Polymer.PropertyAccessors = Polymer.dedupingMixin(superClass => {
/**
* @polymer
* @mixinClass
* @implements {Polymer_PropertyAccessors}
* @extends HTMLElement
* @unrestricted
*/
class PropertyAccessors extends superClass {
/**
* Generates property accessors for all attributes in the standard
* static `observedAttributes` array.
*
* Attribute names are mapped to property names using the `dash-case` to
* `camelCase` convention
*
*/
static createPropertiesForAttributes() {
let a$ = this.observedAttributes;
for (let i=0; i < a$.length; i++) {
this.prototype._createPropertyAccessor(caseMap.dashToCamelCase(a$[i]));
}
}
constructor() {
super();
/** @type {boolean} */
this.__serializing;
/** @type {number} */
this.__dataCounter;
/** @type {boolean} */
this.__dataEnabled;
/** @type {boolean} */
this.__dataReady;
/** @type {boolean} */
this.__dataInvalid;
/** @type {!Object} */
this.__data;
/** @type {Object} */
this.__dataPending;
/** @type {Object} */
this.__dataOld;
/** @type {Object} */
this.__dataProto;
/** @type {Object} */
this.__dataHasAccessor;
/** @type {Object} */
this.__dataInstanceProps;
this._initializeProperties();
}
/**
* Implements native Custom Elements `attributeChangedCallback` to
* set an attribute value to a property via `_attributeToProperty`.
*
* @param {string} name Name of attribute that changed
* @param {?string} old Old attribute value
* @param {?string} value New attribute value
*/
attributeChangedCallback(name, old, value) {
if (old !== value) {
this._attributeToProperty(name, value);
}
}
/**
* Initializes the local storage for property accessors.
*
* Provided as an override point for performing any setup work prior
* to initializing the property accessor system.
*
* @protected
*/
_initializeProperties() {
this.__serializing = false;
this.__dataCounter = 0;
this.__dataEnabled = false;
this.__dataReady = false;
this.__dataInvalid = false;
this.__data = {};
this.__dataPending = null;
this.__dataOld = null;
if (this.__dataProto) {
this._initializeProtoProperties(this.__dataProto);
this.__dataProto = null;
}
// Capture instance properties; these will be set into accessors
// during first flush. Don't set them here, since we want
// these to overwrite defaults/constructor assignments
for (let p in this.__dataHasAccessor) {
if (this.hasOwnProperty(p)) {
this.__dataInstanceProps = this.__dataInstanceProps || {};
this.__dataInstanceProps[p] = this[p];
delete this[p];
}
}
}
/**
* Called at instance time with bag of properties that were overwritten
* by accessors on the prototype when accessors were created.
*
* The default implementation sets these properties back into the
* setter at instance time. This method is provided as an override
* point for customizing or providing more efficient initialization.
*
* @param {Object} props Bag of property values that were overwritten
* when creating property accessors.
* @protected
*/
_initializeProtoProperties(props) {
for (let p in props) {
this._setProperty(p, props[p]);
}
}
/**
* Called at ready time with bag of instance properties that overwrote
* accessors when the element upgraded.
*
* The default implementation sets these properties back into the
* setter at ready time. This method is provided as an override
* point for customizing or providing more efficient initialization.
*
* @param {Object} props Bag of property values that were overwritten
* when creating property accessors.
* @protected
*/
_initializeInstanceProperties(props) {
Object.assign(this, props);
}
/**
* Ensures the element has the given attribute. If it does not,
* assigns the given value to the attribute.
*
*
* @param {string} attribute Name of attribute to ensure is set.
* @param {string} value of the attribute.
*/
_ensureAttribute(attribute, value) {
if (!this.hasAttribute(attribute)) {
this._valueToNodeAttribute(this, value, attribute);
}
}
/**
* Deserializes an attribute to its associated property.
*
* This method calls the `_deserializeValue` method to convert the string to
* a typed value.
*
* @param {string} attribute Name of attribute to deserialize.
* @param {?string} value of the attribute.
* @param {*=} type type to deserialize to.
*/
_attributeToProperty(attribute, value, type) {
// Don't deserialize back to property if currently reflecting
if (!this.__serializing) {
let property = caseMap.dashToCam