6dbd65861f51e5196363ad24b4481d76e9a6fab0.svn-base
3.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// 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;
};
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" : do_stat,
"defun" : do_stat,
"if" : do_stat,
"while" : do_stat,
"do" : do_stat,
"for" : do_stat,
"for-in" : do_stat,
"switch" : do_stat,
"with" : do_stat
}, 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);
}
// note however that the following is broken. I guess we
// should add the block brackets in this case...
for (var i = 0; i < 5; ++i)
console.log("foo");
}