fix corner case in side_effects (#4752)

fixes #4751
This commit is contained in:
Alex Lam S.L
2021-03-07 20:19:51 +00:00
committed by GitHub
parent 31e7d25cad
commit f52b0e7c31
9 changed files with 277 additions and 45 deletions

View File

@@ -4797,15 +4797,9 @@ merge(Compressor.prototype, {
|| this.right.has_side_effects(compressor); || this.right.has_side_effects(compressor);
}); });
def(AST_Binary, function(compressor) { def(AST_Binary, function(compressor) {
var lhs = this.left; return this.left.has_side_effects(compressor)
if (lhs.has_side_effects(compressor)) return true; || this.right.has_side_effects(compressor)
var rhs = this.right; || this.operator == "in" && !is_object(this.right);
var op = this.operator;
if (!rhs.has_side_effects(compressor)) return op == "in" && !is_object(rhs);
if (op == "&&" && rhs instanceof AST_PropAccess && lhs.equivalent_to(rhs.expression)) {
return rhs instanceof AST_Sub && rhs.property.has_side_effects(compressor);
}
return true;
}); });
def(AST_Block, function(compressor) { def(AST_Block, function(compressor) {
return any(this.body, compressor); return any(this.body, compressor);
@@ -7220,17 +7214,6 @@ merge(Compressor.prototype, {
if (!rhs) return left.drop_side_effect_free(compressor, first_in_statement); if (!rhs) return left.drop_side_effect_free(compressor, first_in_statement);
if (lazy_op[op] && rhs.has_side_effects(compressor)) { if (lazy_op[op] && rhs.has_side_effects(compressor)) {
var node = this; var node = this;
if (op == "&&"
&& rhs instanceof AST_PropAccess
&& left.equivalent_to(rhs.expression)
&& !left.has_side_effects(compressor)) {
var prop = rhs instanceof AST_Sub
&& rhs.property.drop_side_effect_free(compressor, first_in_statement);
if (!prop) return left.drop_side_effect_free(compressor, first_in_statement);
node = node.clone();
node.right = prop;
return node.drop_side_effect_free(compressor, first_in_statement);
}
if (rhs !== right) { if (rhs !== right) {
node = node.clone(); node = node.clone();
node.right = rhs.drop_side_effect_free(compressor); node.right = rhs.drop_side_effect_free(compressor);
@@ -7242,13 +7225,12 @@ merge(Compressor.prototype, {
right: node.right, right: node.right,
}); });
return first_in_statement ? best_of_statement(node, negated) : best_of_expression(node, negated); return first_in_statement ? best_of_statement(node, negated) : best_of_expression(node, negated);
} else { }
var lhs = left.drop_side_effect_free(compressor, first_in_statement); var lhs = left.drop_side_effect_free(compressor, first_in_statement);
if (!lhs) return rhs; if (!lhs) return rhs;
rhs = rhs.drop_side_effect_free(compressor); rhs = rhs.drop_side_effect_free(compressor);
if (!rhs) return lhs; if (!rhs) return lhs;
return make_sequence(this, [ lhs, rhs ]); return make_sequence(this, [ lhs, rhs ]);
}
}); });
def(AST_Call, function(compressor, first_in_statement) { def(AST_Call, function(compressor, first_in_statement) {
var self = this; var self = this;

View File

@@ -2862,7 +2862,7 @@ lvalues_def: {
expect: { expect: {
var a = 0, b = 1; var a = 0, b = 1;
a = b++, b = +void 0; a = b++, b = +void 0;
a && a++; a && a[a++];
console.log(a, b); console.log(a, b);
} }
expect_stdout: true expect_stdout: true
@@ -5096,7 +5096,7 @@ issue_2878: {
} }
b = f2(); b = f2();
a = 1; a = 1;
b && b[console]; b && b.b;
f2(); f2();
})(); })();
console.log(c); console.log(c);
@@ -5109,7 +5109,7 @@ issue_2878: {
} }
b = f2(), b = f2(),
a = 1, a = 1,
b && console, b && b.b,
f2(); f2();
})(), })(),
console.log(c); console.log(c);
@@ -6544,7 +6544,7 @@ issue_3520: {
(function f() { (function f() {
c = 0; c = 0;
var i = void 0; var i = void 0;
var f = f && f[console && i]; var f = f && f[i];
})(); })();
a += b; a += b;
c && b++; c && b++;
@@ -6558,7 +6558,7 @@ issue_3520: {
for (var i = 2; --i >= 0;) { for (var i = 2; --i >= 0;) {
(function() { (function() {
c = 0; c = 0;
var f = f && f[console && void 0]; var f = f && f[void 0];
})(); })();
a += b; a += b;
c && b++; c && b++;

View File

@@ -2726,8 +2726,8 @@ issue_3944: {
} }
expect: { expect: {
void function f() { void function f() {
while (b = void 0, b = console.log(0 == (b && b.p)), void 0); while (a = 0 == (a = void 0), console.log(a), void 0);
var b; var a;
f; f;
}(); }();
} }

View File

@@ -2923,6 +2923,7 @@ issue_4568: {
issue_4729: { issue_4729: {
options = { options = {
ie8: true, ie8: true,
pure_getters: true,
toplevel: true, toplevel: true,
unused: true, unused: true,
} }

View File

@@ -2723,7 +2723,7 @@ issue_4135: {
var c = function() { var c = function() {
var d = 0; var d = 0;
function f() { function f() {
d && d[console]; d && d.p;
} }
f(); f();
this; this;
@@ -2735,7 +2735,7 @@ issue_4135: {
0; 0;
a++; a++;
if (!a) if (!a)
c = (a++, c = 0, void (c && console)); c = (a++, c = 0, void (c && c.p));
var c; var c;
console.log(a, -1, c); console.log(a, -1, c);
} }

View File

@@ -1220,6 +1220,104 @@ drop_arguments: {
expect_stdout: "PASS" expect_stdout: "PASS"
} }
lvalues_def: {
options = {
collapse_vars: true,
pure_getters: true,
side_effects: true,
unused: true,
}
input: {
var a = 0, b = 1;
var a = b++, b = +function() {}();
a && a[a++];
console.log(a, b);
}
expect: {
var a = 0, b = 1;
a = b++, b = +void 0;
a && a++;
console.log(a, b);
}
expect_stdout: true
}
side_effects_assign: {
options = {
evaluate: true,
pure_getters: true,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
}
input: {
var a = typeof void (a && a.in == 1, 0);
console.log(a);
}
expect: {
var a = "undefined";
console.log(a);
}
expect_stdout: "undefined"
}
issue_2062: {
options = {
booleans: true,
collapse_vars: true,
conditionals: true,
pure_getters: true,
side_effects: true,
}
input: {
var a = 1;
if ([ a || a++ + a--, a++ + a--, a && a.var ]);
console.log(a);
}
expect: {
var a = 1;
a || (a++, a--), a++, a--;
console.log(a);
}
expect_stdout: "1"
}
issue_2878: {
options = {
collapse_vars: true,
pure_getters: true,
sequences: true,
}
input: {
var c = 0;
(function(a, b) {
function f2() {
if (a) c++;
}
b = f2();
a = 1;
b && b.b;
f2();
})();
console.log(c);
}
expect: {
var c = 0;
(function(a, b) {
function f2() {
if (a) c++;
}
b = f2(),
a = 1,
f2();
})(),
console.log(c);
}
expect_stdout: "1"
}
issue_3427: { issue_3427: {
options = { options = {
assignments: true, assignments: true,
@@ -1242,6 +1340,74 @@ issue_3427: {
expect_stdout: true expect_stdout: true
} }
issue_3490_1: {
options = {
conditionals: true,
dead_code: true,
inline: true,
pure_getters: true,
sequences: true,
side_effects: true,
toplevel: true,
}
input: {
var b = 42, c = "FAIL";
if ({
3: function() {
var a;
return (a && a.p) < this;
}(),
}) c = "PASS";
if (b) while ("" == typeof d);
console.log(c, b);
}
expect: {
var b = 42, c = "FAIL";
if (function() {
var a;
}(), c = "PASS", b) while ("" == typeof d);
console.log(c, b);
}
expect_stdout: "PASS 42"
}
issue_4135: {
options = {
evaluate: true,
inline: true,
merge_vars: true,
pure_getters: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = 0, b = 0;
--b;
a++;
if (!a)
var c = function() {
var d = 0;
function f() {
d && d.p;
}
f();
this;
}(a++);
console.log(a, b, c);
}
expect: {
var a = 0;
0;
a++;
if (!a)
var c = void a++;
console.log(a, -1, c);
}
expect_stdout: "1 -1 undefined"
}
issue_4440: { issue_4440: {
options = { options = {
pure_getters: "strict", pure_getters: "strict",
@@ -1270,3 +1436,57 @@ issue_4440: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_4730_1: {
options = {
pure_getters: true,
side_effects: true,
}
input: {
var a;
console.log("PASS") + (a && a[a.p]);
}
expect: {
var a;
console.log("PASS");
}
expect_stdout: "PASS"
}
issue_4730_2: {
options = {
pure_getters: true,
side_effects: true,
}
input: {
var a;
!console.log("PASS") || a && a[a.p];
}
expect: {
var a;
console.log("PASS");
}
expect_stdout: "PASS"
}
issue_4751: {
options = {
pure_getters: true,
side_effects: true,
}
input: {
var o = {
get p() {
console.log("PASS");
},
};
o && o.p;
}
expect: {
var o = {
get p() {
console.log("PASS");
},
};
}
}

View File

@@ -2554,7 +2554,7 @@ side_effects_assign: {
console.log(a); console.log(a);
} }
expect: { expect: {
var a = "undefined"; var a = typeof void (a && a.in);
console.log(a); console.log(a);
} }
expect_stdout: "undefined" expect_stdout: "undefined"
@@ -2595,7 +2595,9 @@ pure_getters_2: {
var a; var a;
var a = a && a.b; var a = a && a.b;
} }
expect: {} expect: {
var a = a && a.b;
}
} }
pure_getters_3: { pure_getters_3: {

View File

@@ -754,12 +754,12 @@ issue_2062: {
} }
input: { input: {
var a = 1; var a = 1;
if ([ a || a++ + a--, a++ + a--, a && a[console] ]); if ([ a || a++ + a--, a++ + a--, a && a.var ]);
console.log(a); console.log(a);
} }
expect: { expect: {
var a = 1; var a = 1;
a || (a++, a--), a++, --a && console; a || (a++, a--), a++, --a && a.var;
console.log(a); console.log(a);
} }
expect_stdout: "1" expect_stdout: "1"
@@ -1097,7 +1097,7 @@ issue_3490_1: {
if ({ if ({
3: function() { 3: function() {
var a; var a;
return (a && a[console]) < this; return (a && a.p) < this;
}(), }(),
}) c = "PASS"; }) c = "PASS";
if (b) while ("" == typeof d); if (b) while ("" == typeof d);
@@ -1107,7 +1107,7 @@ issue_3490_1: {
var b = 42, c = "FAIL"; var b = 42, c = "FAIL";
if (function() { if (function() {
var a; var a;
a && console; a && a.p;
}(), c = "PASS", b) while ("" == typeof d); }(), c = "PASS", b) while ("" == typeof d);
console.log(c, b); console.log(c, b);
} }

View File

@@ -561,6 +561,7 @@ drop_side_effect_free_call: {
issue_4730_1: { issue_4730_1: {
options = { options = {
pure_getters: "strict",
side_effects: true, side_effects: true,
} }
input: { input: {
@@ -569,13 +570,15 @@ issue_4730_1: {
} }
expect: { expect: {
var a; var a;
console.log("PASS"); console.log("PASS"),
a && a[a.p];
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_4730_2: { issue_4730_2: {
options = { options = {
pure_getters: "strict",
side_effects: true, side_effects: true,
} }
input: { input: {
@@ -584,7 +587,31 @@ issue_4730_2: {
} }
expect: { expect: {
var a; var a;
console.log("PASS"); !console.log("PASS") || a && a[a.p];
}
expect_stdout: "PASS"
}
issue_4751: {
options = {
pure_getters: "strict",
side_effects: true,
}
input: {
var o = {
get p() {
console.log("PASS");
},
};
o && o.p;
}
expect: {
var o = {
get p() {
console.log("PASS");
},
};
o && o.p;
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }