Merge branch 'master' into harmony
This commit is contained in:
@@ -67,6 +67,7 @@ function Compressor(options, false_by_default) {
|
||||
if_return : !false_by_default,
|
||||
join_vars : !false_by_default,
|
||||
collapse_vars : false,
|
||||
reduce_vars : false,
|
||||
cascade : !false_by_default,
|
||||
side_effects : !false_by_default,
|
||||
pure_getters : false,
|
||||
@@ -1138,7 +1139,7 @@ merge(Compressor.prototype, {
|
||||
this._evaluating = true;
|
||||
try {
|
||||
var d = this.definition();
|
||||
if (d && d.constant && d.init) {
|
||||
if (d && (d.constant || compressor.option("reduce_vars") && !d.modified) && d.init) {
|
||||
return ev(d.init, compressor);
|
||||
}
|
||||
} finally {
|
||||
@@ -2400,6 +2401,12 @@ merge(Compressor.prototype, {
|
||||
// typeof always returns a non-empty string, thus it's
|
||||
// always true in booleans
|
||||
compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start);
|
||||
if (self.expression.has_side_effects(compressor)) {
|
||||
return make_node(AST_Seq, self, {
|
||||
car: self.expression,
|
||||
cdr: make_node(AST_True, self)
|
||||
});
|
||||
}
|
||||
return make_node(AST_True, self);
|
||||
}
|
||||
if (e instanceof AST_Binary && self.operator == "!") {
|
||||
@@ -2586,8 +2593,8 @@ merge(Compressor.prototype, {
|
||||
case "+":
|
||||
var ll = self.left.evaluate(compressor);
|
||||
var rr = self.right.evaluate(compressor);
|
||||
if ((ll.length > 1 && ll[0] instanceof AST_String && ll[1]) ||
|
||||
(rr.length > 1 && rr[0] instanceof AST_String && rr[1])) {
|
||||
if ((ll.length > 1 && ll[0] instanceof AST_String && ll[1] && !self.right.has_side_effects(compressor)) ||
|
||||
(rr.length > 1 && rr[0] instanceof AST_String && rr[1] && !self.left.has_side_effects(compressor))) {
|
||||
compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
|
||||
return make_node(AST_True, self);
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ function OutputStream(options) {
|
||||
keep_quoted_props: false,
|
||||
shorthand : undefined,
|
||||
ecma : 5,
|
||||
wrap_iife : false,
|
||||
}, true);
|
||||
|
||||
if (typeof options.ascii_identifiers === 'undefined')
|
||||
@@ -79,6 +80,50 @@ function OutputStream(options) {
|
||||
if (options.shorthand === undefined)
|
||||
options.shorthand = options.ecma > 5;
|
||||
|
||||
// Convert comment option to RegExp if neccessary and set up comments filter
|
||||
if (typeof options.comments === "string" && /^\/.*\/[a-zA-Z]*$/.test(options.comments)) {
|
||||
var regex_pos = options.comments.lastIndexOf("/");
|
||||
options.comments = new RegExp(
|
||||
options.comments.substr(1, regex_pos - 1),
|
||||
options.comments.substr(regex_pos + 1)
|
||||
);
|
||||
}
|
||||
if (options.comments instanceof RegExp) {
|
||||
options.comments = (function(f) {
|
||||
return function(comment) {
|
||||
return comment.type == "comment5" || f.test(comment.value);
|
||||
}
|
||||
})(options.comments);
|
||||
}
|
||||
else if (typeof options.comments === "function") {
|
||||
options.comments = (function(f) {
|
||||
return function(comment) {
|
||||
return comment.type == "comment5" || f(this, comment);
|
||||
}
|
||||
})(options.comments);
|
||||
}
|
||||
else if (options.comments === "some") {
|
||||
options.comments = function(comment) {
|
||||
var text = comment.value;
|
||||
var type = comment.type;
|
||||
if (type == "comment2") {
|
||||
// multiline comment
|
||||
return /@preserve|@license|@cc_on/i.test(text);
|
||||
}
|
||||
return type == "comment5";
|
||||
}
|
||||
}
|
||||
else if (options.comments){ // NOTE includes "all" option
|
||||
options.comments = function() {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// Falsy case, so reject all comments, except shebangs
|
||||
options.comments = function(comment) {
|
||||
return comment.type == "comment5";
|
||||
}
|
||||
}
|
||||
|
||||
var indentation = 0;
|
||||
var current_col = 0;
|
||||
var current_line = 1;
|
||||
@@ -484,7 +529,7 @@ function OutputStream(options) {
|
||||
|
||||
AST_Node.DEFMETHOD("add_comments", function(output){
|
||||
if (output._readonly) return;
|
||||
var c = output.option("comments"), self = this;
|
||||
var self = this;
|
||||
var start = self.start;
|
||||
if (start && !start._comments_dumped) {
|
||||
start._comments_dumped = true;
|
||||
@@ -507,19 +552,7 @@ function OutputStream(options) {
|
||||
}));
|
||||
}
|
||||
|
||||
if (!c) {
|
||||
comments = comments.filter(function(comment) {
|
||||
return comment.type == "comment5";
|
||||
});
|
||||
} else if (c.test) {
|
||||
comments = comments.filter(function(comment){
|
||||
return comment.type == "comment5" || c.test(comment.value);
|
||||
});
|
||||
} else if (typeof c == "function") {
|
||||
comments = comments.filter(function(comment){
|
||||
return comment.type == "comment5" || c(self, comment);
|
||||
});
|
||||
}
|
||||
comments = comments.filter(output.option("comments"), self);
|
||||
|
||||
// Keep single line comments after nlb, after nlb
|
||||
if (!output.option("beautify") && comments.length > 0 &&
|
||||
@@ -570,7 +603,16 @@ function OutputStream(options) {
|
||||
// a function expression needs parens around it when it's provably
|
||||
// the first token to appear in a statement.
|
||||
PARENS(AST_Function, function(output){
|
||||
return first_in_statement(output);
|
||||
if (first_in_statement(output)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (output.option('wrap_iife')) {
|
||||
var p = output.parent();
|
||||
return p instanceof AST_Call && p.expression === this;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// same goes for an object literal, because otherwise it would be
|
||||
|
||||
18
lib/scope.js
18
lib/scope.js
@@ -256,12 +256,16 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
}
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
var name = node.name;
|
||||
if (name == "eval" && tw.parent() instanceof AST_Call) {
|
||||
var parent = tw.parent();
|
||||
if (name == "eval" && parent instanceof AST_Call) {
|
||||
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
|
||||
s.uses_eval = true;
|
||||
}
|
||||
}
|
||||
var sym = node.scope.find_variable(name);
|
||||
if (node.scope instanceof AST_Lambda && name == "arguments") {
|
||||
node.scope.uses_arguments = true;
|
||||
}
|
||||
if (!sym) {
|
||||
var g;
|
||||
if (globals.has(name)) {
|
||||
@@ -272,12 +276,12 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
g.global = true;
|
||||
globals.set(name, g);
|
||||
}
|
||||
node.thedef = g;
|
||||
if (func && name == "arguments") {
|
||||
func.uses_arguments = true;
|
||||
}
|
||||
} else {
|
||||
node.thedef = sym;
|
||||
sym = g;
|
||||
}
|
||||
node.thedef = sym;
|
||||
if (parent instanceof AST_Unary && (parent.operator === '++' || parent.operator === '--')
|
||||
|| parent instanceof AST_Assign && parent.left === node) {
|
||||
sym.modified = true;
|
||||
}
|
||||
node.reference();
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user