support arrow function (#4385)

This commit is contained in:
Alex Lam S.L
2020-12-17 10:23:41 +00:00
committed by GitHub
parent 75e9fd8417
commit a96f087ac3
11 changed files with 732 additions and 117 deletions

View File

@@ -49,6 +49,7 @@ function Compressor(options, false_by_default) {
TreeTransformer.call(this, this.before, this.after);
this.options = defaults(options, {
arguments : !false_by_default,
arrows : !false_by_default,
assignments : !false_by_default,
booleans : !false_by_default,
collapse_vars : !false_by_default,
@@ -1372,7 +1373,8 @@ merge(Compressor.prototype, {
function is_iife_call(node) {
if (node.TYPE != "Call") return false;
return is_function(node.expression) || is_iife_call(node.expression);
var exp = node.expression;
return exp instanceof AST_AsyncFunction || exp instanceof AST_Function || is_iife_call(exp);
}
function is_undeclared_ref(node) {
@@ -3573,12 +3575,20 @@ merge(Compressor.prototype, {
return map;
}
AST_Lambda.DEFMETHOD("first_statement", function() {
var body = this.body;
function skip_directives(body) {
for (var i = 0; i < body.length; i++) {
var stat = body[i];
if (!(stat instanceof AST_Directive)) return stat;
}
}
AST_Arrow.DEFMETHOD("first_statement", function() {
if (this.value) return make_node(AST_Return, this.value, {
value: this.value
});
return skip_directives(this.body);
});
AST_Lambda.DEFMETHOD("first_statement", function() {
return skip_directives(this.body);
});
function try_evaluate(compressor, node) {
@@ -4170,6 +4180,9 @@ merge(Compressor.prototype, {
def(AST_Statement, function() {
throw new Error("Cannot negate a statement");
});
def(AST_Arrow, function() {
return basic_negation(this);
});
def(AST_AsyncFunction, function() {
return basic_negation(this);
});
@@ -4568,6 +4581,10 @@ merge(Compressor.prototype, {
result = false;
return true;
}
if (node instanceof AST_This) {
if (scopes.length == 0 && self instanceof AST_Arrow) result = false;
return true;
}
}));
return result;
});
@@ -4651,6 +4668,28 @@ merge(Compressor.prototype, {
return trim_block(self);
});
OPT(AST_Arrow, function(self, compressor) {
if (!compressor.option("arrows")) return self;
if (self.value) {
var value = self.value;
if (is_undefined(value, compressor)) {
self.value = null;
} else if (value instanceof AST_UnaryPrefix && value.operator == "void") {
self.body.push(make_node(AST_SimpleStatement, value, {
body: value.expression
}));
self.value = null;
}
} else if (self.body.length == 1) {
var stat = self.body[0];
if (stat instanceof AST_Return && stat.value) {
self.body.pop();
self.value = stat.value;
}
}
return self;
});
OPT(AST_Function, function(self, compressor) {
self.body = tighten_body(self.body, compressor);
if (compressor.option("inline")) for (var i = 0; i < self.body.length; i++) {
@@ -6316,6 +6355,7 @@ merge(Compressor.prototype, {
})) return this;
return make_sequence(this, values.map(convert_spread));
});
def(AST_Arrow, return_null);
def(AST_Assign, function(compressor) {
var left = this.left;
if (left instanceof AST_PropAccess) {
@@ -7702,7 +7742,7 @@ merge(Compressor.prototype, {
}
}
var fn = exp instanceof AST_SymbolRef ? exp.fixed_value() : exp;
var is_func = fn instanceof AST_Defun || fn instanceof AST_Function;
var is_func = fn instanceof AST_Arrow || fn instanceof AST_Defun || fn instanceof AST_Function;
var stat = is_func && fn.first_statement();
var can_inline = is_func
&& compressor.option("inline")
@@ -7772,10 +7812,11 @@ merge(Compressor.prototype, {
}
if (compressor.option("side_effects")
&& all(fn.body, is_empty)
&& (fn !== exp || fn_name_unused(fn, compressor))
&& !(fn instanceof AST_Arrow && fn.value)
&& all(fn.argnames, function(argname) {
return !(argname instanceof AST_Destructured);
})
&& (fn !== exp || fn_name_unused(fn, compressor))) {
})) {
var args = self.args.map(function(arg) {
return arg instanceof AST_Spread ? make_node(AST_Array, arg, {
elements: [ arg ],
@@ -7814,9 +7855,11 @@ merge(Compressor.prototype, {
function can_flatten_body(stat) {
var len = fn.body.length;
if (compressor.option("inline") < 3) {
return len == 1 && return_value(stat);
if (len < 2) {
stat = return_value(stat);
if (stat) return stat;
}
if (compressor.option("inline") < 3) return false;
stat = null;
for (var i = 0; i < len; i++) {
var line = fn.body[i];
@@ -9833,7 +9876,7 @@ merge(Compressor.prototype, {
&& expr instanceof AST_SymbolRef
&& is_arguments(def = expr.definition())
&& prop instanceof AST_Number
&& (fn = expr.scope.resolve()) === find_lambda()
&& (fn = def.scope) === find_lambda()
&& !(assigned && fn.uses_arguments === "d")) {
var index = prop.value;
if (parent instanceof AST_UnaryPrefix && parent.operator == "delete") {
@@ -9936,6 +9979,7 @@ merge(Compressor.prototype, {
while (p = compressor.parent(i++)) {
if (p instanceof AST_Lambda) {
if (p instanceof AST_Accessor) return;
if (p instanceof AST_Arrow) continue;
fn_parent = compressor.parent(i);
return p;
}
@@ -9943,13 +9987,14 @@ merge(Compressor.prototype, {
}
});
AST_Arrow.DEFMETHOD("contains_this", return_false);
AST_Scope.DEFMETHOD("contains_this", function() {
var result;
var self = this;
self.walk(new TreeWalker(function(node) {
if (result) return true;
if (node instanceof AST_This) return result = true;
if (node !== self && node instanceof AST_Scope) return true;
if (node !== self && node instanceof AST_Scope && !(node instanceof AST_Arrow)) return true;
}));
return result;
});