Compare commits

..

18 Commits

Author SHA1 Message Date
Mihai Bazon
188e28efd7 v2.3.6 2013-05-23 23:42:32 +03:00
Mihai Bazon
2df48924cc Merge pull request #213 from mattrobenolt/patch-1
SourceMapping pragma has changed to //#
2013-05-22 11:30:54 -07:00
Mihai Bazon
9fc6796d2a Add negate_iife option to the code generator.
See discussion in a9511dfbe5
2013-05-22 21:22:14 +03:00
Mihai Bazon
9fc8a52142 Set "global" on undeclared SymbolDef-s 2013-05-22 13:08:19 +03:00
Matt Robenolt
3a21861580 The extra /* */ isn't needed now 2013-05-21 08:50:21 -06:00
Matt Robenolt
1dbffd48ea SourceMapping pragma has changed to //#
See: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit

The spec was updated on May 16th since `//@` was causing some issues with IE.
2013-05-21 08:46:27 -06:00
Mihai Bazon
22a038e6a2 Fix output of statement: new function(){...};
Close #209
2013-05-20 08:27:37 +03:00
Mihai Bazon
f652372c9a v2.3.5 2013-05-19 14:25:05 +03:00
Mihai Bazon
ad1fc3b71a Fix package.json (use repository instead of repositories) 2013-05-19 14:24:33 +03:00
Mihai Bazon
2b40a5ac62 v2.3.4 2013-05-15 13:27:40 +03:00
Mihai Bazon
ca3388cf5a Add --expr, an option to parse a single expression (suitable for JSON) 2013-05-15 13:27:23 +03:00
Mihai Bazon
caa8896a8a Only compress code in new Function if all arguments are strings. 2013-05-14 18:36:31 +03:00
Mihai Bazon
d13aa3954d v2.3.3 2013-05-14 11:33:28 +03:00
Mihai Bazon
f64539fb76 Compress code passed to new Function if it's a constant.
Only for `--unsafe`.

Close #203
2013-05-14 10:47:06 +03:00
Mihai Bazon
d56ebd7d7b Fix a["1_1"]
Close #204
2013-05-14 10:42:34 +03:00
Mihai Bazon
3edfe7d0ee Merge pull request #202 from nschonni/add-travis-ci
Add CI build for supported Node versions
2013-05-10 02:56:24 -07:00
Nick Schonning
46814f88d9 Add Travis build badge to README 2013-05-08 23:48:12 -04:00
Nick Schonning
4a19802d0c Add CI build for supported Node versions 2013-05-08 23:42:06 -04:00
11 changed files with 87 additions and 16 deletions

7
.travis.yml Normal file
View File

@@ -0,0 +1,7 @@
language: node_js
node_js:
- "0.4"
- "0.6"
- "0.8"
- "0.10"
- "0.11"

View File

@@ -1,5 +1,6 @@
UglifyJS 2 UglifyJS 2
========== ==========
[![Build Status](https://travis-ci.org/mishoo/UglifyJS2.png)](https://travis-ci.org/mishoo/UglifyJS2)
UglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit. UglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit.
@@ -286,6 +287,10 @@ can pass additional arguments that control the code output:
you pass `false` then whenever possible we will use a newline instead of a you pass `false` then whenever possible we will use a newline instead of a
semicolon, leading to more readable output of uglified code (size before semicolon, leading to more readable output of uglified code (size before
gzip could be smaller; size after gzip insignificantly larger). gzip could be smaller; size after gzip insignificantly larger).
- `negate-iife` (default `!beautify`) -- prefer negation, rather than
parens, for "Immediately-Called Function Expressions". This defaults to
`true` when beautification is off, and `false` if beautification is on;
pass it manually to force a value.
### Keeping copyright notices or other comments ### Keeping copyright notices or other comments

View File

@@ -20,9 +20,10 @@ mangling you need to use `-c` and `-m`.\
") ")
.describe("source-map", "Specify an output file where to generate source map.") .describe("source-map", "Specify an output file where to generate source map.")
.describe("source-map-root", "The path to the original source to be included in the source map.") .describe("source-map-root", "The path to the original source to be included in the source map.")
.describe("source-map-url", "The path to the source map to be added in //@ sourceMappingURL. Defaults to the value passed with --source-map.") .describe("source-map-url", "The path to the source map to be added in //# sourceMappingURL. Defaults to the value passed with --source-map.")
.describe("in-source-map", "Input source map, useful if you're compressing JS that was generated from some other original code.") .describe("in-source-map", "Input source map, useful if you're compressing JS that was generated from some other original code.")
.describe("screw-ie8", "Pass this flag if you don't care about full compliance with Internet Explorer 6-8 quirks (by default UglifyJS will try to be IE-proof).") .describe("screw-ie8", "Pass this flag if you don't care about full compliance with Internet Explorer 6-8 quirks (by default UglifyJS will try to be IE-proof).")
.describe("expr", "Parse a single expression, rather than a program (for parsing JSON)")
.describe("p", "Skip prefix for original filenames that appear in source maps. \ .describe("p", "Skip prefix for original filenames that appear in source maps. \
For example -p 3 will drop 3 directories from file names and ensure they are relative paths.") For example -p 3 will drop 3 directories from file names and ensure they are relative paths.")
.describe("o", "Output file (default STDOUT).") .describe("o", "Output file (default STDOUT).")
@@ -76,6 +77,8 @@ You need to pass an argument to this option to specify the name that your module
.string("e") .string("e")
.string("comments") .string("comments")
.string("wrap") .string("wrap")
.boolean("expr")
.boolean("screw-ie8") .boolean("screw-ie8")
.boolean("export-all") .boolean("export-all")
.boolean("self") .boolean("self")
@@ -242,8 +245,9 @@ async.eachLimit(files, 1, function (file, cb) {
} }
else { else {
TOPLEVEL = UglifyJS.parse(code, { TOPLEVEL = UglifyJS.parse(code, {
filename: file, filename : file,
toplevel: TOPLEVEL toplevel : TOPLEVEL,
expression : ARGS.expr,
}); });
}; };
}); });
@@ -305,7 +309,7 @@ async.eachLimit(files, 1, function (file, cb) {
if (SOURCE_MAP) { if (SOURCE_MAP) {
fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8"); fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8");
output += "\n/*\n//@ sourceMappingURL=" + (ARGS.source_map_url || ARGS.source_map) + "\n*/"; output += "\n//# sourceMappingURL=" + (ARGS.source_map_url || ARGS.source_map);
} }
if (OUTPUT_FILE) { if (OUTPUT_FILE) {

View File

@@ -1589,6 +1589,45 @@ merge(Compressor.prototype, {
operator: "+", operator: "+",
right: make_node(AST_String, self, { value: "" }) right: make_node(AST_String, self, { value: "" })
}); });
case "Function":
if (all(self.args, function(x){ return x instanceof AST_String })) {
// quite a corner-case, but we can handle it:
// https://github.com/mishoo/UglifyJS2/issues/203
// if the code argument is a constant, then we can minify it.
try {
var code = "(function(" + self.args.slice(0, -1).map(function(arg){
return arg.value;
}).join(",") + "){" + self.args[self.args.length - 1].value + "})()";
var ast = parse(code);
ast.figure_out_scope();
var comp = new Compressor(compressor.options);
ast = ast.transform(comp);
ast.figure_out_scope();
ast.mangle_names();
var fun = ast.body[0].body.expression;
var args = fun.argnames.map(function(arg, i){
return make_node(AST_String, self.args[i], {
value: arg.print_to_string()
});
});
var code = OutputStream();
AST_BlockStatement.prototype._codegen.call(fun, fun, code);
code = code.toString().replace(/^\{|\}$/g, "");
args.push(make_node(AST_String, self.args[self.args.length - 1], {
value: code
}));
self.args = args;
return self;
} catch(ex) {
if (ex instanceof JS_Parse_Error) {
compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start);
compressor.warn(ex.toString());
} else {
console.log(ex);
}
}
}
break;
} }
} }
else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) { else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) {
@@ -1965,8 +2004,8 @@ merge(Compressor.prototype, {
var prop = self.property; var prop = self.property;
if (prop instanceof AST_String && compressor.option("properties")) { if (prop instanceof AST_String && compressor.option("properties")) {
prop = prop.getValue(); prop = prop.getValue();
if (compressor.option("screw_ie8") && RESERVED_WORDS(prop) if ((compressor.option("screw_ie8") && RESERVED_WORDS(prop))
|| !(RESERVED_WORDS(prop)) && is_identifier_string(prop)) { || (!(RESERVED_WORDS(prop)) && is_identifier_string(prop))) {
return make_node(AST_Dot, self, { return make_node(AST_Dot, self, {
expression : self.expression, expression : self.expression,
property : prop property : prop

View File

@@ -60,7 +60,8 @@ function OutputStream(options) {
bracketize : false, bracketize : false,
semicolons : true, semicolons : true,
comments : false, comments : false,
preserve_line : false preserve_line : false,
negate_iife : !(options && options.beautify),
}, true); }, true);
var indentation = 0; var indentation = 0;
@@ -352,7 +353,7 @@ function OutputStream(options) {
var self = this, generator = self._codegen; var self = this, generator = self._codegen;
stream.push_node(self); stream.push_node(self);
var needs_parens = self.needs_parens(stream); var needs_parens = self.needs_parens(stream);
var fc = self instanceof AST_Function && !stream.option("beautify"); var fc = self instanceof AST_Function && stream.option("negate_iife");
if (force_parens || (needs_parens && !fc)) { if (force_parens || (needs_parens && !fc)) {
stream.with_parens(function(){ stream.with_parens(function(){
self.add_comments(stream); self.add_comments(stream);
@@ -1122,7 +1123,7 @@ function OutputStream(options) {
if (p instanceof AST_Statement && p.body === node) if (p instanceof AST_Statement && p.body === node)
return true; return true;
if ((p instanceof AST_Seq && p.car === node ) || if ((p instanceof AST_Seq && p.car === node ) ||
(p instanceof AST_Call && p.expression === node ) || (p instanceof AST_Call && p.expression === node && !(p instanceof AST_New) ) ||
(p instanceof AST_Dot && p.expression === node ) || (p instanceof AST_Dot && p.expression === node ) ||
(p instanceof AST_Sub && p.expression === node ) || (p instanceof AST_Sub && p.expression === node ) ||
(p instanceof AST_Conditional && p.condition === node ) || (p instanceof AST_Conditional && p.condition === node ) ||

View File

@@ -170,6 +170,7 @@ function is_identifier_char(ch) {
function is_identifier_string(str){ function is_identifier_string(str){
var i = str.length; var i = str.length;
if (i == 0) return false; if (i == 0) return false;
if (is_digit(str.charCodeAt(0))) return false;
while (--i >= 0) { while (--i >= 0) {
if (!is_identifier_char(str.charAt(i))) if (!is_identifier_char(str.charAt(i)))
return false; return false;
@@ -587,9 +588,10 @@ var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "nam
function parse($TEXT, options) { function parse($TEXT, options) {
options = defaults(options, { options = defaults(options, {
strict : false, strict : false,
filename : null, filename : null,
toplevel : null toplevel : null,
expression : false
}); });
var S = { var S = {
@@ -1385,6 +1387,10 @@ function parse($TEXT, options) {
return ret; return ret;
}; };
if (options.expression) {
return expression(true);
}
return (function(){ return (function(){
var start = S.token; var start = S.token;
var body = []; var body = [];

View File

@@ -187,6 +187,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
} else { } else {
g = new SymbolDef(self, globals.size(), node); g = new SymbolDef(self, globals.size(), node);
g.undeclared = true; g.undeclared = true;
g.global = true;
globals.set(name, g); globals.set(name, g);
} }
node.thedef = g; node.thedef = g;

View File

@@ -44,7 +44,6 @@
"use strict"; "use strict";
// Tree transformer helpers. // Tree transformer helpers.
// XXX: eventually I should refactor the compressor to use this infrastructure.
function TreeTransformer(before, after) { function TreeTransformer(before, after) {
TreeWalker.call(this); TreeWalker.call(this);

View File

@@ -245,6 +245,13 @@ function makePredicate(words) {
return new Function("str", f); return new Function("str", f);
}; };
function all(array, predicate) {
for (var i = array.length; --i >= 0;)
if (!predicate(array[i]))
return false;
return true;
};
function Dictionary() { function Dictionary() {
this._values = Object.create(null); this._values = Object.create(null);
this._size = 0; this._size = 0;

View File

@@ -3,17 +3,17 @@
"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.3.2", "version": "2.3.6",
"engines": { "node" : ">=0.4.0" }, "engines": { "node" : ">=0.4.0" },
"maintainers": [{ "maintainers": [{
"name": "Mihai Bazon", "name": "Mihai Bazon",
"email": "mihai.bazon@gmail.com", "email": "mihai.bazon@gmail.com",
"web": "http://lisperator.net/" "web": "http://lisperator.net/"
}], }],
"repositories": [{ "repository": {
"type": "git", "type": "git",
"url": "https://github.com/mishoo/UglifyJS2.git" "url": "https://github.com/mishoo/UglifyJS2.git"
}], },
"dependencies": { "dependencies": {
"async" : "~0.2.6", "async" : "~0.2.6",
"source-map" : "~0.1.7", "source-map" : "~0.1.7",

View File

@@ -20,6 +20,7 @@ dot_properties: {
a["*"] = "asterisk"; a["*"] = "asterisk";
a["\u0EB3"] = "unicode"; a["\u0EB3"] = "unicode";
a[""] = "whitespace"; a[""] = "whitespace";
a["1_1"] = "foo";
} }
expect: { expect: {
a.foo = "bar"; a.foo = "bar";
@@ -27,6 +28,7 @@ dot_properties: {
a["*"] = "asterisk"; a["*"] = "asterisk";
a.\u0EB3 = "unicode"; a.\u0EB3 = "unicode";
a[""] = "whitespace"; a[""] = "whitespace";
a["1_1"] = "foo";
} }
} }