From: Alex Lam S.L Date: Sat, 25 Mar 2017 15:03:26 +0000 (+0800) Subject: fix `has_side_effects()` (#1675) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=b19aa58cff73ea59438346db094de4a54463d669;p=UglifyJS.git fix `has_side_effects()` (#1675) `AST_Try` is an `AST_Block`, so besides try block we also need to inspect catch and finally blocks for possible side effects. Also extend this functionality to handle `AST_If` and `AST_LabeledStatement` while we are at it. fixes #1673 --- diff --git a/lib/compress.js b/lib/compress.js index bea9c9a4..805a84a7 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1600,14 +1600,29 @@ merge(Compressor.prototype, { return false; }); - def(AST_Block, function(compressor){ - for (var i = this.body.length; --i >= 0;) { - if (this.body[i].has_side_effects(compressor)) + function any(list, compressor) { + for (var i = list.length; --i >= 0;) + if (list[i].has_side_effects(compressor)) return true; - } return false; - }); + } + def(AST_Block, function(compressor){ + return any(this.body, compressor); + }); + def(AST_Try, function(compressor){ + return any(this.body, compressor) + || this.bcatch && this.bcatch.has_side_effects(compressor) + || this.bfinally && this.bfinally.has_side_effects(compressor); + }); + def(AST_If, function(compressor){ + return this.condition.has_side_effects(compressor) + || this.body && this.body.has_side_effects(compressor) + || this.alternative && this.alternative.has_side_effects(compressor); + }); + def(AST_LabeledStatement, function(compressor){ + return this.body.has_side_effects(compressor); + }); def(AST_SimpleStatement, function(compressor){ return this.body.has_side_effects(compressor); }); @@ -1633,19 +1648,13 @@ merge(Compressor.prototype, { return this.global() && this.undeclared(); }); def(AST_Object, function(compressor){ - for (var i = this.properties.length; --i >= 0;) - if (this.properties[i].has_side_effects(compressor)) - return true; - return false; + return any(this.properties, compressor); }); def(AST_ObjectProperty, function(compressor){ return this.value.has_side_effects(compressor); }); def(AST_Array, function(compressor){ - for (var i = this.elements.length; --i >= 0;) - if (this.elements[i].has_side_effects(compressor)) - return true; - return false; + return any(this.elements, compressor); }); def(AST_Dot, function(compressor){ if (!compressor.option("pure_getters")) return true; diff --git a/test/compress/issue-1673.js b/test/compress/issue-1673.js new file mode 100644 index 00000000..59686abf --- /dev/null +++ b/test/compress/issue-1673.js @@ -0,0 +1,127 @@ +side_effects_catch: { + options = { + reduce_vars: true, + side_effects: true, + unused: true, + } + input: { + function f() { + function g() { + try { + throw 0; + } catch (e) { + console.log("PASS"); + } + } + g(); + } + f(); + } + expect: { + function f() { + (function() { + try { + throw 0; + } catch (e) { + console.log("PASS"); + } + })(); + } + f(); + } + expect_stdout: "PASS" +} + +side_effects_else: { + options = { + reduce_vars: true, + side_effects: true, + unused: true, + } + input: { + function f(x) { + function g() { + if (x); + else console.log("PASS"); + } + g(); + } + f(0); + } + expect: { + function f(x) { + (function() { + if (x); + else console.log("PASS"); + })(); + } + f(0); + } + expect_stdout: "PASS" +} + +side_effects_finally: { + options = { + reduce_vars: true, + side_effects: true, + unused: true, + } + input: { + function f() { + function g() { + try { + } catch (e) { + } finally { + console.log("PASS"); + } + } + g(); + } + f(); + } + expect: { + function f() { + (function() { + try { + } catch (e) { + } finally { + console.log("PASS"); + } + })(); + } + f(); + } + expect_stdout: "PASS" +} + +side_effects_label: { + options = { + reduce_vars: true, + side_effects: true, + unused: true, + } + input: { + function f(x) { + function g() { + L: { + console.log("PASS"); + break L; + } + } + g(); + } + f(0); + } + expect: { + function f(x) { + (function() { + L: { + console.log("PASS"); + break L; + } + })(); + } + f(0); + } + expect_stdout: "PASS" +}