Merge branch 'master' into harmony
This commit is contained in:
committed by
Richard van Velzen
commit
6fd9b338dd
@@ -72,13 +72,15 @@ function Compressor(options, false_by_default) {
|
||||
pure_getters : false,
|
||||
pure_funcs : null,
|
||||
negate_iife : !false_by_default,
|
||||
screw_ie8 : false,
|
||||
screw_ie8 : true,
|
||||
drop_console : false,
|
||||
angular : false,
|
||||
warnings : true,
|
||||
global_defs : {},
|
||||
passes : 1,
|
||||
}, true);
|
||||
var sequences = this.options["sequences"];
|
||||
this.sequences_limit = sequences == 1 ? 200 : sequences | 0;
|
||||
this.warnings_produced = {};
|
||||
};
|
||||
|
||||
@@ -190,7 +192,7 @@ merge(Compressor.prototype, {
|
||||
if ((1 / val) < 0) {
|
||||
return make_node(AST_UnaryPrefix, orig, {
|
||||
operator: "-",
|
||||
expression: make_node(AST_Number, null, { value: -val })
|
||||
expression: make_node(AST_Number, orig, { value: -val })
|
||||
});
|
||||
}
|
||||
|
||||
@@ -274,7 +276,7 @@ merge(Compressor.prototype, {
|
||||
if (compressor.option("if_return")) {
|
||||
statements = handle_if_return(statements, compressor);
|
||||
}
|
||||
if (compressor.option("sequences")) {
|
||||
if (compressor.sequences_limit > 0) {
|
||||
statements = sequencesize(statements, compressor);
|
||||
}
|
||||
if (compressor.option("join_vars")) {
|
||||
@@ -737,7 +739,7 @@ merge(Compressor.prototype, {
|
||||
seq = [];
|
||||
};
|
||||
statements.forEach(function(stat){
|
||||
if (stat instanceof AST_SimpleStatement && seqLength(seq) < 2000) {
|
||||
if (stat instanceof AST_SimpleStatement && seqLength(seq) < compressor.sequences_limit) {
|
||||
seq.push(stat.body);
|
||||
} else {
|
||||
push_seq();
|
||||
@@ -1079,32 +1081,38 @@ merge(Compressor.prototype, {
|
||||
throw def;
|
||||
});
|
||||
def(AST_Binary, function(c){
|
||||
var left = this.left, right = this.right;
|
||||
var left = this.left, right = this.right, result;
|
||||
switch (this.operator) {
|
||||
case "&&" : return ev(left, c) && ev(right, c);
|
||||
case "||" : return ev(left, c) || ev(right, c);
|
||||
case "|" : return ev(left, c) | ev(right, c);
|
||||
case "&" : return ev(left, c) & ev(right, c);
|
||||
case "^" : return ev(left, c) ^ ev(right, c);
|
||||
case "+" : return ev(left, c) + ev(right, c);
|
||||
case "*" : return ev(left, c) * ev(right, c);
|
||||
case "**" : return Math.pow(ev(left, c), ev(right, c));
|
||||
case "/" : return ev(left, c) / ev(right, c);
|
||||
case "%" : return ev(left, c) % ev(right, c);
|
||||
case "-" : return ev(left, c) - ev(right, c);
|
||||
case "<<" : return ev(left, c) << ev(right, c);
|
||||
case ">>" : return ev(left, c) >> ev(right, c);
|
||||
case ">>>" : return ev(left, c) >>> ev(right, c);
|
||||
case "==" : return ev(left, c) == ev(right, c);
|
||||
case "===" : return ev(left, c) === ev(right, c);
|
||||
case "!=" : return ev(left, c) != ev(right, c);
|
||||
case "!==" : return ev(left, c) !== ev(right, c);
|
||||
case "<" : return ev(left, c) < ev(right, c);
|
||||
case "<=" : return ev(left, c) <= ev(right, c);
|
||||
case ">" : return ev(left, c) > ev(right, c);
|
||||
case ">=" : return ev(left, c) >= ev(right, c);
|
||||
case "&&" : result = ev(left, c) && ev(right, c); break;
|
||||
case "||" : result = ev(left, c) || ev(right, c); break;
|
||||
case "|" : result = ev(left, c) | ev(right, c); break;
|
||||
case "&" : result = ev(left, c) & ev(right, c); break;
|
||||
case "^" : result = ev(left, c) ^ ev(right, c); break;
|
||||
case "+" : result = ev(left, c) + ev(right, c); break;
|
||||
case "*" : result = ev(left, c) * ev(right, c); break;
|
||||
case "**" : result = Math.pow(ev(left, c), ev(right, c)); break;
|
||||
case "/" : result = ev(left, c) / ev(right, c); break;
|
||||
case "%" : result = ev(left, c) % ev(right, c); break;
|
||||
case "-" : result = ev(left, c) - ev(right, c); break;
|
||||
case "<<" : result = ev(left, c) << ev(right, c); break;
|
||||
case ">>" : result = ev(left, c) >> ev(right, c); break;
|
||||
case ">>>" : result = ev(left, c) >>> ev(right, c); break;
|
||||
case "==" : result = ev(left, c) == ev(right, c); break;
|
||||
case "===" : result = ev(left, c) === ev(right, c); break;
|
||||
case "!=" : result = ev(left, c) != ev(right, c); break;
|
||||
case "!==" : result = ev(left, c) !== ev(right, c); break;
|
||||
case "<" : result = ev(left, c) < ev(right, c); break;
|
||||
case "<=" : result = ev(left, c) <= ev(right, c); break;
|
||||
case ">" : result = ev(left, c) > ev(right, c); break;
|
||||
case ">=" : result = ev(left, c) >= ev(right, c); break;
|
||||
default:
|
||||
throw def;
|
||||
}
|
||||
throw def;
|
||||
if (isNaN(result) && c.find_parent(AST_With)) {
|
||||
// leave original expression as is
|
||||
throw def;
|
||||
}
|
||||
return result;
|
||||
});
|
||||
def(AST_Conditional, function(compressor){
|
||||
return ev(this.condition, compressor)
|
||||
@@ -2678,13 +2686,16 @@ merge(Compressor.prototype, {
|
||||
if (defines && HOP(defines, self.name)) {
|
||||
return make_node_from_constant(compressor, defines[self.name], self);
|
||||
}
|
||||
switch (self.name) {
|
||||
case "undefined":
|
||||
return make_node(AST_Undefined, self);
|
||||
case "NaN":
|
||||
return make_node(AST_NaN, self).transform(compressor);
|
||||
case "Infinity":
|
||||
return make_node(AST_Infinity, self).transform(compressor);
|
||||
// testing against !self.scope.uses_with first is an optimization
|
||||
if (!self.scope.uses_with || !compressor.find_parent(AST_With)) {
|
||||
switch (self.name) {
|
||||
case "undefined":
|
||||
return make_node(AST_Undefined, self);
|
||||
case "NaN":
|
||||
return make_node(AST_NaN, self).transform(compressor);
|
||||
case "Infinity":
|
||||
return make_node(AST_Infinity, self).transform(compressor);
|
||||
}
|
||||
}
|
||||
}
|
||||
return self;
|
||||
@@ -2816,7 +2827,7 @@ merge(Compressor.prototype, {
|
||||
if (consequent.is_constant(compressor)
|
||||
&& alternative.is_constant(compressor)
|
||||
&& consequent.equivalent_to(alternative)) {
|
||||
var consequent_value = consequent.constant_value();
|
||||
var consequent_value = consequent.constant_value(compressor);
|
||||
if (self.condition.has_side_effects(compressor)) {
|
||||
return AST_Seq.from_array([self.condition, make_node_from_constant(compressor, consequent_value, self)]);
|
||||
} else {
|
||||
|
||||
@@ -94,6 +94,15 @@
|
||||
return new AST_ObjectGetter(args);
|
||||
}
|
||||
},
|
||||
ArrayExpression: function(M) {
|
||||
return new AST_Array({
|
||||
start : my_start_token(M),
|
||||
end : my_end_token(M),
|
||||
elements : M.elements.map(function(elem){
|
||||
return elem === null ? new AST_Hole() : from_moz(elem);
|
||||
})
|
||||
});
|
||||
},
|
||||
ObjectExpression: function(M) {
|
||||
return new AST_Object({
|
||||
start : my_start_token(M),
|
||||
@@ -206,7 +215,6 @@
|
||||
map("CatchClause", AST_Catch, "param>argname, body%body");
|
||||
|
||||
map("ThisExpression", AST_This);
|
||||
map("ArrayExpression", AST_Array, "elements@elements");
|
||||
map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body");
|
||||
map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
|
||||
map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right");
|
||||
@@ -302,6 +310,13 @@
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_Array, function To_Moz_ArrayExpression(M) {
|
||||
return {
|
||||
type: "ArrayExpression",
|
||||
elements: M.elements.map(to_moz)
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_Object, function To_Moz_ObjectExpression(M) {
|
||||
return {
|
||||
type: "ObjectExpression",
|
||||
|
||||
@@ -64,7 +64,7 @@ function OutputStream(options) {
|
||||
comments : false,
|
||||
shebang : true,
|
||||
preserve_line : false,
|
||||
screw_ie8 : false,
|
||||
screw_ie8 : true,
|
||||
preamble : null,
|
||||
quote_style : 0,
|
||||
keep_quoted_props: false,
|
||||
@@ -998,8 +998,8 @@ function OutputStream(options) {
|
||||
// adds the block brackets if needed.
|
||||
if (!self.body)
|
||||
return output.force_semicolon();
|
||||
if (self.body instanceof AST_Do
|
||||
&& !output.option("screw_ie8")) {
|
||||
if (self.body instanceof AST_Do) {
|
||||
// Unconditionally use the if/do-while workaround for all browsers.
|
||||
// https://github.com/mishoo/UglifyJS/issues/#issue/57 IE
|
||||
// croaks with "syntax error" on code like this: if (foo)
|
||||
// do ... while(cond); else ... we need block brackets
|
||||
|
||||
79
lib/parse.js
79
lib/parse.js
@@ -112,7 +112,9 @@ var OPERATORS = makePredicate([
|
||||
"||"
|
||||
]);
|
||||
|
||||
var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\uFEFF"));
|
||||
var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\uFEFF"));
|
||||
|
||||
var NEWLINE_CHARS = makePredicate(characters("\n\r\u2028\u2029"));
|
||||
|
||||
var PUNC_AFTER_EXPRESSION = makePredicate(characters(";]),:"));
|
||||
|
||||
@@ -263,7 +265,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
var ch = get_full_char(S.text, S.pos++);
|
||||
if (signal_eof && !ch)
|
||||
throw EX_EOF;
|
||||
if ("\r\n\u2028\u2029".indexOf(ch) >= 0) {
|
||||
if (NEWLINE_CHARS(ch)) {
|
||||
S.newline_before = S.newline_before || !in_string;
|
||||
++S.line;
|
||||
S.col = 0;
|
||||
@@ -294,7 +296,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
var text = S.text;
|
||||
for (var i = S.pos, n = S.text.length; i < n; ++i) {
|
||||
var ch = text[i];
|
||||
if (ch == '\n' || ch == '\r')
|
||||
if (NEWLINE_CHARS(ch))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
@@ -346,8 +348,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
};
|
||||
|
||||
function skip_whitespace() {
|
||||
var ch;
|
||||
while (WHITESPACE_CHARS(ch = peek()) || ch == "\u2028" || ch == "\u2029")
|
||||
while (WHITESPACE_CHARS(peek()))
|
||||
next();
|
||||
};
|
||||
|
||||
@@ -388,7 +389,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
if (!isNaN(valid)) {
|
||||
return token("num", valid);
|
||||
} else {
|
||||
parse_error("Invalid syntax: " + num);
|
||||
parse_error("SyntaxError: Invalid syntax: " + num);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -401,7 +402,6 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
case 98 : return "\b";
|
||||
case 118 : return "\u000b"; // \v
|
||||
case 102 : return "\f";
|
||||
case 48 : return "\0";
|
||||
case 120 : return String.fromCharCode(hex_bytes(2)); // \x
|
||||
case 117 : // \u
|
||||
if (peek() == "{") {
|
||||
@@ -426,9 +426,27 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
if (ch >= "0" && ch <= "7")
|
||||
return read_octal_escape_sequence(ch);
|
||||
return ch;
|
||||
};
|
||||
|
||||
function read_octal_escape_sequence(ch) {
|
||||
// Read
|
||||
var p = peek();
|
||||
if (p >= "0" && p <= "7") {
|
||||
ch += next(true);
|
||||
if (ch[0] <= "3" && (p = peek()) >= "0" && p <= "7")
|
||||
ch += next(true);
|
||||
}
|
||||
|
||||
// Parse
|
||||
if (ch === "0") return "\0";
|
||||
if (ch.length > 0 && next_token.has_directive("use strict"))
|
||||
parse_error("SyntaxError: Octal literals are not allowed in strict mode");
|
||||
return String.fromCharCode(parseInt(ch, 8));
|
||||
}
|
||||
|
||||
function hex_bytes(n) {
|
||||
var num = 0;
|
||||
for (; n > 0; --n) {
|
||||
@@ -440,32 +458,12 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
return num;
|
||||
};
|
||||
|
||||
var read_string = with_eof_error("Unterminated string constant", function(quote_char){
|
||||
var read_string = with_eof_error("SyntaxError: Unterminated string constant", function(quote_char){
|
||||
var quote = next(), ret = "";
|
||||
for (;;) {
|
||||
var ch = next(true, true);
|
||||
if (ch == "\\") {
|
||||
var octal_len = 0, first = null;
|
||||
ch = read_while(function(ch){
|
||||
if (ch >= "0" && ch <= "7") {
|
||||
if (!first) {
|
||||
first = ch;
|
||||
return ++octal_len;
|
||||
}
|
||||
else if (first <= "3" && octal_len <= 2) return ++octal_len;
|
||||
else if (first >= "4" && octal_len <= 1) return ++octal_len;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (octal_len > 0) {
|
||||
if (ch !== "0" && next_token.has_directive("use strict"))
|
||||
parse_error("Octal literals are not allowed in strict mode");
|
||||
ch = String.fromCharCode(parseInt(ch, 8));
|
||||
} else {
|
||||
ch = read_escaped_char(true);
|
||||
}
|
||||
}
|
||||
else if ("\r\n\u2028\u2029".indexOf(ch) >= 0) parse_error("Unterminated string constant");
|
||||
if (ch == "\\") ch = read_escaped_char(true);
|
||||
else if (NEWLINE_CHARS(ch)) parse_error("SyntaxError: Unterminated string constant");
|
||||
else if (ch == quote) break;
|
||||
ret += ch;
|
||||
}
|
||||
@@ -490,21 +488,14 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
return next_token;
|
||||
};
|
||||
|
||||
var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function(){
|
||||
var skip_multiline_comment = with_eof_error("SyntaxError: Unterminated multiline comment", function(){
|
||||
var regex_allowed = S.regex_allowed;
|
||||
var i = find("*/", true);
|
||||
var text = S.text.substring(S.pos, i).replace(/\r\n|\r/g, '\n');
|
||||
var a = text.split("\n"), n = a.length;
|
||||
var text = S.text.substring(S.pos, i).replace(/\r\n|\r|\u2028|\u2029/g, '\n');
|
||||
// update stream position
|
||||
S.pos = i + 2;
|
||||
S.line += n - 1;
|
||||
if (n > 1) S.col = a[n - 1].length;
|
||||
else S.col += a[n - 1].length;
|
||||
S.col += 2;
|
||||
var nlb = S.newline_before = S.newline_before || text.indexOf("\n") >= 0;
|
||||
forward(text.length /* doesn't count \r\n as 2 char while S.pos - i does */ + 2);
|
||||
S.comments_before.push(token("comment2", text, true));
|
||||
S.regex_allowed = regex_allowed;
|
||||
S.newline_before = nlb;
|
||||
return next_token;
|
||||
});
|
||||
|
||||
@@ -552,9 +543,11 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
return name;
|
||||
};
|
||||
|
||||
var read_regexp = with_eof_error("Unterminated regular expression", function(regexp){
|
||||
var read_regexp = with_eof_error("SyntaxError: Unterminated regular expression", function(regexp){
|
||||
var prev_backslash = false, ch, in_class = false;
|
||||
while ((ch = next(true))) if (prev_backslash) {
|
||||
while ((ch = next(true))) if (NEWLINE_CHARS(ch)) {
|
||||
parse_error("SyntaxError: Unexpected line terminator");
|
||||
} else if (prev_backslash) {
|
||||
regexp += "\\" + ch;
|
||||
prev_backslash = false;
|
||||
} else if (ch == "[") {
|
||||
@@ -567,8 +560,6 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
break;
|
||||
} else if (ch == "\\") {
|
||||
prev_backslash = true;
|
||||
} else if ("\r\n\u2028\u2029".indexOf(ch) >= 0) {
|
||||
parse_error("Unexpected line terminator");
|
||||
} else {
|
||||
regexp += ch;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ SymbolDef.prototype = {
|
||||
|
||||
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
options = defaults(options, {
|
||||
screw_ie8: false,
|
||||
screw_ie8: true,
|
||||
cache: null
|
||||
});
|
||||
|
||||
@@ -449,7 +449,7 @@ AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
|
||||
eval : false,
|
||||
sort : false, // Ignored. Flag retained for backwards compatibility.
|
||||
toplevel : false,
|
||||
screw_ie8 : false,
|
||||
screw_ie8 : true,
|
||||
keep_fnames : false,
|
||||
keep_classnames : false
|
||||
});
|
||||
|
||||
13
lib/utils.js
13
lib/utils.js
@@ -227,10 +227,19 @@ function makePredicate(words) {
|
||||
}
|
||||
cats.push([words[i]]);
|
||||
}
|
||||
function quote(word) {
|
||||
return JSON.stringify(word).replace(/[\u2028\u2029]/g, function(s) {
|
||||
switch (s) {
|
||||
case "\u2028": return "\\u2028";
|
||||
case "\u2029": return "\\u2029";
|
||||
}
|
||||
return s;
|
||||
});
|
||||
}
|
||||
function compareTo(arr) {
|
||||
if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";";
|
||||
if (arr.length == 1) return f += "return str === " + quote(arr[0]) + ";";
|
||||
f += "switch(str){";
|
||||
for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":";
|
||||
for (var i = 0; i < arr.length; ++i) f += "case " + quote(arr[i]) + ":";
|
||||
f += "return true}return false;";
|
||||
}
|
||||
// When there are more than three length categories, an outer
|
||||
|
||||
Reference in New Issue
Block a user