Skip to content

Commit

Permalink
style property optimizations: reify only used properties and cache st…
Browse files Browse the repository at this point in the history
…yles based only on the properties elements use;

added `customStyle` object that can be used to provide imperative scope style property values.
  • Loading branch information
Steven Orvell committed May 16, 2015
1 parent e999a92 commit 8bab868
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 75 deletions.
2 changes: 2 additions & 0 deletions polymer.html
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
this._poolContent();
// manage configuration
this._setupConfigure();
// setup style properties
this._setupStyleProperties();
// host stack
this._pushHost();
// instantiate template
Expand Down
2 changes: 1 addition & 1 deletion src/lib/custom-style.html
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
// used applied element from HTMLImports polyfill or this
var e = this.__appliedElement || this;
var rules = styleUtil.rulesForStyle(e);
propertyUtils.decorateRules(rules);
propertyUtils.decorateStyles([e]);
this._rulesToDefaultProperties(rules);
// NOTE: go async to give a chance to collect properties into
// the StyleDefaults before applying
Expand Down
39 changes: 26 additions & 13 deletions src/lib/style-cache.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,43 +9,56 @@
-->
<script>

Polymer.StyleCache = function() {
Polymer.StyleCache = function(keyName) {
this.cache = {};
if (keyName) {
this._keyName = keyName;
}
}

Polymer.StyleCache.prototype = {

MAX: 100,

_prepare: function(style, scope, bag, styles) {
style._scope = scope;
style._styleProperties = bag;
style._styles = styles;
},
_keyName: '_cacheKey',

store: function(is, style, scope, bag, styles) {
this._prepare(style, scope, bag, styles);
store: function(is, style, keyProperties, keyStyles) {
style[this._keyName] = {
properties: keyProperties,
styles: keyStyles
}
var s$ = this.cache[is] = this.cache[is] || [];
s$.push(style);
if (s$.length > this.MAX) {
s$.shift();
}
},

retrieve: function(is, properties, styles) {
retrieve: function(is, keyProperties, keyStyles) {
var cache = this.cache[is];
if (cache) {
for (var i=0, s; i < cache.length; i++) {
// look through cache backwards as most recent push is last.
for (var i=cache.length-1, s; i >= 0; i--) {
s = cache[i];
if (this._objectsEqual(properties, s._styleProperties) &&
this._objectsEqual(styles, s._styles)) {
key = s[this._keyName];
if (this._objectsEqual(keyProperties, key.properties) &&
keyStyles === key.styles) {
return s;
}
}
}
},

// TODO(sorvell): intentionally a weak check here, good enough?
clear: function() {
for (var i in this.cache) {
for (var j=0; j< this.cache[i].length; j++) {
this.cache[i][j][this._keyName] = null;
}
}
this.cache = {};

This comment has been minimized.

Copy link
@kevinpschaaf

kevinpschaaf May 18, 2015

Member

no need to clear keys from entries?

},

// note, intentionally a simple check here, should be good enough
_objectsEqual: function(target, source) {
for (var i in target) {
if (target[i] !== source[i]) {
Expand Down
17 changes: 11 additions & 6 deletions src/lib/style-defaults.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,32 @@
this._properties = null;
},

// NOTE: this object can be used as a styling scope so it has an api
// similar to that of an element wrt style properties
get _styleProperties() {
if (!this._properties) {
// force rules to reparse since they may be out of date
this.style.__cssRules =
styleUtil.parser.parse(this.style.textContent);
styleProperties.decorateRules(this.style.__cssRules);
styleUtil.clearStyleRules(this.style);
styleProperties.decorateStyles(this._styles);
// NOTE: reset cache for own properties; it may have been set when
// an element in an import applied styles (e.g. custom-style)
this._styles._ownStyleProperties = null;
this._styles._rootStyleProperties = null;
this._properties = styleProperties
.rootPropertiesFromStyles(this._styles);
}
return this._properties;
},

_needsStyleProperties: function() {},

_computeStyleProperties: function() {
return this._styleProperties;
}

};

api._styles = [api.style];

api.applyCss('');

// exports
return api;

Expand Down
2 changes: 2 additions & 0 deletions src/lib/style-extends.html
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@
}
target.extends = target.extends || (target.extends = []);
target.extends.push(source);
// TODO: this misses `%foo, .bar` as an unetended selector but
// this seems rare and could possibly be unsupported.
source.selector = source.selector.replace(this.rx.STRIP, '');
source.selector = (source.selector && source.selector + ',\n') +
target.selector;
Expand Down
50 changes: 31 additions & 19 deletions src/lib/style-properties.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@

return {

// decorate rules with property info: whether it produces or consumes them
decorateRules: function(rules) {
if (rules.propertyInfo) {
return;
}
var info = {};
var self = this;
styleUtil.forEachStyleRule(rules, function(rule) {
var p = self.decorateRule(rule);
// TODO(sorvell): mix?
info.cssText = info.cssText || p.cssText;
info.properties = info.properties || p.properties;
// decorates styles with rule info and returns an array of used style
// property names
decorateStyles: function(styles) {
var self = this, props = {};
styleUtil.forRulesInStyles(styles, function(rule) {
self.decorateRule(rule);
self.collectPropertiesInCssText(rule.propertyInfo.cssText, props);
});
rules.propertyInfo = info;
// return this list of property names *consumes* in these styles.
var names = [];
for (var i in props) {
names.push(i);
}
return names;
},

// decorate a single rule with property info
Expand Down Expand Up @@ -93,10 +93,21 @@
return customCssText;
},

collectPropertiesInCssText: function(cssText, props) {
var m;
while (m = this.rx.VAR_CAPTURE.exec(cssText)) {
props[m[1]] = true;
}
},

// turns custom properties into realized values.
reify: function(props) {
for (var i in props) {
props[i] = this.valueForProperty(props[i], props);
// big perf optimization here: reify only *own* properties
// since this object has __proto__ of the element's scope properties
var names = Object.getOwnPropertyNames(props);
for (var i=0, n; i < names.length; i++) {
n = names[i];
props[n] = this.valueForProperty(props[n], props);
}
},

Expand Down Expand Up @@ -124,7 +135,7 @@
property = property.replace(this.rx.VAR_MATCH, fn);
}
}
return property && property.trim();
return property && property.trim() || '';
},

// note: we do not yet support mixin within mixin
Expand Down Expand Up @@ -183,7 +194,7 @@
// these rules may already be shimmed and it's $ to reparse,
// so we check `is` value as a fallback
rootPropertiesFromStyles: function(styles) {
if (!styles._ownStyleProperties) {
if (!styles._rootStyleProperties) {
var props = {}, self = this;
styleUtil.forRulesInStyles(styles, function(rule) {
if (!rule.propertyInfo) {
Expand All @@ -194,9 +205,9 @@
self.collectProperties(rule, props);
}
});
styles._ownStyleProperties = props;
styles._rootStyleProperties = props;
}
return styles._ownStyleProperties;
return styles._rootStyleProperties;
},

transformStyles: function(element, properties, scopeSelector) {
Expand Down Expand Up @@ -284,6 +295,7 @@
VAR_ASSIGN: /(?:^|;\s*)(--[^\:;]*?):\s*?(?:([^;{]*?)|{([^}]*)})(?=;)/gim,
MIXIN_MATCH: /(?:^|\W+)@apply[\s]*\(([^)]*)\);?/im,
VAR_MATCH: /(^|\W+)var\([\s]*([^,)]*)[\s]*,?[\s]*([^,)]*)[\s]*?\)/gim,
VAR_CAPTURE: /\([\s]*(--[^,\s)]*)(?:,[\s]*(--[^,\s)]*))?(?:\)|,)/gim,
BRACKETED: /\{[^}]*\}/g,
HOST_PREFIX: '(?:^|[^.])',
HOST_SUFFIX: '($|[.:[\\s>+~])'
Expand Down
4 changes: 4 additions & 0 deletions src/lib/style-util.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
return style.__cssRules;
},

clearStyleRules: function(style) {
style.__cssRules = null;
},

forEachStyleRule: function(node, callback) {
var s = node.selector;
var skipRules = false;
Expand Down
Loading

0 comments on commit 8bab868

Please sign in to comment.