From 17bc75aead02e6dc7d031b34e1c8b7122201cdf4 Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Wed, 9 Mar 2016 13:49:31 -0800 Subject: [PATCH 01/77] check for native css variables --- src/lib/style-util.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lib/style-util.html b/src/lib/style-util.html index 16dc0c7fbe..bf63db69d2 100644 --- a/src/lib/style-util.html +++ b/src/lib/style-util.html @@ -15,7 +15,11 @@ Polymer.StyleUtil = (function() { return { - + HAS_NATIVE_VARIABLES: (function() { + var el = document.createElement('div'); + el.style.cssText = '--foo:blue'; + return el.style.getPropertyValue('--foo') === 'blue'; + })(), MODULE_STYLES_SELECTOR: 'style, link[rel=import][type~=css], template', INCLUDE_ATTR: 'include', From ff5658aad5eb24e40aa907d127c5763d9bcf075d Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Thu, 10 Mar 2016 14:03:06 -0800 Subject: [PATCH 02/77] keep custom properties, still unpack mixins --- src/lib/style-properties.html | 7 ++++--- src/lib/style-util.html | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/lib/style-properties.html b/src/lib/style-properties.html index 709b8993df..457ddf1e62 100644 --- a/src/lib/style-properties.html +++ b/src/lib/style-properties.html @@ -54,7 +54,8 @@ // TODO(sorvell): workaround parser seeing mixins as additional rules rule.rules = null; } - info.cssText = this.collectCssText(rule); + info.cssText = styleUtil.HAS_NATIVE_VARIABLES ? + rule.parsedCssText : this.collectCssText(rule); rule.propertyInfo = info; return info; }, @@ -150,7 +151,7 @@ m = p.match(this.rx.MIXIN_MATCH); if (m) { p = this.valueForProperty(props[m[1]], props); - } else { + } else if (!styleUtil.HAS_NATIVE_VARIABLES) { var colon = p.indexOf(':'); if (colon !== -1) { var pp = p.substring(colon); @@ -355,7 +356,7 @@ // note: we use only the scope class (.x-foo-42) and not the hostSelector // (x-foo) to scope :host rules; this helps make property host rules // have low specificity. They are overrideable by class selectors but, - // unfortunately, not by type selectors (e.g. overriding via + // unfortunately, not by type selectors (e.g. overriding via // `.special` is ok, but not by `x-foo`). _scopeSelector: function(rule, hostRx, hostSelector, viaAttr, scopeId) { rule.transformedSelector = rule.transformedSelector || rule.selector; diff --git a/src/lib/style-util.html b/src/lib/style-util.html index bf63db69d2..c4bf1101dc 100644 --- a/src/lib/style-util.html +++ b/src/lib/style-util.html @@ -23,14 +23,14 @@ MODULE_STYLES_SELECTOR: 'style, link[rel=import][type~=css], template', INCLUDE_ATTR: 'include', - toCssText: function(rules, callback, preserveProperties) { + toCssText: function(rules, callback) { if (typeof rules === 'string') { rules = this.parser.parse(rules); } if (callback) { this.forEachRule(rules, callback); } - return this.parser.stringify(rules, preserveProperties); + return this.parser.stringify(rules, this.HAS_NATIVE_VARIABLES); }, forRulesInStyles: function(styles, styleRuleCallback, keyframesRuleCallback) { From 5ea78b0fa516ad4054668c2becf4423af1bd01e2 Mon Sep 17 00:00:00 2001 From: Steven Orvell Date: Fri, 11 Mar 2016 15:15:08 -0800 Subject: [PATCH 03/77] make `updateStyles` (modulo @apply) work with native custom properties. make `getComputedStyleValue` work with native custom properties. --- src/lib/style-defaults.html | 4 +++ src/lib/style-properties.html | 18 ++++++++++ src/standard/x-styling.html | 31 ++++++++++------ test/unit/styling-cross-scope-var.html | 49 +++++++++++++++----------- 4 files changed, 70 insertions(+), 32 deletions(-) diff --git a/src/lib/style-defaults.html b/src/lib/style-defaults.html index c015da7462..983bfa8241 100644 --- a/src/lib/style-defaults.html +++ b/src/lib/style-defaults.html @@ -14,6 +14,7 @@ Polymer.StyleDefaults = (function() { var styleProperties = Polymer.StyleProperties; + var styleUtil = Polymer.StyleUtil; var StyleCache = Polymer.StyleCache; var api = { @@ -79,6 +80,9 @@ s = s.__importElement || s; s._apply(); } + if (styleUtil.HAS_NATIVE_VARIABLES) { + styleProperties.updateNativeStyleProperties(document.documentElement, this.customStyle); + } } }; diff --git a/src/lib/style-properties.html b/src/lib/style-properties.html index 457ddf1e62..464c8e7f1c 100644 --- a/src/lib/style-properties.html +++ b/src/lib/style-properties.html @@ -439,6 +439,24 @@ } }, + /* Applies a set of properties to an element's style natively (used to + * support element.customStyle / element.updateStyles + */ + // TODO(dfreedm): @apply. + updateNativeStyleProperties: function(element, properties) { + // remove existing properties + for (var i=0; i < element.style.length; i++) { + element.style.removeProperty(element.style[i]); + } + // apply properties + for (var p in properties) { + // NOTE: for bc with shim, don't apply null values. + if (properties[p] !== null) { + element.style.setProperty(p, properties[p]); + } + } + }, + rx: { VAR_ASSIGN: /(?:^|[;\s{]\s*)(--[\w-]*?)\s*:\s*(?:([^;{]*)|{([^}]*)})(?:(?=[;\s}])|$)/gi, MIXIN_MATCH: /(?:^|\W+)@apply[\s]*\(([^)]*)\)/i, diff --git a/src/standard/x-styling.html b/src/standard/x-styling.html index 23150ed4f8..c998e14c36 100644 --- a/src/standard/x-styling.html +++ b/src/standard/x-styling.html @@ -7,6 +7,7 @@ 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 --> + @@ -17,6 +18,7 @@ var serializeValueToAttribute = Polymer.Base.serializeValueToAttribute; + var styleUtil = Polymer.StyleUtil; var propertyUtils = Polymer.StyleProperties; var styleTransformer = Polymer.StyleTransformer; var styleDefaults = Polymer.StyleDefaults; @@ -47,7 +49,8 @@ * @return {String} the computed value */ getComputedStyleValue: function(property) { - return this._styleProperties && this._styleProperties[property] || + return !styleUtil.HAS_NATIVE_VARIABLES && this._styleProperties ? + this._styleProperties[property] : getComputedStyle(this).getPropertyValue(property); }, @@ -61,8 +64,10 @@ this._customStyle = null; }, + // TODO(dfreedm): should only be true iff browser doesn't support + // native custom properties. _needsStyleProperties: function() { - return Boolean(this._ownStylePropertyNames && + return Boolean(this._ownStylePropertyNames && this._ownStylePropertyNames.length); }, @@ -240,16 +245,20 @@ if (properties) { this.mixin(this.customStyle, properties); } - // skip applying properties to self if not used - if (this._needsStyleProperties()) { - this._updateStyleProperties(); - // when an element doesn't use style properties, its own properties - // should be invalidated so elements down the tree update ok. + if (styleUtil.HAS_NATIVE_VARIABLES) { + propertyUtils.updateNativeStyleProperties(this, this.customStyle); } else { - this._styleProperties = null; - } - if (this._styleCache) { - this._styleCache.clear(); + // skip applying properties to self if not used + if (this._needsStyleProperties()) { + this._updateStyleProperties(); + // when an element doesn't use style properties, its own properties + // should be invalidated so elements down the tree update ok. + } else { + this._styleProperties = null; + } + if (this._styleCache) { + this._styleCache.clear(); + } } // always apply properties to root this._updateRootStyles(); diff --git a/test/unit/styling-cross-scope-var.html b/test/unit/styling-cross-scope-var.html index 36d0063b0d..02289d71ad 100644 --- a/test/unit/styling-cross-scope-var.html +++ b/test/unit/styling-cross-scope-var.html @@ -85,7 +85,7 @@ padding: 8px; } - :root { + *, :host { --gc4-scope: 5px solid green; } @@ -146,9 +146,10 @@ display: block; } - :root { + *, :host { --grand-child-scope-var: var(--rename); } + overrides: @@ -187,7 +188,7 @@ display: block; } - :root { + *, :host { --fillin: 16px; } @@ -205,7 +206,7 @@ From 6589a5083b19e3655c0023f06618090626f14b6a Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Mon, 14 Mar 2016 16:00:53 -0700 Subject: [PATCH 09/77] fix rules with property and mixin definitions for native --- src/lib/css-parse.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/css-parse.html b/src/lib/css-parse.html index b3c8344680..27ca8e034c 100644 --- a/src/lib/css-parse.html +++ b/src/lib/css-parse.html @@ -112,7 +112,7 @@ var cssText = ''; if (node.cssText || node.rules) { var r$ = node.rules; - if (r$ && (preserveProperties || !this._hasMixinRules(r$))) { + if (r$ && !this._hasMixinRules(r$)) { for (var i=0, l=r$.length, r; (i Date: Tue, 15 Mar 2016 17:19:25 -0700 Subject: [PATCH 10/77] First draft of @apply shim ```css --foo: { color: red; border: 2px solid black; } @apply --foo; ``` becomes ```css --foo-color: red; --foo-border: 2px solid black; color: var(--foo-color); border: var(--foo-border); ``` --- src/lib/style-properties.html | 4 +- src/standard/apply-shim.html | 96 +++++++++++++++++++++++++++++++++++ src/standard/styling.html | 39 +++++++------- src/standard/x-styling.html | 5 +- test/smoke/style.html | 38 ++++++++++++++ 5 files changed, 162 insertions(+), 20 deletions(-) create mode 100644 src/standard/apply-shim.html create mode 100644 test/smoke/style.html diff --git a/src/lib/style-properties.html b/src/lib/style-properties.html index bea8f59606..1cecda9177 100644 --- a/src/lib/style-properties.html +++ b/src/lib/style-properties.html @@ -74,7 +74,7 @@ var any; while ((m = rx.exec(cssText))) { // note: group 2 is var, 3 is mixin - properties[m[1]] = (m[2] || m[3]).trim(); + properties[m[1].trim()] = (m[2] || m[3]).trim(); any = true; } return any; @@ -465,7 +465,7 @@ rx: { VAR_ASSIGN: /(?:^|[;\s{]\s*)(--[\w-]*?)\s*:\s*(?:([^;{]*)|{([^}]*)})(?:(?=[;\s}])|$)/gi, - MIXIN_MATCH: /(?:^|\W+)@apply[\s]*\(([^)]*)\)/i, + MIXIN_MATCH: /(?:^|\W+)@apply[\s]*\(?([^)]*)\)?/i, // note, this supports: // var(--a) // var(--a, --b) diff --git a/src/standard/apply-shim.html b/src/standard/apply-shim.html new file mode 100644 index 0000000000..ace6486cf0 --- /dev/null +++ b/src/standard/apply-shim.html @@ -0,0 +1,96 @@ + + + + + + + diff --git a/src/standard/styling.html b/src/standard/styling.html index db0321a0f1..b52ff9de41 100644 --- a/src/standard/styling.html +++ b/src/standard/styling.html @@ -36,32 +36,37 @@ }, _prepStyles: function() { - // under shady dom we always output a shimmed style (which may be - // empty) so that other dynamic stylesheets can always be placed - // after the element's main stylesheet. - // This helps ensure element styles are always in registration order. - if (!nativeShadow) { - this._scopeStyle = styleUtil.applyStylePlaceHolder(this.is); + if (this._encapsulateStyle === undefined) { + this._encapsulateStyle = !nativeShadow && + Boolean(this._template); } - }, - - _prepShimStyles: function() { if (this._template) { - if (this._encapsulateStyle === undefined) { - this._encapsulateStyle = !nativeShadow; - } this._styles = this._collectStyles(); + // prepare to shim style properties. + this._prepStyleProperties(); // calculate shimmed styles (we must always do this as it // stores shimmed style data in the css rules for later use) var cssText = styleTransformer.elementStyles(this); - // prepare to shim style properties. - this._prepStyleProperties(); // do we really need to output static shimmed styles? // only if no custom properties are used since otherwise // styles are applied via property shimming. - if (!this._needsStyleProperties() && this._styles.length) { - styleUtil.applyCss(cssText, this.is, - nativeShadow ? this._template.content : null, this._scopeStyle); + var needsStatic = this._styles.length && + !this._needsStyleProperties(); + // under shady dom we always output a shimmed style (which may be + // empty) so that other dynamic stylesheets can always be placed + // after the element's main stylesheet. + // This helps ensure element styles are always in registration order. + if (needsStatic || !nativeShadow) { + // NOTE: IE has css style ordering issues unless there's at least a + // space in the stylesheet. + cssText = needsStatic ? cssText : ' '; + var style = styleUtil.applyCss(cssText, this.is, + nativeShadow ? this._template.content : null); + // keep track of style when in document scope (polyfill) so we can + // attach property styles after it. + if (!nativeShadow) { + this._scopeStyle = style; + } } } else { this._styles = []; diff --git a/src/standard/x-styling.html b/src/standard/x-styling.html index 324f69e4d1..51af7f19a0 100644 --- a/src/standard/x-styling.html +++ b/src/standard/x-styling.html @@ -13,6 +13,7 @@ + + + + + From 5d700e5ac164f548d356499101d95e54b85f6c3b Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Thu, 17 Mar 2016 16:24:14 -0700 Subject: [PATCH 11/77] step 3 --- src/standard/apply-shim.html | 66 ++++++++++++++++++++++++------------ test/smoke/style.html | 8 ++++- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/src/standard/apply-shim.html b/src/standard/apply-shim.html index ace6486cf0..1da5cf7bf5 100644 --- a/src/standard/apply-shim.html +++ b/src/standard/apply-shim.html @@ -26,6 +26,13 @@ var mixinMap = Object.create(null); function mapSet(name, prop) { + var old = mixinMap[name]; + if (old) { + var reset = diff(old, prop); + reset.forEach(function(r) { + prop[r] = 'initial'; + }) + } mixinMap[name] = prop; } @@ -47,21 +54,28 @@ function flattenMixin(name, props) { return Object.keys(props).map(function(p){ return name + '-' + p + ': ' + props[p]; - }).join(';'); + }).join('; '); } function applyVars(name, props) { return Object.keys(props).map(function(p){ return p + ': var(' + name + '-' + p + ')'; - }).join(';'); + }).join('; '); } function textToProps(text) { var props = text.split(';'); var out = {}; - for (var i = 0, sp; i < props.length; i++) { - sp = props[i].split(':'); - out[sp[0].trim()] = sp[1].trim(); + for (var i = 0, p, sp; i < props.length; i++) { + p = props[i]; + if (p) { + sp = p.split(':'); + if (sp.length >= 2) { + out[sp[0].trim()] = sp.slice(1).map(function(n) { + return n.trim(); + }).join(':'); + } + } } return out; } @@ -69,24 +83,32 @@ return { transform: function(styles) { styleUtil.forRulesInStyles(styles, function(n){ - var m; - while ((m = propertyUtils.rx.VAR_ASSIGN.exec(n.cssText))) { - // mixin assignment - if (m[3]) { - var prefix = m[0].slice(0, m[0].indexOf('--')); - var name = m[1].trim(); - var subprops = textToProps(m[3]); + var cssText = n.cssText; + // produce variables + cssText = cssText.replace(propertyUtils.rx.VAR_ASSIGN, + function(all, name, _, mixin) { + if (!mixin) { + return all; + } + var prefix = all.slice(0, all.indexOf('--')); + name = name.trim(); + var subprops = textToProps(mixin); mapSet(name, subprops); - n.cssText = n.cssText.replace(m[0], prefix + flattenMixin(name, subprops)); - } - } - while((m = propertyUtils.rx.MIXIN_MATCH.exec(n.cssText))) { - var name = m[1].replace(/;$/, ''); - var prefix = m[0].slice(0, m[0].indexOf('@apply')); - var mixin = mapGet(name); - var vars = applyVars(name, mixin); - n.cssText = n.cssText.replace(m[0], prefix + vars); - } + return prefix + flattenMixin(name, subprops); + }); + // consume mixins + cssText = cssText.replace(propertyUtils.rx.MIXIN_MATCH, + function(all, name) { + var prefix = all.slice(0, all.indexOf('@apply')); + name = name.replace(/;$/, ''); + var mixin = mapGet(name); + var vars = ''; + if (mixin) { + vars = applyVars(name, mixin) + ';'; + } + return prefix + vars; + }); + n.cssText = cssText; }, function(n){ console.log(n); }); diff --git a/test/smoke/style.html b/test/smoke/style.html index c9c89a874e..f3967fce86 100644 --- a/test/smoke/style.html +++ b/test/smoke/style.html @@ -1,6 +1,7 @@ + @@ -14,7 +15,10 @@ --blue: blue; --foo: { background-color: red; - border: 2px solid gray + border: 2px solid gray; + }; + --foo: { + box-shadow: 20px 20px 20px orange; }; } @@ -28,9 +32,11 @@ From 62dc8b9920a995ce365209f1ffd3d2eec1526ece Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Mon, 21 Mar 2016 16:12:33 -0700 Subject: [PATCH 12/77] Process stylesheets in custom-styles move apply-shim to lib Fix some tests --- src/{standard => lib}/apply-shim.html | 64 ++++++++++++------------ src/lib/custom-style.html | 8 +++ src/standard/styling.html | 3 ++ src/standard/x-styling.html | 2 +- test/smoke/style.html | 3 ++ test/unit/custom-style.html | 6 --- test/unit/styling-cross-scope-apply.html | 22 +++++--- test/unit/styling-scoped-elements.html | 2 +- 8 files changed, 62 insertions(+), 48 deletions(-) rename src/{standard => lib}/apply-shim.html (67%) diff --git a/src/standard/apply-shim.html b/src/lib/apply-shim.html similarity index 67% rename from src/standard/apply-shim.html rename to src/lib/apply-shim.html index 1da5cf7bf5..aa54134b2d 100644 --- a/src/standard/apply-shim.html +++ b/src/lib/apply-shim.html @@ -17,8 +17,6 @@ 'use strict'; var propertyUtils = Polymer.StyleProperties; - var styleTransformer = Polymer.StyleTransformer; - var styleDefaults = Polymer.StyleDefaults; var styleUtil = Polymer.StyleUtil; // map of mixin to property names @@ -80,38 +78,40 @@ return out; } + function assign(all, name, _, mixin) { + if (!mixin) { + return all; + } + mixin = mixin.replace(propertyUtils.rx.MIXIN_MATCH, apply); + var prefix = all.slice(0, all.indexOf('--')); + name = name.trim(); + var subprops = textToProps(mixin); + mapSet(name, subprops); + return prefix + flattenMixin(name, subprops); + } + + function apply(all, name) { + var prefix = all.slice(0, all.indexOf('@apply')); + name = name.replace(/;\s*/m, ''); + var mixin = mapGet(name); + var vars = ''; + if (mixin) { + vars = applyVars(name, mixin) + ';'; + } + return prefix + vars; + } + return { transform: function(styles) { - styleUtil.forRulesInStyles(styles, function(n){ - var cssText = n.cssText; - // produce variables - cssText = cssText.replace(propertyUtils.rx.VAR_ASSIGN, - function(all, name, _, mixin) { - if (!mixin) { - return all; - } - var prefix = all.slice(0, all.indexOf('--')); - name = name.trim(); - var subprops = textToProps(mixin); - mapSet(name, subprops); - return prefix + flattenMixin(name, subprops); - }); - // consume mixins - cssText = cssText.replace(propertyUtils.rx.MIXIN_MATCH, - function(all, name) { - var prefix = all.slice(0, all.indexOf('@apply')); - name = name.replace(/;$/, ''); - var mixin = mapGet(name); - var vars = ''; - if (mixin) { - vars = applyVars(name, mixin) + ';'; - } - return prefix + vars; - }); - n.cssText = cssText; - }, function(n){ - console.log(n); - }); + styleUtil.forRulesInStyles(styles, this.transformRule, this.transformRule); + }, + transformRule: function(rule) { + var cssText = rule.cssText; + // produce variables + cssText = cssText.replace(propertyUtils.rx.VAR_ASSIGN, assign); + // consume mixins + cssText = cssText.replace(propertyUtils.rx.MIXIN_MATCH, apply); + rule.cssText = cssText; } }; })(); diff --git a/src/lib/custom-style.html b/src/lib/custom-style.html index f730d80b60..a02f5887b9 100644 --- a/src/lib/custom-style.html +++ b/src/lib/custom-style.html @@ -10,6 +10,7 @@ + + + +
+
+ + + + diff --git a/test/smoke/style-transformer/styling.html b/test/smoke/style-transformer/styling.html new file mode 100644 index 0000000000..0071b91145 --- /dev/null +++ b/test/smoke/style-transformer/styling.html @@ -0,0 +1,8 @@ + + + From 96d341ac683b5ee9964de530ccc029bceff084ec Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Thu, 31 Mar 2016 11:31:26 -0700 Subject: [PATCH 26/77] Move regexes from style-properties to style-util for easier sharing Clean up dependencies in apply-shim Remove lazyRegister hack --- src/lib/apply-shim.html | 90 ++++++----------------------------- src/lib/style-properties.html | 25 ++-------- src/lib/style-util.html | 22 +++++++++ 3 files changed, 40 insertions(+), 97 deletions(-) diff --git a/src/lib/apply-shim.html b/src/lib/apply-shim.html index 2c6918cf88..9944605100 100644 --- a/src/lib/apply-shim.html +++ b/src/lib/apply-shim.html @@ -7,21 +7,16 @@ 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 --> - - - - - + \ No newline at end of file + diff --git a/src/lib/style-defaults.html b/src/lib/style-defaults.html index 983bfa8241..3107ac4fc5 100644 --- a/src/lib/style-defaults.html +++ b/src/lib/style-defaults.html @@ -9,13 +9,14 @@ --> + - - diff --git a/test/smoke/style-transformer/styling.html b/test/smoke/style-transformer/styling.html index 0071b91145..c87fe14459 100644 --- a/test/smoke/style-transformer/styling.html +++ b/test/smoke/style-transformer/styling.html @@ -6,3 +6,4 @@ }; + From 39b067f5a7913142c6e12ec9f7b1f2fb2c4443d4 Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Thu, 14 Apr 2016 14:02:46 -0700 Subject: [PATCH 29/77] actually let uses set useNativeCSSProperties false --- src/lib/settings.html | 7 +++++-- src/standard/x-styling.html | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/lib/settings.html b/src/lib/settings.html index c501cd1f63..ef05237a34 100644 --- a/src/lib/settings.html +++ b/src/lib/settings.html @@ -51,8 +51,11 @@ && CSS.supports && CSS.supports('box-shadow', '0 0 0 var(--foo)')); // apply shim depends on lazyRegister - settings.useNativeCSSProperties = settings.useNativeCSSProperties || - settings.hasNativeCSSProperties && settings.lazyRegister; + var nativeCSSPropertiesDefined = settings.useNativeCSSProperties !== undefined; + if (!nativeCSSPropertiesDefined) { + settings.useNativeCSSProperties = settings.useNativeCSSProperties || + settings.hasNativeCSSProperties && settings.lazyRegister; + } return settings; })() diff --git a/src/standard/x-styling.html b/src/standard/x-styling.html index 2a224ac47a..f9651ff920 100644 --- a/src/standard/x-styling.html +++ b/src/standard/x-styling.html @@ -75,7 +75,7 @@ // TODO(dfreedm): should only be true iff browser doesn't support // native custom properties. _needsStyleProperties: function() { - return Boolean(this._ownStylePropertyNames && + return Boolean(!nativeVariables && this._ownStylePropertyNames && this._ownStylePropertyNames.length); }, From 6eca881c181df0f33929f2bb5870137b8679980d Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Thu, 14 Apr 2016 14:42:24 -0700 Subject: [PATCH 30/77] SCOPE_SELECTORS needs to work with built selectors for custom-style and elements --- src/lib/style-properties.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib/style-properties.html b/src/lib/style-properties.html index 02339d2cda..b5cbc161de 100644 --- a/src/lib/style-properties.html +++ b/src/lib/style-properties.html @@ -471,7 +471,10 @@ rx: styleUtil.rx, HOST_SELECTORS: [':host'], - SCOPE_SELECTORS: [':root'], + // :root for elements and custom-styles without native custom properties + // html for custom-styles with native custom properties + // :host > * for elements with native custom properties + SCOPE_SELECTORS: [':root', 'html', ':host > *'], XSCOPE_NAME: 'x-scope' }; From a96210cafadad3cbefe110fbe7d50257a4008870 Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Mon, 18 Apr 2016 12:54:11 -0700 Subject: [PATCH 31/77] No need to decorate styles for apply shim --- src/lib/style-properties.html | 3 +-- src/standard/x-styling.html | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/lib/style-properties.html b/src/lib/style-properties.html index b5cbc161de..56a93f979a 100644 --- a/src/lib/style-properties.html +++ b/src/lib/style-properties.html @@ -58,8 +58,7 @@ // TODO(sorvell): workaround parser seeing mixins as additional rules rule.rules = null; } - info.cssText = nativeVariables ? - rule.parsedCssText : this.collectCssText(rule); + info.cssText = this.collectCssText(rule); rule.propertyInfo = info; return info; }, diff --git a/src/standard/x-styling.html b/src/standard/x-styling.html index f9651ff920..60eb17c456 100644 --- a/src/standard/x-styling.html +++ b/src/standard/x-styling.html @@ -12,7 +12,6 @@ - diff --git a/src/lib/settings.html b/src/lib/settings.html index ef05237a34..c83528e0ac 100644 --- a/src/lib/settings.html +++ b/src/lib/settings.html @@ -53,7 +53,7 @@ // apply shim depends on lazyRegister var nativeCSSPropertiesDefined = settings.useNativeCSSProperties !== undefined; if (!nativeCSSPropertiesDefined) { - settings.useNativeCSSProperties = settings.useNativeCSSProperties || + settings.useNativeCSSProperties = settings.hasNativeCSSProperties && settings.lazyRegister; } diff --git a/test/smoke/style.html b/test/smoke/style.html index ee4b61e90c..d84c0df059 100644 --- a/test/smoke/style.html +++ b/test/smoke/style.html @@ -5,49 +5,53 @@ - - - + + + + + From 558a3f70a773e7cb749179cd7ef46b4774c0ad19 Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Tue, 19 Apr 2016 11:45:51 -0700 Subject: [PATCH 33/77] Fix @apply consumption to incrementally process rule text When >1 mixin is consumed, correctly use properties produced by last mixin as fallbacks for current mixin LOTS more comments, more descriptive comment names Micro-opts --- src/lib/apply-shim.html | 127 +++++++++++++++++++++------------------- 1 file changed, 67 insertions(+), 60 deletions(-) diff --git a/src/lib/apply-shim.html b/src/lib/apply-shim.html index a8ee29f8a1..c24020b34e 100644 --- a/src/lib/apply-shim.html +++ b/src/lib/apply-shim.html @@ -34,8 +34,8 @@ } // return properties that are not used by the new definition of a mixin - // diff([a, b], [b]) -> [a] - function diff(oldSet, newSet) { + // diffProperties([a, b], [b]) -> [a] + function diffProperties(oldSet, newSet) { var diff = []; if (oldSet && oldSet.length) { for (var i = 0, old; i < oldSet.length; i++) { @@ -48,36 +48,27 @@ return diff; } - // - function flattenMixin(mixinName, propNames, propMap, resetProps) { + // produce variables in place of a mixin definition + function defineMixinProperties(mixinName, propNames, propMap, oldProps) { var out = []; var i, p, v; - // reset variables that are overriden by the current mixin - for (i = 0; i < resetProps.length; i++) { - p = resetProps[i]; - out.push(mixinName + '-' + p + ': initial'); - } // set variables defined by current mixin for (i = 0; i < propNames.length; i++) { p = propNames[i]; v = propMap[p]; out.push(mixinName + '-' + p + ': ' + v); } - return out.join(';\n'); - } - - function applyVars(mixinName, propNames, fallbacks) { - return propNames.map(function(p) { - var fallback = fallbacks && fallbacks[p]; - var parts = [p, ': var(', mixinName, '-', p]; - if (fallback) { - parts.push(',', fallback); - } - parts.push(')'); - return parts.join(''); - }).join(';\n'); + // reset variables that are overriden by the current mixin + var resetProps = diffProperties(oldProps, propNames); + for (i = 0; i < resetProps.length; i++) { + p = resetProps[i]; + out.push(mixinName + '-' + p + ': initial'); + } + return out.join(';\n') + ';'; } + // "parse" a mixin definition into a map of properties and values + // textToProps('border: 2px solid black') -> ('border', '2px solid black') function textToProps(text) { var props = text.split(';'); var out = {}; @@ -85,17 +76,17 @@ p = props[i]; if (p) { sp = p.split(':'); - if (sp.length >= 2) { - out[sp[0].trim()] = sp.slice(1).map(function(n) { - return n.trim(); - }).join(':'); + // ignore lines that aren't definitions like @media + if (sp.length > 1) { + // some properties may have ':' in the value, like data urls + out[sp[0].trim()] = sp.slice(1).join(':'); } } } return out; } - function assign(matchText, propertyName, valueProperty, valueMixin) { + function mixinAssignment(matchText, propertyName, valueProperty, valueMixin) { // handle case where property value is a mixin if (valueProperty) { VAR_MATCH.lastIndex = 0; @@ -110,52 +101,68 @@ if (!valueMixin) { return matchText; } - valueMixin = consumeMixins(valueMixin); + var mixinAsProperties = mixinApplication(valueMixin); var prefix = matchText.slice(0, matchText.indexOf('--')); - var mixinProps = textToProps(valueMixin); + var mixinProps = textToProps(mixinAsProperties); var propNames = Object.keys(mixinProps); var oldProps = mapGet(propertyName); - var resetProps = diff(oldProps, propNames); mapSet(propertyName, propNames); - return prefix + flattenMixin(propertyName, propNames, mixinProps, resetProps); - } - - function apply(matchText, mixinName, fallbacks) { - var prefix = matchText.slice(0, matchText.indexOf('@apply')); - mixinName = mixinName.replace(APPLY_NAME_CLEAN, ''); - var vars = ''; - var mixin = mapGet(mixinName); - if (mixin) { - vars = applyVars(mixinName, mixin, fallbacks) + ';'; - } - return prefix + vars; - } - - function collectDefaultsBeforeApply(fullText) { - // search for properties from last @apply up to (but not including) this @apply - var applyPos = fullText.indexOf('@apply'); - // find props defined before this @apply, after last @apply - var textBeforeApply = fullText.slice(0, applyPos); - return textToProps(textBeforeApply); + return prefix + defineMixinProperties(propertyName, propNames, mixinProps, oldProps); } // fix shim'd var syntax // var(--a, --b) -> var(--a, var(--b)); function fixVars(matchText, prefix, value, fallback) { + // if fallback doesn't exist, or isn't a broken variable, abort if (!fallback || fallback.indexOf('--') !== 0) { return matchText; } - return prefix + 'var(' + value + ',var(' + fallback + '));'; + return [prefix, 'var(', value, ', var(', fallback, '));'].join(''); + } + + // produce variable consumption at the site of mixin consumption + // @apply --foo; -> forAll ${propname} in --foo ~> --foo-${propname}: ${value} + function applyMixinProperties(mixinName, fallbacks) { + mixinName = mixinName.replace(APPLY_NAME_CLEAN, ''); + var out = ''; + var mixinProperties = mapGet(mixinName); + if (mixinProperties) { + var vars = []; + for (var i = 0, p, f, parts; i < mixinProperties.length; i++) { + p = mixinProperties[i]; + f = fallbacks && fallbacks[p]; + parts = [p, ': var(', mixinName, '-', p]; + // if a property is defined in this rule, use it as a fallback to this variable + if (f) { + parts.push(',', f); + } + parts.push(')'); + vars.push(parts.join('')); + } + out = vars.join(';\n'); + } + return out; } - function consumeMixins(text) { - var m, matchText, mixinName; - MIXIN_MATCH.lastIndex = 0; + // replace mixin consumption with variable consumption + function mixinApplication(text) { + var m; + // loop over text until all mixins with defintions have been applied while((m = MIXIN_MATCH.exec(text))) { - matchText = m[0]; - mixinName = m[1]; - var defaults = collectDefaultsBeforeApply(text); - text = text.replace(matchText, apply(matchText, mixinName, defaults)); + var matchText = m[0]; + var mixinName = m[1]; + var idx = m.index; + // collect properties before apply to be "defaults" if mixin might override them + // match includes a "prefix", so find the start and end positions of @apply + var applyPos = idx + matchText.indexOf('@apply'); + var afterApplyPos = idx + matchText.length; + // find props defined before this @apply + var textBeforeApply = text.slice(0, applyPos); + var textAfterApply = text.slice(afterApplyPos); + var defaults = textToProps(textBeforeApply); + var replacement = applyMixinProperties(mixinName, defaults); + // use regex match position to replace mixin, keep linear processing time + text = [textBeforeApply, replacement, textAfterApply].join(''); } return text; } @@ -178,9 +185,9 @@ // fix shim variables cssText = cssText.replace(VAR_MATCH, fixVars); // produce variables - cssText = cssText.replace(VAR_ASSIGN, assign); + cssText = cssText.replace(VAR_ASSIGN, mixinAssignment); // consume mixins - return consumeMixins(cssText); + return mixinApplication(cssText); } }; From 1dc1ccb890f67ec1d0f2edbe8d487675b985e5e5 Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Tue, 19 Apr 2016 12:00:07 -0700 Subject: [PATCH 34/77] MORE APPLY SHIM TESTING Actually test apply shim (needs lazyRegister), and test with shadow dom --- test/runner.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/runner.html b/test/runner.html index 6ef64721da..9095009738 100644 --- a/test/runner.html +++ b/test/runner.html @@ -56,9 +56,13 @@ 'unit/styling-extends.html', 'unit/styling-remote.html', 'unit/styling-cross-scope-var.html', - 'unit/styling-cross-scope-apply.html', + 'unit/styling-cross-scope-var.html?lazyRegister', 'unit/styling-cross-scope-var.html?dom=shadow', + 'unit/styling-cross-scope-var.html?dom=shadow&lazyRegister', + 'unit/styling-cross-scope-apply.html', + 'unit/styling-cross-scope-apply.html?lazyRegister', 'unit/styling-cross-scope-apply.html?dom=shadow', + 'unit/styling-cross-scope-apply.html?dom=shadow&lazyRegister', 'unit/styling-cross-scope-unknown-host.html', 'unit/custom-style.html', 'unit/custom-style.html?dom=shadow', From f2798589f52a43deede72d286bf82646dcdb598c Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Wed, 20 Apr 2016 16:22:12 -0700 Subject: [PATCH 35/77] Make sure @apply without parens works in property shim as expected --- src/lib/apply-shim.html | 2 + src/lib/css-parse.html | 2 +- src/lib/settings.html | 9 +- src/lib/style-properties.html | 11 +-- src/lib/style-util.html | 4 +- test/runner.html | 10 ++- test/smoke/style-transformer/smoke.html | 2 +- test/smoke/style.html | 12 ++- test/unit/styling-cross-scope-apply.html | 104 ++++++++++++++++++++++- 9 files changed, 129 insertions(+), 27 deletions(-) diff --git a/src/lib/apply-shim.html b/src/lib/apply-shim.html index c24020b34e..e4ce8f18b7 100644 --- a/src/lib/apply-shim.html +++ b/src/lib/apply-shim.html @@ -49,6 +49,8 @@ } // produce variables in place of a mixin definition + // 'foo', ['background'], {background: 'red'} -> '--foo-background: red' + // 'foo', ['color'], {color: 'blue'} -> '--foo-background: inital; --foo-color: red' function defineMixinProperties(mixinName, propNames, propMap, oldProps) { var out = []; var i, p, v; diff --git a/src/lib/css-parse.html b/src/lib/css-parse.html index 27ca8e034c..d760d7557f 100644 --- a/src/lib/css-parse.html +++ b/src/lib/css-parse.html @@ -175,7 +175,7 @@ port: /@import[^;]*;/gim, customProp: /(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?(?:[;\n]|$)/gim, mixinProp: /(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?{[^}]*?}(?:[;\n]|$)?/gim, - mixinApply: /\b@apply\b\s*\(?[^);]*?\)?\s*(?:[;\n]|$)?/gim, + mixinApply: /@apply\s*\(?[^);]*\)?\s*(?:[;\n]|$)?/gim, varApply: /[^;:]*?:[^;]*?var\([^;]*\)(?:[;\n]|$)?/gim, keyframesRule: /^@[^\s]*keyframes/, multipleSpaces: /\s+/g diff --git a/src/lib/settings.html b/src/lib/settings.html index c83528e0ac..7ea426887c 100644 --- a/src/lib/settings.html +++ b/src/lib/settings.html @@ -50,12 +50,9 @@ (!navigator.userAgent.match('AppleWebKit/601.5') && window.CSS && CSS.supports && CSS.supports('box-shadow', '0 0 0 var(--foo)')); - // apply shim depends on lazyRegister - var nativeCSSPropertiesDefined = settings.useNativeCSSProperties !== undefined; - if (!nativeCSSPropertiesDefined) { - settings.useNativeCSSProperties = - settings.hasNativeCSSProperties && settings.lazyRegister; - } + // apply shim is opt-in and depends on lazyRegister + settings.useNativeCSSProperties = settings.lazyRegister && + settings.hasNativeCSSProperties && settings.useNativeCSSProperties; return settings; })() diff --git a/src/lib/style-properties.html b/src/lib/style-properties.html index 56a93f979a..4f65f897b0 100644 --- a/src/lib/style-properties.html +++ b/src/lib/style-properties.html @@ -98,11 +98,12 @@ collectPropertiesInCssText: function(cssText, props) { var m; - while ((m = this.rx.VAR_CAPTURE.exec(cssText))) { - props[m[1]] = true; - var def = m[2]; - if (def && def.match(this.rx.IS_VAR)) { - props[def] = true; + while ((m = this.rx.VAR_CONSUMED.exec(cssText))) { + var name = m[1]; + // This regex catches all variable names, and following non-whitespace char + // If next char is not ':', then variable is a consumer + if (m[2] !== ':') { + props[name] = true; } } }, diff --git a/src/lib/style-util.html b/src/lib/style-util.html index 774e61ce6b..1ab72bee5c 100644 --- a/src/lib/style-util.html +++ b/src/lib/style-util.html @@ -172,7 +172,7 @@ rx: { VAR_ASSIGN: /(?:^|[;\s{]\s*)(--[\w-]*?)\s*:\s*(?:([^;{]*)|{([^}]*)})(?:(?=[;\s}])|$)/gi, - MIXIN_MATCH: /(?:^|\W+)@apply[\s]*\(?([^);\n]*)\)?/gi, + MIXIN_MATCH: /(?:^|\W+)@apply\s*\(?([^);\n]*)\)?/gi, // note, this supports: // var(--a) // var(--a, --b) @@ -184,7 +184,7 @@ // var(--a, var(--b, var(--c, fallback-literal))) // var(--a, var(--b, var(--c, fallback-literal(with-one-nested-parentheses)))) VAR_MATCH: /(^|\W+)var\([\s]*([^,)]*)[\s]*,?[\s]*((?:[^,()]*)|(?:[^;()]*\([^;)]*\)+))[\s]*?\)/gi, - VAR_CAPTURE: /\([\s]*(--[^,\s)]*)(?:,[\s]*(?:var\(\s*)?(--[^,\s)]*)\)?)?(?:\)|,)/gi, + VAR_CONSUMED: /(--[\w-]+)\s*([:,;)]|$)/gi, ANIMATION_MATCH: /(animation\s*:)|(animation-name\s*:)/, IS_VAR: /^--/, BRACKETED: /\{[^}]*\}/g, diff --git a/test/runner.html b/test/runner.html index 9095009738..34377e66d3 100644 --- a/test/runner.html +++ b/test/runner.html @@ -56,16 +56,18 @@ 'unit/styling-extends.html', 'unit/styling-remote.html', 'unit/styling-cross-scope-var.html', - 'unit/styling-cross-scope-var.html?lazyRegister', + 'unit/styling-cross-scope-var.html?lazyRegister&useNativeCSSProperties', 'unit/styling-cross-scope-var.html?dom=shadow', - 'unit/styling-cross-scope-var.html?dom=shadow&lazyRegister', + 'unit/styling-cross-scope-var.html?dom=shadow&lazyRegister&useNativeCSSProperties', 'unit/styling-cross-scope-apply.html', - 'unit/styling-cross-scope-apply.html?lazyRegister', + 'unit/styling-cross-scope-apply.html?lazyRegister&useNativeCSSProperties', 'unit/styling-cross-scope-apply.html?dom=shadow', - 'unit/styling-cross-scope-apply.html?dom=shadow&lazyRegister', + 'unit/styling-cross-scope-apply.html?dom=shadow&lazyRegister&useNativeCSSProperties', 'unit/styling-cross-scope-unknown-host.html', 'unit/custom-style.html', + 'unit/custom-style.html?lazyRegister&useNativeCSSProperties', 'unit/custom-style.html?dom=shadow', + 'unit/custom-style.html?dom=shadow&lazyRegister&useNativeCSSProperties', 'unit/custom-style-late.html', 'unit/dynamic-import.html', 'unit/templatizer.html', diff --git a/test/smoke/style-transformer/smoke.html b/test/smoke/style-transformer/smoke.html index f119f5ef1c..7fbe81ec93 100644 --- a/test/smoke/style-transformer/smoke.html +++ b/test/smoke/style-transformer/smoke.html @@ -17,7 +17,7 @@ function transformCss(css, scope, ext) { var rules = Polymer.CssParse.parse(css); - if (Polymer.Settings.hasNativeCSSProperties) { + if (Polymer.Settings.useNativeCSSProperties) { Polymer.ApplyShim.transform([{__cssRules: rules}]); } Polymer.StyleTransformer.css(rules, scope, ext); diff --git a/test/smoke/style.html b/test/smoke/style.html index d84c0df059..57b5bb5a5f 100644 --- a/test/smoke/style.html +++ b/test/smoke/style.html @@ -8,21 +8,17 @@