From 66c126ffde664e75a6ca9c28fe63d40cc2207d45 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Tue, 3 Jul 2018 16:44:23 +0800 Subject: [PATCH] fix corner case in `ie8` (#3207) fixes #3206 --- lib/compress.js | 112 +++++++++++++++++++++---------------------- test/compress/ie8.js | 45 +++++++++++++++++ 2 files changed, 101 insertions(+), 56 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index da84df17..c28305a4 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -336,13 +336,10 @@ merge(Compressor.prototype, { def.chained = false; def.direct_access = false; def.escaped = false; - if (def.scope.pinned()) { - def.fixed = false; - } else if (!compressor.exposed(def)) { - def.fixed = def.init; - } else { - def.fixed = false; - } + def.fixed = !def.scope.pinned() + && !compressor.exposed(def) + && !(def.init instanceof AST_Function && def.init !== def.scope) + && def.init; if (def.fixed instanceof AST_Defun && !all(def.references, function(ref) { var scope = ref.scope; do { @@ -3444,6 +3441,7 @@ merge(Compressor.prototype, { if (scope !== self) return; if (node instanceof AST_Function && node.name + && !compressor.option("ie8") && !compressor.option("keep_fnames")) { var def = node.name.definition(); // any declarations with same name will overshadow @@ -3927,8 +3925,39 @@ merge(Compressor.prototype, { } def(AST_Node, return_this); - def(AST_Constant, return_null); - def(AST_This, return_null); + def(AST_Accessor, return_null); + def(AST_Array, function(compressor, first_in_statement) { + var values = trim(this.elements, compressor, first_in_statement); + return values && make_sequence(this, values); + }); + def(AST_Assign, function(compressor) { + var left = this.left; + if (left.has_side_effects(compressor) + || compressor.has_directive("use strict") + && left instanceof AST_PropAccess + && left.expression.is_constant()) { + return this; + } + this.write_only = true; + if (root_expr(left).is_constant_expression(compressor.find_parent(AST_Scope))) { + return this.right.drop_side_effect_free(compressor); + } + return this; + }); + def(AST_Binary, function(compressor, first_in_statement) { + var right = this.right.drop_side_effect_free(compressor); + if (!right) return this.left.drop_side_effect_free(compressor, first_in_statement); + if (lazy_op[this.operator]) { + if (right === this.right) return this; + var node = this.clone(); + node.right = right; + return node; + } else { + var left = this.left.drop_side_effect_free(compressor, first_in_statement); + if (!left) return this.right.drop_side_effect_free(compressor, first_in_statement); + return make_sequence(this, [ left, right ]); + } + }); def(AST_Call, function(compressor, first_in_statement) { if (!this.is_expr_pure(compressor)) { if (this.expression.is_call_pure(compressor)) { @@ -3959,36 +3988,6 @@ merge(Compressor.prototype, { var args = trim(this.args, compressor, first_in_statement); return args && make_sequence(this, args); }); - def(AST_Accessor, return_null); - def(AST_Function, return_null); - def(AST_Binary, function(compressor, first_in_statement) { - var right = this.right.drop_side_effect_free(compressor); - if (!right) return this.left.drop_side_effect_free(compressor, first_in_statement); - if (lazy_op[this.operator]) { - if (right === this.right) return this; - var node = this.clone(); - node.right = right; - return node; - } else { - var left = this.left.drop_side_effect_free(compressor, first_in_statement); - if (!left) return this.right.drop_side_effect_free(compressor, first_in_statement); - return make_sequence(this, [ left, right ]); - } - }); - def(AST_Assign, function(compressor) { - var left = this.left; - if (left.has_side_effects(compressor) - || compressor.has_directive("use strict") - && left instanceof AST_PropAccess - && left.expression.is_constant()) { - return this; - } - this.write_only = true; - if (root_expr(left).is_constant_expression(compressor.find_parent(AST_Scope))) { - return this.right.drop_side_effect_free(compressor); - } - return this; - }); def(AST_Conditional, function(compressor) { var consequent = this.consequent.drop_side_effect_free(compressor); var alternative = this.alternative.drop_side_effect_free(compressor); @@ -4008,6 +4007,14 @@ merge(Compressor.prototype, { node.alternative = alternative; return node; }); + def(AST_Constant, return_null); + def(AST_Dot, function(compressor, first_in_statement) { + if (this.expression.may_throw_on_access(compressor)) return this; + return this.expression.drop_side_effect_free(compressor, first_in_statement); + }); + def(AST_Function, function(compressor) { + return this.name && compressor.option("ie8") ? this : null; + }); def(AST_Unary, function(compressor, first_in_statement) { if (unary_side_effects[this.operator]) { this.write_only = !this.expression.has_side_effects(compressor); @@ -4021,9 +4028,6 @@ merge(Compressor.prototype, { } return expression; }); - def(AST_SymbolRef, function(compressor) { - return this.is_declared(compressor) ? null : this; - }); def(AST_Object, function(compressor, first_in_statement) { var values = trim(this.properties, compressor, first_in_statement); return values && make_sequence(this, values); @@ -4031,13 +4035,13 @@ merge(Compressor.prototype, { def(AST_ObjectProperty, function(compressor, first_in_statement) { return this.value.drop_side_effect_free(compressor, first_in_statement); }); - def(AST_Array, function(compressor, first_in_statement) { - var values = trim(this.elements, compressor, first_in_statement); - return values && make_sequence(this, values); - }); - def(AST_Dot, function(compressor, first_in_statement) { - if (this.expression.may_throw_on_access(compressor)) return this; - return this.expression.drop_side_effect_free(compressor, first_in_statement); + def(AST_Sequence, function(compressor) { + var last = this.tail_node(); + var expr = last.drop_side_effect_free(compressor); + if (expr === last) return this; + var expressions = this.expressions.slice(0, -1); + if (expr) expressions.push(expr); + return make_sequence(this, expressions); }); def(AST_Sub, function(compressor, first_in_statement) { if (this.expression.may_throw_on_access(compressor)) return this; @@ -4047,14 +4051,10 @@ merge(Compressor.prototype, { if (!property) return expression; return make_sequence(this, [ expression, property ]); }); - def(AST_Sequence, function(compressor) { - var last = this.tail_node(); - var expr = last.drop_side_effect_free(compressor); - if (expr === last) return this; - var expressions = this.expressions.slice(0, -1); - if (expr) expressions.push(expr); - return make_sequence(this, expressions); + def(AST_SymbolRef, function(compressor) { + return this.is_declared(compressor) ? null : this; }); + def(AST_This, return_null); })(function(node, func) { node.DEFMETHOD("drop_side_effect_free", func); }); diff --git a/test/compress/ie8.js b/test/compress/ie8.js index d5b61cbd..3fce9ef4 100644 --- a/test/compress/ie8.js +++ b/test/compress/ie8.js @@ -666,3 +666,48 @@ issue_3197_2_ie8: { } expect_stdout: "true" } + +issue_3206_1: { + options = { + evaluate: true, + ie8: false, + reduce_vars: true, + typeofs: true, + unused: true, + } + input: { + console.log(function() { + var foo = function bar() {}; + return "function" == typeof bar; + }()); + } + expect: { + console.log(function() { + return "function" == typeof bar; + }()); + } + expect_stdout: "false" +} + +issue_3206_2: { + options = { + evaluate: true, + ie8: true, + reduce_vars: true, + typeofs: true, + unused: true, + } + input: { + console.log(function() { + var foo = function bar() {}; + return "function" == typeof bar; + }()); + } + expect: { + console.log(function() { + (function bar() {}); + return "function" == typeof bar; + }()); + } + expect_stdout: "false" +} -- 2.34.1