Javascript – Alternative for eval() in javascript for expression evaluation

computation-expressionsjavascriptparsing

I'm looking at the alternative that can substitute the use of eval() and new Function() javascript techniques. I'm developing a solution build with javascript and the platform on which it is built (Salesforce) recently has announced they're introducing CSP (content security policy) that will block the use of eval(), and other unsafe functions.

My solution is using eval function to evaluate string expressions and do some other magic stuff. I'm looking for some alternative, ideally without writing my own parser.

As I have mentioned, I use eval to evaluate expressions. Expressions that should be to be supported are usually like:

  • String comparison eval("'something' == 'something'") // return true
  • Calculations eval("2 + 2 * 3)" // return 8
  • && and || support eval("1 == 1 && 'cat' == 'dog'") // return false
  • Conditional operators,
    • at least ternary eval("(1 == 2 ? 'dog' : 'cat')") // return "cat"
    • full if-else would be really great: eval("if(1 == 2) { 'dog' } else if (1 == 3) { 'dog' } else { 'nothing' }") // return "nothing"
  • Some basic Math class methods, e.g.: eval("Math.ceil(12.313)"); // return 13

Capabilities that would be really great to have

  • Inject variable new Function("var item = this; item.number = 10;", item); // item is variable defined outside of eval and I want to dynamically modify it within eval()
  • Inject function definition eval("invert('123')") // return 321, invert() is a function defined somewhere else

I'm looking for something that is:

  • Relatively close to Javascript syntax (but I would accept if it would be some different language that can be interpreted by some js library compliant with CSP)
  • Not too much dependent on other libraries
  • Can be loaded without node.js etc (standalone js library)

Best Answer

What you are looking for is a simple expression language that can be evaluated from within ECMAScript (which is just another way of saying there exists an interpreter written in ECMAScript). Thankfully, such a language and interpreter already exists: Jexl.

Jexl is a simple ECMAScript expression language that features pretty much everything you listed:

  • unary and binary operators, mathematical, logical and string operations,
  • comparison operators,
  • a conditional operator, and
  • you can pass a context object whose properties can be accessed like global variables in the expression.

This last one is not exactly what you are asking about, because you were asking about accessing arbitrary ECMAScript identifiers, but it is arguably more safe: you can only access what is explicitly passed in. And if you really wanted to, you could pass in the context object { window: window } and then your expression has access to the global window object and can do every evil thing you never imagined.

It also has some features you didn't list:

  • collections with filter operations: listOfPeople[.name == "John"] will return a sub-array of listOfPeople with only those people whose name property is "John" and
  • transformation pipelines: "A;B;C"|lower|split(";") // => ["a", "b", "c"].

It sounds like this is exactly what you are looking for.

Related Topic