aboutsummaryrefslogtreecommitdiff
path: root/lib/compress.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compress.js')
-rw-r--r--lib/compress.js65
1 files changed, 55 insertions, 10 deletions
diff --git a/lib/compress.js b/lib/compress.js
index a46cd42b..ffc19b25 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -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;
});