Compare commits

..

21 Commits

Author SHA1 Message Date
Mihai Bazon
16953c2064 v2.2.3 2013-01-04 22:50:53 +02:00
Mihai Bazon
6b14f7c224 Fix handling of labels in nested scopes 2013-01-04 14:17:33 +02:00
Mihai Bazon
130c623be7 Support output, mangle and compress options to UglifyJS.minify.
Close #57
Close #86
Close #33
2013-01-04 11:25:13 +02:00
Mihai Bazon
47c9895d59 Merge pull request #87 from BenoitZugmeyer/master
Add a --version option
2013-01-03 02:28:35 -08:00
Benoît Zugmeyer
ba403331c5 Set --version as a boolean #87 2013-01-03 11:22:37 +01:00
Benoît Zugmeyer
e82e89d1b0 --version option 2013-01-03 11:07:53 +01:00
Mihai Bazon
83a4ebfedc Implement -m sort=true
close #83
2013-01-02 12:39:00 +02:00
Mihai Bazon
9916d0e547 Accept string or number as name of an accessor.
[not sure I'm happy about this fix]

Reference mishoo/UglifyJS#478
2012-12-22 01:24:04 +02:00
Mihai Bazon
31c4a37e37 Optimize new Array(1, 2, 3) → [1, 2, 3]
Close #74
2012-12-21 21:04:35 +02:00
Mihai Bazon
08219f0cee Fix output when semicolons is off.
(need to force a semicolon for the empty body of an `if`)

Close #72
2012-12-21 11:57:08 +02:00
Mihai Bazon
c4993e1e5c Small cleanup 2012-12-12 11:51:55 +02:00
Mihai Bazon
6064bea3db v2.2.2 2012-12-06 14:25:18 +02:00
Mihai Bazon
98978fc827 Add proper parens in "NoIn" expressions.
fix #60.
2012-12-06 12:27:57 +02:00
Mihai Bazon
16430acc1f small improvement on merging assignments into hoisted vars 2012-12-05 13:14:49 +02:00
Mihai Bazon
320c110b33 When hoisting variables, try to merge in assignments that follow. 2012-12-05 12:30:25 +02:00
Mihai Bazon
dbe33bbfc5 Revert "Fixed reading from STDIN."
It breaks usage like this:

    echo '...code...' | uglifyjs

This reverts commit e48802ad29.
2012-11-30 11:33:50 +02:00
Mihai Bazon
b5c3253b49 Add test for issue #59 2012-11-30 11:26:37 +02:00
Mihai Bazon
5cc90db7d0 Don't messup compressor stack while optimizing Switch
Fix #59
2012-11-30 11:16:09 +02:00
Mihai Bazon
f427e5efc7 Merge pull request #58 from roxeteer/master
Fixed reading from STDIN
2012-11-29 01:23:07 -08:00
Visa Kopu
e48802ad29 Fixed reading from STDIN. 2012-11-29 10:51:15 +02:00
Mihai Bazon
13c4dfcabd fix #55 2012-11-24 10:02:08 +02:00
11 changed files with 228 additions and 81 deletions

View File

@@ -79,6 +79,7 @@ The available options are:
--export-all Only used when --wrap, this tells UglifyJS to add code to --export-all Only used when --wrap, this tells UglifyJS to add code to
automatically export all globals. [boolean] automatically export all globals. [boolean]
-v, --verbose Verbose [boolean] -v, --verbose Verbose [boolean]
-V, --version Print version number and exits. [boolean]
Specify `--output` (`-o`) to declare the output file. Otherwise the output Specify `--output` (`-o`) to declare the output file. Otherwise the output
goes to STDOUT. goes to STDOUT.
@@ -130,7 +131,7 @@ input files from the command line.
## Mangler options ## Mangler options
To enable the mangler you need to pass `--mangle` (`-m`). Optionally you To enable the mangler you need to pass `--mangle` (`-m`). Optionally you
can pass `-m sort` (we'll possibly have other flags in the future) in order can pass `-m sort=true` (we'll possibly have other flags in the future) in order
to assign shorter names to most frequently used variables. This saves a few to assign shorter names to most frequently used variables. This saves a few
hundred bytes on jQuery before gzip, but the output is _bigger_ after gzip hundred bytes on jQuery before gzip, but the output is _bigger_ after gzip
(and seems to happen for other libraries I tried it on) therefore it's not (and seems to happen for other libraries I tried it on) therefore it's not
@@ -213,6 +214,7 @@ will evaluate references to them to the value itself and drop unreachable
code as usual. The possible downside of this approach is that the build code as usual. The possible downside of this approach is that the build
will contain the `const` declarations. will contain the `const` declarations.
<a name="codegen-options"></a>
## Beautifier options ## Beautifier options
The code generator tries to output shortest code possible by default. In The code generator tries to output shortest code possible by default. In
@@ -366,9 +368,19 @@ no sense otherwise).
Other options: Other options:
- `warnings` (default `false`) — pass `true` to display compressor warnings. - `warnings` (default `false`) — pass `true` to display compressor warnings.
- `fromString` (default `false`) — if you pass `true` then you can pass - `fromString` (default `false`) — if you pass `true` then you can pass
JavaScript source code, rather than file names. JavaScript source code, rather than file names.
- `mangle` — pass `false` to skip mangling names.
- `output` (default `null`) — pass an object if you wish to specify
additional [output options][codegen]. The defaults are optimized
for best compression.
- `compress` (default `{}`) — pass `false` to skip compressing entirely.
Pass an object to specify custom [compressor options][compressor].
We could add more options to `UglifyJS.minify` — if you need additional We could add more options to `UglifyJS.minify` — if you need additional
functionality please suggest! functionality please suggest!
@@ -516,3 +528,5 @@ The `source_map_options` (optional) can contain the following properties:
[acorn]: https://github.com/marijnh/acorn [acorn]: https://github.com/marijnh/acorn
[source-map]: https://github.com/mozilla/source-map [source-map]: https://github.com/mozilla/source-map
[sm-spec]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit [sm-spec]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
[codegen]: http://lisperator.net/uglifyjs/codegen
[compressor]: http://lisperator.net/uglifyjs/compress

View File

@@ -49,6 +49,7 @@ You need to pass an argument to this option to specify the name that your module
.describe("export-all", "Only used when --wrap, this tells UglifyJS to add code to automatically export all globals.") .describe("export-all", "Only used when --wrap, this tells UglifyJS to add code to automatically export all globals.")
.describe("lint", "Display some scope warnings") .describe("lint", "Display some scope warnings")
.describe("v", "Verbose") .describe("v", "Verbose")
.describe("V", "Print version number and exit.")
.alias("p", "prefix") .alias("p", "prefix")
.alias("o", "output") .alias("o", "output")
@@ -58,6 +59,7 @@ You need to pass an argument to this option to specify the name that your module
.alias("c", "compress") .alias("c", "compress")
.alias("d", "define") .alias("d", "define")
.alias("r", "reserved") .alias("r", "reserved")
.alias("V", "version")
.string("source-map") .string("source-map")
.string("source-map-root") .string("source-map-root")
@@ -74,6 +76,7 @@ You need to pass an argument to this option to specify the name that your module
.boolean("acorn") .boolean("acorn")
.boolean("spidermonkey") .boolean("spidermonkey")
.boolean("lint") .boolean("lint")
.boolean("V")
.wrap(80) .wrap(80)
@@ -82,6 +85,12 @@ You need to pass an argument to this option to specify the name that your module
normalize(ARGS); normalize(ARGS);
if (ARGS.version || ARGS.V) {
var json = require("../package.json");
sys.puts(json.name + ' ' + json.version);
process.exit(0);
}
if (ARGS.ast_help) { if (ARGS.ast_help) {
var desc = UglifyJS.describe_ast(); var desc = UglifyJS.describe_ast();
sys.puts(typeof desc == "string" ? desc : JSON.stringify(desc, null, 2)); sys.puts(typeof desc == "string" ? desc : JSON.stringify(desc, null, 2));

View File

@@ -287,9 +287,9 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
}, },
wrap_commonjs: function(name, export_all) { wrap_commonjs: function(name, export_all) {
var self = this; var self = this;
var to_export = [];
if (export_all) { if (export_all) {
self.figure_out_scope(); self.figure_out_scope();
var to_export = [];
self.walk(new TreeWalker(function(node){ self.walk(new TreeWalker(function(node){
if (node instanceof AST_SymbolDeclaration && node.definition().global) { if (node instanceof AST_SymbolDeclaration && node.definition().global) {
if (!find_if(function(n){ return n.name == node.name }, to_export)) if (!find_if(function(n){ return n.name == node.name }, to_export))

View File

@@ -883,18 +883,23 @@ merge(Compressor.prototype, {
&& !self.uses_eval && !self.uses_eval
) { ) {
var in_use = []; var in_use = [];
var initializations = new Dictionary();
// pass 1: find out which symbols are directly used in // pass 1: find out which symbols are directly used in
// this scope (not in nested scopes). // this scope (not in nested scopes).
var scope = this; var scope = this;
var tw = new TreeWalker(function(node, descend){ var tw = new TreeWalker(function(node, descend){
if (node !== self) { if (node !== self) {
if (node instanceof AST_Defun) { if (node instanceof AST_Defun) {
initializations.add(node.name.name, node);
return true; // don't go in nested scopes return true; // don't go in nested scopes
} }
if (node instanceof AST_Definitions && scope === self) { if (node instanceof AST_Definitions && scope === self) {
node.definitions.forEach(function(def){ node.definitions.forEach(function(def){
if (def.value && def.value.has_side_effects()) { if (def.value) {
def.value.walk(tw); initializations.add(def.name.name, def.value);
if (def.value.has_side_effects()) {
def.value.walk(tw);
}
} }
}); });
return true; return true;
@@ -919,16 +924,15 @@ merge(Compressor.prototype, {
for (var i = 0; i < in_use.length; ++i) { for (var i = 0; i < in_use.length; ++i) {
in_use[i].orig.forEach(function(decl){ in_use[i].orig.forEach(function(decl){
// undeclared globals will be instanceof AST_SymbolRef // undeclared globals will be instanceof AST_SymbolRef
if (decl instanceof AST_SymbolDeclaration) { var init = initializations.get(decl.name);
decl.init.forEach(function(init){ if (init) init.forEach(function(init){
var tw = new TreeWalker(function(node){ var tw = new TreeWalker(function(node){
if (node instanceof AST_SymbolRef) { if (node instanceof AST_SymbolRef) {
push_uniq(in_use, node.definition()); push_uniq(in_use, node.definition());
} }
});
init.walk(tw);
}); });
} init.walk(tw);
});
}); });
} }
// pass 3: we should drop declarations not in_use // pass 3: we should drop declarations not in_use
@@ -1100,13 +1104,71 @@ merge(Compressor.prototype, {
} }
); );
self = self.transform(tt); self = self.transform(tt);
if (vars_found > 0) hoisted.unshift(make_node(AST_Var, self, { if (vars_found > 0) {
definitions: vars.map(function(def){ // collect only vars which don't show up in self's arguments list
def = def.clone(); var defs = [];
def.value = null; vars.each(function(def, name){
return def; if (self instanceof AST_Lambda
}) && find_if(function(x){ return x.name == def.name.name },
})); self.argnames)) {
vars.del(name);
} else {
def = def.clone();
def.value = null;
defs.push(def);
vars.set(name, def);
}
});
if (defs.length > 0) {
// try to merge in assignments
for (var i = 0; i < self.body.length;) {
if (self.body[i] instanceof AST_SimpleStatement) {
var expr = self.body[i].body, sym, assign;
if (expr instanceof AST_Assign
&& expr.operator == "="
&& (sym = expr.left) instanceof AST_Symbol
&& vars.has(sym.name))
{
var def = vars.get(sym.name);
if (def.value) break;
def.value = expr.right;
remove(defs, def);
defs.push(def);
self.body.splice(i, 1);
continue;
}
if (expr instanceof AST_Seq
&& (assign = expr.car) instanceof AST_Assign
&& assign.operator == "="
&& (sym = assign.left) instanceof AST_Symbol
&& vars.has(sym.name))
{
var def = vars.get(sym.name);
if (def.value) break;
def.value = assign.right;
remove(defs, def);
defs.push(def);
self.body[i].body = expr.cdr;
continue;
}
}
if (self.body[i] instanceof AST_EmptyStatement) {
self.body.splice(i, 1);
continue;
}
if (self.body[i] instanceof AST_BlockStatement) {
var tmp = [ i, 1 ].concat(self.body[i].body);
self.body.splice.apply(self.body, tmp);
continue;
}
break;
}
defs = make_node(AST_Var, self, {
definitions: defs
});
hoisted.push(defs);
};
}
self.body = dirs.concat(hoisted, self.body); self.body = dirs.concat(hoisted, self.body);
} }
return self; return self;
@@ -1430,7 +1492,7 @@ merge(Compressor.prototype, {
return node; return node;
} }
}); });
tt.stack = compressor.stack; // so that's able to see parent nodes tt.stack = compressor.stack.slice(); // so that's able to see parent nodes
self = self.transform(tt); self = self.transform(tt);
} catch(ex) { } catch(ex) {
if (ex !== self) throw ex; if (ex !== self) throw ex;
@@ -1539,7 +1601,7 @@ merge(Compressor.prototype, {
case "Function": case "Function":
case "Error": case "Error":
case "Array": case "Array":
return make_node(AST_Call, self, self); return make_node(AST_Call, self, self).transform(compressor);
} }
} }
} }

View File

@@ -340,23 +340,25 @@ function OutputStream(options) {
/* -----[ utils ]----- */ /* -----[ utils ]----- */
function DEFPRINT(nodetype, generator) { function DEFPRINT(nodetype, generator) {
nodetype.DEFMETHOD("print", function(stream){ nodetype.DEFMETHOD("_codegen", generator);
var self = this; };
stream.push_node(self);
if (self.needs_parens(stream)) { AST_Node.DEFMETHOD("print", function(stream, force_parens){
stream.with_parens(function(){ var self = this, generator = self._codegen;
self.add_comments(stream); stream.push_node(self);
self.add_source_map(stream); if (force_parens || self.needs_parens(stream)) {
generator(self, stream); stream.with_parens(function(){
});
} else {
self.add_comments(stream); self.add_comments(stream);
self.add_source_map(stream); self.add_source_map(stream);
generator(self, stream); generator(self, stream);
} });
stream.pop_node(); } else {
}); self.add_comments(stream);
}; self.add_source_map(stream);
generator(self, stream);
}
stream.pop_node();
});
AST_Node.DEFMETHOD("print_to_string", function(options){ AST_Node.DEFMETHOD("print_to_string", function(options){
var s = OutputStream(options); var s = OutputStream(options);
@@ -467,18 +469,6 @@ function OutputStream(options) {
return true; return true;
} }
} }
// for (var i = (foo in bar);;); ← perhaps useless, but valid syntax
if (this.operator == "in") {
// the “NoIn” stuff :-\
// UglifyJS 1.3.3 misses this one.
if ((p instanceof AST_For || p instanceof AST_ForIn) && p.init === this)
return true;
if (p instanceof AST_VarDef) {
var v = output.parent(1), p2 = output.parent(2);
if ((p2 instanceof AST_For || p2 instanceof AST_ForIn) && p2.init === v)
return true;
}
}
}); });
PARENS(AST_PropAccess, function(output){ PARENS(AST_PropAccess, function(output){
@@ -622,7 +612,11 @@ function OutputStream(options) {
output.space(); output.space();
output.with_parens(function(){ output.with_parens(function(){
if (self.init) { if (self.init) {
self.init.print(output); if (self.init instanceof AST_Definitions) {
self.init.print(output);
} else {
parenthesize_for_noin(self.init, output, true);
}
output.print(";"); output.print(";");
output.space(); output.space();
} else { } else {
@@ -734,7 +728,7 @@ function OutputStream(options) {
// to the inner IF). This function checks for this case and // to the inner IF). This function checks for this case and
// adds the block brackets if needed. // adds the block brackets if needed.
if (!self.body) if (!self.body)
return output.semicolon(); return output.force_semicolon();
if (self.body instanceof AST_Do if (self.body instanceof AST_Do
&& output.option("ie_proof")) { && output.option("ie_proof")) {
// https://github.com/mishoo/UglifyJS/issues/#issue/57 IE // https://github.com/mishoo/UglifyJS/issues/#issue/57 IE
@@ -758,7 +752,7 @@ function OutputStream(options) {
} }
else break; else break;
} }
self.body.print(output); force_statement(self.body, output);
}; };
DEFPRINT(AST_If, function(self, output){ DEFPRINT(AST_If, function(self, output){
output.print("if"); output.print("if");
@@ -866,13 +860,32 @@ function OutputStream(options) {
DEFPRINT(AST_Const, function(self, output){ DEFPRINT(AST_Const, function(self, output){
self._do_print(output, "const"); self._do_print(output, "const");
}); });
function parenthesize_for_noin(node, output, noin) {
if (!noin) node.print(output);
else try {
// need to take some precautions here:
// https://github.com/mishoo/UglifyJS2/issues/60
node.walk(new TreeWalker(function(node){
if (node instanceof AST_Binary && node.operator == "in")
throw output;
}));
node.print(output);
} catch(ex) {
if (ex !== output) throw ex;
node.print(output, true);
}
};
DEFPRINT(AST_VarDef, function(self, output){ DEFPRINT(AST_VarDef, function(self, output){
self.name.print(output); self.name.print(output);
if (self.value) { if (self.value) {
output.space(); output.space();
output.print("="); output.print("=");
output.space(); output.space();
self.value.print(output); var p = output.parent(1);
var noin = p instanceof AST_For || p instanceof AST_ForIn;
parenthesize_for_noin(self.value, output, noin);
} }
}); });
@@ -891,7 +904,7 @@ function OutputStream(options) {
DEFPRINT(AST_New, function(self, output){ DEFPRINT(AST_New, function(self, output){
output.print("new"); output.print("new");
output.space(); output.space();
AST_Call.prototype.print.call(self, output); AST_Call.prototype._codegen(self, output);
}); });
AST_Seq.DEFMETHOD("_do_print", function(output){ AST_Seq.DEFMETHOD("_do_print", function(output){

View File

@@ -881,11 +881,14 @@ function parse($TEXT, options) {
}; };
var function_ = function(in_statement, ctor) { var function_ = function(in_statement, ctor) {
var name = is("name") ? as_symbol(in_statement var is_accessor = ctor === AST_Accessor;
? AST_SymbolDefun var name = (is("name") ? as_symbol(in_statement
: ctor === AST_Accessor ? AST_SymbolDefun
? AST_SymbolAccessor : is_accessor
: AST_SymbolLambda) : null; ? AST_SymbolAccessor
: AST_SymbolLambda)
: is_accessor && (is("string") || is("num")) ? as_atom_node()
: null);
if (in_statement && !name) if (in_statement && !name)
unexpected(); unexpected();
expect("("); expect("(");

View File

@@ -84,9 +84,12 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
if (node instanceof AST_Scope) { if (node instanceof AST_Scope) {
node.init_scope_vars(nesting); node.init_scope_vars(nesting);
var save_scope = node.parent_scope = scope; var save_scope = node.parent_scope = scope;
var save_labels = labels;
++nesting; ++nesting;
scope = node; scope = node;
labels = new Dictionary();
descend(); descend();
labels = save_labels;
scope = save_scope; scope = save_scope;
--nesting; --nesting;
return true; // don't descend again in TreeWalker return true; // don't descend again in TreeWalker
@@ -110,9 +113,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
labels.del(l.name); labels.del(l.name);
return true; // no descend again return true; // no descend again
} }
if (node instanceof AST_SymbolDeclaration) {
node.init_scope_vars();
}
if (node instanceof AST_Symbol) { if (node instanceof AST_Symbol) {
node.scope = scope; node.scope = scope;
} }
@@ -128,8 +128,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
// scope. Don't like this fix but seems we can't do any // scope. Don't like this fix but seems we can't do any
// better. IE: please die. Please! // better. IE: please die. Please!
(node.scope = scope.parent_scope).def_function(node); (node.scope = scope.parent_scope).def_function(node);
node.init.push(tw.parent());
} }
else if (node instanceof AST_SymbolDefun) { else if (node instanceof AST_SymbolDefun) {
// Careful here, the scope where this should be defined is // Careful here, the scope where this should be defined is
@@ -138,14 +136,12 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
// instanceof AST_Scope) but we get to the symbol a bit // instanceof AST_Scope) but we get to the symbol a bit
// later. // later.
(node.scope = scope.parent_scope).def_function(node); (node.scope = scope.parent_scope).def_function(node);
node.init.push(tw.parent());
} }
else if (node instanceof AST_SymbolVar else if (node instanceof AST_SymbolVar
|| node instanceof AST_SymbolConst) { || node instanceof AST_SymbolConst) {
var def = scope.def_variable(node); var def = scope.def_variable(node);
def.constant = node instanceof AST_SymbolConst; def.constant = node instanceof AST_SymbolConst;
def = tw.parent(); def = tw.parent();
if (def.value) node.init.push(def);
} }
else if (node instanceof AST_SymbolCatch) { else if (node instanceof AST_SymbolCatch) {
// XXX: this is wrong according to ECMA-262 (12.4). the // XXX: this is wrong according to ECMA-262 (12.4). the
@@ -246,10 +242,6 @@ AST_SymbolRef.DEFMETHOD("reference", function() {
this.frame = this.scope.nesting - def.scope.nesting; this.frame = this.scope.nesting - def.scope.nesting;
}); });
AST_SymbolDeclaration.DEFMETHOD("init_scope_vars", function(){
this.init = [];
});
AST_Label.DEFMETHOD("init_scope_vars", function(){ AST_Label.DEFMETHOD("init_scope_vars", function(){
this.references = []; this.references = [];
}); });
@@ -351,6 +343,7 @@ AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
return defaults(options, { return defaults(options, {
except : [], except : [],
eval : false, eval : false,
sort : false
}); });
}); });
@@ -371,12 +364,16 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
return true; // don't descend again in TreeWalker return true; // don't descend again in TreeWalker
} }
if (node instanceof AST_Scope) { if (node instanceof AST_Scope) {
var p = tw.parent(); var p = tw.parent(), a = [];
node.variables.each(function(symbol){ node.variables.each(function(symbol){
if (options.except.indexOf(symbol.name) < 0) { if (options.except.indexOf(symbol.name) < 0) {
to_mangle.push(symbol); a.push(symbol);
} }
}); });
if (options.sort) a.sort(function(a, b){
return b.references.length - a.references.length;
});
to_mangle.push.apply(to_mangle, a);
return; return;
} }
if (node instanceof AST_Label) { if (node instanceof AST_Label) {

View File

@@ -255,6 +255,14 @@ Dictionary.prototype = {
this._values["$" + key] = val; this._values["$" + key] = val;
return this; return this;
}, },
add: function(key, val) {
if (this.has(key)) {
this.get(key).push(val);
} else {
this.set(key, [ val ]);
}
return this;
},
get: function(key) { return this._values["$" + key] }, get: function(key) { return this._values["$" + key] },
del: function(key) { del: function(key) {
if (this.has(key)) { if (this.has(key)) {

View File

@@ -3,7 +3,7 @@
"description": "JavaScript parser, mangler/compressor and beautifier toolkit", "description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"homepage": "http://lisperator.net/uglifyjs", "homepage": "http://lisperator.net/uglifyjs",
"main": "tools/node.js", "main": "tools/node.js",
"version": "2.2.1", "version": "2.2.3",
"engines": { "node" : ">=0.4.0" }, "engines": { "node" : ">=0.4.0" },
"maintainers": [{ "maintainers": [{
"name": "Mihai Bazon", "name": "Mihai Bazon",

30
test/compress/issue-59.js Normal file
View File

@@ -0,0 +1,30 @@
keep_continue: {
options = {
dead_code: true,
evaluate: true
};
input: {
while (a) {
if (b) {
switch (true) {
case c():
d();
}
continue;
}
f();
}
}
expect: {
while (a) {
if (b) {
switch (true) {
case c():
d();
}
continue;
}
f();
}
}
}

View File

@@ -56,6 +56,9 @@ exports.minify = function(files, options) {
inSourceMap : null, inSourceMap : null,
fromString : false, fromString : false,
warnings : false, warnings : false,
mangle : {},
output : null,
compress : {}
}); });
if (typeof files == "string") if (typeof files == "string")
files = [ files ]; files = [ files ];
@@ -73,16 +76,20 @@ exports.minify = function(files, options) {
}); });
// 2. compress // 2. compress
toplevel.figure_out_scope(); if (options.compress) {
var sq = UglifyJS.Compressor({ var compress = { warnings: options.warnings };
warnings: options.warnings, UglifyJS.merge(compress, options.compress);
}); toplevel.figure_out_scope();
toplevel = toplevel.transform(sq); var sq = UglifyJS.Compressor(compress);
toplevel = toplevel.transform(sq);
}
// 3. mangle // 3. mangle
toplevel.figure_out_scope(); if (options.mangle) {
toplevel.compute_char_frequency(); toplevel.figure_out_scope();
toplevel.mangle_names(); toplevel.compute_char_frequency();
toplevel.mangle_names(options.mangle);
}
// 4. output // 4. output
var map = null; var map = null;
@@ -95,7 +102,11 @@ exports.minify = function(files, options) {
orig: inMap, orig: inMap,
root: options.sourceRoot root: options.sourceRoot
}); });
var stream = UglifyJS.OutputStream({ source_map: map }); var output = { source_map: map };
if (options.output) {
UglifyJS.merge(output, options.output);
}
var stream = UglifyJS.OutputStream(output);
toplevel.print(stream); toplevel.print(stream);
return { return {
code : stream + "", code : stream + "",