How to instruct Closure Compiler not to rename/remove a local variable?

779 views Asked by At

In the following code, I need the variable some_var not to be renamed or removed by Google's Closure Compiler.

function scopedEval(code){
    var some_var = 'world' ;
    return eval('('+code+')') ;
}
scopedEval('alert("hello, "+some_var)') ;

The code to be eval-ed relies on the existence of a few variables, so I need them to be left untouched.

How can I instruct Closure Compiler to do that?

PS:
Please disregard the issue about the use of eval being a bad practice. That's another matter entirely.

2

There are 2 answers

3
Peter Olson On

There might be some Closure Compiler options allowing this sort of thing specifically, but failing that, I would tackle the problem one of these two ways:

Option 1

Create a global object to store your variables, and then use the js_externs option to prevent it from being munged:

// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @output_file_name default.js
// @js_externs vars
// ==/ClosureCompiler==
vars = {};

Then you can apply string properties to this object that should be left untouched

function scopedEval(code){
    vars['some_var'] = 'world';
    return eval('('+code+')');
}
scopedEval('alert("hello, "+vars["some_var"])');

Option 2

If for some reason vars['some_var'] won't work for you and you need to use some_var literally inside the evaled code, then you can use with to get around this. In this case, you don't need to declare vars as an extern.

function scopedEval(code){
    var vars = {
      "some_var": "world"
    };
    with(vars) {
      return eval('('+code+')');
    }
}
scopedEval('alert("hello, "+some_var)');

I'll leave it up to your discretion whether or not you feel dirty using the two features of JavaScript that attract the most vitriol together, namely with and eval.

4
John On

One option is to use the function constructor:

var scopedEval = new Function(
    "code", 
    "var some_var = 'world'; return eval('('+code+')');");