Skip to content

Commit f4a403f

Browse files
committed
enhance arrows
1 parent 4a92cdc commit f4a403f

File tree

2 files changed

+202
-20
lines changed

2 files changed

+202
-20
lines changed

lib/compress.js

+65-20
Original file line numberDiff line numberDiff line change
@@ -2143,12 +2143,16 @@ Compressor.prototype.compress = function(node) {
21432143
if (sequencesize_2(statements, compressor)) changed = 7;
21442144
if (!changed && last_changed == 7) break;
21452145
}
2146-
if (compressor.option("join_vars")) {
2147-
if (join_consecutive_vars(statements)) changed = 8;
2146+
if (compressor.option("arrows") && compressor.option("module")) {
2147+
if (arrowify(statements)) changed = 8;
21482148
if (!changed && last_changed == 8) break;
21492149
}
2150+
if (compressor.option("join_vars")) {
2151+
if (join_consecutive_vars(statements)) changed = 9;
2152+
if (!changed && last_changed == 9) break;
2153+
}
21502154
if (compressor.option("collapse_vars")) {
2151-
if (collapse(statements, compressor)) changed = 9;
2155+
if (collapse(statements, compressor)) changed = 10;
21522156
}
21532157
} while (changed && max_iter-- > 0);
21542158
return statements;
@@ -4252,6 +4256,48 @@ Compressor.prototype.compress = function(node) {
42524256
}
42534257
}
42544258

4259+
function arrowify(statements) {
4260+
var changed = false, defns = [], len = 0;
4261+
statements.forEach(function(stat) {
4262+
var def;
4263+
if ((stat instanceof AST_AsyncDefun || stat instanceof AST_Defun)
4264+
&& !stat.uses_arguments
4265+
&& !stat.pinned()
4266+
&& (def = stat.name.definition()).escaped
4267+
&& def.escaped.depth != 1
4268+
&& !compressor.exposed(def)
4269+
&& !stat.contains_this()) {
4270+
var name = make_node(AST_SymbolVar, stat.name);
4271+
var arrow = make_node(is_async(stat) ? AST_AsyncArrow : AST_Arrow, stat);
4272+
arrow.init_vars(stat.parent_scope, stat);
4273+
arrow.variables.del("arguments");
4274+
var defn = make_node(AST_VarDef, stat, {
4275+
name: name,
4276+
value: arrow,
4277+
});
4278+
defns.push(defn);
4279+
def.orig.push(name);
4280+
def.eliminated++;
4281+
if (def.fixed) {
4282+
var fixed = function() {
4283+
return defn.value;
4284+
};
4285+
fixed.assigns = [ defn ];
4286+
if (def.fixed === stat) def.fixed = fixed;
4287+
def.references.forEach(function(node) {
4288+
if (node.fixed === stat) node.fixed = fixed;
4289+
});
4290+
}
4291+
changed = true;
4292+
} else {
4293+
statements[len++] = stat;
4294+
}
4295+
});
4296+
statements.length = len;
4297+
if (defns.length > 0) statements.unshift(make_node(AST_Var, compressor.self(), { definitions: defns }));
4298+
return changed;
4299+
}
4300+
42554301
function extract_exprs(body) {
42564302
if (body instanceof AST_Assign) return [ body ];
42574303
if (body instanceof AST_Sequence) return body.expressions.slice();
@@ -11138,7 +11184,7 @@ Compressor.prototype.compress = function(node) {
1113811184
&& !exp.uses_arguments
1113911185
&& !exp.pinned()
1114011186
&& !exp.contains_this()) {
11141-
var arrow = make_node(is_async(exp) ? AST_AsyncArrow : AST_Arrow, exp, exp);
11187+
var arrow = make_node(is_async(exp) ? AST_AsyncArrow : AST_Arrow, exp);
1114211188
arrow.init_vars(exp.parent_scope, exp);
1114311189
arrow.variables.del("arguments");
1114411190
self.expression = arrow.transform(compressor);
@@ -12807,50 +12853,49 @@ Compressor.prototype.compress = function(node) {
1280712853
var value;
1280812854
if (def.recursive_refs > 0) {
1280912855
value = fixed.clone(true);
12810-
var defun_def = value.name.definition();
12811-
var lambda_def = value.variables.get(value.name.name);
12856+
var lambda_def = value.variables.get(self.name);
1281212857
var name = lambda_def && lambda_def.orig[0];
1281312858
var def_fn_name, symbol_type;
1281412859
if (value instanceof AST_Class) {
1281512860
def_fn_name = "def_function";
1281612861
symbol_type = AST_SymbolClass;
1281712862
} else {
1281812863
def_fn_name = "def_variable";
12819-
symbol_type = AST_SymbolLambda;
12864+
symbol_type = value.name ? AST_SymbolLambda : AST_SymbolVar;
1282012865
}
1282112866
if (!(name instanceof symbol_type)) {
1282212867
name = make_node(symbol_type, value.name);
1282312868
name.scope = value;
12824-
value.name = name;
12869+
if (value.name) value.name = name;
1282512870
lambda_def = value[def_fn_name](name);
1282612871
lambda_def.recursive_refs = def.recursive_refs;
1282712872
}
1282812873
value.walk(new TreeWalker(function(node) {
1282912874
if (node instanceof AST_SymbolDeclaration) {
1283012875
if (node !== name) {
12831-
var def = node.definition();
12832-
def.orig.push(node);
12833-
def.eliminated++;
12876+
var d = node.definition();
12877+
d.orig.push(node);
12878+
d.eliminated++;
1283412879
}
1283512880
return;
1283612881
}
1283712882
if (!(node instanceof AST_SymbolRef)) return;
12838-
var def = node.definition();
12839-
if (def === defun_def) {
12840-
node.thedef = def = lambda_def;
12883+
var d = node.definition();
12884+
if (d === def) {
12885+
node.thedef = d = lambda_def;
1284112886
} else {
12842-
def.single_use = false;
12887+
d.single_use = false;
1284312888
var fn = node.fixed_value();
1284412889
if (is_lambda(fn)
1284512890
&& fn.name
12846-
&& fn.name.definition() === def
12847-
&& def.scope === fn.name.scope
12848-
&& fixed.variables.get(fn.name.name) === def) {
12891+
&& fn.name.definition() === d
12892+
&& d.scope === fn.name.scope
12893+
&& fixed.variables.get(fn.name.name) === d) {
1284912894
fn.name = fn.name.clone();
12850-
node.thedef = def = value.variables.get(fn.name.name) || value[def_fn_name](fn.name);
12895+
node.thedef = d = value.variables.get(fn.name.name) || value[def_fn_name](fn.name);
1285112896
}
1285212897
}
12853-
def.references.push(node);
12898+
d.references.push(node);
1285412899
}));
1285512900
} else {
1285612901
if (fixed instanceof AST_Scope) {

test/compress/arrows.js

+137
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,143 @@ keep_new_var: {
829829
node_version: ">=4"
830830
}
831831

832+
arrowify: {
833+
options = {
834+
arrows: true,
835+
module: true,
836+
reduce_vars: true,
837+
toplevel: true,
838+
unused: true,
839+
}
840+
input: {
841+
function f() {
842+
return "foo";
843+
}
844+
console.log(typeof f());
845+
}
846+
expect: {
847+
console.log(typeof (() => "foo")());
848+
}
849+
expect_stdout: "string"
850+
node_version: ">=4"
851+
}
852+
853+
no_arrowify: {
854+
options = {
855+
arrows: true,
856+
module: true,
857+
reduce_vars: true,
858+
toplevel: false,
859+
unused: true,
860+
}
861+
input: {
862+
// may be referenced by prepending code
863+
function f() {
864+
return "foo";
865+
}
866+
console.log(typeof f());
867+
}
868+
expect: {
869+
function f() {
870+
return "foo";
871+
}
872+
console.log(typeof f());
873+
}
874+
expect_stdout: "string"
875+
}
876+
877+
no_arrowify_new: {
878+
options = {
879+
arrows: true,
880+
module: true,
881+
reduce_vars: true,
882+
toplevel: true,
883+
}
884+
input: {
885+
function f() {}
886+
console.log(typeof new f(f));
887+
}
888+
expect: {
889+
function f() {}
890+
console.log(typeof new f(f));
891+
}
892+
expect_stdout: "object"
893+
}
894+
895+
arrowify_new: {
896+
options = {
897+
arrows: true,
898+
module: true,
899+
passes: 2,
900+
reduce_vars: true,
901+
side_effects: true,
902+
toplevel: true,
903+
unused: true,
904+
}
905+
input: {
906+
function f() {
907+
console.log("PASS");
908+
}
909+
new f(f);
910+
}
911+
expect: {
912+
(() => {
913+
console.log("PASS");
914+
})();
915+
}
916+
expect_stdout: "PASS"
917+
}
918+
919+
arrowify_recursive: {
920+
options = {
921+
arrows: true,
922+
inline: true,
923+
module: true,
924+
reduce_vars: true,
925+
toplevel: true,
926+
unused: true,
927+
}
928+
input: {
929+
function f() {
930+
return (() => f)();
931+
}
932+
console.log(typeof f());
933+
}
934+
expect: {
935+
var f = () => f;
936+
console.log(typeof f);
937+
}
938+
expect_stdout: "function"
939+
node_version: ">=4"
940+
}
941+
942+
arrowify_farg: {
943+
options = {
944+
arrows: true,
945+
module: true,
946+
reduce_vars: true,
947+
toplevel: true,
948+
unused: true,
949+
}
950+
input: {
951+
function f(a) {
952+
console.log(a);
953+
}
954+
f("PASS");
955+
function g() {}
956+
f;
957+
}
958+
expect: {
959+
var f = a => {
960+
console.log(a);
961+
};
962+
f("PASS");
963+
f;
964+
}
965+
expect_stdout: "PASS"
966+
node_version: ">=4"
967+
}
968+
832969
issue_4388: {
833970
options = {
834971
inline: true,

0 commit comments

Comments
 (0)