Skip to content
1 change: 1 addition & 0 deletions app/client/src/ce/entities/DataTree/dataTreeJSAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ export const generateDataTreeJSAction = (
dynamicBindingPathList: dynamicBindingPathList,
variables: listVariables,
dependencyMap: dependencyMap,
actionNames: actions.map((action) => action.name),
},
};
};
1 change: 1 addition & 0 deletions app/client/src/ce/entities/DataTree/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export interface JSActionEntityConfig extends EntityConfig {
moduleId?: string;
moduleInstanceId?: string;
isPublic?: boolean;
actionNames: string[];
}

export interface JSActionEntity {
Expand Down
2 changes: 2 additions & 0 deletions app/client/src/ce/entities/FeatureFlag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export const FEATURE_FLAG = {
"release_table_custom_loading_state_enabled",
release_custom_widget_ai_builder: "release_custom_widget_ai_builder",
ab_request_new_integration_enabled: "ab_request_new_integration_enabled",
release_evaluation_scope_cache: "release_evaluation_scope_cache",
} as const;

export type FeatureFlag = keyof typeof FEATURE_FLAG;
Expand Down Expand Up @@ -81,6 +82,7 @@ export const DEFAULT_FEATURE_FLAG_VALUE: FeatureFlags = {
release_table_custom_loading_state_enabled: false,
release_custom_widget_ai_builder: false,
ab_request_new_integration_enabled: false,
release_evaluation_scope_cache: false,
};

export const AB_TESTING_EVENT_KEYS = {
Expand Down
14 changes: 9 additions & 5 deletions app/client/src/ce/workers/Evaluation/Actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ export enum ExecutionType {
/**
* This method returns new dataTree with entity function and platform function
*/
export const addDataTreeToContext = (args: {
EVAL_CONTEXT: EvalContext;
export const getDataTreeContext = (args: {
dataTree: Readonly<DataTree>;
removeEntityFunctions?: boolean;
isTriggerBased: boolean;
Expand All @@ -50,10 +49,11 @@ export const addDataTreeToContext = (args: {
const {
configTree,
dataTree,
EVAL_CONTEXT,
isTriggerBased,
removeEntityFunctions = false,
} = args;
const EVAL_CONTEXT: EvalContext = {};

const dataTreeEntries = Object.entries(dataTree);
const entityFunctionCollection: Record<string, Record<string, Function>> = {};

Expand Down Expand Up @@ -96,15 +96,19 @@ export const addDataTreeToContext = (args: {
}

if (removeEntityFunctions)
return removeEntityFunctionsFromEvalContext(
removeEntityFunctionsFromEvalContext(
entityFunctionCollection,
EVAL_CONTEXT,
);

if (!isTriggerBased) return;
if (!isTriggerBased) {
return EVAL_CONTEXT;
}

// if eval is not trigger based i.e., sync eval then we skip adding entity function to evalContext
addEntityFunctionsToEvalContext(EVAL_CONTEXT, entityFunctionCollection);

return EVAL_CONTEXT;
};

export const addEntityFunctionsToEvalContext = (
Expand Down
13 changes: 13 additions & 0 deletions app/client/src/ce/workers/Evaluation/evaluationUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1104,6 +1104,19 @@ export const isNotEntity = (entity: DataTreeEntity) => {
export const isEntityAction = (entity: DataTreeEntity) => {
return isAction(entity);
};

export const isPropertyAnEntityAction = (
entity: DataTreeEntity,
propertyPath: string,
entityConfig: DataTreeEntityConfig,
) => {
if (!isJSAction(entity)) return false;

const { actionNames } = entityConfig as JSActionEntityConfig;

return actionNames.includes(propertyPath);
};

export const convertMicroDiffToDeepDiff = (
microDiffDifferences: Difference[],
): Diff<unknown, unknown>[] =>
Expand Down
9 changes: 0 additions & 9 deletions app/client/src/entities/Engine/AppViewerEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import {
waitForSegmentInit,
waitForFetchUserSuccess,
} from "ee/sagas/userSagas";
import { waitForFetchEnvironments } from "ee/sagas/EnvironmentSagas";
import { fetchJSCollectionsForView } from "actions/jsActionActions";
import {
fetchAppThemesAction,
Expand Down Expand Up @@ -154,14 +153,6 @@ export default class AppViewerEngine extends AppEngine {
yield call(waitForSegmentInit, true);
endSpan(waitForSegmentSpan);

const waitForEnvironmentsSpan = startNestedSpan(
"AppViewerEngine.waitForFetchEnvironments",
rootSpan,
);

yield call(waitForFetchEnvironments);
endSpan(waitForEnvironmentsSpan);

yield put(fetchAllPageEntityCompletion([executePageLoadActions()]));

endSpan(loadAppEntitiesSpan);
Expand Down
2 changes: 2 additions & 0 deletions app/client/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// This file must be executed as early as possible to ensure the preloads are triggered ASAP
import "./preload-route-chunks";
// Initialise eval worker instance
import "utils/workerInstances";

import React from "react";
import "./wdyr";
Expand Down
3 changes: 2 additions & 1 deletion app/client/src/sagas/ActionExecution/PluginActionSaga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ import log from "loglevel";
import { EMPTY_RESPONSE } from "components/editorComponents/emptyResponse";
import type { AppState } from "ee/reducers";
import { DEFAULT_EXECUTE_ACTION_TIMEOUT_MS } from "ee/constants/ApiConstants";
import { evaluateActionBindings, evalWorker } from "sagas/EvaluationsSaga";
import { evaluateActionBindings } from "sagas/EvaluationsSaga";
import { evalWorker } from "utils/workerInstances";
import { isBlobUrl, parseBlobUrl } from "utils/AppsmithUtils";
import { getType, Types } from "utils/TypeHelpers";
import { matchPath } from "react-router";
Expand Down
2 changes: 1 addition & 1 deletion app/client/src/sagas/ActionExecution/geolocationSaga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { showToastOnExecutionError } from "sagas/ActionExecution/errorUtils";
import { setUserCurrentGeoLocation } from "actions/browserRequestActions";
import type { Channel } from "redux-saga";
import { channel } from "redux-saga";
import { evalWorker } from "sagas/EvaluationsSaga";
import { evalWorker } from "utils/workerInstances";
import type {
TGetGeoLocationDescription,
TWatchGeoLocationDescription,
Expand Down
2 changes: 1 addition & 1 deletion app/client/src/sagas/EvalWorkerActionSagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import type { TMessage } from "utils/MessageUtil";
import { MessageType } from "utils/MessageUtil";
import type { ResponsePayload } from "../sagas/EvaluationsSaga";
import {
evalWorker,
executeTriggerRequestSaga,
updateDataTreeHandler,
} from "../sagas/EvaluationsSaga";
import { evalWorker } from "utils/workerInstances";
import { handleStoreOperations } from "./ActionExecution/StoreActionSaga";
import type { EvalTreeResponseData } from "workers/Evaluation/types";
import isEmpty from "lodash/isEmpty";
Expand Down
2 changes: 1 addition & 1 deletion app/client/src/sagas/EvaluationsSaga.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import {
defaultAffectedJSObjects,
evalQueueBuffer,
evaluateTreeSaga,
evalWorker,
} from "./EvaluationsSaga";
import { evalWorker } from "utils/workerInstances";
import { expectSaga } from "redux-saga-test-plan";
import { EVAL_WORKER_ACTIONS } from "ee/workers/Evaluation/evalWorkerActions";
import { select } from "redux-saga/effects";
Expand Down
19 changes: 4 additions & 15 deletions app/client/src/sagas/EvaluationsSaga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
import { getMetaWidgets, getWidgets, getWidgetsMeta } from "sagas/selectors";
import type { WidgetTypeConfigMap } from "WidgetProvider/factory";
import WidgetFactory from "WidgetProvider/factory";
import { GracefulWorkerService } from "utils/WorkerUtil";
import { evalWorker } from "utils/workerInstances";
import type { EvalError, EvaluationError } from "utils/DynamicBindingUtils";
import { PropertyEvaluationErrorType } from "utils/DynamicBindingUtils";
import { EVAL_WORKER_ACTIONS } from "ee/workers/Evaluation/evalWorkerActions";
Expand Down Expand Up @@ -117,21 +117,10 @@ import {
getCurrentPageId,
} from "selectors/editorSelectors";
import { getInstanceId } from "ee/selectors/tenantSelectors";
import { waitForFetchEnvironments } from "ee/sagas/EnvironmentSagas";

const APPSMITH_CONFIGS = getAppsmithConfigs();

export const evalWorker = new GracefulWorkerService(
new Worker(
new URL("../workers/Evaluation/evaluation.worker.ts", import.meta.url),
{
type: "module",
// Note: the `Worker` part of the name is slightly important – LinkRelPreload_spec.js
// relies on it to find workers in the list of all requests.
name: "evalWorker",
},
),
);

let widgetTypeConfigMap: WidgetTypeConfigMap;

export function* updateDataTreeHandler(
Expand Down Expand Up @@ -305,6 +294,8 @@ export function* evaluateTreeSaga(
evalTreeRequestData,
);

yield call(waitForFetchEnvironments);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this to the postEvalActionDispatcher definition and add comments.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

waiting on this to be moved


yield call(
updateDataTreeHandler,
{
Expand Down Expand Up @@ -901,5 +892,3 @@ export default function* evaluationSagaListeners() {
}
}
}

export { evalWorker as EvalWorker };
2 changes: 1 addition & 1 deletion app/client/src/sagas/JSLibrarySaga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { getCurrentApplicationId } from "selectors/editorSelectors";
import CodemirrorTernService from "utils/autocomplete/CodemirrorTernService";
import { EVAL_WORKER_ACTIONS } from "ee/workers/Evaluation/evalWorkerActions";
import { validateResponse } from "./ErrorSagas";
import { EvalWorker } from "./EvaluationsSaga";
import { evalWorker as EvalWorker } from "utils/workerInstances";
import log from "loglevel";
import { APP_MODE } from "entities/App";
import { getAppMode } from "ee/selectors/applicationSelectors";
Expand Down
13 changes: 13 additions & 0 deletions app/client/src/utils/workerInstances.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { GracefulWorkerService } from "./WorkerUtil";

export const evalWorker = new GracefulWorkerService(
new Worker(
new URL("../workers/Evaluation/evaluation.worker.ts", import.meta.url),
{
type: "module",
// Note: the `Worker` part of the name is slightly important – LinkRelPreload_spec.js
// relies on it to find workers in the list of all requests.
name: "evalWorker",
},
),
);
4 changes: 1 addition & 3 deletions app/client/src/workers/Evaluation/JSObject/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,6 @@ describe("saveResolvedFunctionsAndJSUpdates", function () {
{
key: "myFun2",
},
{
key: "myFun2",
},
],
bindingPaths: {
body: "SMART_SUBSTITUTE",
Expand All @@ -216,6 +213,7 @@ describe("saveResolvedFunctionsAndJSUpdates", function () {
pluginType: "JS",
name: "JSObject1",
actionId: "64013546b956c26882acc587",
actionNames: ["myFun1", "myFun2"],
} as JSActionEntityConfig,
};
const entityName = "JSObject1";
Expand Down
7 changes: 4 additions & 3 deletions app/client/src/workers/Evaluation/__tests__/Actions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { EvalContext } from "workers/Evaluation/evaluate";
import { createEvaluationContext } from "workers/Evaluation/evaluate";
import { MessageType } from "utils/MessageUtil";
import {
addDataTreeToContext,
getDataTreeContext,
addPlatformFunctionsToEvalContext,
} from "ee/workers/Evaluation/Actions";
import TriggerEmitter, { BatchKey } from "../fns/utils/TriggerEmitter";
Expand Down Expand Up @@ -548,12 +548,13 @@ describe("Test addDataTreeToContext method", () => {
const evalContext: EvalContext = {};

beforeAll(() => {
addDataTreeToContext({
EVAL_CONTEXT: evalContext,
const EVAL_CONTEXT = getDataTreeContext({
dataTree: dataTree as unknown as DataTree,
configTree,
isTriggerBased: true,
});

Object.assign(evalContext, EVAL_CONTEXT);
addPlatformFunctionsToEvalContext(evalContext);
});

Expand Down
4 changes: 2 additions & 2 deletions app/client/src/workers/Evaluation/__tests__/evaluate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ describe("evaluateSync", () => {
errors: [
{
errorMessage: {
name: "ReferenceError",
message: "setImmediate is not defined",
name: "TypeError",
message: "setImmediate is not a function",
},
errorType: "PARSE",
kind: {
Expand Down
48 changes: 34 additions & 14 deletions app/client/src/workers/Evaluation/evaluate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
PrimitiveErrorModifier,
TypeErrorModifier,
} from "./errorModifier";
import { addDataTreeToContext } from "ee/workers/Evaluation/Actions";
import { getDataTreeContext } from "ee/workers/Evaluation/Actions";
import { set } from "lodash";
import { klona } from "klona";
import { getEntityNameAndPropertyPath } from "ee/workers/Evaluation/evaluationUtils";
Expand Down Expand Up @@ -103,7 +103,7 @@ const ignoreGlobalObjectKeys = new Set([
"location",
]);

function resetWorkerGlobalScope() {
export function resetWorkerGlobalScope() {
const jsLibraryAccessorSet = JSLibraryAccessor.getSet();

for (const key of Object.keys(self)) {
Expand Down Expand Up @@ -273,14 +273,15 @@ export const createEvaluationContext = (args: createEvaluationContextArgs) => {
Object.assign(EVAL_CONTEXT, context.globalContext);
}

addDataTreeToContext({
EVAL_CONTEXT,
const dataTreeContext = getDataTreeContext({
dataTree,
configTree,
removeEntityFunctions: !!removeEntityFunctions,
isTriggerBased,
});

Object.assign(EVAL_CONTEXT, dataTreeContext);

overrideEvalContext(EVAL_CONTEXT, context?.overrideContext);

return EVAL_CONTEXT;
Expand Down Expand Up @@ -373,7 +374,8 @@ export default function evaluateSync(
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
evalArguments?: Array<any>,
configTree?: ConfigTree,
configTree: ConfigTree = {},
scopeCache?: EvalContext,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we name the variable to be able to explain it's usecase.

Suggested change
scopeCache?: EvalContext,
evalContextCache?: EvalContext,

): EvalResult {
return (function () {
const errors: EvaluationError[] = [];
Expand All @@ -394,16 +396,34 @@ export default function evaluateSync(
};
}

resetWorkerGlobalScope();
self["$isDataField"] = true;
const EVAL_CONTEXT: EvalContext = {};

setEvalContext({
dataTree,
configTree,
isDataField: true,
isTriggerBased: isJSCollection,
context,
evalArguments,
});
///// Adding callback data
EVAL_CONTEXT.ARGUMENTS = evalArguments;
//// Adding contextual data not part of data tree
EVAL_CONTEXT.THIS_CONTEXT = context?.thisContext || {};

if (context?.globalContext) {
Object.assign(EVAL_CONTEXT, context.globalContext);
}

if (scopeCache) {
Object.assign(EVAL_CONTEXT, scopeCache);
} else {
const dataTreeContext = getDataTreeContext({
dataTree,
configTree,
removeEntityFunctions: false,
isTriggerBased: isJSCollection,
});

Object.assign(EVAL_CONTEXT, dataTreeContext);
}

overrideEvalContext(EVAL_CONTEXT, context?.overrideContext);

Object.assign(self, EVAL_CONTEXT);

try {
result = indirectEval(script);
Expand Down
Loading