ds4/src/expression-evaluation/evaluator.ts

38 lines
1.2 KiB
TypeScript

// SPDX-FileCopyrightText: 2022 Johannes Loher
//
// SPDX-License-Identifier: MIT
import { Validator } from "./validator";
export class Evaluator<Context extends object> {
context?: Context;
validator: Validator;
constructor({
context,
predicate = Validator.defaultPredicate,
}: { context?: Context; predicate?: (identifier: string) => boolean } = {}) {
let actualPredicate = predicate;
if (context) {
this.context = new Proxy(context, {
has: () => true,
get: (t, k) => (k === Symbol.unscopables ? undefined : t[k as keyof typeof t]),
});
actualPredicate = (identifier: string) =>
predicate(identifier) || Object.getOwnPropertyNames(Math).includes(identifier);
}
this.validator = new Validator(actualPredicate);
}
evaluate(expression: string): unknown {
this.validator.validate(expression);
const body = `with (sandbox) { return ${expression}; }`;
const evaluate = new Function("sandbox", body);
return evaluate(this.context ?? {});
}
}
export const defaultEvaluator = new Evaluator();
export const mathEvaluator = new Evaluator({ context: Math });