1/** 2@license 3Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 4This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt 5The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt 6The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt 7Code distributed by Google as part of the polymer project is also 8subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt 9*/ 10 11'use strict'; 12 13import ApplyShim from '../src/apply-shim.js'; 14import templateMap from '../src/template-map.js'; 15import {getIsExtends, toCssText, elementHasBuiltCss} from '../src/style-util.js'; 16import * as ApplyShimUtils from '../src/apply-shim-utils.js'; 17import {getComputedStyleValue, updateNativeProperties} from '../src/common-utils.js'; 18import {CustomStyleInterfaceInterface} from '../src/custom-style-interface.js'; // eslint-disable-line no-unused-vars 19import {nativeCssVariables, nativeShadow, cssBuild} from '../src/style-settings.js'; 20 21/** @const {ApplyShim} */ 22const applyShim = new ApplyShim(); 23 24class ApplyShimInterface { 25 constructor() { 26 /** @type {?CustomStyleInterfaceInterface} */ 27 this.customStyleInterface = null; 28 applyShim['invalidCallback'] = ApplyShimUtils.invalidate; 29 } 30 ensure() { 31 if (this.customStyleInterface) { 32 return; 33 } 34 if (window.ShadyCSS.CustomStyleInterface) { 35 this.customStyleInterface = 36 /** @type {!CustomStyleInterfaceInterface} */ ( 37 window.ShadyCSS.CustomStyleInterface); 38 this.customStyleInterface['transformCallback'] = (style) => { 39 applyShim.transformCustomStyle(style); 40 }; 41 this.customStyleInterface['validateCallback'] = () => { 42 requestAnimationFrame(() => { 43 if (this.customStyleInterface['enqueued']) { 44 this.flushCustomStyles(); 45 } 46 }); 47 } 48 } 49 } 50 /** 51 * @param {!HTMLTemplateElement} template 52 * @param {string} elementName 53 */ 54 prepareTemplate(template, elementName) { 55 this.ensure(); 56 if (elementHasBuiltCss(template)) { 57 return; 58 } 59 templateMap[elementName] = template; 60 let ast = applyShim.transformTemplate(template, elementName); 61 // save original style ast to use for revalidating instances 62 template['_styleAst'] = ast; 63 } 64 flushCustomStyles() { 65 this.ensure(); 66 if (!this.customStyleInterface) { 67 return; 68 } 69 let styles = this.customStyleInterface['processStyles'](); 70 if (!this.customStyleInterface['enqueued']) { 71 return; 72 } 73 for (let i = 0; i < styles.length; i++ ) { 74 let cs = styles[i]; 75 let style = this.customStyleInterface['getStyleForCustomStyle'](cs); 76 if (style) { 77 applyShim.transformCustomStyle(style); 78 } 79 } 80 this.customStyleInterface['enqueued'] = false; 81 } 82 /** 83 * @param {HTMLElement} element 84 * @param {Object=} properties 85 */ 86 styleSubtree(element, properties) { 87 this.ensure(); 88 if (properties) { 89 updateNativeProperties(element, properties); 90 } 91 if (element.shadowRoot) { 92 this.styleElement(element); 93 let shadowChildren = 94 /** @type {!ParentNode} */ (element.shadowRoot).children || 95 element.shadowRoot.childNodes; 96 for (let i = 0; i < shadowChildren.length; i++) { 97 this.styleSubtree(/** @type {HTMLElement} */(shadowChildren[i])); 98 } 99 } else { 100 let children = element.children || element.childNodes; 101 for (let i = 0; i < children.length; i++) { 102 this.styleSubtree(/** @type {HTMLElement} */(children[i])); 103 } 104 } 105 } 106 /** 107 * @param {HTMLElement} element 108 */ 109 styleElement(element) { 110 this.ensure(); 111 let {is} = getIsExtends(element); 112 let template = templateMap[is]; 113 if (template && elementHasBuiltCss(template)) { 114 return; 115 } 116 if (template && !ApplyShimUtils.templateIsValid(template)) { 117 // only revalidate template once 118 if (!ApplyShimUtils.templateIsValidating(template)) { 119 this.prepareTemplate(template, is); 120 ApplyShimUtils.startValidatingTemplate(template); 121 } 122 // update this element instance 123 let root = element.shadowRoot; 124 if (root) { 125 let style = /** @type {HTMLStyleElement} */(root.querySelector('style')); 126 if (style) { 127 // reuse the template's style ast, it has all the original css text 128 style['__cssRules'] = template['_styleAst']; 129 style.textContent = toCssText(template['_styleAst']) 130 } 131 } 132 } 133 } 134 /** 135 * @param {Object=} properties 136 */ 137 styleDocument(properties) { 138 this.ensure(); 139 this.styleSubtree(document.body, properties); 140 } 141} 142 143if (!window.ShadyCSS || !window.ShadyCSS.ScopingShim) { 144 const applyShimInterface = new ApplyShimInterface(); 145 let CustomStyleInterface = window.ShadyCSS && window.ShadyCSS.CustomStyleInterface; 146 147 /** @suppress {duplicate} */ 148 window.ShadyCSS = { 149 /** 150 * @param {!HTMLTemplateElement} template 151 * @param {string} elementName 152 * @param {string=} elementExtends 153 */ 154 prepareTemplate(template, elementName, elementExtends) { // eslint-disable-line no-unused-vars 155 applyShimInterface.flushCustomStyles(); 156 applyShimInterface.prepareTemplate(template, elementName); 157 }, 158 159 /** 160 * @param {!HTMLTemplateElement} template 161 * @param {string} elementName 162 * @param {string=} elementExtends 163 */ 164 prepareTemplateStyles(template, elementName, elementExtends) { 165 window.ShadyCSS.prepareTemplate(template, elementName, elementExtends); 166 }, 167 168 /** 169 * @param {!HTMLTemplateElement} template 170 * @param {string} elementName 171 */ 172 prepareTemplateDom(template, elementName) {}, // eslint-disable-line no-unused-vars 173 174 /** 175 * @param {!HTMLElement} element 176 * @param {Object=} properties 177 */ 178 styleSubtree(element, properties) { 179 applyShimInterface.flushCustomStyles(); 180 applyShimInterface.styleSubtree(element, properties); 181 }, 182 183 /** 184 * @param {!HTMLElement} element 185 */ 186 styleElement(element) { 187 applyShimInterface.flushCustomStyles(); 188 applyShimInterface.styleElement(element); 189 }, 190 191 /** 192 * @param {Object=} properties 193 */ 194 styleDocument(properties) { 195 applyShimInterface.flushCustomStyles(); 196 applyShimInterface.styleDocument(properties); 197 }, 198 199 /** 200 * @param {Element} element 201 * @param {string} property 202 * @return {string} 203 */ 204 getComputedStyleValue(element, property) { 205 return getComputedStyleValue(element, property); 206 }, 207 208 flushCustomStyles() { 209 applyShimInterface.flushCustomStyles(); 210 }, 211 212 nativeCss: nativeCssVariables, 213 nativeShadow: nativeShadow, 214 cssBuild: cssBuild 215 }; 216 217 if (CustomStyleInterface) { 218 window.ShadyCSS.CustomStyleInterface = CustomStyleInterface; 219 } 220} 221 222window.ShadyCSS.ApplyShim = applyShim; 223