4

How to parse javascript expressions using uglifyjs ? Though an excellent library, Lack of documentation makes it more difficult to understand!

These Links helped me to some extent.

Now I know this is what needs to be done

  • Parse to generate AST
  • create custom Walks
  • Translate AST
  • Generate code
  • Eval generated code

Is this correct? or Am I missing something?

A simple example with walker code to play around would be much helpful and appreciated

Prashant Bhate
  • 10,907
  • 7
  • 47
  • 82
  • For walking, take a look at [this thread](http://stackoverflow.com/questions/5827612/node-js-fs-readdir-recursive-directory-search) – Roshambo Oct 17 '12 at 19:08

1 Answers1

3

I am also new to uglifyjs. I think that it is a great library however it lacks good documentation or examples. One use of uglifyjs that I think is very nice is to create a static analysis tool. For that reason I want to share a small script that I wrote that finds in a js file all variables that have a small name for example var d=3; Those variable names are not very descriptive and make it difficult to maintain big programs. So I demand all variable names to be at least 3 characters long. To make things a little more interesting we should not mark as defects the counter variables in For..loops and For..in loops.

That said we can create this smallVariables.js.

var smallVariableNames = [];

function addBadVariableName(line,value){
    smallVariableNames.push(line + " "+value);
}

var UglifyJS = require("../tools/node"); //Please install node first
var parser = UglifyJS.parser             // Parse input.js file and create AST 
    , fs = require('fs')
    , filename = 'input.js';


var toplevel = UglifyJS.parse(String(fs.readFileSync(filename)));
var walker = new UglifyJS.TreeWalker(function(node){  //walk AST 
var statement = JSON.parse(JSON.stringify(node));

if  (node instanceof UglifyJS.AST_VarDef || node instanceof UglifyJS.AST_Constant) 

    {

    var parentForIn = walker.find_parent(UglifyJS.AST_ForIn); //in order to avoid init vars in for..in loops 
    var parentLoopVariable ="";
    if (parentForIn) {

        parentLoopVariable = JSON.parse(JSON.stringify(parentForIn));
        parentLoopVariable = parentLoopVariable["init"];
        parentLoopVariable = parentLoopVariable["definitions"];
        if (parentLoopVariable)
        parentLoopVariable = parentLoopVariable[0].name["end"].value;
    }
    var parentFor = walker.find_parent(UglifyJS.AST_For); //in order to avoid init vars in for loops 

    if (parentFor) {
         parentLoopVariable = JSON.parse(JSON.stringify(parentFor));
        parentLoopVariable = parentLoopVariable["init"];
        parentLoopVariable = parentLoopVariable["definitions"];
        if (parentLoopVariable)
            parentLoopVariable = parentLoopVariable[0].name["end"].value;
    }


        var expression = statement["name"];
        if (expression) {
            variableName = node.start.value
            if(variableName  && variableName.length < 3 && variableName !== parentLoopVariable)
                {
                    addBadVariableName(node.start.line,variableName); 
                }
        }


    }
});
toplevel.walk(walker);
for (line in smallVariableNames)
    console.log(smallVariableNames[line]);

In a few words, our script we read the "input.js" file, parse it, walk to the tree and find all those small variables.

Ok now that we have our script how we can test it!! I have saved the script in the folder %UGLIFY-JS%/test/ The most quick way (if you have node.js and uglify.js) installed is to run in command: *node node_modules/uglify-js/test/smallVariables.js*

Depending on your input file you will see some line numbers and small variable names. In this way you can put whatever rule fits your need. The AST Tree is a very powerful tool.

Also I have found really usefull the following article: http://lisperator.net/uglifyjs/walk

alexopoulos7
  • 794
  • 7
  • 27