aboutsummaryrefslogtreecommitdiff
path: root/lib/compress.js
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2020-12-17 22:18:47 +0000
committerGitHub <noreply@github.com>2020-12-18 06:18:47 +0800
commit4fa54b075c4507901fd3750e8fc7834cf7e9c809 (patch)
tree3e9ef13a3c3db1035115d7bf1ddee98577c7b0aa /lib/compress.js
parentab82be82b28c8fed0643569700d9b5ff2f093aea (diff)
downloadtracifyjs-4fa54b075c4507901fd3750e8fc7834cf7e9c809.tar.gz
tracifyjs-4fa54b075c4507901fd3750e8fc7834cf7e9c809.zip
enhance `reduce_vars` (#4392)
Diffstat (limited to 'lib/compress.js')
-rw-r--r--lib/compress.js115
1 files changed, 56 insertions, 59 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 8fe0ad62..fa59ef5e 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -672,6 +672,53 @@ merge(Compressor.prototype, {
return true;
}
+ function reduce_iife(tw, descend, compressor) {
+ var fn = this;
+ fn.inlined = false;
+ var iife = tw.parent();
+ var hit = fn instanceof AST_AsyncFunction;
+ var aborts = false;
+ fn.walk(new TreeWalker(function(node) {
+ if (hit) return aborts = true;
+ if (node instanceof AST_Return) return hit = true;
+ if (node instanceof AST_Scope && node !== fn) return true;
+ }));
+ if (aborts) push(tw);
+ reset_variables(tw, compressor, fn);
+ // Virtually turn IIFE parameters into variable definitions:
+ // (function(a,b) {...})(c,d) => (function() {var a=c,b=d; ...})()
+ // So existing transformation rules can work on them.
+ var safe = !fn.uses_arguments || tw.has_directive("use strict");
+ fn.argnames.forEach(function(arg, i) {
+ var value = iife.args[i];
+ scan_declaration(tw, arg, function() {
+ var j = fn.argnames.indexOf(arg);
+ return (j < 0 ? value : iife.args[j]) || make_node(AST_Undefined, iife);
+ }, function(node, fixed) {
+ var d = node.definition();
+ if (safe && d.fixed === undefined) {
+ mark(tw, d);
+ tw.loop_ids[d.id] = tw.in_loop;
+ var value = iife.args[i];
+ d.fixed = fixed;
+ d.fixed.assigns = [ arg ];
+ } else {
+ d.fixed = false;
+ }
+ });
+ });
+ if (fn instanceof AST_Arrow && fn.value) {
+ fn.value.walk(tw);
+ } else {
+ walk_body(fn, tw);
+ }
+ var safe_ids = tw.safe_ids;
+ pop(tw);
+ walk_defuns(tw, fn);
+ if (!aborts) tw.safe_ids = safe_ids;
+ return true;
+ }
+
def(AST_Assign, function(tw, descend, compressor) {
var node = this;
var left = node.left;
@@ -771,10 +818,14 @@ merge(Compressor.prototype, {
tw.find_parent(AST_Scope).may_call_this();
var exp = this.expression;
if (is_function(exp)) {
+ var iife = !exp.name;
this.args.forEach(function(arg) {
arg.walk(tw);
+ if (arg instanceof AST_Spread) iife = false;
});
+ if (iife) exp.reduce_vars = reduce_iife;
exp.walk(tw);
+ if (iife) delete exp.reduce_vars;
return true;
} else if (exp instanceof AST_SymbolRef) {
var def = exp.definition();
@@ -861,62 +912,6 @@ merge(Compressor.prototype, {
tw.in_loop = saved_loop;
return true;
});
- def(AST_Function, function(tw, descend, compressor) {
- var fn = this;
- fn.inlined = false;
- var iife;
- if (!fn.name
- && (iife = tw.parent()) instanceof AST_Call
- && iife.expression === fn
- && all(iife.args, function(arg) {
- return !(arg instanceof AST_Spread);
- })) {
- var hit = false;
- var aborts = false;
- fn.walk(new TreeWalker(function(node) {
- if (hit) return aborts = true;
- if (node instanceof AST_Return) return hit = true;
- if (node instanceof AST_Scope && node !== fn) return true;
- }));
- if (aborts) push(tw);
- reset_variables(tw, compressor, fn);
- // Virtually turn IIFE parameters into variable definitions:
- // (function(a,b) {...})(c,d) => (function() {var a=c,b=d; ...})()
- // So existing transformation rules can work on them.
- var safe = !fn.uses_arguments || tw.has_directive("use strict");
- fn.argnames.forEach(function(arg, i) {
- var value = iife.args[i];
- scan_declaration(tw, arg, function() {
- var j = fn.argnames.indexOf(arg);
- return (j < 0 ? value : iife.args[j]) || make_node(AST_Undefined, iife);
- }, function(node, fixed) {
- var d = node.definition();
- if (safe && d.fixed === undefined) {
- mark(tw, d);
- tw.loop_ids[d.id] = tw.in_loop;
- var value = iife.args[i];
- d.fixed = fixed;
- d.fixed.assigns = [ arg ];
- } else {
- d.fixed = false;
- }
- });
- });
- walk_body(fn, tw);
- var safe_ids = tw.safe_ids;
- pop(tw);
- walk_defuns(tw, fn);
- if (!aborts) tw.safe_ids = safe_ids;
- } else {
- push(tw);
- reset_variables(tw, compressor, fn);
- descend();
- pop(tw);
- if (fn.name) mark_escaped(tw, fn.name.definition(), fn, fn.name, fn, 0, 1);
- walk_defuns(tw, fn);
- }
- return true;
- });
def(AST_If, function(tw) {
this.condition.walk(tw);
push(tw);
@@ -936,12 +931,14 @@ merge(Compressor.prototype, {
return true;
});
def(AST_Lambda, function(tw, descend, compressor) {
- this.inlined = false;
+ var fn = this;
+ fn.inlined = false;
push(tw);
- reset_variables(tw, compressor, this);
+ reset_variables(tw, compressor, fn);
descend();
pop(tw);
- walk_defuns(tw, this);
+ if (fn.name) mark_escaped(tw, fn.name.definition(), fn, fn.name, fn, 0, 1);
+ walk_defuns(tw, fn);
return true;
});
def(AST_Switch, function(tw, descend, compressor) {