aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2021-06-20 20:13:05 +0100
committerGitHub <noreply@github.com>2021-06-21 03:13:05 +0800
commite368d3971588c78413a91d89c23356d2f511c723 (patch)
treedcdaded481f64ec48b896f82b72f9a8111a6718a
parentfd8dec61ad0e83caa72691b56e1d36b6f29203a8 (diff)
downloadtracifyjs-e368d3971588c78413a91d89c23356d2f511c723.tar.gz
tracifyjs-e368d3971588c78413a91d89c23356d2f511c723.zip
fix corner cases in `reduce_vars` & `side_effects` (#5016)
fixes #5015
-rw-r--r--lib/compress.js48
-rw-r--r--test/compress/classes.js83
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"
+}