faster style-scope setPropertyValues

No need for so many for loops
This commit is contained in:
Martin Guillon
2020-12-02 16:57:25 +01:00
parent aa2ba2c374
commit 9a8e7c45ab
2 changed files with 26 additions and 39 deletions

View File

@ -669,7 +669,7 @@ interface ChangeAccumulator {
export class SelectorsMatch<T extends Node> implements ChangeAccumulator { export class SelectorsMatch<T extends Node> implements ChangeAccumulator {
public changeMap: ChangeMap<T> = new Map<T, Changes>(); public changeMap: ChangeMap<T> = new Map<T, Changes>();
public selectors; public selectors: SelectorCore[];
public addAttribute(node: T, attribute: string): void { public addAttribute(node: T, attribute: string): void {
const deps: Changes = this.properties(node); const deps: Changes = this.properties(node);

View File

@ -399,7 +399,7 @@ export class CssState {
_onDynamicStateChangeHandler: () => void; _onDynamicStateChangeHandler: () => void;
_appliedChangeMap: Readonly<ChangeMap<ViewBase>>; _appliedChangeMap: Readonly<ChangeMap<ViewBase>>;
_appliedPropertyValues: Readonly<Record<string, unknown>>; _appliedPropertyValues: Record<string, unknown>;
_appliedAnimations: ReadonlyArray<kam.KeyframeAnimation>; _appliedAnimations: ReadonlyArray<kam.KeyframeAnimation>;
_appliedSelectorsVersion: number; _appliedSelectorsVersion: number;
@ -553,60 +553,47 @@ export class CssState {
const newPropertyValues = new view.style.PropertyBag(); const newPropertyValues = new view.style.PropertyBag();
matchingSelectors.forEach((selector) => selector.ruleset.declarations.forEach((declaration) => (newPropertyValues[declaration.property] = declaration.value))); matchingSelectors.forEach((selector) => selector.ruleset.declarations.forEach((declaration) => (newPropertyValues[declaration.property] = declaration.value)));
const oldProperties = this._appliedPropertyValues; const oldProperties = this._appliedPropertyValues || {};
let isCssExpressionInUse = false;
// Update values for the scope's css-variables // Update values for the scope's css-variables
view.style.resetScopedCssVariables(); view.style.resetScopedCssVariables();
const valuesToApply = {};
for (const property in newPropertyValues) { for (const property in newPropertyValues) {
const value = newPropertyValues[property]; let value = newPropertyValues[property];
if (property in oldProperties && oldProperties[property] === value) {
// Skip unchanged values
delete oldProperties[property]
continue;
}
if (isCssVariable(property)) { if (isCssVariable(property)) {
view.style.setScopedCssVariable(property, value); view.style.setScopedCssVariable(property, value);
delete oldProperties[property]
delete newPropertyValues[property]; delete newPropertyValues[property];
continue; continue;
} }
if (isCssVariableExpression(value) || isCssCalcExpression(value)) {
isCssExpressionInUse = isCssExpressionInUse || isCssVariableExpression(value) || isCssCalcExpression(value); value = evaluateCssExpressions(view, property, newPropertyValues[property]);
}
if (isCssExpressionInUse) {
// Evalute css-expressions to get the latest values.
for (const property in newPropertyValues) {
const value = evaluateCssExpressions(view, property, newPropertyValues[property]);
if (value === unsetValue) {
delete newPropertyValues[property];
continue;
}
newPropertyValues[property] = value;
} }
if (value === unsetValue) {
delete newPropertyValues[property];
continue;
}
valuesToApply[property] = value;
} }
// Property values are fully updated, freeze the object to be used for next update.
Object.freeze(newPropertyValues);
// Unset removed values // Unset removed values
for (const property in oldProperties) { for (const property in oldProperties) {
if (!(property in newPropertyValues)) { if (property in view.style) {
if (property in view.style) { view.style[`css:${property}`] = unsetValue;
view.style[`css:${property}`] = unsetValue; }
} else { else {
// TRICKY: How do we unset local value? // TRICKY: How do we unset local value?
}
} }
} }
// Set new values to the style // Set new values to the style
for (const property in newPropertyValues) { for (const property in valuesToApply) {
if (oldProperties && property in oldProperties && oldProperties[property] === newPropertyValues[property]) { const value = valuesToApply[property];
// Skip unchanged values
continue;
}
const value = newPropertyValues[property];
try { try {
if (property in view.style) { if (property in view.style) {
view.style[`css:${property}`] = value; view.style[`css:${property}`] = value;