enhance join_vars (#5739)

This commit is contained in:
Alex Lam S.L
2022-11-22 17:57:16 +00:00
committed by GitHub
parent 68d62a8a31
commit e5cbd3e0f3
4 changed files with 195 additions and 26 deletions

View File

@@ -487,7 +487,7 @@ Compressor.prototype.compress = function(node) {
return all(def.orig, function(sym) { return all(def.orig, function(sym) {
if (sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet) { if (sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet) {
if (sym instanceof AST_SymbolImport) return true; if (sym instanceof AST_SymbolImport) return true;
return compressor && can_varify(compressor, sym); return compressor && safe_from_tdz(compressor, sym);
} }
return !(keep_lambda && sym instanceof AST_SymbolLambda); return !(keep_lambda && sym instanceof AST_SymbolLambda);
}); });
@@ -525,10 +525,11 @@ Compressor.prototype.compress = function(node) {
function reset_def(tw, compressor, def) { function reset_def(tw, compressor, def) {
def.assignments = 0; def.assignments = 0;
def.bool_return = 0; def.bool_return = 0;
def.drop_return = 0;
def.cross_loop = false; def.cross_loop = false;
def.direct_access = false; def.direct_access = false;
def.drop_return = 0;
def.escaped = []; def.escaped = [];
def.first_decl = null;
def.fixed = !def.const_redefs def.fixed = !def.const_redefs
&& !def.scope.pinned() && !def.scope.pinned()
&& !compressor.exposed(def) && !compressor.exposed(def)
@@ -951,6 +952,7 @@ Compressor.prototype.compress = function(node) {
function visit(node, fixed) { function visit(node, fixed) {
var d = node.definition(); var d = node.definition();
if (!d.first_decl && d.references.length == 0) d.first_decl = node;
if (fixed && safe && d.fixed === undefined) { if (fixed && safe && d.fixed === undefined) {
mark(tw, d); mark(tw, d);
tw.loop_ids[d.id] = tw.in_loop; tw.loop_ids[d.id] = tw.in_loop;
@@ -1371,10 +1373,18 @@ Compressor.prototype.compress = function(node) {
return true; return true;
}); });
def(AST_SymbolCatch, function() { def(AST_SymbolCatch, function() {
this.definition().fixed = false; var d = this.definition();
if (!d.first_decl && d.references.length == 0) d.first_decl = this;
d.fixed = false;
});
def(AST_SymbolDeclaration, function() {
var d = this.definition();
if (!d.first_decl && d.references.length == 0) d.first_decl = this;
}); });
def(AST_SymbolImport, function() { def(AST_SymbolImport, function() {
this.definition().fixed = false; var d = this.definition();
d.first_decl = this;
d.fixed = false;
}); });
def(AST_SymbolRef, function(tw, descend, compressor) { def(AST_SymbolRef, function(tw, descend, compressor) {
var ref = this; var ref = this;
@@ -1558,6 +1568,8 @@ Compressor.prototype.compress = function(node) {
walk_defn(); walk_defn();
} else if (tw.parent() instanceof AST_Let) { } else if (tw.parent() instanceof AST_Let) {
walk_defn(); walk_defn();
} else {
node.name.walk(tw);
} }
return true; return true;
@@ -1566,6 +1578,7 @@ Compressor.prototype.compress = function(node) {
return node.value || make_node(AST_Undefined, node); return node.value || make_node(AST_Undefined, node);
}, function(name, fixed) { }, function(name, fixed) {
var d = name.definition(); var d = name.definition();
if (!d.first_decl && d.references.length == 0) d.first_decl = name;
if (fixed && safe_to_assign(tw, d, true)) { if (fixed && safe_to_assign(tw, d, true)) {
mark(tw, d); mark(tw, d);
tw.loop_ids[d.id] = tw.in_loop; tw.loop_ids[d.id] = tw.in_loop;
@@ -4249,7 +4262,7 @@ Compressor.prototype.compress = function(node) {
} }
function join_consecutive_vars(statements) { function join_consecutive_vars(statements) {
var changed = false, defs; var changed = false, defs, prev_defs;
for (var i = 0, j = -1; i < statements.length; i++) { for (var i = 0, j = -1; i < statements.length; i++) {
var stat = statements[i]; var stat = statements[i];
var prev = statements[j]; var prev = statements[j];
@@ -4257,6 +4270,14 @@ Compressor.prototype.compress = function(node) {
if (prev && prev.TYPE == stat.TYPE) { if (prev && prev.TYPE == stat.TYPE) {
prev.definitions = prev.definitions.concat(stat.definitions); prev.definitions = prev.definitions.concat(stat.definitions);
changed = true; changed = true;
} else if (stat && prev instanceof AST_Let && stat.can_letify(compressor)) {
prev.definitions = prev.definitions.concat(to_let(stat).definitions);
changed = true;
} else if (prev && stat instanceof AST_Let && prev.can_letify(compressor)) {
defs = prev_defs;
statements[j] = prev = to_let(prev);
prev.definitions = prev.definitions.concat(stat.definitions);
changed = true;
} else if (defs && defs.TYPE == stat.TYPE && declarations_only(stat)) { } else if (defs && defs.TYPE == stat.TYPE && declarations_only(stat)) {
defs.definitions = defs.definitions.concat(stat.definitions); defs.definitions = defs.definitions.concat(stat.definitions);
changed = true; changed = true;
@@ -4271,6 +4292,7 @@ Compressor.prototype.compress = function(node) {
} else { } else {
j++; j++;
} }
prev_defs = defs;
statements[j] = defs = stat; statements[j] = defs = stat;
} else { } else {
statements[++j] = stat; statements[++j] = stat;
@@ -4288,6 +4310,7 @@ Compressor.prototype.compress = function(node) {
prev.definitions = prev.definitions.concat(stat.init.definitions); prev.definitions = prev.definitions.concat(stat.init.definitions);
} }
stat = stat.clone(); stat = stat.clone();
prev_defs = defs;
defs = stat.init = prev; defs = stat.init = prev;
statements[j] = merge_defns(stat); statements[j] = merge_defns(stat);
changed = true; changed = true;
@@ -4297,6 +4320,7 @@ Compressor.prototype.compress = function(node) {
stat.init = null; stat.init = null;
changed = true; changed = true;
} else if (stat.init instanceof AST_Var) { } else if (stat.init instanceof AST_Var) {
prev_defs = defs;
defs = stat.init; defs = stat.init;
exprs = merge_assigns(prev, stat.init); exprs = merge_assigns(prev, stat.init);
if (exprs) { if (exprs) {
@@ -9365,7 +9389,7 @@ Compressor.prototype.compress = function(node) {
} }
}, true)) { }, true)) {
self.init = to_var(self.init, self.resolve()); self.init = to_var(self.init, self.resolve());
} else if (can_letify(self.init, compressor, 1)) { } else if (self.init.can_letify(compressor, true)) {
self.init = to_let(self.init); self.init = to_let(self.init);
} }
} }
@@ -10213,19 +10237,34 @@ Compressor.prototype.compress = function(node) {
}); });
} }
function can_letify(stat, compressor, assigned) { (function(def) {
if (!(stat instanceof AST_Const)) return false; def(AST_Node, return_false);
if (!compressor.option("module") && all(stat.definitions, function(defn) { def(AST_Const, function(compressor, assigned) {
return defn.name instanceof AST_SymbolConst; assigned = assigned ? 1 : 0;
})) return false; var defns = this.definitions;
return all(stat.definitions, function(defn) { if (!compressor.option("module") && all(defns, function(defn) {
return !defn.name.match_symbol(function(node) { return defn.name instanceof AST_SymbolConst;
if (node instanceof AST_SymbolDeclaration) return node.definition().assignments != assigned; })) return false;
}, true); return all(defns, function(defn) {
return !defn.name.match_symbol(function(node) {
if (node instanceof AST_SymbolDeclaration) return node.definition().assignments != assigned;
}, true);
});
}); });
} def(AST_Var, function(compressor) {
return all(this.definitions, function(defn) {
return !defn.name.match_symbol(function(node) {
if (!(node instanceof AST_SymbolDeclaration)) return false;
if (node.definition().first_decl !== node) return true;
return !safe_from_tdz(compressor, node);
}, true);
});
});
})(function(node, func) {
node.DEFMETHOD("can_letify", func);
});
function can_varify(compressor, sym) { function safe_from_tdz(compressor, sym) {
var def = sym.definition(); var def = sym.definition();
return (def.fixed || def.fixed === 0) return (def.fixed || def.fixed === 0)
&& is_safe_lexical(def) && is_safe_lexical(def)
@@ -10233,25 +10272,25 @@ Compressor.prototype.compress = function(node) {
&& !may_overlap(compressor, def); && !may_overlap(compressor, def);
} }
function varify(self, compressor) { AST_Definitions.DEFMETHOD("can_varify", function(compressor) {
if (all(self.definitions, function(defn) { return all(this.definitions, function(defn) {
return !defn.name.match_symbol(function(node) { return !defn.name.match_symbol(function(node) {
if (node instanceof AST_SymbolDeclaration) return !can_varify(compressor, node); if (node instanceof AST_SymbolDeclaration) return !safe_from_tdz(compressor, node);
}, true); }, true);
})) return to_var(self, compressor.find_parent(AST_Scope)); });
} });
OPT(AST_Const, function(self, compressor) { OPT(AST_Const, function(self, compressor) {
if (!compressor.option("varify")) return self; if (!compressor.option("varify")) return self;
var decl = varify(self, compressor); if (self.can_varify(compressor)) return to_var(self, compressor.find_parent(AST_Scope));
if (decl) return decl; if (self.can_letify(compressor)) return to_let(self);
if (can_letify(self, compressor, 0)) return to_let(self);
return self; return self;
}); });
OPT(AST_Let, function(self, compressor) { OPT(AST_Let, function(self, compressor) {
if (!compressor.option("varify")) return self; if (!compressor.option("varify")) return self;
return varify(self, compressor) || self; if (self.can_varify(compressor)) return to_var(self, compressor.find_parent(AST_Scope));
return self;
}); });
function trim_optional_chain(node, compressor) { function trim_optional_chain(node, compressor) {

View File

@@ -3,6 +3,7 @@
"use strict"; "use strict";
require("../tools/tty");
var createHash = require("crypto").createHash; var createHash = require("crypto").createHash;
var fetch = require("./fetch"); var fetch = require("./fetch");
var spawn = require("child_process").spawn; var spawn = require("child_process").spawn;

View File

@@ -1130,6 +1130,130 @@ default_init: {
node_version: ">=4" node_version: ">=4"
} }
join_let_var_1: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
var a = "foo";
let b = "bar";
for (var c of [ a, b ])
console.log(c);
}
expect: {
"use strict";
let a = "foo", b = "bar";
for (var c of [ a, b ])
console.log(c);
}
expect_stdout: [
"foo",
"bar",
]
node_version: ">=4"
}
join_let_var_2: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
let a = "foo";
var b = "bar";
for (let c of [ a, b ])
console.log(c);
}
expect: {
"use strict";
let a = "foo", b = "bar";
for (let c of [ a, b ])
console.log(c);
}
expect_stdout: [
"foo",
"bar",
]
node_version: ">=4"
}
keep_let_var_1: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
var a = "foo";
let b = "bar";
for (var c of [ a, b ])
console.log(c);
function f() {
return a;
}
console.log(f(f));
}
expect: {
"use strict";
var a = "foo", c;
let b = "bar";
for (c of [ a, b ])
console.log(c);
function f() {
return a;
}
console.log(f(f));
}
expect_stdout: [
"foo",
"bar",
"foo",
]
node_version: ">=4"
}
keep_let_var_2: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
let a = "foo";
var b = "bar";
for (let c of [ a, b ])
console.log(c);
function f() {
return b;
}
console.log(f(f));
}
expect: {
"use strict";
let a = "foo";
var b = "bar";
for (let c of [ a, b ])
console.log(c);
function f() {
return b;
}
console.log(f(f));
}
expect_stdout: [
"foo",
"bar",
"bar",
]
node_version: ">=4"
}
issue_4191: { issue_4191: {
options = { options = {
functions: true, functions: true,

View File

@@ -41,6 +41,11 @@ rm -rf tmp/buble \
@@ -309 +309 @@ export default class BlockStatement extends Node { @@ -309 +309 @@ export default class BlockStatement extends Node {
- let cont = false; // TODO implement proper continue... - let cont = false; // TODO implement proper continue...
+ let cont = !declarations; // TODO implement proper continue... + let cont = !declarations; // TODO implement proper continue...
--- a/src/program/types/VariableDeclaration.js
+++ b/src/program/types/VariableDeclaration.js
@@ -38 +38 @@ export default class VariableDeclaration extends Node {
- code.remove(c, declarator.id.start);
+ code.remove(c, declarator.id.start, lastDeclaratorIsPattern);
EOF EOF
ERR=$?; if [ "$ERR" != "0" ]; then echo "Error: $ERR"; exit $ERR; fi ERR=$?; if [ "$ERR" != "0" ]; then echo "Error: $ERR"; exit $ERR; fi
minify_in_situ "src" \ minify_in_situ "src" \