cache eval() result - javascript

In Javascript, is it possible to cache the results of eval?
For example it would be great if I could:
var str="some code...";
var code = eval(str);
//later on...
code.reExecute();

You can make str the body of a function and use New Function instead of eval.
var fn = new Function([param1, param2,...], str);
And reuse it by calling fn(p1, p2,...)
Or use eval, and make str be something like
var fn = eval("(function(a){alert(a);})")

The result of the 'eval' call is to evaluate the javascript. Javascript (in browsers) does not offer any kind of 'compile' function.
The closest you could get (using eval) is:
var cached_func = eval('function() {' + str + '}');
Then you can call the cached_func later.

Make a function that evaluates and stores the result in a cache object for asynchronous retrieval:
var Cache = { } ;
function evalString(string) {
var evaluated = eval(string) ;
Cache.evalResult = evaluated ;
}
You may then call that code like this:
Cache.evalResult(/* arguments */) ;
On a side note, "eval is evil" as http://www.jslint.com will tell you, since it may open the door for external manipulation of your content. Why do you need to eval that function it in the first place?

Related

In javascript, how to set function parameter names when creating function via "new Function()"?

Trying to set the parameter names in a function, via new Function(fnBody), to correlate to dynamic function-body-text variables.
const myFnBody = " return myParam; "; // dynamic fn-text, expecting 'myParam' variable.
const myFunc = new Function(myFnBody); // create the function with the body-text.
const myParamVal = "Hello world."; // setup argument
console.log(myFunc(myParamVal)); // output: undefined, not 'Hello world.' as desired.
console output is undefined because "myParam" isn't linked to the first argument (arguments[0]) in the function call context.
Want function to assign first arg (arguments[0]) to a "myParam" parameter, as in:
const myFunc = function (myParam) { return myParam; }
I need this for running dynamic code written with parameter-names in mind: similar to "require" and "exports" from CommonJS. The code is expecting values passed with specific parameter/variable names.
The best i've been able to come up with is to pre-set a variable via the arguments collection, then add the actual dynamic function-text:
let dynamicFnText = {SOME USER DEFINED FN BODY-TEXT, such as "return myParam;"};
let myFnBody = ""; // start the fn-body as text (string)
myFnBody += "const myParam = arguments[0];"; // prefix a parameter value via the arguments
myFnBody += dynamicFnText; // append the dynamic fn text, which expects 'myParam' variable.
let myFunc = new Function(myFnBody);
let myParam = "Hello world.";
console.log(myFunc(myParam)); // 'Hello world."
Using eval: Yes, i could use eval(), as in:
let myFunc = eval("(function (myParam) {" + dynamicFnText + "})"); // fn with 'myParam'
However, i'm trying to avoid the "evil" eval() function. Should i not be concerned about using eval() in this manner?
I guess i was expecting some sort of .setParameters() method on the function (new Function()) instance. Or something like new Function(paramNamesArray, fnBody).
Any help appreciated. Thanks.
Or something like new Function(paramNamesArray, fnBody)
Close! It would be new Function(...paramNamesArray, fnBody).
The Function constructor supports multiple arguments. The last argument is the function body. Any arguments before that are the names of the parameters.
So in your case with myParam, you'd pass "myParam: as the first argument:
const myFunc = new Function("myParam", myFnBody);
Live Example:
const myFnBody = " return myParam; ";
const myFunc = new Function("myParam", myFnBody);
const myParamVal = "Hello world.";
console.log(myFunc(myParamVal));
Going back to your paramNamesArray concept, you might do:
const myFunc = new Function(...paramNamesArray, myFnBody);
Live Example:
const myFnBody = " return myParam; ";
const paramNamesArray = ["myParam"];
const myFunc = new Function(...paramNamesArray, myFnBody);
const myParamVal = "Hello world.";
console.log(myFunc(myParamVal));
However, i'm trying to avoid the "evil" eval() function. Should i not be concerned about using eval() in this manner?
new Function is only the tiniest bit less of a problem than using eval. Both allow arbitrary code execution, which means both require that you fully trust the code you're evaluating with them. You don't want to take code from User A and run that code in User B's context (unless User B expressly expects and allows that, like when we click "Run code snippet" here on SO). The very minor way that new Function is slightly less problematic than eval is that it can't be used to access things in local scope, and eval can. (You can fix that by using indirect eval, which also can't use local scope.)
There are times when eval or new Function is what you need to use, but those use cases are very rare. Bottom line: If you're worried about using eval, worry about using new Function. It's (almost) just as "bad."
Just specify the parameter name in addition to the function body when invoking new Function:
const myFnBody = " return myParam; "; // dynamic fn-text, expecting 'myParam' variable.
const myFunc = new Function('myParam', myFnBody); // create the function with the body-text.
const myParamVal = "Hello world."; // setup argument
console.log(myFunc(myParamVal));
Since this comes from the user, make sure the user provides a list of arguments their function will accept, then list them in the new Function argument list as needed.
Should i not be concerned about using eval() in this manner?
No, you shouldn't - new Function is just as unsafe as eval. If you'll be using new Function, you may as well be using eval (from a security standpoint), since it allows for the execution of dynamic (and possibly unsafe) code.

How do you call fat arrow function stored in string without using eval?

How do you call fat arrow function like below (stored in string) without using eval?
"g => { alert(g); }"
With using eval, the below code is working fine, but I want to avoid using eval.
eval("g => { alert(g); }")('hello')
I hope I could do something like below using "new Function", but I have no luck so far.
new Function("g => { alert(g); }")('hello')
Thanks so much in advance.
from MDN
The Function constructor creates a new Function object. Calling the constructor directly can create functions dynamically, but suffers from security and performance issues similar to eval.
that said, you can easyly parse your string to use function constructor, for example:
const str = [g,body] = "g => { console.log(g); }".split(" => ");
var myFunc = new Function(g, body);
myFunc("hello");
const str2 = [args,body] = "(h,i) => {console.log(h,i);}".split(" => ");
const [h,i] = args.replace(/\(|\)/g,"").split(",");
var myFunc2 = new Function(h,i, body);
myFunc2("hello","buddy");
Anything you do, including your own JS interpreter, is going to be a functional equivalent to eval. Calling eval() function is not a security gap by itself. Executing unsanitized code is what is a security issue, and that's the thing you are trying to do here. Using eval or any equivalent creates an XSS vulnerability.
If you use real interpreter written in JS, you may be able to sandbox the code and mitigate the risk, but it's still a grey area.
OTOH, if you have valid reasons to consider the code in question to be sanitized, there's no good reason to not use eval.
Be aware that you can't reliably sanitize JS code. Anything can be done with very little JS syntax available, so either the code is from a trusted source or it should never be run.
All that said, perhaps the simplest way to get your function compiled with new Function is
(new Function('return ('+code+')'))()
This is almost exact equivalent to calling eval(code), just without any access to the local namespace. Using eval() directly should be slightly faster (omits creating unnecessary function object).
in theory, this works. Still seems like a bad idea.
var fatso = "g => { alert(g); }";
var s = document.createElement("script");
s.innerText = "function callMe(f) { var a = " + fatso + "; a(f) }"
document.head.appendChild(s);
callMe("hello");

Executing javascript functions stored as string using AngularJS

Is there any way to inject JavaScript code stored in a string in AngularJS controllers dynamically?
var dynamicJS = "function DoSomething(value){var x = 1+1 return 2;}"
I have to dynamically inject the above function into my AngularJS controller and have it be called on selection change of drop-down, the values of which are bound to the AngularJS controller. The reason is the JavaScript function would vary based on my each row of data which I have based on my configuration at an application level. I am aware we can make use of $eval but would like to get some better approaches, if any exist.
Can anyone give me any idea on this?
Note: I am using AngularJS v1.4.5
I would believe the easier way will be to parse the String and then use the function constructor.
Something like this:
var DoSomething = new Function('value', 'var x = 1+1 return 2');
There are multiple ways to achieve this.
Function object
Create a Function, passing the one argument (i.e. value) and functionBody as parameters:
var dynamicJS = "var x = 1+1; return 2;"
var DoSomething = new Function("value", dynamicJS );
eval()
While arguably more dangerous1, eval() can be used.
var dynamicJS = "function DoSomething(value){var x = 1+1 return 2;}"\
eval(dynamicJS);
Because you mentioned in a comment
"it is intranet application and not going to outer world. no issues on this for this req."
this would likely be fine but please read the section below.
Caution
From the this section of the MDN documentation about eval():
Don't use eval needlessly!
eval() is a dangerous function, which executes the code it's passed with the privileges of the caller. If you run eval() with a string that could be affected by a malicious party, you may end up running malicious code on the user's machine with the permissions of your webpage / extension. More importantly, third party code can see the scope in which eval() was invoked, which can lead to possible attacks in ways to which the similar Function is not susceptible.
eval() is also generally slower than the alternatives, since it has to
invoke the JS interpreter, while many other constructs are optimized by modern JS engines.
There are safer (and faster!) alternatives to eval() for common use-cases.
2
See a demonstration of these techniques utilized below. Click on the buttons corresponding to each technique to see the output on the console.
var dynamicJS = "function DoSomething(value){var x = 1+1; return 2;}"
var functionBody = "var x = 1+1; return 2;";
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('eval').addEventListener('click', function() {
eval(dynamicJS);
console.log('DoSomething(3) -> ',DoSomething(3));
});
document.getElementById('function').addEventListener('click', function() {
var dynamicFunction = new Function("value", functionBody);
console.log('dynamic function(3) ->',dynamicFunction(3));
});
});
<button id="eval">click to eval</button>
<button id="function">click to use Function</button>
1https://stackoverflow.com/a/4599946/1575353
2https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#Don't_use_eval_needlessly!
Perhaps try something like:
function myFunc(obj){
var param = obj.hasOwnProperty('param') ? obj.param : undefined;
console.log(param);
}
var funcString = "myFunc({ param: 'something' });",
Construct = new Function(funcString);
Construct();
Haven't tested it to be honest ... but this way you avoid eval().
more info on Function object

how to make javascript string a function call [duplicate]

This question already has answers here:
How to execute a JavaScript function when I have its name as a string
(36 answers)
Closed 6 years ago.
I have string logo.cr.Button and function
logo.cr.Button = function(){
//something
}
var strg = 'logo.cr.Button';
strg();
now somehow i have to make that string a function call
like strg(); but it is saying
strg is not a constructor
here
Generally when we write JavaScript functions the resulting function declaration looks like this:
function demo() {
// function stuff here
}
You’re probably more than aware that “In JavaScript Functions are first-class Objects”. It’s a phrase that is spouted everywhere, and for good reason. It’s a very powerful idea that has worked to elevate JavaScript to where it is. We’re not going into the details of first-class objects here. All we care about is the fact that, in JavaScript, functions are objects.
This means that the above function can also be declared by calling its Constructor:
var demo = new Function();
Now lets imagine we have a function with parameters and instructions:
function demo(name, age) {
console.log('my name is ' + name);
console.log('my age is ' + age);
}
and now to convert it to Constructor syntax:
var demo = new Function(
"name,age",
"console.log('my name is ' + name);" +
"console.log('my age is ' + age);"
);
This makes it pretty easy to see that these two functions are the same, they are just declared differently. The important difference is that one has easily accessible strings that we should be able to manipulate.
This applies to your function in a very similar way.
var strfunc = new Function ("", "logo.cr.Button()");
I can't seem to format this because I'm on mobile. But i will asap.
Use eval("logo.cr.Button")();
This will execute the function, of course if you have an object like:
var logo = {
cr: {
}
};
This won't work because JavaScript thinks you are using dot notation. When you write logo.cr.Button() JavaScript is looking for a function Button() within the object cr which is in the object logo.
I recommend changing the name to logoCrButton = function()...
You could use eval, but its not recommended.
Secury issues are just one reason, because an user might exploit eval to execute different code that is not supposed to be executed. Within this question it is explained fully.
var logo={cr:{}};
logo.cr.Button = function(){
console.log("something");
}
var string = "logo.cr.Button()";
eval(string);
If you can avoid eval then use a normal function call, an object or an array instead. For insteads Iterating through an array is much better and more stable compared to evaluating some parameters dynamically, as you can see here.
This second example does not use eval, but nevertheless you can call a certain function by using a string:
var obj={logo:{cr:{Button:function(){console.log("something");}}}};
var string = "logo.cr.Button";
function callFunctionByString(string,obj){
var parts = string.split('.');
parts.forEach(function(part){
obj = obj[part];
});
obj();
}
callFunctionByString(string,obj);
Hope this helps.

Dynamically execute a function in JavaScript

I would like to call a function whose name I have in a variable.
For example:
I get the string "pageTracker._trackpageview('/url/page1.page'); " dynamically and assign it to a variable as below
var myFunction = pageTracker._trackpageview('/url/page1.page');";
Now when I submit the page I want to execute the function which is in variable myFunction.
Thank you all.
function functionFromString(funcDef) {
try {
return (new Function("return function() {" + funcDef + "};"))();
} catch (e) {
alert(e);
return (function() {});
}
}
var myFunction = "pageTracker._trackpageview('/url/page1.page');";
var realFunction = functionFromString(myFunction);
realFunction();
Why do it this way?
Just doing eval runs the function right away. If there are errors thrown in the called function itself we can't tell the difference between that and an error in parsing. So by creating a function out of the text, we can separate when we parse it from when we execute it.
Just using newFunction = Function(myFunction) won't compile it, so it's slower. So using new Function() to return a function (that in turn creates a function) is our trick. We could use eval this way, too, but I like new Function better.
What others have said about being really careful with eval (and new Function()) is true. It can be an opening for malicious script.
You can do this with the JavaScript eval() function. Just be careful about controlling the value passed to eval() as it will execute whatever string it is given.
eval("pageTracker._trackpageview('/url/page1.page');");
You are not simply trying to execute a function whose name you have but a complex line of code with a receiver, a method name and a literal string argument. The only way to execute an arbitrary snippet of codes is with eval() But eval() is dangerous. If you're not very careful, someone can pass malignant code to your script that will be executed inside the eval() call.
You can make use of eval in javascript..
var myFunction = "pageTracker._trackpageview('/url/page1.page');";
//...
eval(myFunction);
Solution: Wrap the function
//define:
var myFunction = function (){pageTracker._trackpageview('/url/page1.page');}
//call:
myFunction();
Full Example:
<html>
<head>
<script type="text/javascript">
var foo = function (){alert('bar');}
</script>
</head>
<body onload="foo();"> </body>
</html>
But this way, you cannot check if parameter is correct url, or encode it ect. And I avoid eval as hell for known reasons.
I would prefer the harder, but more safe way - if it is a string, it can be parsed:
//test dub
pageTracker = {
_trackpageview: function(path) {alert(path)}
}
var str = "pageTracker._trackpageview('/url/page1.page')";
//get param
var urlpathregex = /\('([a-z0-9\-._~%!$&'()*+,;=:#\/]+)'\)/;
var param = urlpathregex.exec(str)[1];
//do some stuff/validation with param
[...]
//get object and function name
var funcregex = /([a-zA-Z0-9_]+)?\.?([a-zA-Z0-9_]+)(?=\()/;
var match = funcregex.exec(str);
var obj, func;
obj = match[1];
func = match[2];
//invoke
window[obj][func](param);
This is just an example, and not copy&paste ready code :) Because to begin with - if you get dynamically "pageTracker._trackpageview('/url/page1.page')" as a string, there is some code smell here already.

Categories

Resources