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

View File

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

View File

@@ -1130,6 +1130,130 @@ default_init: {
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: {
options = {
functions: true,

View File

@@ -41,6 +41,11 @@ rm -rf tmp/buble \
@@ -309 +309 @@ export default class BlockStatement extends Node {
- let cont = false; // 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
ERR=$?; if [ "$ERR" != "0" ]; then echo "Error: $ERR"; exit $ERR; fi
minify_in_situ "src" \