11

I thought that eval() was supported in Lightning in Summer 18. According to the release notes, it is:

The eval() function is now available in Locker Service, even when Strict CSP is enabled. This addition improves support for third-party libraries that evaluate code dynamically.

I've tried to use it (I have a component with admin-defined formula fields to be evaluated client-side), but I cannot save a component which uses eval(). In a simple test-case, my controller contains the following:

return eval('1');

When I try to save (even in Dev Console, I ruled out my IDE and I did check the API version in 43), I get an error from the linter:

ESLINT_ERROR: {c:SafeEval - CONTROLLER} line:col [18:20] --> Invalid SecureWindow API, eval was blacklisted : Source

I can get to it indirectly by having a static resource to wrapper up the eval like this:

window.nebcEval = function (expressionToEval) {
    return eval(expressionToEval);
}

Does this mean eval() is only supported in a static resource?

1

Aidan, we have found an issue with the liner, and in some scenarios, it blocked eval and returned the error that you have encountered. We have submitted fix, and you should have it within a couple of weeks in your environment!

  • 2
    Brilliant, I really appreciate that you and others at Salesforce are reading these posts, responding to them and, when necessary, fixing things for us – Aidan Aug 22 '18 at 7:36
2

After doing some digging, i realized that the enablement of eval() for locker service might be for a entirely different use case.

Every time you log in to a website, a session is established so you don’t have to log in again for every page load. The browser usually stores sessions in cookies and all cookies are stored in a “cookie jar.” Locker Service protects the cookie jar from unauthorized use, but previously had to disable “unsafe-eval” with Content Security Policy (CSP) to make that protection effective.

Beginning with Summer ‘18, Locker Service provides a safe eval() and a safe Function() to improve compatibility with third-party code while maintaining full protection, and turning on CSP doesn’t disable those APIs anymore. For example, templating engines can really improve the maintainability of a project when creating HTML. To accelerate the output, those engines often use Function() to produce a compiled version.

If your project depends directly on a templating engine (such as the one provided by the hugely popular underscore.js and lodash.js), or indirectly via another dependency (such as Backbone.js), Locker Service has you covered. Secure Function() will ensure everything runs normally, while at the same time preventing access to other namespaces or to the Lightning framework itself.

What's new in locker service

Based on the above here my guess is static resource might be your only option. I wouldn't suggest using eval() unless absolutely necessary for your use case!

  • 1
    Excellent answer... thanks for finding that. I know you shouldn't use eval or Function() unless necessary, but the only other way I can think of to have client-side evaluated formulas would be to come up with my own formula language and compile it myself. I leave writing parsers and compilers to the clever people :) – Aidan Aug 14 '18 at 8:49
  • @Aidan I agree! – codeyinthecloud Aug 14 '18 at 12:59
0

Limitation: In Locker Service, eval() always works in the global scope of the namespace. The eval() function can’t access the local variables within the scope in which it’s called. Normally, eval() has two modes of execution. When you invoke eval() directly, it works in the local scope. When you invoke it via a reference, it works in the global scope. Locker Service supports only the latter.

For example, suppose that you execute the following code.

window.foo = 1;
function bar() {
  var foo = 2;
  return eval("foo");
}

A call to bar() returns 2 when evaluation is performed in the local scope, and returns 1 when it’s performed in the global scope. If you must use variables from the local scope, refactor your code. Use a Function(), declare the local variables as parameters, pass them as arguments, and add a return statement.

window.foo = 1;
function bar() {
  var foo = 2;
  return Function("foo","return foo")(foo);
}

Reference :- Changes in Locker Service

So what you have specified in your simple Test case,

return eval('1');

Check your code for the local scope as per the definition above.

  • Thanks for trying to help, but the problem I'm having is with saving the Lightning Component, and having the linter reject it. I don't think that the variable scope Lightning uses at runtime is relevant. In fact, the way I'm using a constant expression in the eval means, to me, that the scope is just irrelevant. – Aidan Aug 13 '18 at 15:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.