Skip to content

Commit 21df344

Browse files
committed
enhance arrows
1 parent cf87290 commit 21df344

File tree

2 files changed

+203
-20
lines changed

2 files changed

+203
-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;
@@ -4253,6 +4257,48 @@ Compressor.prototype.compress = function(node) {
42534257
}
42544258
}
42554259

4260+
function arrowify(statements) {
4261+
var changed = false, defns = [], len = 0;
4262+
statements.forEach(function(stat) {
4263+
var def;
4264+
if ((stat instanceof AST_AsyncDefun || stat instanceof AST_Defun)
4265+
&& !stat.uses_arguments
4266+
&& !stat.pinned()
4267+
&& (def = stat.name.definition()).escaped
4268+
&& def.escaped.depth != 1
4269+
&& !compressor.exposed(def)
4270+
&& !stat.contains_this()) {
4271+
var name = make_node(AST_SymbolVar, stat.name);
4272+
var arrow = make_node(is_async(stat) ? AST_AsyncArrow : AST_Arrow, stat);
4273+
arrow.init_vars(stat.parent_scope, stat);
4274+
arrow.variables.del("arguments");
4275+
var defn = make_node(AST_VarDef, stat, {
4276+
name: name,
4277+
value: arrow,
4278+
});
4279+
defns.push(defn);
4280+
def.orig.push(name);
4281+
def.eliminated++;
4282+
if (def.fixed) {
4283+
var fixed = function() {
4284+
return defn.value;
4285+
};
4286+
fixed.assigns = [ defn ];
4287+
if (def.fixed === stat) def.fixed = fixed;
4288+
def.references.forEach(function(node) {
4289+
if (node.fixed === stat) node.fixed = fixed;
4290+
});
4291+
}
4292+
changed = true;
4293+
} else {
4294+
statements[len++] = stat;
4295+
}
4296+
});
4297+
statements.length = len;
4298+
if (defns.length > 0) statements.unshift(make_node(AST_Var, compressor.self(), { definitions: defns }));
4299+
return changed;
4300+
}
4301+
42564302
function extract_exprs(body) {
42574303
if (body instanceof AST_Assign) return [ body ];
42584304
if (body instanceof AST_Sequence) return body.expressions.slice();
@@ -11139,7 +11185,7 @@ Compressor.prototype.compress = function(node) {
1113911185
&& !exp.uses_arguments
1114011186
&& !exp.pinned()
1114111187
&& !exp.contains_this()) {
11142-
var arrow = make_node(is_async(exp) ? AST_AsyncArrow : AST_Arrow, exp, exp);
11188+
var arrow = make_node(is_async(exp) ? AST_AsyncArrow : AST_Arrow, exp);
1114311189
arrow.init_vars(exp.parent_scope, exp);
1114411190
arrow.variables.del("arguments");
1114511191
self.expression = arrow.transform(compressor);
@@ -12808,50 +12854,49 @@ Compressor.prototype.compress = function(node) {
1280812854
var value;
1280912855
if (def.recursive_refs > 0) {
1281012856
value = fixed.clone(true);
12811-
var defun_def = value.name.definition();
12812-
var lambda_def = value.variables.get(value.name.name);
12857+
var lambda_def = value.variables.get(self.name);
1281312858
var name = lambda_def && lambda_def.orig[0];
1281412859
var def_fn_name, symbol_type;
1281512860
if (value instanceof AST_Class) {
1281612861
def_fn_name = "def_function";
1281712862
symbol_type = AST_SymbolClass;
1281812863
} else {
1281912864
def_fn_name = "def_variable";
12820-
symbol_type = AST_SymbolLambda;
12865+
symbol_type = value.name ? AST_SymbolLambda : AST_SymbolVar;
1282112866
}
1282212867
if (!(name instanceof symbol_type)) {
1282312868
name = make_node(symbol_type, value.name);
1282412869
name.scope = value;
12825-
value.name = name;
12870+
if (value.name) value.name = name;
1282612871
lambda_def = value[def_fn_name](name);
1282712872
lambda_def.recursive_refs = def.recursive_refs;
1282812873
}
1282912874
value.walk(new TreeWalker(function(node) {
1283012875
if (node instanceof AST_SymbolDeclaration) {
1283112876
if (node !== name) {
12832-
var def = node.definition();
12833-
def.orig.push(node);
12834-
def.eliminated++;
12877+
var d = node.definition();
12878+
d.orig.push(node);
12879+
d.eliminated++;
1283512880
}
1283612881
return;
1283712882
}
1283812883
if (!(node instanceof AST_SymbolRef)) return;
12839-
var def = node.definition();
12840-
if (def === defun_def) {
12841-
node.thedef = def = lambda_def;
12884+
var d = node.definition();
12885+
if (d === def) {
12886+
node.thedef = d = lambda_def;
1284212887
} else {
12843-
def.single_use = false;
12888+
d.single_use = false;
1284412889
var fn = node.fixed_value();
1284512890
if (is_lambda(fn)
1284612891
&& fn.name
12847-
&& fn.name.definition() === def
12848-
&& def.scope === fn.name.scope
12849-
&& fixed.variables.get(fn.name.name) === def) {
12892+
&& fn.name.definition() === d
12893+
&& d.scope === fn.name.scope
12894+
&& fixed.variables.get(fn.name.name) === d) {
1285012895
fn.name = fn.name.clone();
12851-
node.thedef = def = value.variables.get(fn.name.name) || value[def_fn_name](fn.name);
12896+
node.thedef = d = value.variables.get(fn.name.name) || value[def_fn_name](fn.name);
1285212897
}
1285312898
}
12854-
def.references.push(node);
12899+
d.references.push(node);
1285512900
}));
1285612901
} else {
1285712902
if (fixed instanceof AST_Scope) {

test/compress/arrows.js

+138
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,144 @@ 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+
node_version: ">=4"
918+
}
919+
920+
arrowify_recursive: {
921+
options = {
922+
arrows: true,
923+
inline: true,
924+
module: true,
925+
reduce_vars: true,
926+
toplevel: true,
927+
unused: true,
928+
}
929+
input: {
930+
function f() {
931+
return (() => f)();
932+
}
933+
console.log(typeof f());
934+
}
935+
expect: {
936+
var f = () => f;
937+
console.log(typeof f);
938+
}
939+
expect_stdout: "function"
940+
node_version: ">=4"
941+
}
942+
943+
arrowify_farg: {
944+
options = {
945+
arrows: true,
946+
module: true,
947+
reduce_vars: true,
948+
toplevel: true,
949+
unused: true,
950+
}
951+
input: {
952+
function f(a) {
953+
console.log(a);
954+
}
955+
f("PASS");
956+
function g() {}
957+
f;
958+
}
959+
expect: {
960+
var f = a => {
961+
console.log(a);
962+
};
963+
f("PASS");
964+
f;
965+
}
966+
expect_stdout: "PASS"
967+
node_version: ">=4"
968+
}
969+
832970
issue_4388: {
833971
options = {
834972
inline: true,

0 commit comments

Comments
 (0)