proper scope look-up & statement trimming

This commit is contained in:
alexlamsl 2017-04-18 14:02:06 +08:00
parent 5d9f1da3ab
commit 1baf3a8f10
2 changed files with 8 additions and 20 deletions

View File

@ -642,12 +642,10 @@ merge(Compressor.prototype, {
// and if it has exactly one reference then attempt to replace its reference // and if it has exactly one reference then attempt to replace its reference
// in the statement with the var value and then erase the var definition. // in the statement with the var value and then erase the var definition.
var self = compressor.self(); var scope = compressor.find_parent(AST_Scope);
var var_defs_removed = false;
var toplevel = compressor.option("toplevel"); var toplevel = compressor.option("toplevel");
for (var stat_index = statements.length; --stat_index >= 0;) { for (var stat_index = statements.length; --stat_index >= 0;) {
var stat = statements[stat_index]; var stat = statements[stat_index];
if (stat instanceof AST_Definitions) continue;
// Process child blocks of statement if present. // Process child blocks of statement if present.
[stat, stat.body, stat.alternative, stat.bcatch, stat.bfinally].forEach(function(node) { [stat, stat.body, stat.alternative, stat.bcatch, stat.bfinally].forEach(function(node) {
@ -681,8 +679,8 @@ merge(Compressor.prototype, {
var_names_seen[var_name] = true; var_names_seen[var_name] = true;
// Only interested in cases with just one reference to the variable. // Only interested in cases with just one reference to the variable.
var def = self.find_variable && self.find_variable(var_name); var def = var_decl.name.definition();
if (!def || !def.references || def.references.length !== 1 if (def.references.length !== 1
|| var_name == "arguments" || (!toplevel && def.global)) { || var_name == "arguments" || (!toplevel && def.global)) {
side_effects_encountered = true; side_effects_encountered = true;
continue; continue;
@ -712,7 +710,7 @@ merge(Compressor.prototype, {
var value_has_side_effects = var_decl.value.has_side_effects(compressor); var value_has_side_effects = var_decl.value.has_side_effects(compressor);
// Non-constant single use vars can only be replaced in same scope. // Non-constant single use vars can only be replaced in same scope.
if (ref.scope !== self) { if (ref.scope !== scope) {
side_effects_encountered |= value_has_side_effects; side_effects_encountered |= value_has_side_effects;
continue; continue;
} }
@ -740,7 +738,7 @@ merge(Compressor.prototype, {
|| (parent instanceof AST_Conditional && node !== parent.condition) || (parent instanceof AST_Conditional && node !== parent.condition)
|| (node instanceof AST_SymbolRef || (node instanceof AST_SymbolRef
&& value_has_side_effects && value_has_side_effects
&& !are_references_in_scope(node.definition(), self)) && !are_references_in_scope(node.definition(), scope))
|| (parent instanceof AST_Binary || (parent instanceof AST_Binary
&& (parent.operator == "&&" || parent.operator == "||") && (parent.operator == "&&" || parent.operator == "||")
&& node === parent.right) && node === parent.right)
@ -774,13 +772,6 @@ merge(Compressor.prototype, {
} }
} }
// Remove extraneous empty statments in block after removing var definitions.
// Leave at least one statement in `statements`.
if (var_defs_removed) for (var i = statements.length; --i >= 0;) {
if (statements.length > 1 && statements[i] instanceof AST_EmptyStatement)
statements.splice(i, 1);
}
return statements; return statements;
function is_lvalue(node, parent) { function is_lvalue(node, parent) {
@ -795,8 +786,8 @@ merge(Compressor.prototype, {
var_defs.splice(var_defs_index, 1); var_defs.splice(var_defs_index, 1);
if (var_defs.length === 0) { if (var_defs.length === 0) {
statements[prev_stat_index] = make_node(AST_EmptyStatement, self); statements.splice(prev_stat_index, 1);
var_defs_removed = true; stat_index--;
} }
// Further optimize statement after substitution. // Further optimize statement after substitution.
stat.reset_opt_flags(compressor); stat.reset_opt_flags(compressor);

View File

@ -282,10 +282,7 @@ collapse_vars_if: {
return "x" != "Bar" + x / 4 ? g9 : g5; return "x" != "Bar" + x / 4 ? g9 : g5;
} }
function f3(x) { function f3(x) {
if (x) { return x ? 1 : 2;
return 1;
}
return 2;
} }
} }
} }