@@ -141,7 +141,7 @@ var ShadowCSS = {
141141 // Shim styles for a given root associated with a name and extendsName
142142 // 1. cache root styles by name
143143 // 2. optionally tag root nodes with scope name
144- // 3. shim polyfill directives /* @polyfill */
144+ // 3. shim polyfill directives /* @polyfill */ and /* @polyfill -rule */
145145 // 4. shim @host and scoping
146146 shimStyling : function ( root , name , extendsName ) {
147147 // use caching to make working with styles nodes easier and to facilitate
@@ -151,10 +151,11 @@ var ShadowCSS = {
151151 if ( this . strictStyling ) {
152152 this . applyScopeToContent ( root , name ) ;
153153 }
154- this . shimPolyfillDirectives ( def . rootStyles , name ) ;
154+ // insert @polyfill and @polyfill-rule rules into style elements
155+ // scoping process takes care of shimming these
156+ this . insertPolyfillDirectives ( def . rootStyles ) ;
157+ this . insertPolyfillRules ( def . rootStyles ) ;
155158 var cssText = this . stylesToShimmedCssText ( def . scopeStyles , name ) ;
156- // note: it's critical that polyfill-rules are not shimmed.
157- cssText += '\n\n' + this . extractPolyfillRules ( def . scopeStyles , name ) ;
158159 // provide shimmedStyle for user extensibility
159160 def . shimmedStyle = cssTextToStyle ( cssText ) ;
160161 if ( root ) {
@@ -205,49 +206,61 @@ var ShadowCSS = {
205206 *
206207 * For example, we convert this rule:
207208 *
208- * (comment start) @polyfill @ host g- menu-item (comment end)
209- * shadow::-webkit-distributed(g- menu-item) {
209+ * (comment start) @polyfill : host menu-item (comment end)
210+ * shadow::-webkit-distributed(menu-item) {
210211 *
211212 * to this:
212213 *
213- * scopeName g- menu-item {
214+ * scopeName menu-item {
214215 *
215216 **/
216- shimPolyfillDirectives : function ( styles , name ) {
217+ insertPolyfillDirectives : function ( styles , name ) {
217218 if ( styles ) {
218219 Array . prototype . forEach . call ( styles , function ( s ) {
219- s . textContent = this . convertPolyfillDirectives ( s . textContent , name ) ;
220+ s . textContent = this . insertPolyfillDirectivesInCssText ( s . textContent ) ;
220221 } , this ) ;
221222 }
222223 } ,
223- convertPolyfillDirectives : function ( cssText , name ) {
224- var r = '' , l = 0 , matches , selector ;
224+ insertPolyfillDirectivesInCssText : function ( cssText , name ) {
225+ var r = '' , l = 0 , matches ;
225226 while ( matches = cssPolyfillCommentRe . exec ( cssText ) ) {
226227 r += cssText . substring ( l , matches . index ) ;
227228 // remove end comment delimiter (*/)
228- selector = matches [ 1 ] . slice ( 0 , - 2 ) . replace ( hostRe , name ) ;
229- r += this . scopeSelector ( selector , name ) + '{' ;
229+ r += matches [ 1 ] . slice ( 0 , - 2 ) + '{' ;
230230 l = cssPolyfillCommentRe . lastIndex ;
231231 }
232232 r += cssText . substring ( l , cssText . length ) ;
233233 return r ;
234234 } ,
235- extractPolyfillRules : function ( styles , name ) {
235+ /*
236+ * Process styles to add rules which will only apply under the polyfill
237+ *
238+ * For example, we convert this rule:
239+ *
240+ * (comment start) @polyfill-rule :host menu-item {
241+ * ... } (comment end)
242+ *
243+ * to this:
244+ *
245+ * scopeName menu-item {...}
246+ *
247+ **/
248+ insertPolyfillRules : function ( styles , name ) {
236249 if ( styles ) {
237- var cssText = '' ;
238250 Array . prototype . forEach . call ( styles , function ( s ) {
239- cssText += this . extractPolyfillRulesFromCssText ( s . textContent , name ) +
240- '\n\n' ;
251+ s . textContent = this . insertPolyfillRulesInCssText ( s . textContent ) ;
241252 } , this ) ;
242253 }
243- return cssText ;
244254 } ,
245- extractPolyfillRulesFromCssText : function ( cssText , name ) {
246- var r = '' , l = 0 , matches , selector ;
255+ insertPolyfillRulesInCssText : function ( cssText , name ) {
256+ var r = '' , l = 0 , matches ;
247257 while ( matches = cssPolyfillRuleCommentRe . exec ( cssText ) ) {
248- rule = matches [ 1 ] . slice ( 0 , - 1 ) . replace ( hostRe , name ) ;
249- r += rule + '\n\n' ;
258+ r += cssText . substring ( l , matches . index ) ;
259+ // remove end comment delimiter (*/)
260+ r += matches [ 1 ] . slice ( 0 , - 1 ) ;
261+ l = cssPolyfillCommentRe . lastIndex ;
250262 }
263+ r += cssText . substring ( l , cssText . length ) ;
251264 return r ;
252265 } ,
253266 // apply @host and scope shimming
@@ -325,6 +338,7 @@ var ShadowCSS = {
325338 } ,
326339 convertScopedStyles : function ( styles , name ) {
327340 var cssText = stylesToCssText ( styles ) . replace ( hostRuleRe , '' ) ;
341+ cssText = this . insertPolyfillHostInCssText ( cssText ) ;
328342 cssText = this . convertPseudos ( cssText ) ;
329343 var rules = cssToRules ( cssText ) ;
330344 cssText = this . scopeRules ( rules , name ) ;
@@ -368,9 +382,19 @@ var ShadowCSS = {
368382 var re = new RegExp ( '^' + matchScope + selectorReSuffix , 'm' ) ;
369383 return ! selector . match ( re ) ;
370384 } ,
385+ insertPolyfillHostInCssText : function ( selector ) {
386+ return selector . replace ( hostRe , polyfillHost ) . replace ( colonHostRe ,
387+ polyfillHost ) ;
388+ } ,
371389 // scope via name and [is=name]
372390 applySimpleSelectorScope : function ( selector , name ) {
373- return name + ' ' + selector + ', ' + '[is=' + name + '] ' + selector ;
391+ var ancestor = name + ' ' , is = '[is=' + name + '] ' ;
392+ if ( selector . match ( polyfillHostRe ) ) {
393+ return selector . replace ( polyfillHostRe , ancestor ) + ', ' +
394+ selector . replace ( polyfillHostRe , is ) ;
395+ } else {
396+ return ancestor + selector + ', ' + is + selector ;
397+ }
374398 } ,
375399 // return a selector with [name] suffix on each simple selector
376400 // e.g. .foo.bar > .zot becomes .foo[name].bar[name] > .zot[name]
@@ -381,7 +405,8 @@ var ShadowCSS = {
381405 splits . forEach ( function ( sep ) {
382406 var parts = scoped . split ( sep ) ;
383407 scoped = parts . map ( function ( p ) {
384- var t = p . trim ( ) ;
408+ // remove :host since it should be unnecessary
409+ var t = p . trim ( ) . replace ( polyfillHostRe , '' ) ;
385410 if ( t && ( splits . indexOf ( t ) < 0 ) && ( t . indexOf ( attrName ) < 0 ) ) {
386411 p = t . replace ( / ( [ ^ : ] * ) ( : * ) ( .* ) / , '$1' + attrName + '$2$3' )
387412 }
@@ -411,7 +436,10 @@ var hostRuleRe = /@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim,
411436 cssPolyfillRuleCommentRe = / \/ \* \s @ p o l y f i l l - r u l e ( [ ^ * ] * \* + ( [ ^ / * ] [ ^ * ] * \* + ) * ) \/ / gim,
412437 cssPseudoRe = / : : ( x - [ ^ \s { , ( ] * ) / gim,
413438 selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$' ,
414- hostRe = / @ h o s t / gim;
439+ hostRe = / @ h o s t / gim,
440+ colonHostRe = / \: h o s t / gim,
441+ polyfillHost = '-host' ,
442+ polyfillHostRe = / - h o s t / gim;
415443
416444function stylesToCssText ( styles , preserveComments ) {
417445 var cssText = '' ;
0 commit comments