fix: Parse js actions for view mode changes (#18357)
* added new function inside parse js actions for view moe * fixing test cases * added evaluateSync with isTriggered false * Add types Add switch case for diff.event Add function get back app mode * Change foreach loops to for of * Dont return jsUpdates from view mode save resolved since no operation is happening Change viewModeSaveResolvedFunctionsAndJSUpdates -> viewModeSaveResolvedFunctions to reflect what it's functionality is * Refactor JSObject code * Refactor code for JSobject * remove any * export parsed object's type from ast * create function for deleteResolvedFunctionsAndCurrentJSCollectionState * Code review changes * Fix tests * Change returns in for of loops to continue Remove try for evaluate sync Js updates return * Fix bug * Fix bug Co-authored-by: Rimil Dey <rimil@appsmith.com> Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
This commit is contained in:
parent
77a225f4dd
commit
efa8b68a47
|
|
@ -139,7 +139,6 @@ describe("generateDataTreeJSAction", () => {
|
||||||
ENTITY_TYPE: "JSACTION",
|
ENTITY_TYPE: "JSACTION",
|
||||||
body:
|
body:
|
||||||
"export default {\n\tmyVar1: [],\n\tmyVar2: {},\n\tmyFun1: () => {\n\t\t//write code here\n\t},\n\tmyFun2: async () => {\n\t\t//use async-await or promises\n\t}\n}",
|
"export default {\n\tmyVar1: [],\n\tmyVar2: {},\n\tmyFun1: () => {\n\t\t//write code here\n\t},\n\tmyFun2: async () => {\n\t\t//use async-await or promises\n\t}\n}",
|
||||||
|
|
||||||
myFun2: {
|
myFun2: {
|
||||||
data: {
|
data: {
|
||||||
users: [{ id: 1, name: "John" }],
|
users: [{ id: 1, name: "John" }],
|
||||||
|
|
@ -159,11 +158,13 @@ describe("generateDataTreeJSAction", () => {
|
||||||
arguments: [],
|
arguments: [],
|
||||||
isAsync: true,
|
isAsync: true,
|
||||||
confirmBeforeExecute: false,
|
confirmBeforeExecute: false,
|
||||||
|
body: "async () => {\n\t\t//use async-await or promises\n\t}",
|
||||||
},
|
},
|
||||||
myFun1: {
|
myFun1: {
|
||||||
arguments: [],
|
arguments: [],
|
||||||
isAsync: false,
|
isAsync: false,
|
||||||
confirmBeforeExecute: false,
|
confirmBeforeExecute: false,
|
||||||
|
body: "() => {\n\t\t//write code here\n\t}",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
bindingPaths: {
|
bindingPaths: {
|
||||||
|
|
@ -350,11 +351,13 @@ describe("generateDataTreeJSAction", () => {
|
||||||
arguments: [],
|
arguments: [],
|
||||||
isAsync: true,
|
isAsync: true,
|
||||||
confirmBeforeExecute: false,
|
confirmBeforeExecute: false,
|
||||||
|
body: "async () => {\n\t\t//use async-await or promises\n\t}",
|
||||||
},
|
},
|
||||||
myFun1: {
|
myFun1: {
|
||||||
arguments: [],
|
arguments: [],
|
||||||
isAsync: false,
|
isAsync: false,
|
||||||
confirmBeforeExecute: false,
|
confirmBeforeExecute: false,
|
||||||
|
body: "() => {\n\t\t//write code here\n\t}",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
bindingPaths: {
|
bindingPaths: {
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ export const generateDataTreeJSAction = (
|
||||||
arguments: action.actionConfiguration.jsArguments,
|
arguments: action.actionConfiguration.jsArguments,
|
||||||
isAsync: action.actionConfiguration.isAsync,
|
isAsync: action.actionConfiguration.isAsync,
|
||||||
confirmBeforeExecute: !!action.confirmBeforeExecute,
|
confirmBeforeExecute: !!action.confirmBeforeExecute,
|
||||||
|
body: action.actionConfiguration.body,
|
||||||
};
|
};
|
||||||
bindingPaths[action.name] = EvaluationSubstitutionType.SMART_SUBSTITUTE;
|
bindingPaths[action.name] = EvaluationSubstitutionType.SMART_SUBSTITUTE;
|
||||||
dynamicBindingPathList.push({ key: action.name });
|
dynamicBindingPathList.push({ key: action.name });
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ export interface MetaArgs {
|
||||||
arguments: Variable[];
|
arguments: Variable[];
|
||||||
isAsync: boolean;
|
isAsync: boolean;
|
||||||
confirmBeforeExecute: boolean;
|
confirmBeforeExecute: boolean;
|
||||||
|
body: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface JSActionEntityConfig {
|
export interface JSActionEntityConfig {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { DataTree, DataTreeJSAction } from "entities/DataTree/dataTreeFactory";
|
||||||
import { isEmpty, set } from "lodash";
|
import { isEmpty, set } from "lodash";
|
||||||
import { EvalErrorTypes } from "utils/DynamicBindingUtils";
|
import { EvalErrorTypes } from "utils/DynamicBindingUtils";
|
||||||
import { JSUpdate, ParsedJSSubAction } from "utils/JSPaneUtils";
|
import { JSUpdate, ParsedJSSubAction } from "utils/JSPaneUtils";
|
||||||
import { isTypeOfFunction, parseJSObjectWithAST } from "@shared/ast";
|
import { NodeTypes, parseJSObjectWithAST, JsObjectProperty } from "@shared/ast";
|
||||||
import DataTreeEvaluator from "workers/common/DataTreeEvaluator";
|
import DataTreeEvaluator from "workers/common/DataTreeEvaluator";
|
||||||
import evaluateSync, { isFunctionAsync } from "workers/Evaluation/evaluate";
|
import evaluateSync, { isFunctionAsync } from "workers/Evaluation/evaluate";
|
||||||
import {
|
import {
|
||||||
|
|
@ -16,6 +16,19 @@ import {
|
||||||
updateJSCollectionInUnEvalTree,
|
updateJSCollectionInUnEvalTree,
|
||||||
} from "workers/Evaluation/JSObject/utils";
|
} from "workers/Evaluation/JSObject/utils";
|
||||||
|
|
||||||
|
type Actions = {
|
||||||
|
name: string;
|
||||||
|
body: string;
|
||||||
|
arguments: Array<{ key: string; value: unknown }>;
|
||||||
|
parsedFunction: any;
|
||||||
|
isAsync: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Variables = {
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Here we update our unEvalTree according to the change in JSObject's body
|
* Here we update our unEvalTree according to the change in JSObject's body
|
||||||
*
|
*
|
||||||
|
|
@ -33,7 +46,7 @@ export const getUpdatedLocalUnEvalTreeAfterJSUpdates = (
|
||||||
const parsedBody = jsUpdates[jsEntity].parsedBody;
|
const parsedBody = jsUpdates[jsEntity].parsedBody;
|
||||||
if (isJSAction(entity)) {
|
if (isJSAction(entity)) {
|
||||||
if (!!parsedBody) {
|
if (!!parsedBody) {
|
||||||
//add/delete/update functions from dataTree
|
// add/delete/update functions from dataTree
|
||||||
localUnEvalTree = updateJSCollectionInUnEvalTree(
|
localUnEvalTree = updateJSCollectionInUnEvalTree(
|
||||||
parsedBody,
|
parsedBody,
|
||||||
entity,
|
entity,
|
||||||
|
|
@ -54,6 +67,110 @@ export const getUpdatedLocalUnEvalTreeAfterJSUpdates = (
|
||||||
|
|
||||||
const regex = new RegExp(/^export default[\s]*?({[\s\S]*?})/);
|
const regex = new RegExp(/^export default[\s]*?({[\s\S]*?})/);
|
||||||
|
|
||||||
|
function deleteResolvedFunctionsAndCurrentJSCollectionState(
|
||||||
|
dataTreeEvalRef: DataTreeEvaluator,
|
||||||
|
entityName: string,
|
||||||
|
) {
|
||||||
|
delete dataTreeEvalRef.resolvedFunctions[entityName];
|
||||||
|
delete dataTreeEvalRef.currentJSCollectionState[entityName];
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseFunction(
|
||||||
|
parsedElement: JsObjectProperty,
|
||||||
|
unEvalDataTree: DataTree,
|
||||||
|
dataTreeEvalRef: DataTreeEvaluator,
|
||||||
|
entityName: string,
|
||||||
|
actions: Actions[],
|
||||||
|
) {
|
||||||
|
const { result } = evaluateSync(
|
||||||
|
parsedElement.value,
|
||||||
|
unEvalDataTree,
|
||||||
|
{},
|
||||||
|
true,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
if (!!result) {
|
||||||
|
let params: Array<{ key: string; value: unknown }> = [];
|
||||||
|
|
||||||
|
if (parsedElement.arguments) {
|
||||||
|
params = parsedElement.arguments.map(({ defaultValue, paramName }) => ({
|
||||||
|
key: paramName,
|
||||||
|
value: defaultValue,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
const functionString: string = parsedElement.value;
|
||||||
|
set(
|
||||||
|
dataTreeEvalRef.resolvedFunctions,
|
||||||
|
`${entityName}.${parsedElement.key}`,
|
||||||
|
result,
|
||||||
|
);
|
||||||
|
set(
|
||||||
|
dataTreeEvalRef.currentJSCollectionState,
|
||||||
|
`${entityName}.${parsedElement.key}`,
|
||||||
|
functionString,
|
||||||
|
);
|
||||||
|
actions.push({
|
||||||
|
name: parsedElement.key,
|
||||||
|
body: functionString,
|
||||||
|
arguments: params,
|
||||||
|
parsedFunction: result,
|
||||||
|
isAsync: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseVariables(
|
||||||
|
variables: Variables[],
|
||||||
|
parsedElement: JsObjectProperty,
|
||||||
|
dataTreeEvalRef: DataTreeEvaluator,
|
||||||
|
entityName: string,
|
||||||
|
) {
|
||||||
|
variables.push({
|
||||||
|
name: parsedElement.key,
|
||||||
|
value: parsedElement.value,
|
||||||
|
});
|
||||||
|
set(
|
||||||
|
dataTreeEvalRef.currentJSCollectionState,
|
||||||
|
`${entityName}.${parsedElement.key}`,
|
||||||
|
parsedElement.value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getParsedBody(
|
||||||
|
parsedObject: Array<JsObjectProperty>,
|
||||||
|
unEvalDataTree: DataTree,
|
||||||
|
dataTreeEvalRef: DataTreeEvaluator,
|
||||||
|
entityName: string,
|
||||||
|
) {
|
||||||
|
const actions: Actions[] = [];
|
||||||
|
const variables: Variables[] = [];
|
||||||
|
for (const parsedElement of parsedObject) {
|
||||||
|
switch (parsedElement.type) {
|
||||||
|
case "literal":
|
||||||
|
continue;
|
||||||
|
case NodeTypes.ArrowFunctionExpression:
|
||||||
|
case NodeTypes.FunctionExpression:
|
||||||
|
parseFunction(
|
||||||
|
parsedElement,
|
||||||
|
unEvalDataTree,
|
||||||
|
dataTreeEvalRef,
|
||||||
|
entityName,
|
||||||
|
actions,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
parseVariables(variables, parsedElement, dataTreeEvalRef, entityName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
actions,
|
||||||
|
variables,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Here we parse the JSObject and then determine
|
* Here we parse the JSObject and then determine
|
||||||
* 1. it's nature : async or sync
|
* 1. it's nature : async or sync
|
||||||
|
|
@ -62,24 +179,26 @@ const regex = new RegExp(/^export default[\s]*?({[\s\S]*?})/);
|
||||||
*
|
*
|
||||||
* @param dataTreeEvalRef
|
* @param dataTreeEvalRef
|
||||||
* @param entity
|
* @param entity
|
||||||
* @param jsUpdates
|
|
||||||
* @param unEvalDataTree
|
* @param unEvalDataTree
|
||||||
* @param entityName
|
* @param entityName
|
||||||
|
* @param jsUpdates
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function saveResolvedFunctionsAndJSUpdates(
|
export function saveResolvedFunctionsAndJSUpdates(
|
||||||
dataTreeEvalRef: DataTreeEvaluator,
|
dataTreeEvalRef: DataTreeEvaluator,
|
||||||
entity: DataTreeJSAction,
|
entity: DataTreeJSAction,
|
||||||
jsUpdates: Record<string, JSUpdate>,
|
|
||||||
unEvalDataTree: DataTree,
|
unEvalDataTree: DataTree,
|
||||||
entityName: string,
|
entityName: string,
|
||||||
|
jsUpdates: Record<string, JSUpdate>,
|
||||||
) {
|
) {
|
||||||
const correctFormat = regex.test(entity.body);
|
const correctFormat = regex.test(entity.body);
|
||||||
if (correctFormat) {
|
if (correctFormat) {
|
||||||
const body = entity.body.replace(/export default/g, "");
|
const body = entity.body.replace(/export default/g, "");
|
||||||
try {
|
try {
|
||||||
delete dataTreeEvalRef.resolvedFunctions[`${entityName}`];
|
deleteResolvedFunctionsAndCurrentJSCollectionState(
|
||||||
delete dataTreeEvalRef.currentJSCollectionState[`${entityName}`];
|
dataTreeEvalRef,
|
||||||
|
entityName,
|
||||||
|
);
|
||||||
const parseStartTime = performance.now();
|
const parseStartTime = performance.now();
|
||||||
const parsedObject = parseJSObjectWithAST(body);
|
const parsedObject = parseJSObjectWithAST(body);
|
||||||
const parseEndTime = performance.now();
|
const parseEndTime = performance.now();
|
||||||
|
|
@ -88,82 +207,23 @@ export function saveResolvedFunctionsAndJSUpdates(
|
||||||
JSObjectName: entityName,
|
JSObjectName: entityName,
|
||||||
JSObjectASTParseTime,
|
JSObjectASTParseTime,
|
||||||
});
|
});
|
||||||
const actions: any = [];
|
|
||||||
const variables: any = [];
|
|
||||||
if (!!parsedObject) {
|
|
||||||
parsedObject.forEach((parsedElement) => {
|
|
||||||
if (isTypeOfFunction(parsedElement.type)) {
|
|
||||||
try {
|
|
||||||
const { result } = evaluateSync(
|
|
||||||
parsedElement.value,
|
|
||||||
unEvalDataTree,
|
|
||||||
{},
|
|
||||||
false,
|
|
||||||
undefined,
|
|
||||||
undefined,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
if (!!result) {
|
|
||||||
let params: Array<{ key: string; value: unknown }> = [];
|
|
||||||
|
|
||||||
if (parsedElement.arguments) {
|
const parsedBody = !!parsedObject
|
||||||
params = parsedElement.arguments.map(
|
? {
|
||||||
({ defaultValue, paramName }) => ({
|
body: entity.body,
|
||||||
key: paramName,
|
...getParsedBody(
|
||||||
value: defaultValue,
|
parsedObject,
|
||||||
}),
|
unEvalDataTree,
|
||||||
);
|
dataTreeEvalRef,
|
||||||
}
|
entityName,
|
||||||
|
),
|
||||||
const functionString = parsedElement.value;
|
|
||||||
set(
|
|
||||||
dataTreeEvalRef.resolvedFunctions,
|
|
||||||
`${entityName}.${parsedElement.key}`,
|
|
||||||
result,
|
|
||||||
);
|
|
||||||
set(
|
|
||||||
dataTreeEvalRef.currentJSCollectionState,
|
|
||||||
`${entityName}.${parsedElement.key}`,
|
|
||||||
functionString,
|
|
||||||
);
|
|
||||||
actions.push({
|
|
||||||
name: parsedElement.key,
|
|
||||||
body: functionString,
|
|
||||||
arguments: params,
|
|
||||||
parsedFunction: result,
|
|
||||||
isAsync: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// in case we need to handle error state
|
|
||||||
}
|
|
||||||
} else if (parsedElement.type !== "literal") {
|
|
||||||
variables.push({
|
|
||||||
name: parsedElement.key,
|
|
||||||
value: parsedElement.value,
|
|
||||||
});
|
|
||||||
set(
|
|
||||||
dataTreeEvalRef.currentJSCollectionState,
|
|
||||||
`${entityName}.${parsedElement.key}`,
|
|
||||||
parsedElement.value,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
: undefined;
|
||||||
const parsedBody = {
|
|
||||||
body: entity.body,
|
set(jsUpdates, `${entityName}`, {
|
||||||
actions: actions,
|
parsedBody,
|
||||||
variables,
|
id: entity.actionId,
|
||||||
};
|
});
|
||||||
set(jsUpdates, `${entityName}`, {
|
|
||||||
parsedBody,
|
|
||||||
id: entity.actionId,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
set(jsUpdates, `${entityName}`, {
|
|
||||||
parsedBody: undefined,
|
|
||||||
id: entity.actionId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
//if we need to push error as popup in case
|
//if we need to push error as popup in case
|
||||||
}
|
}
|
||||||
|
|
@ -181,74 +241,152 @@ export function saveResolvedFunctionsAndJSUpdates(
|
||||||
return jsUpdates;
|
return jsUpdates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function viewModeSaveResolvedFunctions(
|
||||||
|
dataTreeEvalRef: DataTreeEvaluator,
|
||||||
|
entity: DataTreeJSAction,
|
||||||
|
unEvalDataTree: DataTree,
|
||||||
|
entityName: string,
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
deleteResolvedFunctionsAndCurrentJSCollectionState(
|
||||||
|
dataTreeEvalRef,
|
||||||
|
entityName,
|
||||||
|
);
|
||||||
|
const jsActions = entity.meta;
|
||||||
|
const jsActionList = Object.keys(jsActions);
|
||||||
|
for (const jsAction of jsActionList) {
|
||||||
|
const { result } = evaluateSync(
|
||||||
|
jsActions[jsAction].body,
|
||||||
|
unEvalDataTree,
|
||||||
|
{},
|
||||||
|
false,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!!result) {
|
||||||
|
const functionString = jsActions[jsAction].body;
|
||||||
|
|
||||||
|
set(
|
||||||
|
dataTreeEvalRef.resolvedFunctions,
|
||||||
|
`${entityName}.${jsAction}`,
|
||||||
|
result,
|
||||||
|
);
|
||||||
|
set(
|
||||||
|
dataTreeEvalRef.currentJSCollectionState,
|
||||||
|
`${entityName}.${jsAction}`,
|
||||||
|
functionString,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
//if we need to push error as popup in case
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseJSActionsWithDifferences(
|
||||||
|
dataTreeEvalRef: DataTreeEvaluator,
|
||||||
|
unEvalDataTree: DataTree,
|
||||||
|
differences: DataTreeDiff[],
|
||||||
|
) {
|
||||||
|
let jsUpdates: Record<string, JSUpdate> = {};
|
||||||
|
for (const diff of differences) {
|
||||||
|
const payLoadPropertyPath = diff.payload.propertyPath;
|
||||||
|
const { entityName, propertyPath } = getEntityNameAndPropertyPath(
|
||||||
|
payLoadPropertyPath,
|
||||||
|
);
|
||||||
|
const entity = unEvalDataTree[entityName];
|
||||||
|
|
||||||
|
if (!isJSAction(entity)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (diff.event) {
|
||||||
|
case DataTreeDiffEvent.DELETE:
|
||||||
|
// when JSObject is deleted, we remove it from currentJSCollectionState & resolvedFunctions
|
||||||
|
deleteResolvedFunctionsAndCurrentJSCollectionState(
|
||||||
|
dataTreeEvalRef,
|
||||||
|
payLoadPropertyPath,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case DataTreeDiffEvent.EDIT:
|
||||||
|
if (propertyPath === "body") {
|
||||||
|
jsUpdates = saveResolvedFunctionsAndJSUpdates(
|
||||||
|
dataTreeEvalRef,
|
||||||
|
entity,
|
||||||
|
unEvalDataTree,
|
||||||
|
entityName,
|
||||||
|
jsUpdates,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DataTreeDiffEvent.NEW:
|
||||||
|
if (propertyPath === "") {
|
||||||
|
jsUpdates = saveResolvedFunctionsAndJSUpdates(
|
||||||
|
dataTreeEvalRef,
|
||||||
|
entity,
|
||||||
|
unEvalDataTree,
|
||||||
|
entityName,
|
||||||
|
jsUpdates,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return parseJSUpdates(jsUpdates, unEvalDataTree, dataTreeEvalRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseJSActionsForViewMode(
|
||||||
|
dataTreeEvalRef: DataTreeEvaluator,
|
||||||
|
unEvalDataTree: DataTree,
|
||||||
|
) {
|
||||||
|
const unEvalDataTreeKeys = Object.keys(unEvalDataTree);
|
||||||
|
for (const entityName of unEvalDataTreeKeys) {
|
||||||
|
const entity = unEvalDataTree[entityName];
|
||||||
|
if (!isJSAction(entity)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
viewModeSaveResolvedFunctions(
|
||||||
|
dataTreeEvalRef,
|
||||||
|
entity,
|
||||||
|
unEvalDataTree,
|
||||||
|
entityName,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function parseJSActions(
|
export function parseJSActions(
|
||||||
dataTreeEvalRef: DataTreeEvaluator,
|
dataTreeEvalRef: DataTreeEvaluator,
|
||||||
unEvalDataTree: DataTree,
|
unEvalDataTree: DataTree,
|
||||||
differences?: DataTreeDiff[],
|
|
||||||
oldUnEvalTree?: DataTree,
|
|
||||||
) {
|
) {
|
||||||
let jsUpdates: Record<string, JSUpdate> = {};
|
let jsUpdates: Record<string, JSUpdate> = {};
|
||||||
if (!!differences && !!oldUnEvalTree) {
|
const unEvalDataTreeKeys = Object.keys(unEvalDataTree);
|
||||||
differences.forEach((diff) => {
|
for (const entityName of unEvalDataTreeKeys) {
|
||||||
const { entityName, propertyPath } = getEntityNameAndPropertyPath(
|
const entity = unEvalDataTree[entityName];
|
||||||
diff.payload.propertyPath,
|
if (!isJSAction(entity)) {
|
||||||
);
|
continue;
|
||||||
const entity = unEvalDataTree[entityName];
|
}
|
||||||
|
jsUpdates = saveResolvedFunctionsAndJSUpdates(
|
||||||
if (!isJSAction(entity)) {
|
dataTreeEvalRef,
|
||||||
return false;
|
entity,
|
||||||
}
|
unEvalDataTree,
|
||||||
|
entityName,
|
||||||
if (diff.event === DataTreeDiffEvent.DELETE) {
|
jsUpdates,
|
||||||
// when JSObject is deleted, we remove it from currentJSCollectionState & resolvedFunctions
|
);
|
||||||
if (
|
|
||||||
dataTreeEvalRef.currentJSCollectionState &&
|
|
||||||
dataTreeEvalRef.currentJSCollectionState[diff.payload.propertyPath]
|
|
||||||
) {
|
|
||||||
delete dataTreeEvalRef.currentJSCollectionState[
|
|
||||||
diff.payload.propertyPath
|
|
||||||
];
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
dataTreeEvalRef.resolvedFunctions &&
|
|
||||||
dataTreeEvalRef.resolvedFunctions[diff.payload.propertyPath]
|
|
||||||
) {
|
|
||||||
delete dataTreeEvalRef.resolvedFunctions[diff.payload.propertyPath];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
(diff.event === DataTreeDiffEvent.EDIT && propertyPath === "body") ||
|
|
||||||
(diff.event === DataTreeDiffEvent.NEW && propertyPath === "")
|
|
||||||
) {
|
|
||||||
jsUpdates = saveResolvedFunctionsAndJSUpdates(
|
|
||||||
dataTreeEvalRef,
|
|
||||||
entity,
|
|
||||||
jsUpdates,
|
|
||||||
unEvalDataTree,
|
|
||||||
entityName,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Object.keys(unEvalDataTree).forEach((entityName) => {
|
|
||||||
const entity = unEvalDataTree[entityName];
|
|
||||||
if (!isJSAction(entity)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
jsUpdates = saveResolvedFunctionsAndJSUpdates(
|
|
||||||
dataTreeEvalRef,
|
|
||||||
entity,
|
|
||||||
jsUpdates,
|
|
||||||
unEvalDataTree,
|
|
||||||
entityName,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
return parseJSUpdates(jsUpdates, unEvalDataTree, dataTreeEvalRef);
|
||||||
|
}
|
||||||
|
|
||||||
Object.keys(jsUpdates).forEach((entityName) => {
|
export function parseJSUpdates(
|
||||||
|
jsUpdates: Record<string, JSUpdate>,
|
||||||
|
unEvalDataTree: DataTree,
|
||||||
|
dataTreeEvalRef: DataTreeEvaluator,
|
||||||
|
) {
|
||||||
|
const jsUpdateKeys = Object.keys(jsUpdates);
|
||||||
|
for (const entityName of jsUpdateKeys) {
|
||||||
const parsedBody = jsUpdates[entityName].parsedBody;
|
const parsedBody = jsUpdates[entityName].parsedBody;
|
||||||
if (!parsedBody) return;
|
if (!parsedBody) continue;
|
||||||
parsedBody.actions = parsedBody.actions.map((action) => {
|
parsedBody.actions = parsedBody.actions.map((action) => {
|
||||||
return {
|
return {
|
||||||
...action,
|
...action,
|
||||||
|
|
@ -262,17 +400,18 @@ export function parseJSActions(
|
||||||
parsedFunction: undefined,
|
parsedFunction: undefined,
|
||||||
} as ParsedJSSubAction;
|
} as ParsedJSSubAction;
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
return { jsUpdates };
|
return jsUpdates;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getJSEntities(dataTree: DataTree) {
|
export function getJSEntities(dataTree: DataTree) {
|
||||||
const jsCollections: Record<string, DataTreeJSAction> = {};
|
const jsCollections: Record<string, DataTreeJSAction> = {};
|
||||||
Object.keys(dataTree).forEach((key: string) => {
|
const dataTreeKeys = Object.keys(dataTree);
|
||||||
|
for (const key of dataTreeKeys) {
|
||||||
const entity = dataTree[key];
|
const entity = dataTree[key];
|
||||||
if (isJSAction(entity)) {
|
if (isJSAction(entity)) {
|
||||||
jsCollections[entity.name] = entity;
|
jsCollections[entity.name] = entity;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
return jsCollections;
|
return jsCollections;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
import {
|
import {
|
||||||
DataTree,
|
DataTree,
|
||||||
|
DataTreeAppsmith,
|
||||||
DataTreeJSAction,
|
DataTreeJSAction,
|
||||||
EvaluationSubstitutionType,
|
EvaluationSubstitutionType,
|
||||||
} from "entities/DataTree/dataTreeFactory";
|
} from "entities/DataTree/dataTreeFactory";
|
||||||
import { ParsedBody, ParsedJSSubAction } from "utils/JSPaneUtils";
|
import { ParsedBody, ParsedJSSubAction } from "utils/JSPaneUtils";
|
||||||
import { unset, set, get } from "lodash";
|
import { unset, set, get } from "lodash";
|
||||||
import { isJSAction } from "workers/Evaluation/evaluationUtils";
|
import { isJSAction } from "workers/Evaluation/evaluationUtils";
|
||||||
|
import { APP_MODE } from "../../../entities/App";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* here we add/remove the properties (variables and actions) which got added/removed from the JSObject parsedBody.
|
* here we add/remove the properties (variables and actions) which got added/removed from the JSObject parsedBody.
|
||||||
|
|
@ -72,6 +74,7 @@ export const updateJSCollectionInUnEvalTree = (
|
||||||
arguments: action.arguments,
|
arguments: action.arguments,
|
||||||
isAsync: false,
|
isAsync: false,
|
||||||
confirmBeforeExecute: false,
|
confirmBeforeExecute: false,
|
||||||
|
body: action.body,
|
||||||
};
|
};
|
||||||
|
|
||||||
const data = get(
|
const data = get(
|
||||||
|
|
@ -238,3 +241,8 @@ export function isJSObjectFunction(
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getAppMode(dataTree: DataTree) {
|
||||||
|
const appsmithObj = dataTree.appsmith as DataTreeAppsmith;
|
||||||
|
return appsmithObj.mode as APP_MODE;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -346,6 +346,14 @@ describe("DataTreeEvaluator", () => {
|
||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
const unEvalTree: UnEvalTree = {
|
const unEvalTree: UnEvalTree = {
|
||||||
|
appsmith: {
|
||||||
|
mode: "EDIT",
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
ENTITY_TYPE: ENTITY_TYPE.APPSMITH,
|
||||||
|
store: {},
|
||||||
|
theme: {},
|
||||||
|
},
|
||||||
Text1: generateDataTreeWidget(
|
Text1: generateDataTreeWidget(
|
||||||
{
|
{
|
||||||
...BASE_WIDGET,
|
...BASE_WIDGET,
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import {
|
||||||
convertPathToString,
|
convertPathToString,
|
||||||
CrashingError,
|
CrashingError,
|
||||||
DataTreeDiff,
|
DataTreeDiff,
|
||||||
|
getAllPaths,
|
||||||
getEntityNameAndPropertyPath,
|
getEntityNameAndPropertyPath,
|
||||||
getImmediateParentsOfPropertyPaths,
|
getImmediateParentsOfPropertyPaths,
|
||||||
isAction,
|
isAction,
|
||||||
|
|
@ -38,7 +39,6 @@ import {
|
||||||
translateDiffEventToDataTreeDiffEvent,
|
translateDiffEventToDataTreeDiffEvent,
|
||||||
trimDependantChangePaths,
|
trimDependantChangePaths,
|
||||||
overrideWidgetProperties,
|
overrideWidgetProperties,
|
||||||
getAllPaths,
|
|
||||||
isValidEntity,
|
isValidEntity,
|
||||||
} from "workers/Evaluation/evaluationUtils";
|
} from "workers/Evaluation/evaluationUtils";
|
||||||
import {
|
import {
|
||||||
|
|
@ -63,14 +63,14 @@ import {
|
||||||
import { DATA_BIND_REGEX } from "constants/BindingsConstants";
|
import { DATA_BIND_REGEX } from "constants/BindingsConstants";
|
||||||
import evaluateSync, {
|
import evaluateSync, {
|
||||||
EvalResult,
|
EvalResult,
|
||||||
EvaluateContext,
|
|
||||||
evaluateAsync,
|
evaluateAsync,
|
||||||
|
EvaluateContext,
|
||||||
} from "workers/Evaluation/evaluate";
|
} from "workers/Evaluation/evaluate";
|
||||||
import { substituteDynamicBindingWithValues } from "workers/Evaluation/evaluationSubstitution";
|
import { substituteDynamicBindingWithValues } from "workers/Evaluation/evaluationSubstitution";
|
||||||
import {
|
import {
|
||||||
|
ENTITY_TYPE as CONSOLE_ENTITY_TYPE,
|
||||||
Severity,
|
Severity,
|
||||||
SourceEntity,
|
SourceEntity,
|
||||||
ENTITY_TYPE as CONSOLE_ENTITY_TYPE,
|
|
||||||
UserLogObject,
|
UserLogObject,
|
||||||
} from "entities/AppsmithConsole";
|
} from "entities/AppsmithConsole";
|
||||||
import { error as logError } from "loglevel";
|
import { error as logError } from "loglevel";
|
||||||
|
|
@ -83,21 +83,27 @@ import {
|
||||||
import { klona } from "klona/full";
|
import { klona } from "klona/full";
|
||||||
import { EvalMetaUpdates } from "./types";
|
import { EvalMetaUpdates } from "./types";
|
||||||
import {
|
import {
|
||||||
updateDependencyMap,
|
|
||||||
createDependencyMap,
|
createDependencyMap,
|
||||||
|
updateDependencyMap,
|
||||||
} from "workers/common/DependencyMap";
|
} from "workers/common/DependencyMap";
|
||||||
import {
|
import {
|
||||||
getJSEntities,
|
getJSEntities,
|
||||||
getUpdatedLocalUnEvalTreeAfterJSUpdates,
|
getUpdatedLocalUnEvalTreeAfterJSUpdates,
|
||||||
|
parseJSActionsForViewMode,
|
||||||
parseJSActions,
|
parseJSActions,
|
||||||
|
parseJSActionsWithDifferences,
|
||||||
} from "workers/Evaluation/JSObject";
|
} from "workers/Evaluation/JSObject";
|
||||||
import { getFixedTimeDifference } from "./utils";
|
import { getFixedTimeDifference } from "./utils";
|
||||||
import { isJSObjectFunction } from "workers/Evaluation/JSObject/utils";
|
import {
|
||||||
|
getAppMode,
|
||||||
|
isJSObjectFunction,
|
||||||
|
} from "workers/Evaluation/JSObject/utils";
|
||||||
import {
|
import {
|
||||||
getValidatedTree,
|
getValidatedTree,
|
||||||
validateActionProperty,
|
validateActionProperty,
|
||||||
validateAndParseWidgetProperty,
|
validateAndParseWidgetProperty,
|
||||||
} from "./validationUtils";
|
} from "./validationUtils";
|
||||||
|
import { APP_MODE } from "../../../entities/App";
|
||||||
|
|
||||||
type SortedDependencies = Array<string>;
|
type SortedDependencies = Array<string>;
|
||||||
|
|
||||||
|
|
@ -142,6 +148,10 @@ export default class DataTreeEvaluator {
|
||||||
sortedValidationDependencies: SortedDependencies = [];
|
sortedValidationDependencies: SortedDependencies = [];
|
||||||
inverseValidationDependencyMap: DependencyMap = {};
|
inverseValidationDependencyMap: DependencyMap = {};
|
||||||
public hasCyclicalDependency = false;
|
public hasCyclicalDependency = false;
|
||||||
|
parseJsActionsConfig = {
|
||||||
|
[APP_MODE.EDIT]: parseJSActions,
|
||||||
|
[APP_MODE.PUBLISHED]: parseJSActionsForViewMode,
|
||||||
|
};
|
||||||
constructor(
|
constructor(
|
||||||
widgetConfigMap: WidgetTypeConfigMap,
|
widgetConfigMap: WidgetTypeConfigMap,
|
||||||
allActionValidationConfig?: {
|
allActionValidationConfig?: {
|
||||||
|
|
@ -190,8 +200,9 @@ export default class DataTreeEvaluator {
|
||||||
//save current state of js collection action and variables to be added to uneval tree
|
//save current state of js collection action and variables to be added to uneval tree
|
||||||
//save functions in resolveFunctions (as functions) to be executed as functions are not allowed in evalTree
|
//save functions in resolveFunctions (as functions) to be executed as functions are not allowed in evalTree
|
||||||
//and functions are saved in dataTree as strings
|
//and functions are saved in dataTree as strings
|
||||||
const parsedCollections = parseJSActions(this, localUnEvalTree);
|
const currentAppMode: APP_MODE = getAppMode(localUnEvalTree);
|
||||||
jsUpdates = parsedCollections.jsUpdates;
|
jsUpdates =
|
||||||
|
this.parseJsActionsConfig[currentAppMode](this, localUnEvalTree) || {};
|
||||||
localUnEvalTree = getUpdatedLocalUnEvalTreeAfterJSUpdates(
|
localUnEvalTree = getUpdatedLocalUnEvalTreeAfterJSUpdates(
|
||||||
jsUpdates,
|
jsUpdates,
|
||||||
localUnEvalTree,
|
localUnEvalTree,
|
||||||
|
|
@ -363,18 +374,18 @@ export default class DataTreeEvaluator {
|
||||||
translateDiffEventToDataTreeDiffEvent(diff, localUnEvalTree),
|
translateDiffEventToDataTreeDiffEvent(diff, localUnEvalTree),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
//save parsed functions in resolveJSFunctions, update current state of js collection
|
// save parsed functions in resolveJSFunctions, update current state of js collection
|
||||||
const parsedCollections = parseJSActions(
|
jsUpdates =
|
||||||
this,
|
(!!jsTranslatedDiffs && !!this.oldUnEvalTree
|
||||||
localUnEvalTree,
|
? parseJSActionsWithDifferences(
|
||||||
jsTranslatedDiffs,
|
this,
|
||||||
this.oldUnEvalTree,
|
localUnEvalTree,
|
||||||
);
|
jsTranslatedDiffs,
|
||||||
|
)
|
||||||
jsUpdates = parsedCollections.jsUpdates;
|
: parseJSActions(this, localUnEvalTree)) || {};
|
||||||
//update local data tree if js body has updated (remove/update/add js functions or variables)
|
// update local data tree if js body has updated (remove/update/add js functions or variables)
|
||||||
localUnEvalTree = getUpdatedLocalUnEvalTreeAfterJSUpdates(
|
localUnEvalTree = getUpdatedLocalUnEvalTreeAfterJSUpdates(
|
||||||
jsUpdates,
|
jsUpdates || {},
|
||||||
localUnEvalTree,
|
localUnEvalTree,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import {
|
||||||
DataTreeAction,
|
DataTreeAction,
|
||||||
DataTreeWidget,
|
DataTreeWidget,
|
||||||
ENTITY_TYPE,
|
ENTITY_TYPE,
|
||||||
|
DataTreeAppsmith,
|
||||||
} from "entities/DataTree/dataTreeFactory";
|
} from "entities/DataTree/dataTreeFactory";
|
||||||
|
|
||||||
export const arrayAccessorCyclicDependency: Record<string, DataTree> = {
|
export const arrayAccessorCyclicDependency: Record<string, DataTree> = {
|
||||||
|
|
@ -210,6 +211,71 @@ export const arrayAccessorCyclicDependency: Record<string, DataTree> = {
|
||||||
privateWidgets: {},
|
privateWidgets: {},
|
||||||
meta: {},
|
meta: {},
|
||||||
} as unknown) as DataTreeWidget,
|
} as unknown) as DataTreeWidget,
|
||||||
|
appsmith: ({
|
||||||
|
user: {
|
||||||
|
email: "anand@appsmith.com",
|
||||||
|
workspaceIds: [
|
||||||
|
"61431979a67ce2289d3c7c6d",
|
||||||
|
"61431a95a67ce2289d3c7c74",
|
||||||
|
"5f7add8687af934ed846dd6a",
|
||||||
|
"5f9fd13993794869fdbb8dcb",
|
||||||
|
"618b5af5da7cd651ee273112",
|
||||||
|
"604ef1c5c046f668d7bcc051",
|
||||||
|
"61b3389cd3e4214454c26bd1",
|
||||||
|
"61b3389cd3e4214454c26bd2",
|
||||||
|
"620a0d896b4b1e154a3c057a",
|
||||||
|
"620b37296b4b1e154a3c1fd7",
|
||||||
|
"60c1a5273535574772b6377b",
|
||||||
|
"6066e71a034ece74b1481ad2",
|
||||||
|
"623b36e34d9aea1b062b15b3",
|
||||||
|
"623b37de4d9aea1b062b170f",
|
||||||
|
"624fe51b457aa64da9e02ed3",
|
||||||
|
"6176537b515e45415cc7fd15",
|
||||||
|
"6206486d6b4b1e154a3be208",
|
||||||
|
],
|
||||||
|
username: "anand@appsmith.com",
|
||||||
|
name: "Anand Srinivasan",
|
||||||
|
enableTelemetry: true,
|
||||||
|
idToken: {
|
||||||
|
sub: "109879730040206968321",
|
||||||
|
email_verified: true,
|
||||||
|
name: "Anand Srinivasan",
|
||||||
|
given_name: "Anand",
|
||||||
|
locale: "en",
|
||||||
|
hd: "appsmith.com",
|
||||||
|
family_name: "Srinivasan",
|
||||||
|
picture:
|
||||||
|
"https://lh3.googleusercontent.com/a-/AOh14Gi4HfYY0sKhaG93YAHB_E5-dL4BkFxdf8ZfQ2w7=s96-c",
|
||||||
|
email: "anand@appsmith.com",
|
||||||
|
},
|
||||||
|
accountNonExpired: true,
|
||||||
|
accountNonLocked: true,
|
||||||
|
credentialsNonExpired: true,
|
||||||
|
emptyInstance: false,
|
||||||
|
isAnonymous: false,
|
||||||
|
isEnabled: true,
|
||||||
|
isSuperUser: false,
|
||||||
|
isConfigurable: true,
|
||||||
|
},
|
||||||
|
URL: {
|
||||||
|
fullPath:
|
||||||
|
"https://app.appsmith.com/app/untitled-application-25/page1-6272179d8a368d6f1efcd0d2/edit",
|
||||||
|
host: "app.appsmith.com",
|
||||||
|
hostname: "app.appsmith.com",
|
||||||
|
queryParams: {},
|
||||||
|
protocol: "https:",
|
||||||
|
pathname:
|
||||||
|
"/app/untitled-application-25/page1-6272179d8a368d6f1efcd0d2/edit",
|
||||||
|
port: "",
|
||||||
|
hash: "",
|
||||||
|
},
|
||||||
|
store: {},
|
||||||
|
geolocation: {
|
||||||
|
canBeRequested: true,
|
||||||
|
},
|
||||||
|
mode: "EDIT",
|
||||||
|
ENTITY_TYPE: ENTITY_TYPE.APPSMITH,
|
||||||
|
} as unknown) as DataTreeAppsmith,
|
||||||
},
|
},
|
||||||
apiSuccessUnEvalTree: {
|
apiSuccessUnEvalTree: {
|
||||||
// success: response -> [{...}, {...}, {...}]
|
// success: response -> [{...}, {...}, {...}]
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import {
|
||||||
DataTreeAction,
|
DataTreeAction,
|
||||||
DataTreeWidget,
|
DataTreeWidget,
|
||||||
ENTITY_TYPE,
|
ENTITY_TYPE,
|
||||||
|
DataTreeAppsmith,
|
||||||
} from "entities/DataTree/dataTreeFactory";
|
} from "entities/DataTree/dataTreeFactory";
|
||||||
|
|
||||||
export const nestedArrayAccessorCyclicDependency: Record<string, DataTree> = {
|
export const nestedArrayAccessorCyclicDependency: Record<string, DataTree> = {
|
||||||
|
|
@ -210,6 +211,53 @@ export const nestedArrayAccessorCyclicDependency: Record<string, DataTree> = {
|
||||||
privateWidgets: {},
|
privateWidgets: {},
|
||||||
meta: {},
|
meta: {},
|
||||||
} as unknown) as DataTreeWidget,
|
} as unknown) as DataTreeWidget,
|
||||||
|
appsmith: ({
|
||||||
|
user: {
|
||||||
|
email: "rathod@appsmith.com",
|
||||||
|
workspaceIds: [
|
||||||
|
"6218a61972ccd9145ec78c57",
|
||||||
|
"621913df0276eb01d22fec44",
|
||||||
|
"60caf8edb1e47a1315f0c48f",
|
||||||
|
"609114fe05c4d35a9f6cbbf2",
|
||||||
|
],
|
||||||
|
username: "rathod@appsmith.com",
|
||||||
|
name: "Rishabh",
|
||||||
|
commentOnboardingState: "RESOLVED",
|
||||||
|
role: "engineer",
|
||||||
|
useCase: "personal project",
|
||||||
|
enableTelemetry: false,
|
||||||
|
emptyInstance: false,
|
||||||
|
accountNonExpired: true,
|
||||||
|
accountNonLocked: true,
|
||||||
|
credentialsNonExpired: true,
|
||||||
|
isAnonymous: false,
|
||||||
|
isEnabled: true,
|
||||||
|
isSuperUser: false,
|
||||||
|
isConfigurable: true,
|
||||||
|
},
|
||||||
|
URL: {
|
||||||
|
fullPath:
|
||||||
|
"https://dev.appsmith.com/applications/6200d1a2b5bfc0392b959cab/pages/6220c268c48234070f8ac65a/edit?a=b",
|
||||||
|
host: "dev.appsmith.com",
|
||||||
|
hostname: "dev.appsmith.com",
|
||||||
|
queryParams: {
|
||||||
|
a: "b",
|
||||||
|
},
|
||||||
|
protocol: "https:",
|
||||||
|
pathname:
|
||||||
|
"/applications/6200d1a2b5bfc0392b959cab/pages/6220c268c48234070f8ac65a/edit",
|
||||||
|
port: "",
|
||||||
|
hash: "",
|
||||||
|
},
|
||||||
|
store: {
|
||||||
|
textColor: "#DF7E65",
|
||||||
|
},
|
||||||
|
geolocation: {
|
||||||
|
canBeRequested: true,
|
||||||
|
},
|
||||||
|
mode: "EDIT",
|
||||||
|
ENTITY_TYPE: ENTITY_TYPE.APPSMITH,
|
||||||
|
} as unknown) as DataTreeAppsmith,
|
||||||
},
|
},
|
||||||
apiSuccessUnEvalTree: {
|
apiSuccessUnEvalTree: {
|
||||||
// success: response -> [ [{...}, {...}, {...}], [{...}, {...}, {...}], [{...}, {...}, {...}] ]
|
// success: response -> [ [{...}, {...}, {...}], [{...}, {...}, {...}], [{...}, {...}, {...}] ]
|
||||||
|
|
|
||||||
|
|
@ -388,6 +388,7 @@ export const asyncTagUnevalTree: DataTree = {
|
||||||
arguments: [],
|
arguments: [],
|
||||||
isAsync: false,
|
isAsync: false,
|
||||||
confirmBeforeExecute: false,
|
confirmBeforeExecute: false,
|
||||||
|
body: "myFun1: () => {\n\t\treturn JSObject2.callApi();\n\t}",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
bindingPaths: {
|
bindingPaths: {
|
||||||
|
|
@ -426,6 +427,7 @@ export const asyncTagUnevalTree: DataTree = {
|
||||||
arguments: [],
|
arguments: [],
|
||||||
isAsync: false,
|
isAsync: false,
|
||||||
confirmBeforeExecute: false,
|
confirmBeforeExecute: false,
|
||||||
|
body: "callApi: () => {\n\t\treturn Api1.run()\n\t}",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
bindingPaths: {
|
bindingPaths: {
|
||||||
|
|
@ -1419,3 +1421,71 @@ export const unEvalTreeWidgetSelectWidget = {
|
||||||
isDirty: false,
|
isDirty: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const emptyTreeWithAppsmithObject = ({
|
||||||
|
appsmith: ({
|
||||||
|
user: {
|
||||||
|
email: "anand@appsmith.com",
|
||||||
|
workspaceIds: [
|
||||||
|
"61431979a67ce2289d3c7c6d",
|
||||||
|
"61431a95a67ce2289d3c7c74",
|
||||||
|
"5f7add8687af934ed846dd6a",
|
||||||
|
"5f9fd13993794869fdbb8dcb",
|
||||||
|
"618b5af5da7cd651ee273112",
|
||||||
|
"604ef1c5c046f668d7bcc051",
|
||||||
|
"61b3389cd3e4214454c26bd1",
|
||||||
|
"61b3389cd3e4214454c26bd2",
|
||||||
|
"620a0d896b4b1e154a3c057a",
|
||||||
|
"620b37296b4b1e154a3c1fd7",
|
||||||
|
"60c1a5273535574772b6377b",
|
||||||
|
"6066e71a034ece74b1481ad2",
|
||||||
|
"623b36e34d9aea1b062b15b3",
|
||||||
|
"623b37de4d9aea1b062b170f",
|
||||||
|
"624fe51b457aa64da9e02ed3",
|
||||||
|
"6176537b515e45415cc7fd15",
|
||||||
|
"6206486d6b4b1e154a3be208",
|
||||||
|
],
|
||||||
|
username: "anand@appsmith.com",
|
||||||
|
name: "Anand Srinivasan",
|
||||||
|
enableTelemetry: true,
|
||||||
|
idToken: {
|
||||||
|
sub: "109879730040206968321",
|
||||||
|
email_verified: true,
|
||||||
|
name: "Anand Srinivasan",
|
||||||
|
given_name: "Anand",
|
||||||
|
locale: "en",
|
||||||
|
hd: "appsmith.com",
|
||||||
|
family_name: "Srinivasan",
|
||||||
|
picture:
|
||||||
|
"https://lh3.googleusercontent.com/a-/AOh14Gi4HfYY0sKhaG93YAHB_E5-dL4BkFxdf8ZfQ2w7=s96-c",
|
||||||
|
email: "anand@appsmith.com",
|
||||||
|
},
|
||||||
|
accountNonExpired: true,
|
||||||
|
accountNonLocked: true,
|
||||||
|
credentialsNonExpired: true,
|
||||||
|
emptyInstance: false,
|
||||||
|
isAnonymous: false,
|
||||||
|
isEnabled: true,
|
||||||
|
isSuperUser: false,
|
||||||
|
isConfigurable: true,
|
||||||
|
},
|
||||||
|
URL: {
|
||||||
|
fullPath:
|
||||||
|
"https://app.appsmith.com/app/untitled-application-25/page1-6272179d8a368d6f1efcd0d2/edit",
|
||||||
|
host: "app.appsmith.com",
|
||||||
|
hostname: "app.appsmith.com",
|
||||||
|
queryParams: {},
|
||||||
|
protocol: "https:",
|
||||||
|
pathname:
|
||||||
|
"/app/untitled-application-25/page1-6272179d8a368d6f1efcd0d2/edit",
|
||||||
|
port: "",
|
||||||
|
hash: "",
|
||||||
|
},
|
||||||
|
store: {},
|
||||||
|
geolocation: {
|
||||||
|
canBeRequested: true,
|
||||||
|
},
|
||||||
|
mode: "EDIT",
|
||||||
|
ENTITY_TYPE: ENTITY_TYPE.APPSMITH,
|
||||||
|
} as unknown) as DataTreeAppsmith,
|
||||||
|
} as unknown) as DataTree;
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,22 @@
|
||||||
import DataTreeEvaluator from ".";
|
import DataTreeEvaluator from ".";
|
||||||
import {
|
import {
|
||||||
asyncTagUnevalTree,
|
asyncTagUnevalTree,
|
||||||
|
emptyTreeWithAppsmithObject,
|
||||||
lintingUnEvalTree,
|
lintingUnEvalTree,
|
||||||
unEvalTree,
|
unEvalTree,
|
||||||
} from "./mockData/mockUnEvalTree";
|
} from "./mockData/mockUnEvalTree";
|
||||||
import { DataTree } from "entities/DataTree/dataTreeFactory";
|
import { DataTree } from "entities/DataTree/dataTreeFactory";
|
||||||
import { DataTreeDiff } from "workers/Evaluation/evaluationUtils";
|
import {
|
||||||
|
DataTreeDiff,
|
||||||
|
DataTreeDiffEvent,
|
||||||
|
} from "workers/Evaluation/evaluationUtils";
|
||||||
import { ALL_WIDGETS_AND_CONFIG } from "utils/WidgetRegistry";
|
import { ALL_WIDGETS_AND_CONFIG } from "utils/WidgetRegistry";
|
||||||
import { arrayAccessorCyclicDependency } from "./mockData/ArrayAccessorTree";
|
import { arrayAccessorCyclicDependency } from "./mockData/ArrayAccessorTree";
|
||||||
import { nestedArrayAccessorCyclicDependency } from "./mockData/NestedArrayAccessorTree";
|
import { nestedArrayAccessorCyclicDependency } from "./mockData/NestedArrayAccessorTree";
|
||||||
import { updateDependencyMap } from "workers/common/DependencyMap";
|
import { updateDependencyMap } from "workers/common/DependencyMap";
|
||||||
import { parseJSActions } from "workers/Evaluation/JSObject";
|
import { parseJSActions } from "workers/Evaluation/JSObject";
|
||||||
import { WidgetConfiguration } from "widgets/constants";
|
import { WidgetConfiguration } from "widgets/constants";
|
||||||
|
import { JSUpdate, ParsedBody } from "../../../utils/JSPaneUtils";
|
||||||
|
|
||||||
const widgetConfigMap: Record<
|
const widgetConfigMap: Record<
|
||||||
string,
|
string,
|
||||||
|
|
@ -21,6 +26,7 @@ const widgetConfigMap: Record<
|
||||||
metaProperties: WidgetConfiguration["properties"]["meta"];
|
metaProperties: WidgetConfiguration["properties"]["meta"];
|
||||||
}
|
}
|
||||||
> = {};
|
> = {};
|
||||||
|
|
||||||
ALL_WIDGETS_AND_CONFIG.map(([, config]) => {
|
ALL_WIDGETS_AND_CONFIG.map(([, config]) => {
|
||||||
if (config.type && config.properties) {
|
if (config.type && config.properties) {
|
||||||
widgetConfigMap[config.type] = {
|
widgetConfigMap[config.type] = {
|
||||||
|
|
@ -209,17 +215,21 @@ describe("DataTreeEvaluator", () => {
|
||||||
|
|
||||||
describe("parseJsActions", () => {
|
describe("parseJsActions", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
dataTreeEvaluator.setupFirstTree(({} as unknown) as DataTree);
|
dataTreeEvaluator.setupFirstTree(
|
||||||
|
(emptyTreeWithAppsmithObject as unknown) as DataTree,
|
||||||
|
);
|
||||||
dataTreeEvaluator.evalAndValidateFirstTree();
|
dataTreeEvaluator.evalAndValidateFirstTree();
|
||||||
});
|
});
|
||||||
it("set's isAsync tag for cross JsObject references", () => {
|
it("set's isAsync tag for cross JsObject references", () => {
|
||||||
const result = parseJSActions(dataTreeEvaluator, asyncTagUnevalTree);
|
const result = parseJSActions(dataTreeEvaluator, asyncTagUnevalTree);
|
||||||
expect(
|
const jsUpdatesForJsObject1 = (result as Record<string, JSUpdate>)[
|
||||||
result.jsUpdates["JSObject1"]?.parsedBody?.actions[0].isAsync,
|
"JSObject1"
|
||||||
).toBe(true);
|
].parsedBody as ParsedBody;
|
||||||
expect(
|
const jsUpdatesForJsObject2 = (result as Record<string, JSUpdate>)[
|
||||||
result.jsUpdates["JSObject2"]?.parsedBody?.actions[0].isAsync,
|
"JSObject2"
|
||||||
).toBe(true);
|
].parsedBody as ParsedBody;
|
||||||
|
expect(jsUpdatesForJsObject1.actions[0].isAsync).toBe(true);
|
||||||
|
expect(jsUpdatesForJsObject2.actions[0].isAsync).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,15 @@ import {
|
||||||
import { ECMA_VERSION, SourceType, NodeTypes } from "./src/constants";
|
import { ECMA_VERSION, SourceType, NodeTypes } from "./src/constants";
|
||||||
|
|
||||||
// JSObjects
|
// JSObjects
|
||||||
import { parseJSObjectWithAST } from "./src/jsObject";
|
import { parseJSObjectWithAST, JsObjectProperty } from "./src/jsObject";
|
||||||
|
|
||||||
// types or intefaces should be exported with type keyword, while enums can be exported like normal functions
|
// types or interfaces should be exported with type keyword, while enums can be exported like normal functions
|
||||||
export type {
|
export type {
|
||||||
ObjectExpression,
|
ObjectExpression,
|
||||||
PropertyNode,
|
PropertyNode,
|
||||||
MemberExpressionData,
|
MemberExpressionData,
|
||||||
IdentifierInfo,
|
IdentifierInfo,
|
||||||
|
JsObjectProperty,
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import {
|
||||||
functionParam,
|
functionParam,
|
||||||
} from "../index";
|
} from "../index";
|
||||||
|
|
||||||
type JsObjectProperty = {
|
export type JsObjectProperty = {
|
||||||
key: string;
|
key: string;
|
||||||
value: string;
|
value: string;
|
||||||
type: string;
|
type: string;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user