From 3a4497a1c3db3a2069d6a5a0d1d8a8295c3ef568 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Fri, 24 Apr 2020 18:29:42 +0100 Subject: fix corner case in `typeofs` (#3818) fixes #3817 --- lib/compress.js | 33 ++++++++++++++++++++++++--------- test/compress/typeof.js | 22 ++++++++++++++++++++++ 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 9420d8d2..3d1b17f3 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -5194,16 +5194,17 @@ merge(Compressor.prototype, { return if_break_in_loop(self, compressor); }); - function mark_locally_defined(condition, consequent, alternative, operator) { + function mark_locally_defined(condition, consequent, alternative) { if (!(condition instanceof AST_Binary)) return; if (!(condition.left instanceof AST_String)) { - if (!operator) operator = condition.operator; - if (condition.operator != operator) return; - switch (operator) { + switch (condition.operator) { case "&&": + mark_locally_defined(condition.left, consequent); + mark_locally_defined(condition.right, consequent); + break; case "||": - mark_locally_defined(condition.left, consequent, alternative, operator); - mark_locally_defined(condition.right, consequent, alternative, operator); + mark_locally_defined(negate(condition.left), alternative); + mark_locally_defined(negate(condition.right), alternative); break; } return; @@ -5235,6 +5236,20 @@ merge(Compressor.prototype, { if (node instanceof AST_SymbolRef && node.definition() === def) node.defined = true; }); body.walk(tw); + + function negate(node) { + if (!(node instanceof AST_Binary)) return; + switch (node.operator) { + case "==": + node = node.clone(); + node.operator = "!="; + return node; + case "!=": + node = node.clone(); + node.operator = "=="; + return node; + } + } } OPT(AST_If, function(self, compressor) { @@ -6623,7 +6638,7 @@ merge(Compressor.prototype, { (self.left.is_number(compressor) && self.right.is_number(compressor)) || (self.left.is_boolean(compressor) && self.right.is_boolean(compressor)) || self.left.equivalent_to(self.right)) { - self.operator = self.operator.substr(0, 2); + self.operator = self.operator.slice(0, 2); } // XXX: intentionally falling down to the next case case "==": @@ -7102,10 +7117,10 @@ merge(Compressor.prototype, { } if (compressor.option("typeofs")) switch (self.operator) { case "&&": - mark_locally_defined(self.left, self.right, null, "&&"); + mark_locally_defined(self.left, self.right, null); break; case "||": - mark_locally_defined(self.left, null, self.right, "||"); + mark_locally_defined(self.left, null, self.right); break; } if (compressor.option("unsafe")) { diff --git a/test/compress/typeof.js b/test/compress/typeof.js index aae7405f..320817ee 100644 --- a/test/compress/typeof.js +++ b/test/compress/typeof.js @@ -435,3 +435,25 @@ emberjs_global: { } expect_stdout: Error("PASS") } + +issue_3817: { + options = { + comparisons: true, + conditionals: true, + passes: 2, + typeofs: true, + } + input: { + if ("A" == typeof A || !console.log("PASS")) switch (false) { + case "undefined" == typeof A: + console.log("FAIL"); + } + } + expect: { + if ("A" == typeof A || !console.log("PASS")) switch (false) { + case "undefined" == typeof A: + console.log("FAIL"); + } + } + expect_stdout: "PASS" +} -- cgit v1.2.3