1 // sample on how to use the parser and walker API to instrument some code
3 var jsp = require("uglify-js").parser;
4 var pro = require("uglify-js").uglify;
6 function instrument(code) {
7 var ast = jsp.parse(code, false, true); // true for the third arg specifies that we want
8 // to have start/end tokens embedded in the
10 var w = pro.ast_walker();
12 function trace (line, comment) {
13 var code = pro.gen_code(line, { beautify: true });
17 if (!comment) comment = ""
18 if (typeof data === "object") {
19 code = code.split(/\n/).shift()
20 args = [ [ "string", data.toString() ],
22 [ "num", data.start.line ],
23 [ "num", data.start.col ],
24 [ "num", data.end.line ],
25 [ "num", data.end.col ]]
27 args = [ [ "string", data ],
31 return [ "call", [ "name", "trace" ], args ];
34 // we're gonna need this to push elements that we're currently looking at, to avoid
39 if (this[0].start && analyzing.indexOf(this) < 0) {
40 // without the `analyzing' hack, w.walk(this) would re-enter here leading
41 // to infinite recursion
44 [ [ "stat", trace(this) ],
51 function do_cond(c, t, f) {
52 return [ this[0], w.walk(c),
53 ["seq", trace(t), w.walk(t) ],
54 ["seq", trace(f), w.walk(f) ]];
57 function do_binary(c, l, r) {
58 if (c !== "&&" && c !== "||") {
59 return [this[0], c, w.walk(l), w.walk(r)];
62 ["seq", trace(l), w.walk(l) ],
63 ["seq", trace(r), w.walk(r) ]];
66 var new_ast = w.with_walkers({
85 "conditional" : do_cond,
90 return pro.gen_code(new_ast, { beautify: true });
94 ////// test code follows.
96 var code = instrument(test.toString());
107 const bar = 6, baz = 7;
109 // switch block. note we can't track case lines the same way.
118 for (var i = 0; i < 5; ++i) {
119 console.log("Hello " + i);
121 for (var i in [ 1, 2, 3]) {
125 for (var i = 0; i < 5; ++i)
128 for (var i = 0; i < 5; ++i) {
132 var k = plurp() ? 1 : 0;
133 var x = a ? doX(y) && goZoo("zoo")
134 : b ? blerg({ x: y })