Skip to content

Commit 643a49e

Browse files
committed
enhance arrows
1 parent cf87290 commit 643a49e

File tree

3 files changed

+251
-20
lines changed

3 files changed

+251
-20
lines changed

lib/compress.js

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ Compressor.prototype.compress = function(node) {
507507
if (parent instanceof AST_Call) return parent.expression !== node || parent instanceof AST_New;
508508
if (parent instanceof AST_ClassField) return parent.value === node && !parent.static;
509509
if (parent instanceof AST_Exit) return parent.value === node && scope.resolve() !== d.scope.resolve();
510+
if (parent instanceof AST_ExportReferences) return true;
510511
if (parent instanceof AST_VarDef) return parent.value === node;
511512
}
512513

@@ -2143,12 +2144,16 @@ Compressor.prototype.compress = function(node) {
21432144
if (sequencesize_2(statements, compressor)) changed = 7;
21442145
if (!changed && last_changed == 7) break;
21452146
}
2146-
if (compressor.option("join_vars")) {
2147-
if (join_consecutive_vars(statements)) changed = 8;
2147+
if (compressor.option("arrows") && compressor.option("module")) {
2148+
if (arrowify(statements)) changed = 8;
21482149
if (!changed && last_changed == 8) break;
21492150
}
2151+
if (compressor.option("join_vars")) {
2152+
if (join_consecutive_vars(statements)) changed = 9;
2153+
if (!changed && last_changed == 9) break;
2154+
}
21502155
if (compressor.option("collapse_vars")) {
2151-
if (collapse(statements, compressor)) changed = 9;
2156+
if (collapse(statements, compressor)) changed = 10;
21522157
}
21532158
} while (changed && max_iter-- > 0);
21542159
return statements;
@@ -4253,6 +4258,48 @@ Compressor.prototype.compress = function(node) {
42534258
}
42544259
}
42554260

4261+
function arrowify(statements) {
4262+
var changed = false, defns = [], len = 0;
4263+
statements.forEach(function(stat) {
4264+
var def;
4265+
if ((stat instanceof AST_AsyncDefun || stat instanceof AST_Defun)
4266+
&& !stat.uses_arguments
4267+
&& !stat.pinned()
4268+
&& (def = stat.name.definition()).escaped
4269+
&& def.escaped.depth != 1
4270+
&& !compressor.exposed(def)
4271+
&& !stat.contains_this()) {
4272+
var name = make_node(AST_SymbolVar, stat.name);
4273+
var arrow = make_node(is_async(stat) ? AST_AsyncArrow : AST_Arrow, stat);
4274+
arrow.init_vars(stat.parent_scope, stat);
4275+
arrow.variables.del("arguments");
4276+
var defn = make_node(AST_VarDef, stat, {
4277+
name: name,
4278+
value: arrow,
4279+
});
4280+
defns.push(defn);
4281+
def.orig.push(name);
4282+
def.eliminated++;
4283+
if (def.fixed) {
4284+
var fixed = function() {
4285+
return defn.value;
4286+
};
4287+
fixed.assigns = [ defn ];
4288+
if (def.fixed === stat) def.fixed = fixed;
4289+
def.references.forEach(function(node) {
4290+
if (node.fixed === stat) node.fixed = fixed;
4291+
});
4292+
}
4293+
changed = true;
4294+
} else {
4295+
statements[len++] = stat;
4296+
}
4297+
});
4298+
statements.length = len;
4299+
if (defns.length > 0) statements.unshift(make_node(AST_Var, compressor.self(), { definitions: defns }));
4300+
return changed;
4301+
}
4302+
42564303
function extract_exprs(body) {
42574304
if (body instanceof AST_Assign) return [ body ];
42584305
if (body instanceof AST_Sequence) return body.expressions.slice();
@@ -11139,7 +11186,7 @@ Compressor.prototype.compress = function(node) {
1113911186
&& !exp.uses_arguments
1114011187
&& !exp.pinned()
1114111188
&& !exp.contains_this()) {
11142-
var arrow = make_node(is_async(exp) ? AST_AsyncArrow : AST_Arrow, exp, exp);
11189+
var arrow = make_node(is_async(exp) ? AST_AsyncArrow : AST_Arrow, exp);
1114311190
arrow.init_vars(exp.parent_scope, exp);
1114411191
arrow.variables.del("arguments");
1114511192
self.expression = arrow.transform(compressor);
@@ -12808,50 +12855,49 @@ Compressor.prototype.compress = function(node) {
1280812855
var value;
1280912856
if (def.recursive_refs > 0) {
1281012857
value = fixed.clone(true);
12811-
var defun_def = value.name.definition();
12812-
var lambda_def = value.variables.get(value.name.name);
12858+
var lambda_def = value.variables.get(self.name);
1281312859
var name = lambda_def && lambda_def.orig[0];
1281412860
var def_fn_name, symbol_type;
1281512861
if (value instanceof AST_Class) {
1281612862
def_fn_name = "def_function";
1281712863
symbol_type = AST_SymbolClass;
1281812864
} else {
1281912865
def_fn_name = "def_variable";
12820-
symbol_type = AST_SymbolLambda;
12866+
symbol_type = value.name ? AST_SymbolLambda : AST_SymbolVar;
1282112867
}
1282212868
if (!(name instanceof symbol_type)) {
1282312869
name = make_node(symbol_type, value.name);
1282412870
name.scope = value;
12825-
value.name = name;
12871+
if (value.name) value.name = name;
1282612872
lambda_def = value[def_fn_name](name);
1282712873
lambda_def.recursive_refs = def.recursive_refs;
1282812874
}
1282912875
value.walk(new TreeWalker(function(node) {
1283012876
if (node instanceof AST_SymbolDeclaration) {
1283112877
if (node !== name) {
12832-
var def = node.definition();
12833-
def.orig.push(node);
12834-
def.eliminated++;
12878+
var d = node.definition();
12879+
d.orig.push(node);
12880+
d.eliminated++;
1283512881
}
1283612882
return;
1283712883
}
1283812884
if (!(node instanceof AST_SymbolRef)) return;
12839-
var def = node.definition();
12840-
if (def === defun_def) {
12841-
node.thedef = def = lambda_def;
12885+
var d = node.definition();
12886+
if (d === def) {
12887+
node.thedef = d = lambda_def;
1284212888
} else {
12843-
def.single_use = false;
12889+
d.single_use = false;
1284412890
var fn = node.fixed_value();
1284512891
if (is_lambda(fn)
1284612892
&& fn.name
12847-
&& fn.name.definition() === def
12848-
&& def.scope === fn.name.scope
12849-
&& fixed.variables.get(fn.name.name) === def) {
12893+
&& fn.name.definition() === d
12894+
&& d.scope === fn.name.scope
12895+
&& fixed.variables.get(fn.name.name) === d) {
1285012896
fn.name = fn.name.clone();
12851-
node.thedef = def = value.variables.get(fn.name.name) || value[def_fn_name](fn.name);
12897+
node.thedef = d = value.variables.get(fn.name.name) || value[def_fn_name](fn.name);
1285212898
}
1285312899
}
12854-
def.references.push(node);
12900+
d.references.push(node);
1285512901
}));
1285612902
} else {
1285712903
if (fixed instanceof AST_Scope) {

test/compress/arrows.js

Lines changed: 138 additions & 0 deletions
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,

test/compress/exports.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,53 @@ instanceof_default_function: {
468468
}
469469
}
470470

471+
no_arrowify_declaration: {
472+
options = {
473+
arrows: true,
474+
module: true,
475+
reduce_vars: true,
476+
toplevel: true,
477+
}
478+
input: {
479+
export function f() {}
480+
}
481+
expect: {
482+
export function f() {}
483+
}
484+
}
485+
486+
no_arrowify_default: {
487+
options = {
488+
arrows: true,
489+
module: true,
490+
reduce_vars: true,
491+
toplevel: true,
492+
}
493+
input: {
494+
export default function f() {}
495+
}
496+
expect: {
497+
export default function f() {}
498+
}
499+
}
500+
501+
no_arrowify_reference: {
502+
options = {
503+
arrows: true,
504+
module: true,
505+
reduce_vars: true,
506+
toplevel: true,
507+
}
508+
input: {
509+
function f() {}
510+
export { f };
511+
}
512+
expect: {
513+
function f() {}
514+
export { f };
515+
}
516+
}
517+
471518
issue_4742_join_vars_1: {
472519
options = {
473520
join_vars: true,

0 commit comments

Comments
 (0)