This commit is contained in:
Alex Lam S.L 2018-02-22 16:29:19 +00:00 committed by GitHub
commit e2266ef883
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 274 additions and 0 deletions

View File

@ -75,6 +75,7 @@ function minify(files, options) {
options.mangle = defaults(options.mangle, { options.mangle = defaults(options.mangle, {
cache: options.nameCache && (options.nameCache.vars || {}), cache: options.nameCache && (options.nameCache.vars || {}),
eval: false, eval: false,
group_voids: false,
ie8: false, ie8: false,
keep_fnames: false, keep_fnames: false,
properties: false, properties: false,

View File

@ -400,6 +400,7 @@ AST_Symbol.DEFMETHOD("global", function(){
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options) { AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options) {
options = defaults(options, { options = defaults(options, {
eval : false, eval : false,
group_voids : false,
ie8 : false, ie8 : false,
keep_fnames : false, keep_fnames : false,
reserved : [], reserved : [],
@ -457,6 +458,15 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
this.walk(tw); this.walk(tw);
to_mangle.forEach(function(def){ def.mangle(options) }); to_mangle.forEach(function(def){ def.mangle(options) });
if (!options.group_voids) return;
if (options.toplevel) this.group_voids(options);
else this.walk(new TreeWalker(function(node) {
if (node instanceof AST_Scope && !(node instanceof AST_Toplevel)) {
node.group_voids(options);
return true;
}
}));
function collect(symbol) { function collect(symbol) {
if (!member(symbol.name, options.reserved)) { if (!member(symbol.name, options.reserved)) {
to_mangle.push(symbol); to_mangle.push(symbol);
@ -522,6 +532,73 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
} }
}); });
AST_Scope.DEFMETHOD("group_voids", function(options) {
var self = this, enclosed = [];
var scopes = [], count = 0;
self.walk(new TreeWalker(function(node, descend) {
if (node instanceof AST_Scope && node !== self) {
scopes.unshift(node);
descend();
if (scopes[0] === node) scopes.shift();
return true;
}
if (count > 0 && scopes.length == 0) return;
if (is_undefined(node)) {
count++;
var scope;
while (scope = scopes.shift()) {
scope.enclosed.forEach(function(def) {
push_uniq(enclosed, def);
});
}
}
}));
if (count < 1) return;
var save = self.enclosed;
self.enclosed = enclosed;
var name = next_mangled(self, options);
self.enclosed = save;
this.transform(new TreeTransformer(function(node) {
if (is_undefined(node)) return new AST_SymbolRef({
name: name,
start: node.start,
end: node.end
});
}));
for (var i = 0, len = this.body.length; i < len; i++) {
var stat = this.body[i];
if (stat instanceof AST_Var) {
stat.definitions.push(make_var_def(stat));
return;
}
}
this.body.push(new AST_Var({
definitions: [ make_var_def(this) ],
start: this.start,
end: this.end
}));
function is_undefined(node) {
return node instanceof AST_Undefined
|| node instanceof AST_UnaryPrefix
&& node.operator == "void"
&& node.expression.is_constant();
}
function make_var_def(node) {
return new AST_VarDef({
name: new AST_SymbolVar({
name: name,
start: node.start,
end: node.end
}),
value: null,
start: node.start,
end: node.end
});
}
});
AST_Node.DEFMETHOD("tail_node", return_this); AST_Node.DEFMETHOD("tail_node", return_this);
AST_Sequence.DEFMETHOD("tail_node", function() { AST_Sequence.DEFMETHOD("tail_node", function() {
return this.expressions[this.expressions.length - 1]; return this.expressions[this.expressions.length - 1];

View File

@ -0,0 +1,196 @@
group_voids: {
options = {
}
mangle = {
group_voids: true,
toplevel: false,
}
input: {
var a = 0;
x = void 0;
if (void 0 === b)
c = void 0;
function f1() {
var a = 1;
console.log(void 0);
}
function f2(undefined) {
var a = 2;
console.log(void 0);
}
function f3() {
var undefined = 3;
console.log(void 0);
}
function f4() {
console.log(void 0);
for (var a = 4;;);
var b = 4;
function g() {
var c = 5;
var d = 5;
console.log(void 0);
}
}
function f5() {
try {
var a = 6;
console.log(void 0);
} catch (e) {
console.log(void 0);
}
}
}
expect: {
var a = 0;
x = void 0;
if (void 0 === b)
c = void 0;
function f1() {
var o = 1, n;
console.log(n);
}
function f2(o) {
var n = 2, v;
console.log(v);
}
function f3() {
var o = 3, n;
console.log(n);
}
function f4() {
console.log(i);
for(var o = 4;;);
var n = 4, i;
function v() {
var o = 5;
var n = 5;
console.log(i);
}
}
function f5() {
try {
var o = 6;
console.log(n);
} catch (o) {
console.log(n);
}
var n;
}
}
}
group_voids_toplevel: {
options = {
}
mangle = {
group_voids: true,
toplevel: true,
}
input: {
var a = 0;
x = void 0;
if (void 0 === b)
c = void 0;
function f1() {
var a = 1;
console.log(void 0);
}
function f2(undefined) {
var a = 2;
console.log(void 0);
}
function f3() {
var undefined = 3;
console.log(void 0);
}
function f4() {
console.log(void 0);
for (var a = 4;;);
var b = 4;
function g() {
var c = 5;
var d = 5;
console.log(void 0);
}
}
function f5() {
try {
var a = 6;
console.log(void 0);
} catch (e) {
console.log(void 0);
}
}
}
expect: {
var o = 0, a;
x = a;
if (a === b)
c = a;
function n() {
var o = 1;
console.log(a);
}
function v(o) {
var n = 2;
console.log(a);
}
function i() {
var o = 3;
console.log(a);
}
function l() {
console.log(a);
for(var o = 4;;);
var n = 4;
function v() {
var o = 5;
var n = 5;
console.log(a);
}
}
function r() {
try {
var o = 6;
console.log(a);
} catch (o) {
console.log(a);
}
}
}
}
group_voids_catch: {
options = {
}
mangle = {
group_voids: true,
}
input: {
(function() {
var a = 1;
console.log(void 0);
try {
throw "FAIL";
} catch (undefined) {
console.log(void 0);
}
})();
}
expect: {
(function() {
var o = 1, c;
console.log(c);
try {
throw "FAIL";
} catch (o) {
console.log(c);
}
})();
}
expect_stdout: [
"undefined",
"undefined",
]
}