enhance join_vars (#5739)
This commit is contained in:
@@ -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) {
|
||||
(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(stat.definitions, function(defn) {
|
||||
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) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
require("../tools/tty");
|
||||
var createHash = require("crypto").createHash;
|
||||
var fetch = require("./fetch");
|
||||
var spawn = require("child_process").spawn;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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" \
|
||||
|
||||
Reference in New Issue
Block a user