## Description Added caching of theme property value since it is a frequent expression, it constitutes 20% of all binding expressions for a large customer app. Expecting a 400ms reduction in LCP for a large customer app. Fixes #`Issue Number` _or_ Fixes `Issue URL` > [!WARNING] > _If no issue exists, please create an issue first, and check with the maintainers if the issue is valid._ ## Automation /ok-to-test tags="@tag.All" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/15880337835> > Commit: 11fab20fe285aa1b3b59c164179902628d35d97d > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=15880337835&attempt=2" target="_blank">Cypress dashboard</a>. > Tags: `@tag.All` > Spec: > <hr>Wed, 25 Jun 2025 17:45:37 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit - **New Features** - Improved performance when evaluating theme-related properties by introducing caching for repeated values. - **Chores** - Added a utility to identify specific theme-related unevaluated values. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
98 lines
2.9 KiB
TypeScript
98 lines
2.9 KiB
TypeScript
import type {
|
|
PropertyOverrideDependency,
|
|
OverridingPropertyPaths,
|
|
WidgetEntity,
|
|
ActionEntity,
|
|
JSActionEntity,
|
|
} from "ee/entities/DataTree/types";
|
|
import type { DataTreeEntity } from "entities/DataTree/dataTreeTypes";
|
|
import { OverridingPropertyType } from "ee/entities/DataTree/types";
|
|
import {
|
|
isAction,
|
|
isJSAction,
|
|
isWidget,
|
|
} from "ee/workers/Evaluation/evaluationUtils";
|
|
import type { Module } from "ee/constants/ModuleConstants";
|
|
interface SetOverridingPropertyParams {
|
|
key: string;
|
|
value: string;
|
|
propertyOverrideDependency: PropertyOverrideDependency;
|
|
overridingPropertyPaths: OverridingPropertyPaths;
|
|
type: OverridingPropertyType;
|
|
}
|
|
|
|
export const setOverridingProperty = ({
|
|
key: propertyName,
|
|
overridingPropertyPaths,
|
|
propertyOverrideDependency,
|
|
type,
|
|
value: overridingPropertyKey,
|
|
}: SetOverridingPropertyParams) => {
|
|
if (!(propertyName in propertyOverrideDependency)) {
|
|
propertyOverrideDependency[propertyName] = {
|
|
[OverridingPropertyType.DEFAULT]: undefined,
|
|
[OverridingPropertyType.META]: undefined,
|
|
};
|
|
}
|
|
|
|
switch (type) {
|
|
case OverridingPropertyType.DEFAULT:
|
|
propertyOverrideDependency[propertyName][OverridingPropertyType.DEFAULT] =
|
|
overridingPropertyKey;
|
|
break;
|
|
|
|
case OverridingPropertyType.META:
|
|
propertyOverrideDependency[propertyName][OverridingPropertyType.META] =
|
|
overridingPropertyKey;
|
|
|
|
break;
|
|
default:
|
|
}
|
|
|
|
if (Array.isArray(overridingPropertyPaths[overridingPropertyKey])) {
|
|
const updatedOverridingProperty = new Set(
|
|
overridingPropertyPaths[overridingPropertyKey],
|
|
);
|
|
|
|
overridingPropertyPaths[overridingPropertyKey] = [
|
|
...updatedOverridingProperty.add(propertyName),
|
|
];
|
|
} else {
|
|
overridingPropertyPaths[overridingPropertyKey] = [propertyName];
|
|
}
|
|
|
|
// if property dependent on metaProperty also has defaultProperty then defaultProperty will also override metaProperty on eval.
|
|
const defaultPropertyName = propertyOverrideDependency[propertyName].DEFAULT;
|
|
|
|
if (type === OverridingPropertyType.META && defaultPropertyName) {
|
|
overridingPropertyPaths[defaultPropertyName].push(overridingPropertyKey);
|
|
}
|
|
};
|
|
|
|
export const generateDataTreeModuleInputs = (
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
moduleInputs: Module["inputsForm"],
|
|
) => {
|
|
return {
|
|
unEvalEntity: null,
|
|
configEntity: null,
|
|
};
|
|
};
|
|
|
|
export function isWidgetActionOrJsObject(
|
|
entity: DataTreeEntity,
|
|
): entity is ActionEntity | WidgetEntity | JSActionEntity {
|
|
return isWidget(entity) || isAction(entity) || isJSAction(entity);
|
|
}
|
|
|
|
const THEME_PROPERTIES = new Set([
|
|
"{{appsmith.theme.fontFamily.appFont}}",
|
|
"{{appsmith.theme.boxShadow.appBoxShadow}}",
|
|
"{{appsmith.theme.colors.primaryColor}}",
|
|
"{{appsmith.theme.borderRadius.appBorderRadius}}",
|
|
]);
|
|
|
|
export function isThemeUnevaluatedValue(value: string): boolean {
|
|
return THEME_PROPERTIES.has(value);
|
|
}
|