diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2021-06-20 20:13:05 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-21 03:13:05 +0800 |
commit | e368d3971588c78413a91d89c23356d2f511c723 (patch) | |
tree | dcdaded481f64ec48b896f82b72f9a8111a6718a | |
parent | fd8dec61ad0e83caa72691b56e1d36b6f29203a8 (diff) | |
download | tracifyjs-e368d3971588c78413a91d89c23356d2f511c723.tar.gz tracifyjs-e368d3971588c78413a91d89c23356d2f511c723.zip |
fix corner cases in `reduce_vars` & `side_effects` (#5016)
fixes #5015
-rw-r--r-- | lib/compress.js | 48 | ||||
-rw-r--r-- | test/compress/classes.js | 83 |
2 files changed, 112 insertions, 19 deletions
diff --git a/lib/compress.js b/lib/compress.js index 5a7461a8..f8289f4a 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1012,6 +1012,11 @@ merge(Compressor.prototype, { reset_def(tw, compressor, def); }); if (node.extends) node.extends.walk(tw); + var props = node.properties.filter(function(prop) { + reset_flags(prop); + if (prop.key instanceof AST_Node) prop.key.walk(tw); + return prop.value; + }); if (node.name) { var d = node.name.definition(); var parent = tw.parent(); @@ -1028,11 +1033,7 @@ merge(Compressor.prototype, { d.fixed = false; } } - node.properties.filter(function(prop) { - reset_flags(prop); - if (prop.key instanceof AST_Node) prop.key.walk(tw); - return prop.value; - }).forEach(function(prop) { + props.forEach(function(prop) { if (!prop.static || prop instanceof AST_ClassField && prop.value.contains_this()) { push(tw); prop.value.walk(tw); @@ -7695,24 +7696,24 @@ merge(Compressor.prototype, { } return self; }); - def(AST_Class, function(compressor, first_in_statement) { + function drop_class(self, compressor, first_in_statement) { var exprs = [], values = []; - var props = this.properties; + var props = self.properties; for (var i = 0; i < props.length; i++) { var prop = props[i]; if (prop.key instanceof AST_Node) exprs.push(prop.key); if (prop.static && prop.value && prop instanceof AST_ClassField && prop.value.has_side_effects(compressor)) { - if (prop.value.contains_this()) return this; + if (prop.value.contains_this()) return self; values.push(prop.value); } } - var base = this.extends; + var base = self.extends; if (base) { if (base instanceof AST_SymbolRef) base = base.fixed_value(); base = !safe_for_extends(base); - if (!base) exprs.unshift(this.extends); + if (!base) exprs.unshift(self.extends); } exprs = trim(exprs, compressor, first_in_statement); if (exprs) first_in_statement = false; @@ -7722,26 +7723,32 @@ merge(Compressor.prototype, { exprs = []; } if (base) { - var node = to_class_expr(this, true); + var node = to_class_expr(self, true); node.properties = []; - if (exprs.length) node.properties.push(make_node(AST_ClassMethod, this, { - key: make_sequence(this, exprs), - value: make_node(AST_Function, this, { + if (exprs.length) node.properties.push(make_node(AST_ClassMethod, self, { + key: make_sequence(self, exprs), + value: make_node(AST_Function, self, { argnames: [], body: [], }).init_vars(node), })); exprs = [ node ]; } - if (values) exprs.push(make_node(AST_Call, this, { - expression: make_node(AST_Arrow, this, { + if (values) exprs.push(make_node(AST_Call, self, { + expression: make_node(AST_Arrow, self, { argnames: [], body: [], - value: make_sequence(this, values), - }).init_vars(this.parent_scope), + value: make_sequence(self, values), + }).init_vars(self.parent_scope), args: [], })); - return make_sequence(this, exprs); + return make_sequence(self, exprs); + } + def(AST_ClassExpression, function(compressor, first_in_statement) { + var self = this; + var name = self.name; + if (name && name.fixed_value() !== self && name.definition().references.length > 0) return self; + return drop_class(self, compressor, first_in_statement); }); def(AST_Conditional, function(compressor) { var consequent = this.consequent.drop_side_effect_free(compressor); @@ -7782,6 +7789,9 @@ merge(Compressor.prototype, { return exprs.length == 0 ? null : make_sequence(this, exprs); }); def(AST_Constant, return_null); + def(AST_DefClass, function(compressor, first_in_statement) { + return drop_class(this, compressor, first_in_statement); + }); def(AST_Dot, function(compressor, first_in_statement) { var expr = this.expression; if (!this.optional && expr.may_throw_on_access(compressor)) return this; diff --git a/test/compress/classes.js b/test/compress/classes.js index 4671fd07..c57842f9 100644 --- a/test/compress/classes.js +++ b/test/compress/classes.js @@ -1792,3 +1792,86 @@ issue_4996_2: { expect_stdout: "0" node_version: ">=12" } + +issue_5015_1: { + options = { + side_effects: true, + } + input: { + "use strict"; + var a; + try { + (class a { + [a]() {} + }); + } catch (e) { + console.log("PASS"); + } + } + expect: { + "use strict"; + var a; + try { + (class a { + [a]() {} + }); + } catch (e) { + console.log("PASS"); + } + } + expect_stdout: "PASS" + node_version: ">=4" +} + +issue_5015_2: { + options = { + reduce_vars: true, + side_effects: true, + toplevel: true, + } + input: { + "use strict"; + try { + new class A { + [(A, 42)]() {} + }(); + } catch (e) { + console.log("PASS"); + } + } + expect: { + "use strict"; + try { + new class A { + [(A, 42)]() {} + }(); + } catch (e) { + console.log("PASS"); + } + } + expect_stdout: "PASS" + node_version: ">=4" +} + +issue_5015_3: { + options = { + reduce_vars: true, + side_effects: true, + toplevel: true, + } + input: { + "use strict"; + (class A { + static f() { + return A; + } + }); + console.log("PASS"); + } + expect: { + "use strict"; + console.log("PASS"); + } + expect_stdout: "PASS" + node_version: ">=4" +} |