fix corner cases with class (#4723)
fixes #4720 fixes #4721 fixes #4722
This commit is contained in:
@@ -874,6 +874,7 @@ var AST_ClassMethod = DEFNODE("ClassMethod", null, {
|
||||
$documentation: "A `class` method",
|
||||
_validate: function() {
|
||||
if (!(this.value instanceof AST_LambdaExpression)) throw new Error("value must be AST_LambdaExpression");
|
||||
if (is_arrow(this.value)) throw new Error("value cannot be AST_Arrow or AST_AsyncArrow");
|
||||
if (this.value.name != null) throw new Error("name of class method's lambda must be null");
|
||||
},
|
||||
}, AST_ClassProperty);
|
||||
|
||||
@@ -409,6 +409,10 @@ merge(Compressor.prototype, {
|
||||
return node instanceof AST_Class || node instanceof AST_Lambda;
|
||||
}
|
||||
|
||||
function safe_for_extends(node) {
|
||||
return node instanceof AST_Class || node instanceof AST_Defun || node instanceof AST_Function;
|
||||
}
|
||||
|
||||
function is_arguments(def) {
|
||||
return def.name == "arguments" && def.scope.uses_arguments;
|
||||
}
|
||||
@@ -4815,7 +4819,7 @@ merge(Compressor.prototype, {
|
||||
var base = this.extends;
|
||||
if (base) {
|
||||
if (base instanceof AST_SymbolRef) base = base.fixed_value();
|
||||
if (!is_lambda(base) || is_arrow(base)) return true;
|
||||
if (!safe_for_extends(base)) return true;
|
||||
}
|
||||
return any(this.properties, compressor);
|
||||
});
|
||||
@@ -5037,7 +5041,7 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
def(AST_Class, function(scope) {
|
||||
var base = this.extends;
|
||||
if (base && (!is_lambda(base) || is_arrow(base))) return false;
|
||||
if (base && !safe_for_extends(base)) return false;
|
||||
return all_constant(this.properties, scope);
|
||||
});
|
||||
def(AST_ClassProperty, function(scope) {
|
||||
@@ -7310,7 +7314,7 @@ merge(Compressor.prototype, {
|
||||
var base = this.extends;
|
||||
if (base) {
|
||||
if (base instanceof AST_SymbolRef) base = base.fixed_value();
|
||||
base = !is_lambda(base) || is_arrow(base);
|
||||
base = !safe_for_extends(base);
|
||||
if (!base) exprs.unshift(this.extends);
|
||||
}
|
||||
exprs = trim(exprs, compressor, first_in_statement);
|
||||
@@ -7320,10 +7324,6 @@ merge(Compressor.prototype, {
|
||||
if (!base && !values) return null;
|
||||
exprs = [];
|
||||
}
|
||||
if (base) exprs.unshift(make_node(AST_ClassExpression, this, {
|
||||
extends: this.extends,
|
||||
properties: [],
|
||||
}));
|
||||
if (values) {
|
||||
var fn = make_node(AST_Arrow, this, {
|
||||
argnames: [],
|
||||
@@ -7336,7 +7336,19 @@ merge(Compressor.prototype, {
|
||||
expression: fn,
|
||||
}));
|
||||
}
|
||||
return make_sequence(this, exprs);
|
||||
exprs = exprs.length ? make_sequence(this, exprs) : null;
|
||||
if (!base) return exprs;
|
||||
var node = make_node(AST_ClassExpression, this, this);
|
||||
node.name = null;
|
||||
node.properties = [];
|
||||
if (exprs) node.properties.push(make_node(AST_ClassMethod, this, {
|
||||
key: exprs,
|
||||
value: make_node(AST_Function, this, {
|
||||
argnames: [],
|
||||
body: [],
|
||||
}).init_vars(node),
|
||||
}));
|
||||
return node;
|
||||
});
|
||||
def(AST_Conditional, function(compressor) {
|
||||
var consequent = this.consequent.drop_side_effect_free(compressor);
|
||||
@@ -10267,6 +10279,8 @@ merge(Compressor.prototype, {
|
||||
single_use = false;
|
||||
} else if (fixed.has_side_effects(compressor)) {
|
||||
single_use = false;
|
||||
} else if (compressor.option("ie8") && fixed instanceof AST_Class) {
|
||||
single_use = false;
|
||||
}
|
||||
if (single_use) fixed.parent_scope = self.scope;
|
||||
} else if (!fixed || !fixed.is_constant_expression() || fixed.drop_side_effect_free(compressor)) {
|
||||
|
||||
@@ -1047,3 +1047,128 @@ issue_4705: {
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=12"
|
||||
}
|
||||
|
||||
issue_4720: {
|
||||
options = {
|
||||
ie8: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
class A {
|
||||
static p = function f() {};
|
||||
}
|
||||
console.log(typeof A.p, typeof f);
|
||||
}
|
||||
expect: {
|
||||
class A {
|
||||
static p = function f() {};
|
||||
}
|
||||
console.log(typeof A.p, typeof f);
|
||||
}
|
||||
expect_stdout: "function undefined"
|
||||
node_version: ">=12"
|
||||
}
|
||||
|
||||
issue_4721: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
var a = "foo";
|
||||
try {
|
||||
(class extends 42 {
|
||||
[a = "bar"]() {}
|
||||
})
|
||||
} catch (e) {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
var a = "foo";
|
||||
try {
|
||||
(class extends 42 {
|
||||
[a = "bar"]() {}
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4722_1: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
try {
|
||||
(class extends function*() {} {});
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
try {
|
||||
(class extends function*() {} {});
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4722_2: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
try {
|
||||
(class extends async function() {} {});
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
try {
|
||||
(class extends async function() {} {});
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
issue_4722_3: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
try {
|
||||
(class extends async function*() {} {});
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
try {
|
||||
(class extends async function*() {} {});
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=10"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user