fix corner cases in booleans & conditionals (#5695)

fixes #5694
This commit is contained in:
Alex Lam S.L
2022-10-03 15:47:15 +01:00
committed by GitHub
parent 140e4e0da8
commit dabcc39b51
5 changed files with 64 additions and 27 deletions

View File

@@ -1748,6 +1748,7 @@ Compressor.prototype.compress = function(node) {
var identifier_atom = makePredicate("Infinity NaN undefined"); var identifier_atom = makePredicate("Infinity NaN undefined");
function is_lhs_read_only(lhs, compressor) { function is_lhs_read_only(lhs, compressor) {
if (lhs instanceof AST_Atom) return true;
if (lhs instanceof AST_ObjectIdentity) return true; if (lhs instanceof AST_ObjectIdentity) return true;
if (lhs instanceof AST_PropAccess) { if (lhs instanceof AST_PropAccess) {
if (lhs.property === "__proto__") return true; if (lhs.property === "__proto__") return true;
@@ -11589,10 +11590,12 @@ Compressor.prototype.compress = function(node) {
if (node instanceof AST_Unary) return true; if (node instanceof AST_Unary) return true;
} }
function extract_lhs(node) { function extract_lhs(node, compressor) {
if (node instanceof AST_Assign) return node.left; if (node instanceof AST_Assign) return is_lhs_read_only(node.left, compressor) ? node : node.left;
if (node instanceof AST_Sequence) return extract_lhs(node.tail_node()); if (node instanceof AST_Sequence) return extract_lhs(node.tail_node());
if (node instanceof AST_UnaryPrefix && UNARY_POSTFIX[node.operator]) return node.expression; if (node instanceof AST_UnaryPrefix && UNARY_POSTFIX[node.operator]) {
return is_lhs_read_only(node.expression, compressor) ? node : node.expression;
}
return node; return node;
} }
@@ -11601,6 +11604,7 @@ Compressor.prototype.compress = function(node) {
if (node instanceof AST_Sub) { if (node instanceof AST_Sub) {
return repeatable(compressor, node.expression) && repeatable(compressor, node.property); return repeatable(compressor, node.expression) && repeatable(compressor, node.property);
} }
if (node instanceof AST_Symbol) return true;
return !node.has_side_effects(compressor); return !node.has_side_effects(compressor);
} }
@@ -11637,7 +11641,7 @@ Compressor.prototype.compress = function(node) {
if (seq !== self) return seq.optimize(compressor); if (seq !== self) return seq.optimize(compressor);
} }
if (compressor.option("assignments") && lazy_op[self.operator]) { if (compressor.option("assignments") && lazy_op[self.operator]) {
var lhs = extract_lhs(self.left); var lhs = extract_lhs(self.left, compressor);
var right = self.right; var right = self.right;
// a || (a = x) ---> a = a || x // a || (a = x) ---> a = a || x
// (a = x) && (a = y) ---> a = (a = x) && y // (a = x) && (a = y) ---> a = (a = x) && y
@@ -11737,7 +11741,7 @@ Compressor.prototype.compress = function(node) {
var in_bool = false; var in_bool = false;
var parent = compressor.parent(); var parent = compressor.parent();
if (compressor.option("booleans")) { if (compressor.option("booleans")) {
var lhs = extract_lhs(self.left); var lhs = extract_lhs(self.left, compressor);
if (lazy_op[self.operator] && !lhs.has_side_effects(compressor)) { if (lazy_op[self.operator] && !lhs.has_side_effects(compressor)) {
// a || a ---> a // a || a ---> a
// (a = x) && a --> a = x // (a = x) && a --> a = x
@@ -12898,7 +12902,7 @@ Compressor.prototype.compress = function(node) {
} }
var consequent = self.consequent; var consequent = self.consequent;
var alternative = self.alternative; var alternative = self.alternative;
var cond_lhs = extract_lhs(condition); var cond_lhs = extract_lhs(condition, compressor);
if (repeatable(compressor, cond_lhs)) { if (repeatable(compressor, cond_lhs)) {
// x ? x : y ---> x || y // x ? x : y ---> x || y
if (cond_lhs.equals(consequent)) return make_node(AST_Binary, self, { if (cond_lhs.equals(consequent)) return make_node(AST_Binary, self, {

View File

@@ -830,3 +830,20 @@ issue_5469: {
} }
expect_stdout: "undefined" expect_stdout: "undefined"
} }
issue_5694: {
options = {
booleans: true,
conditionals: true,
}
input: {
var undefined;
// Node.js v0.12~6 (vm): 42
console.log((undefined = 42) && undefined);
}
expect: {
var undefined;
console.log((undefined = 42) && undefined);
}
expect_stdout: true
}

View File

@@ -76,14 +76,12 @@ self_comparison_1: {
comparisons: true, comparisons: true,
} }
input: { input: {
var a, b;
a === a; a === a;
a !== b; a !== b;
b.c === a.c; b.c === a.c;
b.c !== b.c; b.c !== b.c;
} }
expect: { expect: {
var a, b;
a == a; a == a;
a !== b; a !== b;
b.c === a.c; b.c === a.c;

View File

@@ -3033,3 +3033,21 @@ issue_5673_2: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_5694: {
options = {
conditionals: true,
}
input: {
FORCE_EXEC = "async()=>{}";
var a = "foo";
// Node.js v0.12~6 (vm): foo
console.log((NaN = a) ? NaN : 42);
}
expect: {
FORCE_EXEC = "async()=>{}";
var a = "foo";
console.log((NaN = a) ? NaN : 42);
}
expect_stdout: "NaN"
}

View File

@@ -976,33 +976,33 @@ nested_if_return: {
if_return: true, if_return: true,
} }
input: { input: {
function f(a, b, c, d, e, f, g, h, i, j, k, l, m, n) { function f() {
if (a) { if (A) {
if (b) if (B)
return b; return B;
if (c) if (C)
return d; return D;
if (e) if (E)
return f; return F;
if (g) if (G)
return h; return H;
if (i) { if (I) {
if (j) if (J)
return k; return K;
return; return;
} }
if (l) { if (L) {
if (m) if (M)
return; return;
return n; return N;
} }
} }
} }
} }
expect: { expect: {
function f(a, b, c, d, e, f, g, h, i, j, k, l, m, n) { function f() {
if (a) if (A)
return b || (c ? d : e ? f : g ? h : i ? j ? k : void 0 : l && !m ? n : void 0); return B || (C ? D : E ? F : G ? H : I ? J ? K : void 0 : L && !M ? N : void 0);
} }
} }
} }