From f2f370cee3708c0d9431594f81e192099fc6900c Mon Sep 17 00:00:00 2001 From: Mihai Bazon Date: Sun, 2 Sep 2012 14:32:00 +0300 Subject: [PATCH] add source mappings for more node types; started CLI utility --- bin/uglifyjs2 | 141 +++++++++++++++++++++++++++++++++++++++++++++++ lib/output.js | 10 ++++ tmp/test-maps.js | 6 +- tmp/test-node.js | 2 +- 4 files changed, 156 insertions(+), 3 deletions(-) create mode 100755 bin/uglifyjs2 diff --git a/bin/uglifyjs2 b/bin/uglifyjs2 new file mode 100755 index 00000000..d7f2657b --- /dev/null +++ b/bin/uglifyjs2 @@ -0,0 +1,141 @@ +#! /usr/bin/env node +// -*- js -*- + +var UglifyJS = require("../tools/node"); +var sys = require("util"); +var optimist = require("optimist"); +var fs = require("fs"); +var ARGS = optimist + .usage("uglifyjs2 [options] input1.js input2.js ...") + .describe("source-map", "Specify an output file where to generate source map") + .describe("source-map-root", "The root of the original source to be included in the source map") + .describe("p", "Skip prefix for original filenames that appear in source maps") + .alias("p", "prefix") + .describe("o", "Output file (default STDOUT)") + .alias("o", "output") + .describe("stats", "Display operations run time on STDERR") + .describe("v", "Verbose") + .argv +; + +for (var i in ARGS) if (ARGS.hasOwnProperty(i) && /-/.test(i)) { + ARGS[i.replace(/-/g, "_")] = ARGS[i]; +} + +if (ARGS.h || ARGS.help) { + sys.puts(optimist.help()); + process.exit(0); +} + +var files = ARGS._.slice(); + +if (files.length == 0) { + sys.error("ERROR: No input files."); + sys.puts(optimist.help()); + process.exit(1); +} + +if (files.indexOf("-") >= 0 && ARGS.source_map) { + sys.error("ERROR: Source map doesn't work with input from STDIN"); + process.exit(1); +} + +if (files.filter(function(el){ return el == "-" }).length > 1) { + sys.error("ERROR: Can read a single file from STDIN (two or more dashes specified)"); + process.exit(1); +} + +var STATS = {}; +var OUTPUT_FILE = ARGS.o; + +var SOURCE_MAP = ARGS.source_map ? UglifyJS.SourceMap({ + file: output, + root: ARGS.source_map_root +}) : null; + +var output = UglifyJS.OutputStream({ + beautify: false, + source_map: SOURCE_MAP +}); + +files.forEach(do_file); + +if (SOURCE_MAP) { + fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8"); +} + +if (OUTPUT_FILE) { + fs.writeFileSync(OUTPUT_FILE, output, "utf8"); +} else { + sys.print(output); + sys.error("\n"); +} + +if (ARGS.stats) { + sys.error(UglifyJS.string_template("Timing information (compressed {count} files):", { + count: files.length + })); + for (var i in STATS) if (STATS.hasOwnProperty(i)) { + sys.error(UglifyJS.string_template("- {name}: {time}s", { + name: i, + time: (STATS[i] / 1000).toFixed(3) + })); + } +} + +/* -----[ functions ]----- */ + +function do_file(file) { + if (ARGS.v) { + sys.error("Compressing " + file); + } + var code = read_whole_file(file); + var ast; + time_it("parse", function(){ + ast = UglifyJS.parse(code); + }); + time_it("scope", function(){ + ast.figure_out_scope(); + }); + time_it("mangle", function(){ + ast.mangle_names(); + }); + time_it("squeeze", function(){ + var compressor = UglifyJS.Compressor(); + ast = ast.squeeze(compressor); + }); + time_it("generate", function(){ + if (SOURCE_MAP) { + if (ARGS.p != null) { + file = file.replace(/^\/+/, "").split(/\/+/).slice(ARGS.p).join("/"); + } + SOURCE_MAP.set_source(file); + } + ast.print(output); + }); +} + +function read_whole_file(filename) { + if (filename == "-") { + // XXX: this sucks. How does one read the whole STDIN + // synchronously? + filename = "/dev/stdin"; + } + try { + return fs.readFileSync(filename, "utf8"); + } catch(ex) { + sys.error("ERROR: can't read file: " + filename); + process.exit(1); + } +} + +function time_it(name, cont) { + var t1 = new Date().getTime(); + var ret = cont(); + if (ARGS.stats) { + var spent = new Date().getTime() - t1; + if (STATS[name]) STATS[name] += spent; + else STATS[name] = spent; + } + return ret; +}; diff --git a/lib/output.js b/lib/output.js index b43d817e..05bd9136 100644 --- a/lib/output.js +++ b/lib/output.js @@ -1009,7 +1009,17 @@ function OutputStream(options) { DEFMAP(AST_Debugger, basic_sourcemap_gen); DEFMAP(AST_Symbol, basic_sourcemap_gen); DEFMAP(AST_Jump, basic_sourcemap_gen); + DEFMAP(AST_StatementWithBody, basic_sourcemap_gen); + DEFMAP(AST_Lambda, basic_sourcemap_gen); DEFMAP(AST_PropAccess, basic_sourcemap_gen); + DEFMAP(AST_Switch, basic_sourcemap_gen); + DEFMAP(AST_BlockStatement, basic_sourcemap_gen); + DEFMAP(AST_Toplevel, noop); + DEFMAP(AST_Try, basic_sourcemap_gen); + DEFMAP(AST_Catch, basic_sourcemap_gen); + DEFMAP(AST_Finally, basic_sourcemap_gen); + DEFMAP(AST_Definitions, basic_sourcemap_gen); + DEFMAP(AST_Constant, basic_sourcemap_gen); DEFMAP(AST_ObjectProperty, function(self, output){ output.add_mapping(self.start, self.key); }); diff --git a/tmp/test-maps.js b/tmp/test-maps.js index c89d105e..438d198f 100755 --- a/tmp/test-maps.js +++ b/tmp/test-maps.js @@ -28,8 +28,10 @@ function do_file(file) { // generate source into the output stream // first reset the current file name in the source map. - map.set_source(file); - ast.print(output); + UglifyJS.time_it("generate", function(){ + map.set_source(file); + ast.print(output); + }); }; files.forEach(do_file); diff --git a/tmp/test-node.js b/tmp/test-node.js index d737afde..ce03b591 100755 --- a/tmp/test-node.js +++ b/tmp/test-node.js @@ -22,7 +22,7 @@ time_it("scope", function(){ ast.figure_out_scope(); }); -ast.scope_warnings(); +// ast.scope_warnings(); time_it("mangle", function(){ ast.mangle_names(); -- 2.34.1