From 54cb67805532667af50947cc3846d2cacc2a0a1d Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Sun, 12 May 2019 03:52:46 +0800 Subject: fix corner case in `assignments` (#3407) fixes #3406 --- lib/compress.js | 29 ++++++++++++------------ test/compress/assignment.js | 36 ------------------------------ test/compress/dead-code.js | 53 ++++++++++++++++++++++++++++++++++++++++++++ test/compress/drop-unused.js | 8 +++---- test/compress/sequences.js | 6 +++++ 5 files changed, 77 insertions(+), 55 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index b63c0512..638fb7c0 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -5395,7 +5395,8 @@ merge(Compressor.prototype, { OPT(AST_UnaryPrefix, function(self, compressor) { var e = self.expression; - if (self.operator == "delete" + if (compressor.option("evaluate") + && self.operator == "delete" && !(e instanceof AST_SymbolRef || e instanceof AST_PropAccess || is_identifier_atom(e))) { @@ -6254,6 +6255,7 @@ merge(Compressor.prototype, { if (compressor.option("dead_code") && self.left instanceof AST_SymbolRef && (def = self.left.definition()).scope === compressor.find_parent(AST_Lambda)) { + if (self.left.is_immutable()) return strip_assignment(); var level = 0, node, parent = self; do { node = parent; @@ -6261,16 +6263,12 @@ merge(Compressor.prototype, { if (parent instanceof AST_Exit) { if (in_try(level, parent)) break; if (is_reachable(def.scope, [ def ])) break; - if (self.operator == "=") return self.right.optimize(compressor); def.fixed = false; - return make_node(AST_Binary, self, { - operator: self.operator.slice(0, -1), - left: self.left, - right: self.right - }).optimize(compressor); + return strip_assignment(); } } while (parent instanceof AST_Binary && parent.right === node - || parent instanceof AST_Sequence && parent.tail_node() === node); + || parent instanceof AST_Sequence && parent.tail_node() === node + || parent instanceof AST_UnaryPrefix); } self = self.lift_sequences(compressor); if (!compressor.option("assignments")) return self; @@ -6302,13 +6300,6 @@ merge(Compressor.prototype, { expression: self.left }); } - if (!compressor.option("ie8") && self.left instanceof AST_Symbol && self.left.is_immutable()) { - return (self.operator == "=" ? self.right : make_node(AST_Binary, self, { - operator: self.operator.slice(0, -1), - left: self.left, - right: self.right - })).optimize(compressor); - } return self; function in_try(level, node) { @@ -6325,6 +6316,14 @@ merge(Compressor.prototype, { } } } + + function strip_assignment() { + return (self.operator != "=" ? make_node(AST_Binary, self, { + operator: self.operator.slice(0, -1), + left: self.left, + right: self.right + }) : maintain_this_binding(compressor, compressor.parent(), self, self.right)).optimize(compressor); + } }); OPT(AST_Conditional, function(self, compressor) { diff --git a/test/compress/assignment.js b/test/compress/assignment.js index 191b892e..ece0185d 100644 --- a/test/compress/assignment.js +++ b/test/compress/assignment.js @@ -311,39 +311,3 @@ issue_3375: { } expect_stdout: "string" } - -issue_3402: { - options = { - assignments: true, - evaluate: true, - functions: true, - passes: 2, - reduce_vars: true, - side_effects: true, - toplevel: true, - typeofs: true, - unused: true, - } - input: { - var f = function f() { - f = 42; - console.log(typeof f); - }; - "function" == typeof f && f(); - "function" == typeof f && f(); - console.log(typeof f); - } - expect: { - function f() { - console.log(typeof f); - } - f(); - f(); - console.log(typeof f); - } - expect_stdout: [ - "function", - "function", - "function", - ] -} diff --git a/test/compress/dead-code.js b/test/compress/dead-code.js index 5f1ca71c..190a3243 100644 --- a/test/compress/dead-code.js +++ b/test/compress/dead-code.js @@ -960,3 +960,56 @@ unsafe_string_replace: { } expect_stdout: "PASS" } + +issue_3402: { + options = { + dead_code: true, + evaluate: true, + functions: true, + passes: 2, + reduce_vars: true, + side_effects: true, + toplevel: true, + typeofs: true, + unused: true, + } + input: { + var f = function f() { + f = 42; + console.log(typeof f); + }; + "function" == typeof f && f(); + "function" == typeof f && f(); + console.log(typeof f); + } + expect: { + function f() { + console.log(typeof f); + } + f(); + f(); + console.log(typeof f); + } + expect_stdout: [ + "function", + "function", + "function", + ] +} + +issue_3406: { + options = { + dead_code: true, + } + input: { + console.log(function f(a) { + return delete (f = a); + }()); + } + expect: { + console.log(function f(a) { + return delete (0, a); + }()); + } + expect_stdout: "true" +} diff --git a/test/compress/drop-unused.js b/test/compress/drop-unused.js index 0869749d..d7f3cf76 100644 --- a/test/compress/drop-unused.js +++ b/test/compress/drop-unused.js @@ -1005,7 +1005,7 @@ issue_1715_4: { delete_assign_1: { options = { booleans: true, - side_effects: true, + evaluate: true, toplevel: true, unused: true, } @@ -1024,7 +1024,7 @@ delete_assign_1: { console.log((1 / 0, !0)); console.log((1 / 0, !0)); console.log((NaN, !0)); - console.log((0 / 0, !0)); + console.log((NaN, !0)); } expect_stdout: true } @@ -1032,8 +1032,8 @@ delete_assign_1: { delete_assign_2: { options = { booleans: true, + evaluate: true, keep_infinity: true, - side_effects: true, toplevel: true, unused: true, } @@ -1052,7 +1052,7 @@ delete_assign_2: { console.log((Infinity, !0)); console.log((1 / 0, !0)); console.log((NaN, !0)); - console.log((0 / 0, !0)); + console.log((NaN, !0)); } expect_stdout: true } diff --git a/test/compress/sequences.js b/test/compress/sequences.js index 47dd4c4f..08a06790 100644 --- a/test/compress/sequences.js +++ b/test/compress/sequences.js @@ -490,6 +490,7 @@ issue_1758: { delete_seq_1: { options = { booleans: true, + evaluate: true, side_effects: true, } input: { @@ -514,6 +515,7 @@ delete_seq_1: { delete_seq_2: { options = { booleans: true, + evaluate: true, side_effects: true, } input: { @@ -538,6 +540,7 @@ delete_seq_2: { delete_seq_3: { options = { booleans: true, + evaluate: true, keep_infinity: true, side_effects: true, } @@ -563,6 +566,7 @@ delete_seq_3: { delete_seq_4: { options = { booleans: true, + evaluate: true, sequences: true, side_effects: true, } @@ -590,6 +594,7 @@ delete_seq_4: { delete_seq_5: { options = { booleans: true, + evaluate: true, keep_infinity: true, sequences: true, side_effects: true, @@ -618,6 +623,7 @@ delete_seq_5: { delete_seq_6: { options = { booleans: true, + evaluate: true, side_effects: true, } input: { -- cgit v1.2.3