adding an imaginary "return undefined" can sometimes help

function f() {
  if (foo) return x();
  if (!bar) return y();
}

==>

function f() {
  return foo ? x() : bar ? void 0 : y();
}
This commit is contained in:
Mihai Bazon
2012-09-14 16:26:30 +03:00
parent 924aa58060
commit 5e83e7ec17
2 changed files with 49 additions and 25 deletions

View File

@@ -190,33 +190,42 @@ function Compressor(options, false_by_default) {
return MAP(statements, function(stat, i){ return MAP(statements, function(stat, i){
if (stat instanceof AST_If if (stat instanceof AST_If
&& stat.body instanceof AST_Return && stat.body instanceof AST_Return
&& !stat.body.value
&& !stat.alternative && !stat.alternative
&& in_lambda) { && in_lambda) {
CHANGED = true; if (!stat.body.value) {
if (i < last) { CHANGED = true;
var rest = statements.slice(i + 1); if (i < last) {
var cond = stat.condition; var rest = statements.slice(i + 1);
while (rest[0] instanceof AST_If var cond = stat.condition;
&& rest[0].body instanceof AST_Return while (rest[0] instanceof AST_If
&& !rest[0].alternative) { && rest[0].body instanceof AST_Return
cond = make_node(AST_Binary, rest[0], { && !rest[0].alternative) {
operator: "||", cond = make_node(AST_Binary, rest[0], {
left: cond, operator: "||",
right: rest[0].condition left: cond,
}); right: rest[0].condition
rest.shift(); });
rest.shift();
}
return MAP.last(make_node(AST_If, stat, {
condition: cond.negate(compressor),
body: make_node(AST_BlockStatement, stat, {
body: rest
}).optimize(compressor)
}).optimize(compressor));
} else {
return make_node(AST_SimpleStatement, stat, {
body: stat.condition
}).optimize(compressor);
} }
return MAP.last(make_node(AST_If, stat, { } else if (i == last && last > 0
condition: cond.negate(compressor), && statements[last - 1] instanceof AST_If
body: make_node(AST_BlockStatement, stat, { && statements[last - 1].body instanceof AST_Return
body: rest && !statements[last - 1].alternative) {
}).optimize(compressor) CHANGED = true;
}).optimize(compressor)); return MAP.splice([ stat, make_node(AST_Return, stat, {
} else { value: make_node(AST_Undefined, stat)
return make_node(AST_SimpleStatement, stat, { })]);
body: stat.condition
}).optimize(compressor);
} }
} }
if (stat instanceof AST_If if (stat instanceof AST_If
@@ -697,7 +706,7 @@ function Compressor(options, false_by_default) {
} }
}); });
self.walk(tw); self.walk(tw);
if (vars_found > 0 && vardecl.length > 0) { if (vars_found > 0 && vardecl.length > 1) {
vardecl.forEach(function(v){ v.hoisted = true }); vardecl.forEach(function(v){ v.hoisted = true });
var node = make_node(AST_Var, self, { var node = make_node(AST_Var, self, {
definitions: Object.keys(vars).map(function(name){ definitions: Object.keys(vars).map(function(name){
@@ -1338,6 +1347,17 @@ function Compressor(options, false_by_default) {
return self.optimize(compressor); return self.optimize(compressor);
}); });
SQUEEZE(AST_SymbolRef, function(self, compressor){
return self.optimize(compressor);
});
AST_SymbolRef.DEFMETHOD("optimize", function(compressor){
if (this.name == "undefined" && this.undeclared()) {
return make_node(AST_Undefined, this);
}
return this;
});
var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ]; var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ];
AST_Assign.DEFMETHOD("optimize", function(compressor){ AST_Assign.DEFMETHOD("optimize", function(compressor){
if (this.operator == "=" if (this.operator == "="

View File

@@ -889,6 +889,10 @@ function OutputStream(options) {
var def = self.definition(); var def = self.definition();
output.print_name(def ? def.mangled_name || def.name : self.name); output.print_name(def ? def.mangled_name || def.name : self.name);
}); });
DEFPRINT(AST_Undefined, function(self, output){
// XXX: should add more options for this
output.print("void 0");
});
DEFPRINT(AST_This, function(self, output){ DEFPRINT(AST_This, function(self, output){
output.print("this"); output.print("this");
}); });