## Description These changes add evalTreeWithDiff to evalWorkerAction. Using this method it will be possible to send the unevalTree and configTree updates from mainThread to trigger evaluation. - This will skip diffing complete unEvaltree ### Next steps after this PR - [ ] Rename EvalTreeWithChanges to evalTreeWithDiff - [ ] Generate Diff instead of updatedValuePaths for the current evalTreeWithChanges references. - [ ] Handle evalTreeWithDiff for - [ ] JSObject updates - [ ] updateDependencyMap Fixes # ## Automation /test js ### 🔍 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/9684706533> > Commit: 3de988af5da9900f4e589a008d28296d05d17f25 > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=9684706533&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.JS` <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [x] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Enhanced widget evaluation logic and improved handling of dynamic bindings and dependencies. - **Bug Fixes** - Corrected type handling in various evaluation functions to improve stability and accuracy. - **Tests** - Updated test cases for widget property setters to include additional tags for better categorization. - **Refactor** - Streamlined function signatures and improved type safety across evaluation utilities. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
175 lines
5.1 KiB
TypeScript
175 lines
5.1 KiB
TypeScript
import { dataTreeEvaluator } from "./handlers/evalTree";
|
|
import type { EvalMetaUpdates } from "@appsmith/workers/common/DataTreeEvaluator/types";
|
|
import { makeEntityConfigsAsObjProperties } from "@appsmith/workers/Evaluation/dataTreeUtils";
|
|
import type {
|
|
EvalTreeResponseData,
|
|
EvalWorkerSyncRequest,
|
|
UpdateTreeResponse,
|
|
} from "./types";
|
|
import { MessageType, sendMessage } from "utils/MessageUtil";
|
|
import { MAIN_THREAD_ACTION } from "@appsmith/workers/Evaluation/evalWorkerActions";
|
|
import type { UpdateDataTreeMessageData } from "sagas/EvalWorkerActionSagas";
|
|
import {
|
|
generateOptimisedUpdatesAndSetPrevState,
|
|
getNewDataTreeUpdates,
|
|
uniqueOrderUpdatePaths,
|
|
} from "./helpers";
|
|
import type { DataTreeDiff } from "@appsmith/workers/Evaluation/evaluationUtils";
|
|
import type DataTreeEvaluator from "workers/common/DataTreeEvaluator";
|
|
|
|
const getDefaultEvalResponse = (): EvalTreeResponseData => ({
|
|
updates: "[]",
|
|
dependencies: {},
|
|
errors: [],
|
|
evalMetaUpdates: [],
|
|
evaluationOrder: [],
|
|
jsUpdates: {},
|
|
logs: [],
|
|
unEvalUpdates: [],
|
|
isCreateFirstTree: false,
|
|
staleMetaIds: [],
|
|
removedPaths: [],
|
|
isNewWidgetAdded: false,
|
|
undefinedEvalValuesMap: {},
|
|
jsVarsCreatedEvent: [],
|
|
});
|
|
|
|
export function evalTreeWithChanges(
|
|
request: EvalWorkerSyncRequest<{
|
|
metaUpdates?: EvalMetaUpdates;
|
|
updatedValuePaths: string[][];
|
|
}>,
|
|
) {
|
|
const { data } = request;
|
|
const { metaUpdates = [], updatedValuePaths } = data;
|
|
|
|
const pathsToSkipFromEval = updatedValuePaths.map((path) => path.join("."));
|
|
|
|
let setupUpdateTreeResponse = {} as UpdateTreeResponse;
|
|
if (dataTreeEvaluator) {
|
|
setupUpdateTreeResponse = dataTreeEvaluator.setupUpdateTreeWithDifferences(
|
|
updatedValuePaths,
|
|
pathsToSkipFromEval,
|
|
);
|
|
}
|
|
|
|
evaluateAndPushResponse(
|
|
dataTreeEvaluator,
|
|
setupUpdateTreeResponse,
|
|
metaUpdates,
|
|
pathsToSkipFromEval,
|
|
);
|
|
}
|
|
|
|
export const getAffectedNodesInTheDataTree = (
|
|
unEvalUpdates: DataTreeDiff[],
|
|
evalOrder: string[],
|
|
) => {
|
|
const allUnevalUpdates = unEvalUpdates.map(
|
|
(update) => update.payload.propertyPath,
|
|
);
|
|
// merge unevalUpdate paths and evalOrder paths
|
|
return uniqueOrderUpdatePaths([...allUnevalUpdates, ...evalOrder]);
|
|
};
|
|
|
|
export const evaluateAndPushResponse = (
|
|
dataTreeEvaluator: DataTreeEvaluator | undefined,
|
|
setupUpdateTreeResponse: UpdateTreeResponse,
|
|
metaUpdates: EvalMetaUpdates,
|
|
additionalPathsAddedAsUpdates: string[],
|
|
) => {
|
|
const response = evaluateAndGenerateResponse(
|
|
dataTreeEvaluator,
|
|
setupUpdateTreeResponse,
|
|
metaUpdates,
|
|
additionalPathsAddedAsUpdates,
|
|
);
|
|
return pushResponseToMainThread(response);
|
|
};
|
|
|
|
export const evaluateAndGenerateResponse = (
|
|
dataTreeEvaluator: DataTreeEvaluator | undefined,
|
|
setupUpdateTreeResponse: UpdateTreeResponse,
|
|
metaUpdates: EvalMetaUpdates,
|
|
additionalPathsAddedAsUpdates: string[],
|
|
): UpdateDataTreeMessageData => {
|
|
// generate default response first and later add updates to it
|
|
const defaultResponse = getDefaultEvalResponse();
|
|
|
|
if (!dataTreeEvaluator) {
|
|
const updates = generateOptimisedUpdatesAndSetPrevState(
|
|
{},
|
|
dataTreeEvaluator,
|
|
[],
|
|
);
|
|
defaultResponse.updates = updates;
|
|
defaultResponse.evalMetaUpdates = [...(metaUpdates || [])];
|
|
return {
|
|
workerResponse: defaultResponse,
|
|
unevalTree: {},
|
|
};
|
|
}
|
|
|
|
const { evalOrder, jsUpdates, unEvalUpdates } = setupUpdateTreeResponse;
|
|
defaultResponse.evaluationOrder = evalOrder;
|
|
defaultResponse.unEvalUpdates = unEvalUpdates;
|
|
defaultResponse.jsUpdates = jsUpdates;
|
|
|
|
const updateResponse = dataTreeEvaluator.evalAndValidateSubTree(
|
|
evalOrder,
|
|
dataTreeEvaluator.oldConfigTree,
|
|
unEvalUpdates,
|
|
);
|
|
|
|
const dataTree = makeEntityConfigsAsObjProperties(
|
|
dataTreeEvaluator.evalTree,
|
|
{
|
|
evalProps: dataTreeEvaluator.evalProps,
|
|
},
|
|
);
|
|
|
|
/** Make sure evalMetaUpdates is sanitized to prevent postMessage failure */
|
|
defaultResponse.evalMetaUpdates = JSON.parse(
|
|
JSON.stringify([...(metaUpdates || []), ...updateResponse.evalMetaUpdates]),
|
|
);
|
|
|
|
defaultResponse.staleMetaIds = updateResponse.staleMetaIds;
|
|
const unevalTree = dataTreeEvaluator.getOldUnevalTree();
|
|
|
|
// when additional paths are required to be added as updates, we extract the updates from the data tree using these paths.
|
|
const additionalUpdates = getNewDataTreeUpdates(
|
|
additionalPathsAddedAsUpdates,
|
|
dataTree,
|
|
);
|
|
// the affected paths is a combination of the eval order and the uneval updates
|
|
// we use this collection to limit the diff between the old and new data tree
|
|
const affectedNodePaths = getAffectedNodesInTheDataTree(
|
|
unEvalUpdates,
|
|
evalOrder,
|
|
);
|
|
|
|
defaultResponse.updates = generateOptimisedUpdatesAndSetPrevState(
|
|
dataTree,
|
|
dataTreeEvaluator,
|
|
affectedNodePaths,
|
|
additionalUpdates,
|
|
);
|
|
dataTreeEvaluator.undefinedEvalValuesMap =
|
|
dataTreeEvaluator.undefinedEvalValuesMap || {};
|
|
|
|
return {
|
|
workerResponse: defaultResponse,
|
|
unevalTree,
|
|
};
|
|
};
|
|
|
|
export const pushResponseToMainThread = (data: UpdateDataTreeMessageData) => {
|
|
sendMessage.call(self, {
|
|
messageType: MessageType.DEFAULT,
|
|
body: {
|
|
data,
|
|
method: MAIN_THREAD_ACTION.UPDATE_DATATREE,
|
|
},
|
|
});
|
|
};
|