mirror of
				https://github.com/NativeScript/NativeScript.git
				synced 2025-11-04 04:18:52 +08:00 
			
		
		
		
	perf: property optimizations (#10850)
This commit is contained in:
		@ -12,9 +12,16 @@ import { calc } from '@csstools/css-calc';
 | 
			
		||||
export { unsetValue } from './property-shared';
 | 
			
		||||
 | 
			
		||||
const cssPropertyNames: string[] = [];
 | 
			
		||||
const HAS_OWN = Object.prototype.hasOwnProperty;
 | 
			
		||||
const symbolPropertyMap = {};
 | 
			
		||||
const cssSymbolPropertyMap = {};
 | 
			
		||||
 | 
			
		||||
// Hoisted regex/constants for hot paths to avoid re-allocation
 | 
			
		||||
const CSS_VARIABLE_NAME_RE = /^--[^,\s]+?$/;
 | 
			
		||||
const DIP_RE = /([0-9]+(\.[0-9]+)?)dip\b/g;
 | 
			
		||||
const UNSET_RE = /unset/g;
 | 
			
		||||
const INFINITY_RE = /infinity/g;
 | 
			
		||||
 | 
			
		||||
const inheritableProperties = new Array<InheritedProperty<any, any>>();
 | 
			
		||||
const inheritableCssProperties = new Array<InheritedCssProperty<any, any>>();
 | 
			
		||||
 | 
			
		||||
@ -50,7 +57,7 @@ export function _getStyleProperties(): CssProperty<any, any>[] {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isCssVariable(property: string) {
 | 
			
		||||
	return /^--[^,\s]+?$/.test(property);
 | 
			
		||||
	return CSS_VARIABLE_NAME_RE.test(property);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isCssCalcExpression(value: string) {
 | 
			
		||||
@ -119,27 +126,31 @@ export function _evaluateCssCalcExpression(value: string) {
 | 
			
		||||
	} else {
 | 
			
		||||
		return value;
 | 
			
		||||
	}
 | 
			
		||||
	return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function _replaceDip(value: string) {
 | 
			
		||||
	return value.replace(/([0-9]+(\.[0-9]+)?)dip\b/g, '$1');
 | 
			
		||||
	return value.replace(DIP_RE, '$1');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function _replaceKeywordsWithValues(value: string) {
 | 
			
		||||
	let cssValue = value;
 | 
			
		||||
	if (cssValue.includes('unset')) {
 | 
			
		||||
		cssValue = cssValue.replace(/unset/g, '0');
 | 
			
		||||
		cssValue = cssValue.replace(UNSET_RE, '0');
 | 
			
		||||
	}
 | 
			
		||||
	if (cssValue.includes('infinity')) {
 | 
			
		||||
		cssValue = cssValue.replace(/infinity/g, '999999');
 | 
			
		||||
		cssValue = cssValue.replace(INFINITY_RE, '999999');
 | 
			
		||||
	}
 | 
			
		||||
	return cssValue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getPropertiesFromMap(map): Property<any, any>[] | CssProperty<any, any>[] {
 | 
			
		||||
	const props = [];
 | 
			
		||||
	Object.getOwnPropertySymbols(map).forEach((symbol) => props.push(map[symbol]));
 | 
			
		||||
 | 
			
		||||
	const symbols = Object.getOwnPropertySymbols(map);
 | 
			
		||||
	const len = symbols.length;
 | 
			
		||||
	const props = new Array(len);
 | 
			
		||||
	for (let i = 0; i < len; i++) {
 | 
			
		||||
		props[i] = map[symbols[i]];
 | 
			
		||||
	}
 | 
			
		||||
	return props;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -240,15 +251,13 @@ export class Property<T extends ViewBase, U> implements TypedPropertyDescriptor<
 | 
			
		||||
							if (this._suspendedUpdates) {
 | 
			
		||||
								this._suspendedUpdates[propertyName] = property;
 | 
			
		||||
							}
 | 
			
		||||
						} else {
 | 
			
		||||
							if (defaultValueKey in this) {
 | 
			
		||||
						} else if (defaultValueKey in this) {
 | 
			
		||||
							this[setNative](this[defaultValueKey]);
 | 
			
		||||
							delete this[defaultValueKey];
 | 
			
		||||
						} else {
 | 
			
		||||
							this[setNative](defaultValue);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					this[key] = value;
 | 
			
		||||
					if (valueChanged) {
 | 
			
		||||
@ -424,15 +433,13 @@ export class CoercibleProperty<T extends ViewBase, U> extends Property<T, U> imp
 | 
			
		||||
							if (this._suspendedUpdates) {
 | 
			
		||||
								this._suspendedUpdates[propertyName] = property;
 | 
			
		||||
							}
 | 
			
		||||
						} else {
 | 
			
		||||
							if (defaultValueKey in this) {
 | 
			
		||||
						} else if (defaultValueKey in this) {
 | 
			
		||||
							this[setNative](this[defaultValueKey]);
 | 
			
		||||
							delete this[defaultValueKey];
 | 
			
		||||
						} else {
 | 
			
		||||
							this[setNative](defaultValue);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					this[key] = value;
 | 
			
		||||
					if (valueChanged) {
 | 
			
		||||
@ -577,7 +584,10 @@ export class CssProperty<T extends Style, U> {
 | 
			
		||||
		const propertyName = options.name;
 | 
			
		||||
		this.name = propertyName;
 | 
			
		||||
 | 
			
		||||
		// Guard against undefined cssName
 | 
			
		||||
		if (options.cssName) {
 | 
			
		||||
			cssPropertyNames.push(options.cssName);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		this.cssName = `css:${options.cssName}`;
 | 
			
		||||
		this.cssLocalName = options.cssName;
 | 
			
		||||
@ -657,15 +667,13 @@ export class CssProperty<T extends Style, U> {
 | 
			
		||||
							if (view._suspendedUpdates) {
 | 
			
		||||
								view._suspendedUpdates[propertyName] = property;
 | 
			
		||||
							}
 | 
			
		||||
						} else {
 | 
			
		||||
							if (defaultValueKey in this) {
 | 
			
		||||
						} else if (defaultValueKey in this) {
 | 
			
		||||
							view[setNative](this[defaultValueKey]);
 | 
			
		||||
							delete this[defaultValueKey];
 | 
			
		||||
						} else {
 | 
			
		||||
							view[setNative](defaultValue);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					this[key] = value;
 | 
			
		||||
					if (valueChanged) {
 | 
			
		||||
@ -743,15 +751,13 @@ export class CssProperty<T extends Style, U> {
 | 
			
		||||
							if (view._suspendedUpdates) {
 | 
			
		||||
								view._suspendedUpdates[propertyName] = property;
 | 
			
		||||
							}
 | 
			
		||||
						} else {
 | 
			
		||||
							if (defaultValueKey in this) {
 | 
			
		||||
						} else if (defaultValueKey in this) {
 | 
			
		||||
							view[setNative](this[defaultValueKey]);
 | 
			
		||||
							delete this[defaultValueKey];
 | 
			
		||||
						} else {
 | 
			
		||||
							view[setNative](defaultValue);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					this[key] = value;
 | 
			
		||||
					if (valueChanged) {
 | 
			
		||||
@ -856,7 +862,9 @@ export class CssAnimationProperty<T extends Style, U> implements CssAnimationPro
 | 
			
		||||
		const propertyName = options.name;
 | 
			
		||||
		this.name = propertyName;
 | 
			
		||||
 | 
			
		||||
		if (options.cssName) {
 | 
			
		||||
			cssPropertyNames.push(options.cssName);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		CssAnimationProperty.properties[propertyName] = this;
 | 
			
		||||
		if (options.cssName && options.cssName !== propertyName) {
 | 
			
		||||
@ -1143,8 +1151,7 @@ export class InheritedCssProperty<T extends Style, U> extends CssProperty<T, U>
 | 
			
		||||
							if (view._suspendedUpdates) {
 | 
			
		||||
								view._suspendedUpdates[propertyName] = property;
 | 
			
		||||
							}
 | 
			
		||||
						} else {
 | 
			
		||||
							if (unsetNativeValue) {
 | 
			
		||||
						} else if (unsetNativeValue) {
 | 
			
		||||
							if (defaultValueKey in this) {
 | 
			
		||||
								view[setNative](this[defaultValueKey]);
 | 
			
		||||
								delete this[defaultValueKey];
 | 
			
		||||
@ -1159,7 +1166,6 @@ export class InheritedCssProperty<T extends Style, U> extends CssProperty<T, U>
 | 
			
		||||
							view[setNative](value);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if (this.hasListeners(eventName)) {
 | 
			
		||||
						this.notify<PropertyChangeData>({
 | 
			
		||||
@ -1356,6 +1362,7 @@ export function applyPendingNativeSetters(view: ViewBase): void {
 | 
			
		||||
	// TODO: Check what happens if a view was suspended and its value was reset, or set back to default!
 | 
			
		||||
	const suspendedUpdates = view._suspendedUpdates;
 | 
			
		||||
	for (const propertyName in suspendedUpdates) {
 | 
			
		||||
		if (!HAS_OWN.call(suspendedUpdates, propertyName)) continue;
 | 
			
		||||
		const property = <PropertyInterface>suspendedUpdates[propertyName];
 | 
			
		||||
		const setNative = property.setNative;
 | 
			
		||||
		if (view[setNative]) {
 | 
			
		||||
@ -1523,9 +1530,11 @@ export function propagateInheritableCssProperties(parentStyle: Style, childStyle
 | 
			
		||||
export function getSetProperties(view: ViewBase): [string, any][] {
 | 
			
		||||
	const result = [];
 | 
			
		||||
 | 
			
		||||
	Object.getOwnPropertyNames(view).forEach((prop) => {
 | 
			
		||||
	const ownProps = Object.getOwnPropertyNames(view);
 | 
			
		||||
	for (let i = 0; i < ownProps.length; i++) {
 | 
			
		||||
		const prop = ownProps[i];
 | 
			
		||||
		result.push([prop, view[prop]]);
 | 
			
		||||
	});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const symbols = Object.getOwnPropertySymbols(view);
 | 
			
		||||
	for (const symbol of symbols) {
 | 
			
		||||
@ -1545,8 +1554,10 @@ export function getComputedCssValues(view: ViewBase): [string, any][] {
 | 
			
		||||
	const result = [];
 | 
			
		||||
	const style = view.style;
 | 
			
		||||
	for (const prop of cssPropertyNames) {
 | 
			
		||||
		if (prop !== undefined && prop !== null) {
 | 
			
		||||
			result.push([prop, style[prop]]);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Add these to enable box model in chrome-devtools styles tab
 | 
			
		||||
	result.push(['top', 'auto']);
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user