2021-04-26 05:41:32 +00:00
|
|
|
import {
|
|
|
|
|
DataTree,
|
|
|
|
|
EvaluationSubstitutionType,
|
|
|
|
|
} from "entities/DataTree/dataTreeFactory";
|
2020-10-21 04:25:32 +00:00
|
|
|
import {
|
2021-01-04 10:16:08 +00:00
|
|
|
DependencyMap,
|
2020-10-21 04:25:32 +00:00
|
|
|
EVAL_WORKER_ACTIONS,
|
|
|
|
|
EvalError,
|
|
|
|
|
EvalErrorTypes,
|
2021-07-07 09:59:44 +00:00
|
|
|
EvaluationError,
|
|
|
|
|
PropertyEvaluationErrorType,
|
2021-02-22 05:00:16 +00:00
|
|
|
} from "utils/DynamicBindingUtils";
|
2021-01-04 10:16:08 +00:00
|
|
|
import {
|
|
|
|
|
CrashingError,
|
2021-04-27 13:39:52 +00:00
|
|
|
getSafeToRenderDataTree,
|
2021-01-04 10:16:08 +00:00
|
|
|
removeFunctions,
|
|
|
|
|
validateWidgetProperty,
|
|
|
|
|
} from "./evaluationUtils";
|
2021-02-22 11:14:08 +00:00
|
|
|
import DataTreeEvaluator from "workers/DataTreeEvaluator";
|
2020-10-21 04:25:32 +00:00
|
|
|
|
|
|
|
|
const ctx: Worker = self as any;
|
|
|
|
|
|
2021-01-04 10:16:08 +00:00
|
|
|
let dataTreeEvaluator: DataTreeEvaluator | undefined;
|
2020-10-21 04:25:32 +00:00
|
|
|
|
2020-12-28 08:42:43 +00:00
|
|
|
//TODO: Create a more complete RPC setup in the subtree-eval branch.
|
2020-12-29 09:25:56 +00:00
|
|
|
function messageEventListener(
|
|
|
|
|
fn: (message: EVAL_WORKER_ACTIONS, requestData: any) => void,
|
|
|
|
|
) {
|
2020-12-28 08:42:43 +00:00
|
|
|
return (e: MessageEvent) => {
|
2020-12-29 09:25:56 +00:00
|
|
|
const startTime = performance.now();
|
2021-05-13 08:35:39 +00:00
|
|
|
const { method, requestData, requestId } = e.data;
|
2020-12-28 08:42:43 +00:00
|
|
|
const responseData = fn(method, requestData);
|
2020-12-29 09:25:56 +00:00
|
|
|
const endTime = performance.now();
|
|
|
|
|
ctx.postMessage({
|
|
|
|
|
requestId,
|
|
|
|
|
responseData,
|
|
|
|
|
timeTaken: (endTime - startTime).toFixed(2),
|
|
|
|
|
});
|
2020-12-28 08:42:43 +00:00
|
|
|
};
|
|
|
|
|
}
|
2020-10-21 04:25:32 +00:00
|
|
|
|
2020-12-28 08:42:43 +00:00
|
|
|
ctx.addEventListener(
|
|
|
|
|
"message",
|
2020-12-29 09:25:56 +00:00
|
|
|
messageEventListener((method, requestData: any) => {
|
|
|
|
|
switch (method) {
|
2020-12-28 08:42:43 +00:00
|
|
|
case EVAL_WORKER_ACTIONS.EVAL_TREE: {
|
2021-05-13 08:35:39 +00:00
|
|
|
const { unevalTree, widgetTypeConfigMap } = requestData;
|
2021-01-04 10:16:08 +00:00
|
|
|
let dataTree: DataTree = unevalTree;
|
|
|
|
|
let errors: EvalError[] = [];
|
2021-02-22 11:14:08 +00:00
|
|
|
let logs: any[] = [];
|
2021-01-04 10:16:08 +00:00
|
|
|
let dependencies: DependencyMap = {};
|
2021-06-04 07:09:36 +00:00
|
|
|
let dataTreeObject: any = {};
|
2021-07-08 07:04:47 +00:00
|
|
|
let evaluationOrder: string[] = [];
|
|
|
|
|
let removedPaths: string[] = [];
|
2020-12-28 08:42:43 +00:00
|
|
|
try {
|
2021-01-04 10:16:08 +00:00
|
|
|
if (!dataTreeEvaluator) {
|
|
|
|
|
dataTreeEvaluator = new DataTreeEvaluator(widgetTypeConfigMap);
|
2021-06-04 07:09:36 +00:00
|
|
|
dataTreeObject = dataTreeEvaluator.createFirstTree(unevalTree);
|
|
|
|
|
dataTree = dataTreeObject.dataTree;
|
|
|
|
|
evaluationOrder = dataTreeObject.evaluationOrder;
|
2021-07-08 07:04:47 +00:00
|
|
|
removedPaths = dataTreeObject.removedPaths;
|
2021-01-04 10:16:08 +00:00
|
|
|
} else {
|
2021-06-04 07:09:36 +00:00
|
|
|
dataTreeObject = dataTreeEvaluator.updateDataTree(unevalTree);
|
|
|
|
|
dataTree = dataTreeObject.dataTree;
|
|
|
|
|
evaluationOrder = dataTreeObject.evaluationOrder;
|
2021-07-08 07:04:47 +00:00
|
|
|
removedPaths = dataTreeObject.removedPaths;
|
2021-01-04 10:16:08 +00:00
|
|
|
}
|
|
|
|
|
|
2020-12-28 08:42:43 +00:00
|
|
|
// We need to clean it to remove any possible functions inside the tree.
|
|
|
|
|
// If functions exist, it will crash the web worker
|
2021-06-04 07:09:36 +00:00
|
|
|
dataTree = dataTree && JSON.parse(JSON.stringify(dataTree));
|
2021-01-14 14:37:21 +00:00
|
|
|
dependencies = dataTreeEvaluator.inverseDependencyMap;
|
2021-01-04 10:16:08 +00:00
|
|
|
errors = dataTreeEvaluator.errors;
|
|
|
|
|
dataTreeEvaluator.clearErrors();
|
2021-02-22 11:14:08 +00:00
|
|
|
logs = dataTreeEvaluator.logs;
|
|
|
|
|
dataTreeEvaluator.clearLogs();
|
2020-12-28 08:42:43 +00:00
|
|
|
} catch (e) {
|
2021-01-04 10:16:08 +00:00
|
|
|
if (dataTreeEvaluator !== undefined) {
|
|
|
|
|
errors = dataTreeEvaluator.errors;
|
2021-02-22 11:14:08 +00:00
|
|
|
logs = dataTreeEvaluator.logs;
|
2021-01-04 10:16:08 +00:00
|
|
|
}
|
|
|
|
|
if (!(e instanceof CrashingError)) {
|
|
|
|
|
errors.push({
|
|
|
|
|
type: EvalErrorTypes.UNKNOWN_ERROR,
|
|
|
|
|
message: e.message,
|
|
|
|
|
});
|
|
|
|
|
console.error(e);
|
|
|
|
|
}
|
2021-04-27 13:39:52 +00:00
|
|
|
dataTree = getSafeToRenderDataTree(unevalTree, widgetTypeConfigMap);
|
2021-01-04 10:16:08 +00:00
|
|
|
dataTreeEvaluator = undefined;
|
2020-12-28 08:42:43 +00:00
|
|
|
}
|
2021-06-04 07:09:36 +00:00
|
|
|
// step 6: eval order
|
2021-01-04 10:16:08 +00:00
|
|
|
return {
|
|
|
|
|
dataTree,
|
|
|
|
|
dependencies,
|
|
|
|
|
errors,
|
2021-06-04 07:09:36 +00:00
|
|
|
evaluationOrder,
|
2021-02-22 11:14:08 +00:00
|
|
|
logs,
|
2021-07-08 07:04:47 +00:00
|
|
|
removedPaths,
|
2021-01-04 10:16:08 +00:00
|
|
|
};
|
2020-12-28 08:42:43 +00:00
|
|
|
}
|
2021-01-14 14:37:21 +00:00
|
|
|
case EVAL_WORKER_ACTIONS.EVAL_ACTION_BINDINGS: {
|
|
|
|
|
const { bindings, executionParams } = requestData;
|
2021-01-04 10:16:08 +00:00
|
|
|
if (!dataTreeEvaluator) {
|
2021-02-16 10:29:08 +00:00
|
|
|
return { values: undefined, errors: [] };
|
2021-01-04 10:16:08 +00:00
|
|
|
}
|
2021-01-14 14:37:21 +00:00
|
|
|
|
|
|
|
|
const values = dataTreeEvaluator.evaluateActionBindings(
|
|
|
|
|
bindings,
|
|
|
|
|
executionParams,
|
2021-01-04 10:16:08 +00:00
|
|
|
);
|
2021-01-14 14:37:21 +00:00
|
|
|
|
2021-01-22 08:10:00 +00:00
|
|
|
const cleanValues = removeFunctions(values);
|
|
|
|
|
|
2021-01-04 10:16:08 +00:00
|
|
|
const errors = dataTreeEvaluator.errors;
|
|
|
|
|
dataTreeEvaluator.clearErrors();
|
2021-01-22 08:10:00 +00:00
|
|
|
return { values: cleanValues, errors };
|
2020-12-28 08:42:43 +00:00
|
|
|
}
|
|
|
|
|
case EVAL_WORKER_ACTIONS.EVAL_TRIGGER: {
|
2021-05-13 08:35:39 +00:00
|
|
|
const { callbackData, dataTree, dynamicTrigger } = requestData;
|
2021-01-04 10:16:08 +00:00
|
|
|
if (!dataTreeEvaluator) {
|
|
|
|
|
return { triggers: [], errors: [] };
|
|
|
|
|
}
|
2021-06-04 07:09:36 +00:00
|
|
|
dataTreeEvaluator.updateDataTree(dataTree);
|
|
|
|
|
const evalTree = dataTreeEvaluator.evalTree;
|
2021-07-07 09:59:44 +00:00
|
|
|
const {
|
|
|
|
|
errors: evalErrors,
|
|
|
|
|
triggers,
|
|
|
|
|
}: {
|
|
|
|
|
errors: EvaluationError[];
|
|
|
|
|
triggers: Array<any>;
|
|
|
|
|
} = dataTreeEvaluator.getDynamicValue(
|
2020-12-28 08:42:43 +00:00
|
|
|
dynamicTrigger,
|
2021-03-13 14:12:21 +00:00
|
|
|
evalTree,
|
2021-04-26 05:41:32 +00:00
|
|
|
EvaluationSubstitutionType.TEMPLATE,
|
2020-12-28 08:42:43 +00:00
|
|
|
true,
|
|
|
|
|
callbackData,
|
|
|
|
|
);
|
2021-01-25 11:19:31 +00:00
|
|
|
const cleanTriggers = removeFunctions(triggers);
|
2021-02-22 05:00:16 +00:00
|
|
|
// Transforming eval errors into eval trigger errors. Since trigger
|
|
|
|
|
// errors occur less, we want to treat it separately
|
2021-07-07 09:59:44 +00:00
|
|
|
const errors = evalErrors
|
|
|
|
|
.filter(
|
|
|
|
|
(error) => error.errorType === PropertyEvaluationErrorType.PARSE,
|
|
|
|
|
)
|
|
|
|
|
.map((error) => ({
|
|
|
|
|
...error,
|
|
|
|
|
message: error.errorMessage,
|
|
|
|
|
type: EvalErrorTypes.EVAL_TRIGGER_ERROR,
|
|
|
|
|
}));
|
2021-01-25 11:19:31 +00:00
|
|
|
return { triggers: cleanTriggers, errors };
|
2020-12-28 08:42:43 +00:00
|
|
|
}
|
|
|
|
|
case EVAL_WORKER_ACTIONS.CLEAR_CACHE: {
|
2021-01-04 10:16:08 +00:00
|
|
|
dataTreeEvaluator = undefined;
|
2020-12-28 08:42:43 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
case EVAL_WORKER_ACTIONS.CLEAR_PROPERTY_CACHE: {
|
|
|
|
|
const { propertyPath } = requestData;
|
2021-01-04 10:16:08 +00:00
|
|
|
if (!dataTreeEvaluator) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
dataTreeEvaluator.clearPropertyCache(propertyPath);
|
2020-12-28 08:42:43 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
case EVAL_WORKER_ACTIONS.CLEAR_PROPERTY_CACHE_OF_WIDGET: {
|
|
|
|
|
const { widgetName } = requestData;
|
2021-01-04 10:16:08 +00:00
|
|
|
if (!dataTreeEvaluator) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
dataTreeEvaluator.clearPropertyCacheOfWidget(widgetName);
|
2020-12-28 08:42:43 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
case EVAL_WORKER_ACTIONS.VALIDATE_PROPERTY: {
|
2021-05-13 08:35:39 +00:00
|
|
|
const { property, props, validation, value } = requestData;
|
2021-01-25 11:19:31 +00:00
|
|
|
return removeFunctions(
|
2021-04-21 14:34:25 +00:00
|
|
|
validateWidgetProperty(property, value, props, validation),
|
2020-12-28 08:42:43 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
default: {
|
2021-01-04 10:16:08 +00:00
|
|
|
console.error("Action not registered on worker", method);
|
2020-12-23 14:18:46 +00:00
|
|
|
}
|
2020-10-24 14:29:53 +00:00
|
|
|
}
|
2020-12-28 08:42:43 +00:00
|
|
|
}),
|
|
|
|
|
);
|