lib/uglify.js in uglifier-1.1.0 vs lib/uglify.js in uglifier-1.2.0
- old
+ new
@@ -302,13 +302,13 @@
}
};
function JS_Parse_Error(message, line, col, pos) {
this.message = message;
- this.line = line;
- this.col = col;
- this.pos = pos;
+ this.line = line + 1;
+ this.col = col + 1;
+ this.pos = pos + 1;
this.stack = new Error().stack;
};
JS_Parse_Error.prototype.toString = function() {
return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack;
@@ -374,16 +374,17 @@
function token(type, value, is_comment) {
S.regex_allowed = ((type == "operator" && !HOP(UNARY_POSTFIX, value)) ||
(type == "keyword" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) ||
(type == "punc" && HOP(PUNC_BEFORE_EXPRESSION, value)));
var ret = {
- type : type,
- value : value,
- line : S.tokline,
- col : S.tokcol,
- pos : S.tokpos,
- nlb : S.newline_before
+ type : type,
+ value : value,
+ line : S.tokline,
+ col : S.tokcol,
+ pos : S.tokpos,
+ endpos : S.pos,
+ nlb : S.newline_before
};
if (!is_comment) {
ret.comments_before = S.comments_before;
S.comments_before = [];
}
@@ -516,12 +517,11 @@
function read_multiline_comment() {
next();
return with_eof_error("Unterminated multiline comment", function(){
var i = find("*/", true),
- text = S.text.substring(S.pos, i),
- tok = token("comment2", text, true);
+ text = S.text.substring(S.pos, i);
S.pos = i + 2;
S.line += text.split("\n").length - 1;
S.newline_before = text.indexOf("\n") >= 0;
// https://github.com/mishoo/UglifyJS/issues/#issue/100
@@ -529,11 +529,11 @@
warn("WARNING: at line " + S.line);
warn("*** Found \"conditional comment\": " + text);
warn("*** UglifyJS DISCARDS ALL COMMENTS. This means your code might no longer work properly in Internet Explorer.");
}
- return tok;
+ return token("comment2", text, true);
});
};
function read_name() {
var backslash = false, name = "", ch;
@@ -980,11 +980,11 @@
var obj = expression();
expect(")");
return as("for-in", init, lhs, obj, in_loop(statement));
};
- var function_ = maybe_embed_tokens(function(in_statement) {
+ var function_ = function(in_statement) {
var name = is("name") ? prog1(S.token.value, next) : null;
if (in_statement && !name)
unexpected();
expect("(");
return as(in_statement ? "defun" : "function",
@@ -1008,11 +1008,11 @@
var a = block_();
--S.in_function;
S.in_loop = loop;
return a;
})());
- });
+ };
function if_() {
var cond = parenthesised(), body = statement(), belse;
if (is("keyword", "else")) {
next();
@@ -1356,11 +1356,11 @@
return str.split("");
};
function member(name, array) {
for (var i = array.length; --i >= 0;)
- if (array[i] === name)
+ if (array[i] == name)
return true;
return false;
};
function HOP(obj, prop) {
@@ -1770,10 +1770,11 @@
var w = ast_walker(), walk = w.walk;
var having_eval = [];
function with_new_scope(cont) {
current_scope = new Scope(current_scope);
+ current_scope.labels = new Scope();
var ret = current_scope.body = cont();
ret.scope = current_scope;
current_scope = current_scope.parent;
return ret;
};
@@ -1802,18 +1803,23 @@
if (d[1]) reference(d[0]);
});
};
};
+ function _breacont(label) {
+ if (label)
+ current_scope.labels.refs[label] = true;
+ };
+
return with_new_scope(function(){
// process AST
var ret = w.with_walkers({
"function": _lambda,
"defun": _lambda,
- "label": function(name, stat) { define(name, "label") },
- "break": function(label) { if (label) reference(label) },
- "continue": function(label) { if (label) reference(label) },
+ "label": function(name, stat) { current_scope.labels.define(name) },
+ "break": _breacont,
+ "continue": _breacont,
"with": function(expr, block) {
for (var s = current_scope; s; s = s.parent)
s.uses_with = true;
},
"var": _vardefs("var"),
@@ -1895,19 +1901,22 @@
return null;
}
};
function _lambda(name, args, body) {
- var is_defun = this[0] == "defun", extra;
- if (name) {
- if (is_defun) name = get_mangled(name);
- else {
- extra = {};
- if (!(scope.uses_eval || scope.uses_with))
- name = extra[name] = scope.next_mangled();
- else
- extra[name] = name;
+ if (!options.no_functions) {
+ var is_defun = this[0] == "defun", extra;
+ if (name) {
+ if (is_defun) name = get_mangled(name);
+ else if (body.scope.references(name)) {
+ extra = {};
+ if (!(scope.uses_eval || scope.uses_with))
+ name = extra[name] = scope.next_mangled();
+ else
+ extra[name] = name;
+ }
+ else name = null;
}
}
body = with_scope(body.scope, function(){
args = MAP(args, function(name){ return get_mangled(name) });
return MAP(body, walk);
@@ -1934,10 +1943,14 @@
return [ this[0], MAP(defs, function(d){
return [ get_mangled(d[0]), walk(d[1]) ];
}) ];
};
+ function _breacont(label) {
+ if (label) return [ this[0], scope.labels.get_mangled(label) ];
+ };
+
return w.with_walkers({
"function": _lambda,
"defun": function() {
// move function declarations to the top when
// they are not in some block.
@@ -1948,13 +1961,20 @@
case "defun":
return MAP.at_top(ast);
}
return ast;
},
- "label": function(label, stat) { return [ this[0], get_mangled(label), walk(stat) ] },
- "break": function(label) { if (label) return [ this[0], get_mangled(label) ] },
- "continue": function(label) { if (label) return [ this[0], get_mangled(label) ] },
+ "label": function(label, stat) {
+ if (scope.labels.refs[label]) return [
+ this[0],
+ scope.labels.get_mangled(label, true),
+ walk(stat)
+ ];
+ return walk(stat);
+ },
+ "break": _breacont,
+ "continue": _breacont,
"var": _vardefs,
"const": _vardefs,
"name": function(name) {
return get_define(name) || [ this[0], get_mangled(name) ];
},
@@ -2364,11 +2384,11 @@
dead_code : true,
no_warnings : false,
keep_comps : true
});
- var w = ast_walker(), walk = w.walk, scope;
+ var w = ast_walker(), walk = w.walk;
function negate(c) {
var not_c = [ "unary-prefix", "!", c ];
switch (c[0]) {
case "unary-prefix":
@@ -2416,19 +2436,10 @@
warn_unreachable(val ? e : t);
return (val ? t : e);
}, make_real_conditional);
};
- function with_scope(s, cont) {
- var _scope = scope;
- scope = s;
- var ret = cont();
- ret.scope = s;
- scope = _scope;
- return ret;
- };
-
function rmblock(block) {
if (block != null && block[0] == "block" && block[1]) {
if (block[1].length == 1)
block = block[1][0];
else if (block[1].length == 0)
@@ -2436,18 +2447,11 @@
}
return block;
};
function _lambda(name, args, body) {
- var is_defun = this[0] == "defun";
- body = with_scope(body.scope, function(){
- var ret = tighten(body, "lambda");
- if (!is_defun && name && !scope.references(name))
- name = null;
- return ret;
- });
- return [ this[0], name, args, body ];
+ return [ this[0], name, args, tighten(body, "lambda") ];
};
// this function does a few things:
// 1. discard useless blocks
// 2. join consecutive var declarations
@@ -2657,13 +2661,11 @@
return [ "sub", walk(expr), [ "num", parseInt(name, 10) ] ];
}
},
"if": make_if,
"toplevel": function(body) {
- return [ "toplevel", with_scope(this.scope, function(){
- return tighten(body);
- }) ];
+ return [ "toplevel", tighten(body) ];
},
"switch": function(expr, body) {
var last = body.length - 1;
return [ "switch", walk(expr), MAP(body, function(branch, i){
var block = tighten(branch[1]);
@@ -2734,11 +2736,10 @@
return [ this[0], op, lvalue, rvalue ];
}
}, function() {
for (var i = 0; i < 2; ++i) {
ast = prepare_ifs(ast);
- ast = ast_add_scope(ast);
ast = walk(ast);
}
return ast;
});
};
@@ -2806,11 +2807,11 @@
space = beautify ? " " : "";
function encode_string(str) {
var ret = make_string(str, options.ascii_only);
if (options.inline_script)
- ret = ret.replace(/<\x2fscript([>/\t\n\f\r ])/gi, "<\\/script$1");
+ ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1");
return ret;
};
function make_name(name) {
name = name.toString();
@@ -3414,24 +3415,42 @@
return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ];
},
"function": _lambda,
"defun": _lambda,
"new": function(ctor, args) {
- if (ctor[0] == "name" && ctor[1] == "Array" && !scope.has("Array")) {
- if (args.length != 1) {
- return [ "array", args ];
- } else {
- return walk([ "call", [ "name", "Array" ], args ]);
+ if (ctor[0] == "name") {
+ if (ctor[1] == "Array" && !scope.has("Array")) {
+ if (args.length != 1) {
+ return [ "array", args ];
+ } else {
+ return walk([ "call", [ "name", "Array" ], args ]);
+ }
+ } else if (ctor[1] == "Object" && !scope.has("Object")) {
+ if (!args.length) {
+ return [ "object", [] ];
+ } else {
+ return walk([ "call", [ "name", "Object" ], args ]);
+ }
+ } else if ((ctor[1] == "RegExp" || ctor[1] == "Function" || ctor[1] == "Error") && !scope.has(ctor[1])) {
+ return walk([ "call", [ "name", ctor[1] ], args]);
}
}
},
"call": function(expr, args) {
if (expr[0] == "dot" && expr[2] == "toString" && args.length == 0) {
// foo.toString() ==> foo+""
return [ "binary", "+", expr[1], [ "string", "" ]];
}
- if (expr[0] == "name" && expr[1] == "Array" && args.length != 1 && !scope.has("Array")) {
- return [ "array", args ];
+ if (expr[0] == "name") {
+ if (expr[1] == "Array" && args.length != 1 && !scope.has("Array")) {
+ return [ "array", args ];
+ }
+ if (expr[1] == "Object" && !args.length && !scope.has("Object")) {
+ return [ "object", [] ];
+ }
+ if (expr[1] == "String" && !scope.has("String")) {
+ return [ "binary", "+", args[0], [ "string", "" ]];
+ }
}
}
}, function() {
return walk(pro.ast_add_scope(ast));
});