aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2020-04-24 18:29:42 +0100
committerGitHub <noreply@github.com>2020-04-25 01:29:42 +0800
commit3a4497a1c3db3a2069d6a5a0d1d8a8295c3ef568 (patch)
tree0aa1f1dc0a75ef5c6c9c1d84b0718288b2e86c0f
parent3ee13cae02174e565ca40462d7b15c4974265871 (diff)
downloadtracifyjs-3a4497a1c3db3a2069d6a5a0d1d8a8295c3ef568.tar.gz
tracifyjs-3a4497a1c3db3a2069d6a5a0d1d8a8295c3ef568.zip
fix corner case in `typeofs` (#3818)
fixes #3817
-rw-r--r--lib/compress.js33
-rw-r--r--test/compress/typeof.js22
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"
+}