expression-language
Version:
Javascript implementation of symfony/expression-language
140 lines (139 loc) • 5.56 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _Lexer = require("./Lexer");
var _Parser = _interopRequireDefault(require("./Parser"));
var _Compiler = _interopRequireDefault(require("./Compiler"));
var _ParsedExpression = _interopRequireDefault(require("./ParsedExpression"));
var _ArrayAdapter = _interopRequireDefault(require("./Cache/ArrayAdapter"));
var _LogicException = _interopRequireDefault(require("./LogicException"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
class ExpressionLanguage {
constructor(cache = null, providers = []) {
/**
* Compiles an expression source code.
*
* @param {Expression|string} expression The expression to compile
* @param {Array} names An array of valid names
*
* @returns {string} The compiled javascript source code
*/
_defineProperty(this, "compile", (expression, names = []) => {
return this.getCompiler().compile(this.parse(expression, names).getNodes()).getSource();
});
/**
* Evaluate an expression
*
* @param {Expression|string} expression The expression to compile
* @param {Object} values An array of values
*
* @returns {*} The result of the evaluation of the expression
*/
_defineProperty(this, "evaluate", (expression, values = {}) => {
return this.parse(expression, Object.keys(values)).getNodes().evaluate(this.functions, values);
});
/**
* Parses an expression
*
* @param {Expression|string} expression The expression to parse
* @param {Array} names An array of valid names
* @returns {ParsedExpression} A ParsedExpression instance
*/
_defineProperty(this, "parse", (expression, names) => {
if (expression instanceof _ParsedExpression.default) {
return expression;
}
names.sort((a, b) => {
let a_value = a,
b_value = b;
if (typeof a === "object") {
a_value = Object.values(a)[0];
}
if (typeof b === "object") {
b_value = Object.values(b)[0];
}
return a_value.localeCompare(b_value);
});
let cacheKeyItems = [];
for (let name of names) {
let value = name;
if (typeof name === "object") {
let tmpName = Object.keys(name)[0],
tmpValue = Object.values(name)[0];
value = tmpName + ":" + tmpValue;
}
cacheKeyItems.push(value);
}
let cacheItem = this.cache.getItem(this.fixedEncodeURIComponent(expression + "//" + cacheKeyItems.join("|"))),
parsedExpression = cacheItem.get();
if (null === parsedExpression) {
let nodes = this.getParser().parse((0, _Lexer.tokenize)(expression), names);
parsedExpression = new _ParsedExpression.default(expression, nodes);
cacheItem.set(parsedExpression);
this.cache.save(cacheItem);
}
return parsedExpression;
});
_defineProperty(this, "fixedEncodeURIComponent", str => {
return encodeURIComponent(str).replace(/[!'()*]/g, function (c) {
return '%' + c.charCodeAt(0).toString(16);
});
});
/**
* Registers a function
*
* @param {string} name The function name
* @param {function} compiler A function able to compile the function
* @param {function} evaluator A function able to evaluate the function
*
* @throws Error
*
* @see ExpressionFunction
*/
_defineProperty(this, "register", (name, compiler, evaluator) => {
if (null !== this.parser) {
throw new _LogicException.default("Registering functions after calling evaluate(), compile(), or parse() is not supported.");
}
this.functions[name] = {
compiler: compiler,
evaluator: evaluator
};
});
_defineProperty(this, "addFunction", expressionFunction => {
this.register(expressionFunction.getName(), expressionFunction.getCompiler(), expressionFunction.getEvaluator());
});
_defineProperty(this, "registerProvider", provider => {
for (let fn of provider.getFunctions()) {
this.addFunction(fn);
}
});
_defineProperty(this, "getParser", () => {
if (null === this.parser) {
this.parser = new _Parser.default(this.functions);
}
return this.parser;
});
_defineProperty(this, "getCompiler", () => {
if (null === this.compiler) {
this.compiler = new _Compiler.default(this.functions);
}
return this.compiler.reset();
});
this.functions = [];
this.parser = null;
this.compiler = null;
this.cache = cache || new _ArrayAdapter.default();
for (let provider of providers) {
this.registerProvider(provider);
}
}
_registerFunctions() {
// TODO figure out a way to replicate "constant" function from PHP
}
}
exports.default = ExpressionLanguage;