0

I have one js files . I load it using other javascrupt file using eval() function. I have seen eval is slow and with some other limtation. Since i need to store my JS file object in cache and use it anytime i need after apllication starts. I dont want to do eval() everytime.

Is there anyway to do it in simple way.

var evalObj;
if(evalObj) {
                console.log('eval object already evaluated');
                _myfunctionInJSFile_(layouts.FormatDate(startTime), threadName, level, categoryName, message);
            }
            else {

                evalObj = eval(fs.readFileSync('./myJSFile', 'utf8'));

                console.log('re evaluating  object ..' );
                _myfunctionInJSFile_(layouts.FormatDate(startTime), threadName, level,message);
            }

myJSFile

 var _sigmaAlarmHandler_ =function(args)
{
    var args = Array.prototype.slice.call(arguments);
    args.unshift();    
        console.log('Alarm : ', args);   
}

Either the conditional eval is not working.

Sohan
  • 6,252
  • 5
  • 35
  • 56
  • possible duplicate of [Parse JSON in JavaScript?](http://stackoverflow.com/questions/4935632/parse-json-in-javascript) – njzk2 Nov 24 '14 at 15:02
  • possible you have not understood the question. I am trying to evluate the Javascript file and use its function . – Sohan Nov 24 '14 at 15:05
  • has your object some methods or it just a collection of values? if it not contains some raw js code you can use `JSON.stringify()` and `JSON.parse()` methods – vp_arth Nov 24 '14 at 15:05
  • It do contains the methods – Sohan Nov 24 '14 at 15:06
  • yes.. i am doing this backend coding in node js – Sohan Nov 24 '14 at 15:07
  • why do you need to store and load the methods, rather that just the data? – njzk2 Nov 24 '14 at 15:07
  • I want to load the method since i need to call it and pass values to the JS files. JS file i am evaluating is an handler to listen to custom messages. – Sohan Nov 24 '14 at 15:08

3 Answers3

0

In node.js you can simple require your js-file:

var obj = require('./myJSFile');
obj.foo();

./myJSFile.js:

exports.foo = function() {
  console.log('foo');
}

This file becomes a module with exported functions, that you need.
It loads once, then every require reuse already loaded module.

vp_arth
  • 14,461
  • 4
  • 37
  • 66
  • Problem here is that, customer writes its own handler in pure JS.i.e myJSFile.js must be pure js – Sohan Nov 24 '14 at 15:12
  • The customer is writing their own JS? Why? – Clint Powell Nov 24 '14 at 15:14
  • To listen to the events like alarm events . I support plugin for shell,JS and .bat files of handlers. – Sohan Nov 24 '14 at 15:16
  • Yeah, seriously. You are letting a customer upload JS and executing? BTW, there is a way to do this, I had to do it a while back. I will find my code and post. – deitch Nov 24 '14 at 15:17
  • @deitch Yes I have this requirement where customer wirtes their own handlers and we support that format. The handlers are used by customers in thier production. – Sohan Nov 24 '14 at 15:19
  • And, you have any conventions anywhere(function names etc.) Why not a module convention? – vp_arth Nov 24 '14 at 15:20
  • @vp_arth . Well i read the file name from json configuration. I guess it is in global context – Sohan Nov 24 '14 at 15:20
  • @vp_arth Looking at basic knowledge of customers or their developers shell scripts/ or pure JS are easy instead to letting them dive into writing node_modules – Sohan Nov 24 '14 at 15:22
  • Sorry, but I can't to help you with this workflow, it's very-very poor. And I think, any solution you'll find, will be like `eval`, because all, that you want - to run raw js code in global context. – vp_arth Nov 24 '14 at 15:25
0

If it is not commonjs-compliant (i.e. using module.exports will not work), then you can run it in its own vm:

var vm = require('vm');
vm.runInNewContext(jscode,{/*globalvars*/});

where the second parameter is an object with global vars made available in the context in which the jscode is run. So if the second param is, say, {a:1,b:"foo"} then your jscode will run with the global variable a set to 1 and the global variable b set to "foo".

The jscode itself is a string that you load from a file or elsewhere.

Think of vm.runInNewContext() as "practice safe eval". Well, relatively safe, you can still do some dangerous stuff if you pass in particular vars, like process or file etc.

I used this for the declarative part of cansecurity http://github.com/deitch/cansecurity for nodejs

You can view the sample in the file lib/declarative.js

Here is the API for vm http://nodejs.org/api/vm.html

There are options to run in the same context, etc. But that is very risky.

When you actually run the code, using your example above:

_myfunctionInJSFile_(layouts.FormatDate(startTime), threadName, level,message);

you are looking to pass in 4 params: startTime, threadName, level, message and execute the function. The issue is that you cannot run the function on the current context. You need the function to be defined and run in the file. So you should have something like:

vm.runInNewContext(jscode,{startTime:layouts.FormatDate(startTime),threadName:threadName,level:level,message:message});

And then the jscode should look like

function _myfunctionInJSFile(startTime,threadName,level,message) {
  // do whatever you need to do
}
// EXECUTE IT - the above vars are set by the global context provide in vm.runInNewContext
_myfunctionInJSFile(startTime,threadName,level,message);

If you prefer to define the function and have it loaded and run in this context, then just use the commonjs format.

deitch
  • 14,019
  • 14
  • 68
  • 96
  • should you to use all declared in `jscode` functions in same context? – vp_arth Nov 24 '14 at 15:28
  • That is your choice. You can execute different code in the same context, the same code multiple times in different contexts, or different code in different contexts. Depends on your needs. – deitch Nov 24 '14 at 15:31
  • How can i pass the values. I need to invoke the method in myJSFile.js See code in question where i call _myfunctionInJSFile_(...) – Sohan Nov 24 '14 at 15:37
  • I read docs, and no, evaled code no access to application context, only to second argument(global_vars). And what difference, if we declare any function in sandbox, but run it in our application context? No difference here. But thanks anyway, I didn't know about this sandboxes. :) – vp_arth Nov 24 '14 at 15:37
  • @vp_arth yeah, the sandbox is great. I don't use it much, but when I do, it is a lifesaver. – deitch Nov 24 '14 at 15:41
  • @Sohan I will update the answer. The short form is you pass in vars in context. – deitch Nov 24 '14 at 15:41
  • I did not get you. i will look at it when you update the answer. – Sohan Nov 24 '14 at 15:47
  • I will update. Usually you pass the variables into the context and have it immediately execute. Are you looking to pass the function back to the parent context and have it execute there? – deitch Nov 24 '14 at 15:49
  • No i will not pass anything back to parent context. I want to understand proper syntax to call fucntion like vm.runInNewContext('myJSFile',whats here?); – Sohan Nov 24 '14 at 15:59
  • "whats here" is global variables passed to the new context. Editing again above. – deitch Nov 24 '14 at 16:05
  • The jscode in my case will be in other JS file right? Since i need to evaluate from passed JS file – Sohan Nov 24 '14 at 16:15
  • @deitch Well this is something different i found out to be and not the proper use case for me to use it right now. Thanks though i fond something new to learn – Sohan Nov 25 '14 at 06:37
0

I think i have found the answer for this.

Since my application is running in node js which uses v8 engine platform. When the application starts v8 engine caches all the code/configuration and can be used anytime. Similarly in my code i will pre-load the JS code using eval and i will do it only once. So on next call i will return only the loaded JS code. Here i need to modify the code to load once. But main point we have look is that in future if any body has similar requirement they can cache their JS codes using eval (thanks to v8 engine) and use it till your application is running.

Sohan
  • 6,252
  • 5
  • 35
  • 56