Compare commits

..

41 Commits

Author SHA1 Message Date
Mihai Bazon
e3342a3cf6 v2.4.14 2014-06-12 17:24:33 +03:00
Mihai Bazon
7bf59b5bcd Actually, even better. #475
- also handle x = + ++y, x = - --y;
- don't use parens, a space suffices.
2014-04-27 21:42:14 +03:00
Mihai Bazon
025f3e9596 Better fix for #475 2014-04-27 20:54:54 +03:00
Mihai Bazon
8258edd8a5 Fix parens in +(+x). Close #475 2014-04-27 20:51:01 +03:00
Mihai Bazon
8669ca219b Merge branch 'master' of github.com:mishoo/UglifyJS2 2014-04-24 10:56:57 +03:00
Mihai Bazon
71652690b6 Merge pull request #445 from ConradIrwin/try-statement
Handle TryStatements trees from acorn >=0.2.0
2014-04-24 10:46:53 +03:00
Mihai Bazon
37693d2812 Update tests. 2014-04-18 11:19:52 +03:00
Mihai Bazon
8fbe200012 Always quote property names that contain non-ASCII characters.
Fix #328
2014-04-18 10:48:44 +03:00
Mihai Bazon
1a34a13e33 Merge pull request #470 from ebednarz/master
Fix sourceMapIncludeSources exception in Node API
2014-04-13 12:54:12 +03:00
OiNutter
ef772b0049 add sourceMappingUrl to output in node module
If options.outSourceMap is specified the sourceMappingURL comment
should be appended to the output stream
2014-04-13 11:48:38 +02:00
ebednarz
6fcabbde08 Fix sourceMapIncludeSources exception in Node API
https://github.com/mishoo/UglifyJS2/issues/459
2014-04-13 11:16:10 +02:00
Mihai Bazon
14f290f8ab Merge pull request #454 from Arnavion/allow-colons-in-wrap_enclose
Allow colons in the pairs passed to AST_Toplevel.wrap_enclose
2014-03-24 15:10:35 +02:00
Arnavion
e2e09d5754 Allow colons in the pairs passed to AST_Toplevel.wrap_enclose 2014-03-22 18:02:21 -07:00
Mihai Bazon
448a8d3845 v2.4.13 2014-03-11 15:22:37 +02:00
Conrad Irwin
514936beb8 Handle TryStatements trees from acorn >=0.2.0 2014-03-06 17:07:49 -08:00
Mihai Bazon
f5c09d0bbf Merge pull request #439 from Arnavion/null-source-in-sourcemap
Handle the case when SourceMapConsumer.originalPositionFor returns null source.
2014-03-03 09:19:39 +02:00
Arnavion
014f655c5f Handle the case when SourceMapConsumer.originalPositionFor returns null source.
This happens when SourceMapConsumer does not have a valid position to map the input line and column. This is a change in mozilla/source-map starting from version 0.1.33

Fixes #436
2014-03-02 19:20:19 -08:00
Mihai Bazon
bf30dc3038 Mangle name of exception when --screw-ie8. Fix #430.
The effect of not mangling it was visible only with --screw-ie8 (otherwise
the names would be mangled exactly because they leaked into the parent
scope).
2014-02-14 13:58:14 +02:00
Mihai Bazon
ef2ef07cbd Add option keep_fargs.
By default it's `false`.  Pass `true` if you need to keep unused function
arguments.

Close #188.
2014-02-08 12:33:56 +02:00
Mihai Bazon
1a4440080d Merge pull request #424 from mattbasta/simplify_conditionals
Simplify nested conditionals if possible
2014-02-07 11:31:11 +02:00
Matt Basta
ac0086a745 Simplify nested conditionals if possible 2014-02-06 12:39:13 -08:00
Mihai Bazon
2494daaf68 Merge pull request #422 from mourner/patch-1
Fix readme typo (when -> with)
2014-02-06 18:13:10 +02:00
Vladimir Agafonkin
9b404f9de6 fix readme typo (when -> with) 2014-02-06 18:11:33 +02:00
Mihai Bazon
5344b7dab8 Fix if_return dropping the alternative. Close #413 2014-01-31 10:44:13 +02:00
Mihai Bazon
0007a53b9c Update source-map 2014-01-26 10:18:20 +02:00
Mihai Bazon
1dd05f44eb Merge branch 'sourcesContent' of https://github.com/arty-name/UglifyJS2 into arty-name-sourcesContent 2014-01-26 10:15:24 +02:00
Mihai Bazon
bf7b122ab2 v2.4.12 2014-01-26 10:11:00 +02:00
Mihai Bazon
e29048b54a Merge branch 'master' of github.com:mishoo/UglifyJS2 2014-01-26 10:07:10 +02:00
Mihai Bazon
2eeb640eca Merge pull request #408 from danielstutzman/escape-null-in-regex
Don't unescape \x00 in regexes (it breaks IE8)
2014-01-26 00:06:19 -08:00
Mihai Bazon
ceb200fe81 Move unescaping regexps under a codegen option (unescape_regexps) 2014-01-26 10:05:55 +02:00
Daniel Stutzman
f5f8239057 Don't unescape \x00 in regexes (it breaks IE8) 2014-01-25 11:55:39 -07:00
Mihai Bazon
6f9d051784 v2.4.11 2014-01-21 11:44:28 +02:00
Mihai Bazon
931862e97f More chars that cannot be unescaped in regexps. 2014-01-21 11:44:00 +02:00
Mihai Bazon
1d0127de21 Fix end token for conditionals. Close #404 2014-01-21 10:38:59 +02:00
Mihai Bazon
2d8fc61677 Merge pull request #402 from lautis/bom-regexps
Don't unescape byte order marks in regexps
2014-01-19 06:14:12 -08:00
Ville Lautanala
1e31011874 Don't unescape byte order marks in regexps 2014-01-19 12:27:03 +02:00
Mihai Bazon
75cdbf19aa v2.4.10 2014-01-18 12:32:45 +02:00
Mihai Bazon
4339bd5cfa Don't unescape \x2f (slash) in regexps. #54 2014-01-18 12:31:50 +02:00
Mihai Bazon
1ab2fdaa10 Fix example 2014-01-17 15:48:47 +02:00
Artemy Tregubenko
f6203bd5a8 added hasOwnProperty check to avoid warnings 2014-01-09 15:20:05 +01:00
Artemy Tregubenko
03cf94ebe8 Added support for sourcesContent property of source map 2014-01-09 15:12:00 +01:00
13 changed files with 160 additions and 51 deletions

View File

@@ -54,6 +54,10 @@ The available options are:
--source-map-url The path to the source map to be added in //#
sourceMappingURL. Defaults to the value passed with
--source-map. [string]
--source-map-include-sources
Pass this flag if you want to include the content of
source files in the source map as sourcesContent
property. [boolean]
--in-source-map Input source map, useful if you're compressing JS that was
generated from some other original code.
--screw-ie8 Pass this flag if you don't care about full compliance
@@ -169,7 +173,7 @@ To enable the mangler you need to pass `--mangle` (`-m`). The following
- `toplevel` — mangle names declared in the toplevel scope (disabled by
default).
- `eval` — mangle names visible in scopes where `eval` or `when` are used
- `eval` — mangle names visible in scopes where `eval` or `with` are used
(disabled by default).
When mangling is enabled but you want to prevent certain names from being
@@ -505,7 +509,7 @@ something like this:
```javascript
var toplevel = null;
files.forEach(function(file){
var code = fs.readFileSync(file);
var code = fs.readFileSync(file, "utf8");
toplevel = UglifyJS.parse(code, {
filename: file,
toplevel: toplevel

View File

@@ -22,6 +22,7 @@ mangling you need to use `-c` and `-m`.\
.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-url", "The path to the source map to be added in //# sourceMappingURL. Defaults to the value passed with --source-map.")
.describe("source-map-include-sources", "Pass this flag if you want to include the content of source files in the source map as sourcesContent property.")
.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("expr", "Parse a single expression, rather than a program (for parsing JSON)")
@@ -88,6 +89,7 @@ You need to pass an argument to this option to specify the name that your module
.string("p")
.boolean("expr")
.boolean("source-map-include-sources")
.boolean("screw-ie8")
.boolean("export-all")
.boolean("self")
@@ -218,6 +220,7 @@ var STATS = {};
var OUTPUT_FILE = ARGS.o;
var TOPLEVEL = null;
var P_RELATIVE = ARGS.p && ARGS.p == "relative";
var SOURCES_CONTENT = {};
var SOURCE_MAP = ARGS.source_map ? UglifyJS.SourceMap({
file: P_RELATIVE ? path.relative(path.dirname(ARGS.source_map), OUTPUT_FILE) : OUTPUT_FILE,
@@ -255,6 +258,7 @@ async.eachLimit(files, 1, function (file, cb) {
}
}
}
SOURCES_CONTENT[file] = code;
time_it("parse", function(){
if (ARGS.spidermonkey) {
var program = JSON.parse(code);
@@ -337,6 +341,15 @@ async.eachLimit(files, 1, function (file, cb) {
if (MANGLE) time_it("mangle", function(){
TOPLEVEL.mangle_names(MANGLE);
});
if (ARGS.source_map_include_sources) {
for (var file in SOURCES_CONTENT) {
if (SOURCES_CONTENT.hasOwnProperty(file)) {
SOURCE_MAP.get().setSourceContent(file, SOURCES_CONTENT[file]);
}
}
}
time_it("generate", function(){
TOPLEVEL.print(output);
});

View File

@@ -295,10 +295,10 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
var parameters = [];
arg_parameter_pairs.forEach(function(pair) {
var split = pair.split(":");
var splitAt = pair.lastIndexOf(":");
args.push(split[0]);
parameters.push(split[1]);
args.push(pair.substr(0, splitAt));
parameters.push(pair.substr(splitAt + 1));
});
var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")";

View File

@@ -61,6 +61,7 @@ function Compressor(options, false_by_default) {
loops : !false_by_default,
unused : !false_by_default,
hoist_funs : !false_by_default,
keep_fargs : false,
hoist_vars : false,
if_return : !false_by_default,
join_vars : !false_by_default,
@@ -376,7 +377,7 @@ merge(Compressor.prototype, {
stat = stat.clone();
stat.condition = stat.condition.negate(compressor);
stat.body = make_node(AST_BlockStatement, stat, {
body: ret
body: as_statement_array(stat.alternative).concat(ret)
});
stat.alternative = make_node(AST_BlockStatement, stat, {
body: body
@@ -1044,18 +1045,20 @@ merge(Compressor.prototype, {
var tt = new TreeTransformer(
function before(node, descend, in_list) {
if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
for (var a = node.argnames, i = a.length; --i >= 0;) {
var sym = a[i];
if (sym.unreferenced()) {
a.pop();
compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", {
name : sym.name,
file : sym.start.file,
line : sym.start.line,
col : sym.start.col
});
if (!compressor.option("keep_fargs")) {
for (var a = node.argnames, i = a.length; --i >= 0;) {
var sym = a[i];
if (sym.unreferenced()) {
a.pop();
compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", {
name : sym.name,
file : sym.start.file,
line : sym.start.line,
col : sym.start.col
});
}
else break;
}
else break;
}
}
if (node instanceof AST_Defun && node !== self) {
@@ -2296,6 +2299,19 @@ merge(Compressor.prototype, {
return consequent;
}
}
// x?y?z:a:a --> x&&y?z:a
if (consequent instanceof AST_Conditional
&& consequent.alternative.equivalent_to(alternative)) {
return make_node(AST_Conditional, self, {
condition: make_node(AST_Binary, self, {
left: self.condition,
operator: "&&",
right: consequent.condition
}),
consequent: consequent.consequent,
alternative: alternative
});
}
return self;
});

View File

@@ -51,7 +51,7 @@
start : my_start_token(M),
end : my_end_token(M),
body : from_moz(M.block).body,
bcatch : from_moz(M.handlers[0]),
bcatch : from_moz(M.handlers ? M.handlers[0] : M.handler),
bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null
});
},

View File

@@ -46,22 +46,23 @@
function OutputStream(options) {
options = defaults(options, {
indent_start : 0,
indent_level : 4,
quote_keys : false,
space_colon : true,
ascii_only : false,
inline_script : false,
width : 80,
max_line_len : 32000,
beautify : false,
source_map : null,
bracketize : false,
semicolons : true,
comments : false,
preserve_line : false,
screw_ie8 : false,
preamble : null,
indent_start : 0,
indent_level : 4,
quote_keys : false,
space_colon : true,
ascii_only : false,
unescape_regexps : false,
inline_script : false,
width : 80,
max_line_len : 32000,
beautify : false,
source_map : null,
bracketize : false,
semicolons : true,
comments : false,
preserve_line : false,
screw_ie8 : false,
preamble : null,
}, true);
var indentation = 0;
@@ -995,8 +996,12 @@ function OutputStream(options) {
DEFPRINT(AST_UnaryPrefix, function(self, output){
var op = self.operator;
output.print(op);
if (/^[a-z]/i.test(op))
if (/^[a-z]/i.test(op)
|| (/[+-]$/.test(op)
&& self.expression instanceof AST_UnaryPrefix
&& /^[+-]/.test(self.expression.operator))) {
output.space();
}
self.expression.print(output);
});
DEFPRINT(AST_UnaryPostfix, function(self, output){
@@ -1118,15 +1123,44 @@ function OutputStream(options) {
DEFPRINT(AST_Number, function(self, output){
output.print(make_num(self.getValue()));
});
function regexp_safe_literal(code) {
return [
0x5c , // \
0x2f , // /
0x2e , // .
0x2b , // +
0x2a , // *
0x3f , // ?
0x28 , // (
0x29 , // )
0x5b , // [
0x5d , // ]
0x7b , // {
0x7d , // }
0x24 , // $
0x5e , // ^
0x3a , // :
0x7c , // |
0x21 , // !
0x0a , // \n
0x0d , // \r
0x00 , // \0
0xfeff , // Unicode BOM
0x2028 , // unicode "line separator"
0x2029 , // unicode "paragraph separator"
].indexOf(code) < 0;
};
DEFPRINT(AST_RegExp, function(self, output){
var str = self.getValue().toString();
if (output.option("ascii_only")) {
str = output.to_ascii(str);
} else {
} else if (output.option("unescape_regexps")) {
str = str.split("\\\\").map(function(str){
return str.replace(/\\u[0-9a-fA-F]{4}|\\x[0-9a-fA-F]{2}/g, function(s){
var code = parseInt(s.substr(2), 16);
return code == 10 || code == 13 || code == 0x2028 || code == 0x2029 ? s : String.fromCharCode(code);
return regexp_safe_literal(code) ? String.fromCharCode(code) : s;
});
}).join("\\\\");
}

View File

@@ -168,14 +168,7 @@ function is_identifier_char(ch) {
};
function is_identifier_string(str){
var i = str.length;
if (i == 0) return false;
if (!is_identifier_start(str.charCodeAt(0))) return false;
while (--i >= 0) {
if (!is_identifier_char(str.charAt(i)))
return false;
}
return true;
return /^[a-z_$][a-z0-9_$]*$/i.test(str);
};
function parse_js_number(num) {
@@ -1381,7 +1374,7 @@ function parse($TEXT, options) {
condition : expr,
consequent : yes,
alternative : expression(false, no_in),
end : peek()
end : prev()
});
}
return expr;

View File

@@ -365,6 +365,10 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
node.mangled_name = name;
return true;
}
if (options.screw_ie8 && node instanceof AST_SymbolCatch) {
to_mangle.push(node.definition());
return;
}
});
this.walk(tw);
to_mangle.forEach(function(def){ def.mangle(options) });

View File

@@ -64,6 +64,9 @@ function SourceMap(options) {
line: orig_line,
column: orig_col
});
if (info.source === null) {
return;
}
source = info.source;
orig_line = info.line;
orig_col = info.column;

View File

@@ -3,7 +3,7 @@
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"homepage": "http://lisperator.net/uglifyjs",
"main": "tools/node.js",
"version": "2.4.9",
"version": "2.4.14",
"engines": { "node" : ">=0.4.0" },
"maintainers": [{
"name": "Mihai Bazon",
@@ -16,7 +16,7 @@
},
"dependencies": {
"async" : "~0.2.6",
"source-map" : "~0.1.7",
"source-map" : "~0.1.33",
"optimist" : "~0.3.5",
"uglify-to-browserify": "~1.0.0"
},

View File

@@ -205,3 +205,30 @@ cond_4: {
some_condition(), do_something();
}
}
cond_5: {
options = {
conditionals: true
};
input: {
if (some_condition()) {
if (some_other_condition()) {
do_something();
} else {
alternate();
}
} else {
alternate();
}
if (some_condition()) {
if (some_other_condition()) {
do_something();
}
}
}
expect: {
some_condition() && some_other_condition() ? do_something() : alternate();
some_condition() && some_other_condition() && do_something();
}
}

View File

@@ -26,7 +26,7 @@ dot_properties: {
a.foo = "bar";
a["if"] = "if";
a["*"] = "asterisk";
a.\u0EB3 = "unicode";
a["\u0EB3"] = "unicode";
a[""] = "whitespace";
a["1_1"] = "foo";
}
@@ -48,7 +48,7 @@ dot_properties_es5: {
a.foo = "bar";
a.if = "if";
a["*"] = "asterisk";
a.\u0EB3 = "unicode";
a["\u0EB3"] = "unicode";
a[""] = "whitespace";
}
}

View File

@@ -64,7 +64,8 @@ exports.minify = function(files, options) {
UglifyJS.base54.reset();
// 1. parse
var toplevel = null;
var toplevel = null,
sourcesContent = {};
if (options.spidermonkey) {
toplevel = UglifyJS.AST_Node.from_mozilla_ast(files);
@@ -75,6 +76,7 @@ exports.minify = function(files, options) {
var code = options.fromString
? file
: fs.readFileSync(file, "utf8");
sourcesContent[file] = code;
toplevel = UglifyJS.parse(code, {
filename: options.fromString ? "?" : file,
toplevel: toplevel
@@ -110,12 +112,25 @@ exports.minify = function(files, options) {
orig: inMap,
root: options.sourceRoot
});
if (options.sourceMapIncludeSources) {
for (var file in sourcesContent) {
if (sourcesContent.hasOwnProperty(file)) {
output.source_map.get().setSourceContent(file, sourcesContent[file]);
}
}
}
}
if (options.output) {
UglifyJS.merge(output, options.output);
}
var stream = UglifyJS.OutputStream(output);
toplevel.print(stream);
if(options.outSourceMap){
stream += "\n//# sourceMappingURL=" + options.outSourceMap;
}
return {
code : stream + "",
map : output.source_map + ""