Shane
Shane

Reputation: 5151

Is it possible to alter javascript with google closure compiler?

I'm working on a modular component framework and have different needs for the code in my test environment vs production. Each component has its own js file and these are being compiled together for production use, but left separate in my dev environment.

In production I want to trap errors in various stages of initialization so as to not break the call stack. In my development (uncompressed javascript), I do not want to trap the errors, so I can quickly get line numbers, etc to find where the breaks occur. Is there any way to use the closure compiler to manipulate a javascript file (such as removing a flagged line such as a comment opener and closer) that might allow me to do this?

For instance:

proto.instantiateChildFromDescriptor = function(childObj, callback, customDiv){
/*ProductionErrorTrap
    try{
/**/
    //code for instantiating a module
/*ProductionErrorTrap
    }catch(e){
        console.log("problem instantiating child in " + this.getName());
        console.error(e);
    }
/**/
}

replacing /*ProductionErrorTrap with /*ProductionErrorTrap*/ would work nicely (so is removing my stars on the second comment block, but they are there)

I can't do this with a find and replace on the files themselves because it would mess with github. I suppose I could create a new copy of the files, run a find and replace on them and compile *those files, but It would be nice if I could do it all in the closure compiler.

Thanks

Upvotes: 1

Views: 347

Answers (3)

lennel
lennel

Reputation: 646

Use compiler flags for advanced mode.

from:
https://developers.google.com/closure/compiler/docs/js-for-compiler

@define {Type} description

For example:

/** @define {boolean} */
var ENABLE_DEBUG = true;

/** @define {boolean} */
goog.userAgent.ASSUME_IE = false;

Indicates a constant that can be overridden by the compiler at compile-time. With the example above, you can pass the flag --define='ENABLE_DEBUG=false' to the compiler to change the value of ENABLE_DEBUG to false.

Upvotes: 1

jjrv
jjrv

Reputation: 4345

I think messing with compiled results, matching comments to emulate ifdefs is pretty unelegant.

You could actually do something like this:

debugTry(function() {
    alert('This is code that might cause an error');
},function(e) {
    alert('Whoops! Caught error '+e);
});

Then while debugging you do:

function debugTry(test,handle) {
    try {
        test();
    } catch(e) {
        handle(e);
    }
}

And in production:

function debugTry(test,handle) {
    test();
}

Closure Compiler is pretty smart. With the first debugTry the example compiles to:

try{alert("This is code that might cause an error")}
catch(a){alert("Whoops! Caught error "+a)};

With the second debugTry it compiles to:

alert("This is code that might cause an error");

As you see, the unnecessary code is detected and eliminated.

Of course, things would be easier if you didn't conditionally include a try block. If it's just some statements included conditionally, not changing the structure of other code, you can do:

/** @const */ var debug = false;

if(debug) {
    alert('Yay for debugging!');
}

The alert will be compiled away.

Upvotes: 1

Shane
Shane

Reputation: 5151

Stephen Chung's comment seems to be the best approach. Adding his comments as an answer to this question for anyone else with this problem. I entered the following into my code

 proto.updateProperties = function(propsObj){
 /** @preserve ProductionErrorTrap try{ /**/
    //do stuff here
 /** @preserve ProductionErrorTrap }catch(e){console.log("problem updating properties in " + this.getName());console.error(e);}/**/
 }

After compressing the javascript I just run a find and replace on the compressed file, remove the line breaks and replace ProductionErrorTrap with ProductionErrorTrap*/ and everything seems to work fine without making a mess of the repository.

Thanks Stephen!

Upvotes: 0

Related Questions