Skip to content

Instantly share code, notes, and snippets.

@alex-seville
Created October 16, 2012 16:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alex-seville/3900493 to your computer and use it in GitHub Desktop.
Save alex-seville/3900493 to your computer and use it in GitHub Desktop.
test uglify parse
// sample on how to use the parser and walker API to instrument some code
var jsp = require("uglify-js").parser;
var pro = require("uglify-js").uglify;
function instrument(code) {
var ast = jsp.parse(code, false, true); // true for the third arg specifies that we want
// to have start/end tokens embedded in the
// statements
var w = pro.ast_walker();
// we're gonna need this to push elements that we're currently looking at, to avoid
// endless recursion.
var analyzing = [];
function do_stat() {
var ret;
if (this[0].start && analyzing.indexOf(this) < 0) {
// without the `analyzing' hack, w.walk(this) would re-enter here leading
// to infinite recursion
analyzing.push(this);
ret = [ "splice", // XXX: "block" is safer
[ [ "stat",
[ "call", [ "name", "trace" ],
[ [ "string", this[0].toString() ],
[ "num", this[0].start.line ],
[ "num", this[0].start.col ],
[ "num", this[0].end.line ],
[ "num", this[0].end.col ]]]],
w.walk(this) ]];
analyzing.pop(this);
}
return ret;
};
function do_stat_bracketCheck() {
var ret;
if (this[0].start && analyzing.indexOf(this) < 0) {
// without the `analyzing' hack, w.walk(this) would re-enter here leading
// to infinite recursion
analyzing.push(this);
ret = [ "block", // XXX: "block" is safer
[ [ "stat",
[ "call", [ "name", "trace" ],
[ [ "string", this[0].toString() ],
[ "num", this[0].start.line ],
[ "num", this[0].start.col ],
[ "num", this[0].end.line ],
[ "num", this[0].end.col ]]]],
w.walk(this) ]];
analyzing.pop(this);
}
return ret;
};
function checkBracket(){
var line = this.join(",");
console.log("l:"+line);
console.log("end:"+JSON.stringify(this[0].end));
if (line.indexOf("stat") < line.indexOf("block") || line.indexOf("block") < 0){
//add block
//I don't know how to do it, but I know that the 'stat' leaf needs to be wrapped by a block token
//basically we artifically insert brackets
return do_stat_bracketCheck.apply(this,arguments);
}else{
return do_stat.apply(this,arguments);
}
}
var new_ast = w.with_walkers({
"stat" : do_stat,
"label" : do_stat,
"break" : do_stat,
"continue" : do_stat,
"debugger" : do_stat,
"var" : do_stat,
"const" : do_stat,
"return" : do_stat,
"throw" : do_stat,
"try" : checkBracket,
"defun" : do_stat,
"if" : checkBracket,
"while" : checkBracket,
"do" : checkBracket,
"for" : checkBracket,
"for-in" : checkBracket,
"switch" : do_stat,
"with" : checkBracket
}, function(){
return w.walk(ast);
});
return pro.gen_code(new_ast, { beautify: true });
}
////// test code follows.
var code = instrument(test.toString());
console.log(code);
function test() {
// simple stats
a = 5;
c += a + b;
"foo";
// var
var foo = 5;
const bar = 6, baz = 7;
// switch block. note we can't track case lines the same way.
switch ("foo") {
case "foo":
return 1;
case "bar":
return 2;
}
// for/for in
for (var i = 0; i < 5; ++i) {
console.log("Hello " + i);
}
for (var i in [ 1, 2, 3]) {
console.log(i);
}
// EDGE CASE 1, no bracket for BREAKS
for (var i = 0; i < 5; ++i)
console.log("foo2");
// EDGE case 2, no bracket if BREAKS
if (a == 5)
console.log("foo3")
//EDGE case 3, mis matching the brackets WORKS
if (a == -1){
console.log("dujh");
}
else
{
console.log("foo3");
}
//EDGE case 4, multi line logical statement WORKS
var out = a == 7 ||
a == 5;
console.log(out);
//EDGE case 5, multi line arithmetic WORKS
var lastcase = 12+
12+
6;
console.log(lastcase);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment