@@ -2282,8 +2282,7 @@ merge(Compressor.prototype, {
|
|||||||
// returns true if this node may be null, undefined or contain `AST_Accessor`
|
// returns true if this node may be null, undefined or contain `AST_Accessor`
|
||||||
(function(def) {
|
(function(def) {
|
||||||
AST_Node.DEFMETHOD("may_throw_on_access", function(compressor) {
|
AST_Node.DEFMETHOD("may_throw_on_access", function(compressor) {
|
||||||
return !compressor.option("pure_getters")
|
return !compressor.option("pure_getters") || this._dot_throw(compressor);
|
||||||
|| this._dot_throw(compressor);
|
|
||||||
});
|
});
|
||||||
function is_strict(compressor) {
|
function is_strict(compressor) {
|
||||||
return /strict/.test(compressor.option("pure_getters"));
|
return /strict/.test(compressor.option("pure_getters"));
|
||||||
@@ -2291,7 +2290,15 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Node, is_strict);
|
def(AST_Node, is_strict);
|
||||||
def(AST_Array, return_false);
|
def(AST_Array, return_false);
|
||||||
def(AST_Assign, function(compressor) {
|
def(AST_Assign, function(compressor) {
|
||||||
return this.operator == "=" && this.right._dot_throw(compressor);
|
if (this.operator != "=") return false;
|
||||||
|
var rhs = this.right;
|
||||||
|
if (!rhs._dot_throw(compressor)) return false;
|
||||||
|
var sym = this.left;
|
||||||
|
if (!(sym instanceof AST_SymbolRef)) return true;
|
||||||
|
if (rhs instanceof AST_Binary && rhs.operator == "||" && sym.name == rhs.left.name) {
|
||||||
|
return rhs.right._dot_throw(compressor);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
def(AST_Binary, function(compressor) {
|
def(AST_Binary, function(compressor) {
|
||||||
return lazy_op[this.operator] && (this.left._dot_throw(compressor) || this.right._dot_throw(compressor));
|
return lazy_op[this.operator] && (this.left._dot_throw(compressor) || this.right._dot_throw(compressor));
|
||||||
@@ -3618,7 +3625,7 @@ merge(Compressor.prototype, {
|
|||||||
var value = null;
|
var value = null;
|
||||||
if (node instanceof AST_Assign) {
|
if (node instanceof AST_Assign) {
|
||||||
if (!in_use || node.left === sym && def.id in fixed_ids && fixed_ids[def.id] !== node) {
|
if (!in_use || node.left === sym && def.id in fixed_ids && fixed_ids[def.id] !== node) {
|
||||||
value = node.right;
|
value = get_rhs(node);
|
||||||
}
|
}
|
||||||
} else if (!in_use) {
|
} else if (!in_use) {
|
||||||
value = make_node(AST_Number, node, {
|
value = make_node(AST_Number, node, {
|
||||||
@@ -3843,6 +3850,15 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function get_rhs(assign) {
|
||||||
|
var rhs = assign.right;
|
||||||
|
if (!assign.write_only) return rhs;
|
||||||
|
if (!(rhs instanceof AST_Binary && lazy_op[rhs.operator])) return rhs;
|
||||||
|
var sym = assign.left;
|
||||||
|
if (!(sym instanceof AST_SymbolRef) || sym.name != rhs.left.name) return rhs;
|
||||||
|
return rhs.right;
|
||||||
|
}
|
||||||
|
|
||||||
function scan_ref_scoped(node, descend) {
|
function scan_ref_scoped(node, descend) {
|
||||||
var node_def, props = [], sym = assign_as_unused(node, props);
|
var node_def, props = [], sym = assign_as_unused(node, props);
|
||||||
if (sym && self.variables.get(sym.name) === (node_def = sym.definition())) {
|
if (sym && self.variables.get(sym.name) === (node_def = sym.definition())) {
|
||||||
@@ -3850,9 +3866,10 @@ merge(Compressor.prototype, {
|
|||||||
prop.walk(tw);
|
prop.walk(tw);
|
||||||
});
|
});
|
||||||
if (node instanceof AST_Assign) {
|
if (node instanceof AST_Assign) {
|
||||||
node.right.walk(tw);
|
var right = get_rhs(node);
|
||||||
|
right.walk(tw);
|
||||||
if (node.left === sym) {
|
if (node.left === sym) {
|
||||||
if (!node_def.chained && sym.fixed_value(true) === node.right) {
|
if (!node_def.chained && sym.fixed_value(true) === right) {
|
||||||
fixed_ids[node_def.id] = node;
|
fixed_ids[node_def.id] = node;
|
||||||
}
|
}
|
||||||
if (!node.write_only) {
|
if (!node.write_only) {
|
||||||
@@ -4163,12 +4180,14 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
def(AST_Assign, function(compressor) {
|
def(AST_Assign, function(compressor) {
|
||||||
var left = this.left;
|
var left = this.left;
|
||||||
if (left.has_side_effects(compressor)
|
if (left instanceof AST_PropAccess) {
|
||||||
|| compressor.has_directive("use strict")
|
var expr = left.expression;
|
||||||
&& left instanceof AST_PropAccess
|
if (expr instanceof AST_Assign && !expr.may_throw_on_access(compressor)) {
|
||||||
&& left.expression.is_constant()) {
|
expr.write_only = true;
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
if (compressor.has_directive("use strict") && expr.is_constant()) return this;
|
||||||
|
}
|
||||||
|
if (left.has_side_effects(compressor)) return this;
|
||||||
this.write_only = true;
|
this.write_only = true;
|
||||||
if (root_expr(left).is_constant_expression(compressor.find_parent(AST_Scope))) {
|
if (root_expr(left).is_constant_expression(compressor.find_parent(AST_Scope))) {
|
||||||
return this.right.drop_side_effect_free(compressor);
|
return this.right.drop_side_effect_free(compressor);
|
||||||
@@ -4243,8 +4262,9 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
def(AST_Constant, return_null);
|
def(AST_Constant, return_null);
|
||||||
def(AST_Dot, function(compressor, first_in_statement) {
|
def(AST_Dot, function(compressor, first_in_statement) {
|
||||||
if (this.expression.may_throw_on_access(compressor)) return this;
|
var expr = this.expression;
|
||||||
return this.expression.drop_side_effect_free(compressor, first_in_statement);
|
if (expr.may_throw_on_access(compressor)) return this;
|
||||||
|
return expr.drop_side_effect_free(compressor, first_in_statement);
|
||||||
});
|
});
|
||||||
def(AST_Function, function(compressor) {
|
def(AST_Function, function(compressor) {
|
||||||
return this.name && compressor.option("ie8") ? this : null;
|
return this.name && compressor.option("ie8") ? this : null;
|
||||||
@@ -5556,20 +5576,29 @@ merge(Compressor.prototype, {
|
|||||||
self.right = tmp;
|
self.right = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (commutativeOperators[self.operator]) {
|
if (commutativeOperators[self.operator] && self.right.is_constant() && !self.left.is_constant()) {
|
||||||
if (self.right.is_constant()
|
|
||||||
&& !self.left.is_constant()) {
|
|
||||||
// if right is a constant, whatever side effects the
|
// if right is a constant, whatever side effects the
|
||||||
// left side might have could not influence the
|
// left side might have could not influence the
|
||||||
// result. hence, force switch.
|
// result. hence, force switch.
|
||||||
|
|
||||||
if (!(self.left instanceof AST_Binary
|
if (!(self.left instanceof AST_Binary
|
||||||
&& PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {
|
&& PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {
|
||||||
reverse();
|
reverse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
self = self.lift_sequences(compressor);
|
self = self.lift_sequences(compressor);
|
||||||
|
if (compressor.option("assignments") && lazy_op[self.operator]) {
|
||||||
|
var assign = self.right;
|
||||||
|
// a || (a = x) => a = a || x
|
||||||
|
// a && (a = x) => a = a && x
|
||||||
|
if (self.left instanceof AST_SymbolRef
|
||||||
|
&& assign instanceof AST_Assign
|
||||||
|
&& assign.operator == "="
|
||||||
|
&& self.left.equivalent_to(assign.left)) {
|
||||||
|
self.right = assign.right;
|
||||||
|
assign.right = self;
|
||||||
|
return assign;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (compressor.option("comparisons")) switch (self.operator) {
|
if (compressor.option("comparisons")) switch (self.operator) {
|
||||||
case "===":
|
case "===":
|
||||||
case "!==":
|
case "!==":
|
||||||
|
|||||||
@@ -311,3 +311,19 @@ issue_3375: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "string"
|
expect_stdout: "string"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3427: {
|
||||||
|
options = {
|
||||||
|
assignments: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var a;
|
||||||
|
a || (a = {});
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2028,3 +2028,37 @@ issue_3375: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "0 0"
|
expect_stdout: "0 0"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3427_1: {
|
||||||
|
options = {
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var a;
|
||||||
|
a = a || {};
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3427_2: {
|
||||||
|
options = {
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var s = "PASS";
|
||||||
|
console.log(s = s || "FAIL");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
var s = "PASS";
|
||||||
|
console.log(s = s || "FAIL");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1187,3 +1187,23 @@ drop_arguments: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3427: {
|
||||||
|
options = {
|
||||||
|
assignments: true,
|
||||||
|
collapse_vars: true,
|
||||||
|
inline: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
(function(b) {
|
||||||
|
b.p = 42;
|
||||||
|
})(a || (a = {}));
|
||||||
|
}
|
||||||
|
expect: {}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user