instrument.js 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // sample on how to use the parser and walker API to instrument some code
  2. var jsp = require("uglify-js").parser;
  3. var pro = require("uglify-js").uglify;
  4. function instrument(code) {
  5. var ast = jsp.parse(code, false, true); // true for the third arg specifies that we want
  6. // to have start/end tokens embedded in the
  7. // statements
  8. var w = pro.ast_walker();
  9. // we're gonna need this to push elements that we're currently looking at, to avoid
  10. // endless recursion.
  11. var analyzing = [];
  12. function do_stat() {
  13. var ret;
  14. if (this[0].start && analyzing.indexOf(this) < 0) {
  15. // without the `analyzing' hack, w.walk(this) would re-enter here leading
  16. // to infinite recursion
  17. analyzing.push(this);
  18. ret = [ "splice", // XXX: "block" is safer
  19. [ [ "stat",
  20. [ "call", [ "name", "trace" ],
  21. [ [ "string", this[0].toString() ],
  22. [ "num", this[0].start.line ],
  23. [ "num", this[0].start.col ],
  24. [ "num", this[0].end.line ],
  25. [ "num", this[0].end.col ]]]],
  26. w.walk(this) ]];
  27. analyzing.pop(this);
  28. }
  29. return ret;
  30. };
  31. var new_ast = w.with_walkers({
  32. "stat" : do_stat,
  33. "label" : do_stat,
  34. "break" : do_stat,
  35. "continue" : do_stat,
  36. "debugger" : do_stat,
  37. "var" : do_stat,
  38. "const" : do_stat,
  39. "return" : do_stat,
  40. "throw" : do_stat,
  41. "try" : do_stat,
  42. "defun" : do_stat,
  43. "if" : do_stat,
  44. "while" : do_stat,
  45. "do" : do_stat,
  46. "for" : do_stat,
  47. "for-in" : do_stat,
  48. "switch" : do_stat,
  49. "with" : do_stat
  50. }, function(){
  51. return w.walk(ast);
  52. });
  53. return pro.gen_code(new_ast, { beautify: true });
  54. }
  55. ////// test code follows.
  56. var code = instrument(test.toString());
  57. console.log(code);
  58. function test() {
  59. // simple stats
  60. a = 5;
  61. c += a + b;
  62. "foo";
  63. // var
  64. var foo = 5;
  65. const bar = 6, baz = 7;
  66. // switch block. note we can't track case lines the same way.
  67. switch ("foo") {
  68. case "foo":
  69. return 1;
  70. case "bar":
  71. return 2;
  72. }
  73. // for/for in
  74. for (var i = 0; i < 5; ++i) {
  75. console.log("Hello " + i);
  76. }
  77. for (var i in [ 1, 2, 3]) {
  78. console.log(i);
  79. }
  80. // note however that the following is broken. I guess we
  81. // should add the block brackets in this case...
  82. for (var i = 0; i < 5; ++i)
  83. console.log("foo");
  84. }