Skip to content

Commit

Permalink
enhance arrows
Browse files Browse the repository at this point in the history
  • Loading branch information
alexlamsl committed Aug 25, 2024
1 parent cf87290 commit 21df344
Show file tree
Hide file tree
Showing 2 changed files with 203 additions and 20 deletions.
85 changes: 65 additions & 20 deletions lib/compress.js
Original file line number Diff line number Diff line change
Expand Up @@ -2143,12 +2143,16 @@ Compressor.prototype.compress = function(node) {
if (sequencesize_2(statements, compressor)) changed = 7;
if (!changed && last_changed == 7) break;
}
if (compressor.option("join_vars")) {
if (join_consecutive_vars(statements)) changed = 8;
if (compressor.option("arrows") && compressor.option("module")) {
if (arrowify(statements)) changed = 8;
if (!changed && last_changed == 8) break;
}
if (compressor.option("join_vars")) {
if (join_consecutive_vars(statements)) changed = 9;
if (!changed && last_changed == 9) break;
}
if (compressor.option("collapse_vars")) {
if (collapse(statements, compressor)) changed = 9;
if (collapse(statements, compressor)) changed = 10;
}
} while (changed && max_iter-- > 0);
return statements;
Expand Down Expand Up @@ -4253,6 +4257,48 @@ Compressor.prototype.compress = function(node) {
}
}

function arrowify(statements) {
var changed = false, defns = [], len = 0;
statements.forEach(function(stat) {
var def;
if ((stat instanceof AST_AsyncDefun || stat instanceof AST_Defun)
&& !stat.uses_arguments
&& !stat.pinned()
&& (def = stat.name.definition()).escaped
&& def.escaped.depth != 1
&& !compressor.exposed(def)
&& !stat.contains_this()) {
var name = make_node(AST_SymbolVar, stat.name);
var arrow = make_node(is_async(stat) ? AST_AsyncArrow : AST_Arrow, stat);
arrow.init_vars(stat.parent_scope, stat);
arrow.variables.del("arguments");
var defn = make_node(AST_VarDef, stat, {
name: name,
value: arrow,
});
defns.push(defn);
def.orig.push(name);
def.eliminated++;
if (def.fixed) {
var fixed = function() {
return defn.value;
};
fixed.assigns = [ defn ];
if (def.fixed === stat) def.fixed = fixed;
def.references.forEach(function(node) {
if (node.fixed === stat) node.fixed = fixed;
});
}
changed = true;
} else {
statements[len++] = stat;
}
});
statements.length = len;
if (defns.length > 0) statements.unshift(make_node(AST_Var, compressor.self(), { definitions: defns }));
return changed;
}

function extract_exprs(body) {
if (body instanceof AST_Assign) return [ body ];
if (body instanceof AST_Sequence) return body.expressions.slice();
Expand Down Expand Up @@ -11139,7 +11185,7 @@ Compressor.prototype.compress = function(node) {
&& !exp.uses_arguments
&& !exp.pinned()
&& !exp.contains_this()) {
var arrow = make_node(is_async(exp) ? AST_AsyncArrow : AST_Arrow, exp, exp);
var arrow = make_node(is_async(exp) ? AST_AsyncArrow : AST_Arrow, exp);
arrow.init_vars(exp.parent_scope, exp);
arrow.variables.del("arguments");
self.expression = arrow.transform(compressor);
Expand Down Expand Up @@ -12808,50 +12854,49 @@ Compressor.prototype.compress = function(node) {
var value;
if (def.recursive_refs > 0) {
value = fixed.clone(true);
var defun_def = value.name.definition();
var lambda_def = value.variables.get(value.name.name);
var lambda_def = value.variables.get(self.name);
var name = lambda_def && lambda_def.orig[0];
var def_fn_name, symbol_type;
if (value instanceof AST_Class) {
def_fn_name = "def_function";
symbol_type = AST_SymbolClass;
} else {
def_fn_name = "def_variable";
symbol_type = AST_SymbolLambda;
symbol_type = value.name ? AST_SymbolLambda : AST_SymbolVar;
}
if (!(name instanceof symbol_type)) {
name = make_node(symbol_type, value.name);
name.scope = value;
value.name = name;
if (value.name) value.name = name;
lambda_def = value[def_fn_name](name);
lambda_def.recursive_refs = def.recursive_refs;
}
value.walk(new TreeWalker(function(node) {
if (node instanceof AST_SymbolDeclaration) {
if (node !== name) {
var def = node.definition();
def.orig.push(node);
def.eliminated++;
var d = node.definition();
d.orig.push(node);
d.eliminated++;
}
return;
}
if (!(node instanceof AST_SymbolRef)) return;
var def = node.definition();
if (def === defun_def) {
node.thedef = def = lambda_def;
var d = node.definition();
if (d === def) {
node.thedef = d = lambda_def;
} else {
def.single_use = false;
d.single_use = false;
var fn = node.fixed_value();
if (is_lambda(fn)
&& fn.name
&& fn.name.definition() === def
&& def.scope === fn.name.scope
&& fixed.variables.get(fn.name.name) === def) {
&& fn.name.definition() === d
&& d.scope === fn.name.scope
&& fixed.variables.get(fn.name.name) === d) {
fn.name = fn.name.clone();
node.thedef = def = value.variables.get(fn.name.name) || value[def_fn_name](fn.name);
node.thedef = d = value.variables.get(fn.name.name) || value[def_fn_name](fn.name);
}
}
def.references.push(node);
d.references.push(node);
}));
} else {
if (fixed instanceof AST_Scope) {
Expand Down
138 changes: 138 additions & 0 deletions test/compress/arrows.js
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,144 @@ keep_new_var: {
node_version: ">=4"
}

arrowify: {
options = {
arrows: true,
module: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f() {
return "foo";
}
console.log(typeof f());
}
expect: {
console.log(typeof (() => "foo")());
}
expect_stdout: "string"
node_version: ">=4"
}

no_arrowify: {
options = {
arrows: true,
module: true,
reduce_vars: true,
toplevel: false,
unused: true,
}
input: {
// may be referenced by prepending code
function f() {
return "foo";
}
console.log(typeof f());
}
expect: {
function f() {
return "foo";
}
console.log(typeof f());
}
expect_stdout: "string"
}

no_arrowify_new: {
options = {
arrows: true,
module: true,
reduce_vars: true,
toplevel: true,
}
input: {
function f() {}
console.log(typeof new f(f));
}
expect: {
function f() {}
console.log(typeof new f(f));
}
expect_stdout: "object"
}

arrowify_new: {
options = {
arrows: true,
module: true,
passes: 2,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function f() {
console.log("PASS");
}
new f(f);
}
expect: {
(() => {
console.log("PASS");
})();
}
expect_stdout: "PASS"
node_version: ">=4"
}

arrowify_recursive: {
options = {
arrows: true,
inline: true,
module: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f() {
return (() => f)();
}
console.log(typeof f());
}
expect: {
var f = () => f;
console.log(typeof f);
}
expect_stdout: "function"
node_version: ">=4"
}

arrowify_farg: {
options = {
arrows: true,
module: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f(a) {
console.log(a);
}
f("PASS");
function g() {}
f;
}
expect: {
var f = a => {
console.log(a);
};
f("PASS");
f;
}
expect_stdout: "PASS"
node_version: ">=4"
}

issue_4388: {
options = {
inline: true,
Expand Down

0 comments on commit 21df344

Please sign in to comment.