node.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. var path = require("path");
  2. var fs = require("fs");
  3. var vm = require("vm");
  4. var sys = require("util");
  5. var UglifyJS = vm.createContext({
  6. sys : sys,
  7. console : console,
  8. MOZ_SourceMap : require("source-map")
  9. });
  10. function load_global(file) {
  11. file = path.resolve(path.dirname(module.filename), file);
  12. try {
  13. var code = fs.readFileSync(file, "utf8");
  14. return vm.runInContext(code, UglifyJS, file);
  15. } catch(ex) {
  16. // XXX: in case of a syntax error, the message is kinda
  17. // useless. (no location information).
  18. sys.debug("ERROR in file: " + file + " / " + ex);
  19. process.exit(1);
  20. }
  21. };
  22. var FILES = exports.FILES = [
  23. "../lib/utils.js",
  24. "../lib/ast.js",
  25. "../lib/parse.js",
  26. "../lib/transform.js",
  27. "../lib/scope.js",
  28. "../lib/output.js",
  29. "../lib/compress.js",
  30. "../lib/sourcemap.js",
  31. "../lib/mozilla-ast.js"
  32. ].map(function(file){
  33. return path.join(path.dirname(fs.realpathSync(__filename)), file);
  34. });
  35. FILES.forEach(load_global);
  36. UglifyJS.AST_Node.warn_function = function(txt) {
  37. sys.error("WARN: " + txt);
  38. };
  39. // XXX: perhaps we shouldn't export everything but heck, I'm lazy.
  40. for (var i in UglifyJS) {
  41. if (UglifyJS.hasOwnProperty(i)) {
  42. exports[i] = UglifyJS[i];
  43. }
  44. }
  45. exports.minify = function(files, options) {
  46. options = UglifyJS.defaults(options, {
  47. outSourceMap : null,
  48. sourceRoot : null,
  49. inSourceMap : null,
  50. fromString : false,
  51. warnings : false,
  52. mangle : {},
  53. output : null,
  54. compress : {}
  55. });
  56. if (typeof files == "string")
  57. files = [ files ];
  58. // 1. parse
  59. var toplevel = null;
  60. files.forEach(function(file){
  61. var code = options.fromString
  62. ? file
  63. : fs.readFileSync(file, "utf8");
  64. toplevel = UglifyJS.parse(code, {
  65. filename: options.fromString ? "?" : file,
  66. toplevel: toplevel
  67. });
  68. });
  69. // 2. compress
  70. if (options.compress) {
  71. var compress = { warnings: options.warnings };
  72. UglifyJS.merge(compress, options.compress);
  73. toplevel.figure_out_scope();
  74. var sq = UglifyJS.Compressor(compress);
  75. toplevel = toplevel.transform(sq);
  76. }
  77. // 3. mangle
  78. if (options.mangle) {
  79. toplevel.figure_out_scope();
  80. toplevel.compute_char_frequency();
  81. toplevel.mangle_names(options.mangle);
  82. }
  83. // 4. output
  84. var inMap = options.inSourceMap;
  85. var output = {};
  86. if (typeof options.inSourceMap == "string") {
  87. inMap = fs.readFileSync(options.inSourceMap, "utf8");
  88. }
  89. if (options.outSourceMap) {
  90. output.source_map = UglifyJS.SourceMap({
  91. file: options.outSourceMap,
  92. orig: inMap,
  93. root: options.sourceRoot
  94. });
  95. }
  96. if (options.output) {
  97. UglifyJS.merge(output, options.output);
  98. }
  99. var stream = UglifyJS.OutputStream(output);
  100. toplevel.print(stream);
  101. return {
  102. code : stream + "",
  103. map : output.source_map + ""
  104. };
  105. };
  106. // exports.describe_ast = function() {
  107. // function doitem(ctor) {
  108. // var sub = {};
  109. // ctor.SUBCLASSES.forEach(function(ctor){
  110. // sub[ctor.TYPE] = doitem(ctor);
  111. // });
  112. // var ret = {};
  113. // if (ctor.SELF_PROPS.length > 0) ret.props = ctor.SELF_PROPS;
  114. // if (ctor.SUBCLASSES.length > 0) ret.sub = sub;
  115. // return ret;
  116. // }
  117. // return doitem(UglifyJS.AST_Node).sub;
  118. // }
  119. exports.describe_ast = function() {
  120. var out = UglifyJS.OutputStream({ beautify: true });
  121. function doitem(ctor) {
  122. out.print("AST_" + ctor.TYPE);
  123. var props = ctor.SELF_PROPS.filter(function(prop){
  124. return !/^\$/.test(prop);
  125. });
  126. if (props.length > 0) {
  127. out.space();
  128. out.with_parens(function(){
  129. props.forEach(function(prop, i){
  130. if (i) out.space();
  131. out.print(prop);
  132. });
  133. });
  134. }
  135. if (ctor.documentation) {
  136. out.space();
  137. out.print_string(ctor.documentation);
  138. }
  139. if (ctor.SUBCLASSES.length > 0) {
  140. out.space();
  141. out.with_block(function(){
  142. ctor.SUBCLASSES.forEach(function(ctor, i){
  143. out.indent();
  144. doitem(ctor);
  145. out.newline();
  146. });
  147. });
  148. }
  149. };
  150. doitem(UglifyJS.AST_Node);
  151. return out + "";
  152. };