fix reduce_vars on catch variable (#1794)

Improved catch handling in `figure_out_scope()` means special case treatment of IE8 is no longer valid in `reset_opt_flags()`.

Also fixed recursive assignment in variable definition.
This commit is contained in:
Alex Lam S.L
2017-04-07 12:32:56 +08:00
committed by GitHub
parent cc6aa3e5ac
commit 281e882d27
2 changed files with 60 additions and 22 deletions

View File

@@ -251,9 +251,7 @@ merge(Compressor.prototype, {
AST_Node.DEFMETHOD("reset_opt_flags", function(compressor, rescan){ AST_Node.DEFMETHOD("reset_opt_flags", function(compressor, rescan){
var reduce_vars = rescan && compressor.option("reduce_vars"); var reduce_vars = rescan && compressor.option("reduce_vars");
var toplevel = compressor.option("toplevel"); var toplevel = compressor.option("toplevel");
var ie8 = !compressor.option("screw_ie8"); var safe_ids = Object.create(null);
var safe_ids = [];
push();
var suppressor = new TreeWalker(function(node) { var suppressor = new TreeWalker(function(node) {
if (node instanceof AST_Symbol) { if (node instanceof AST_Symbol) {
var d = node.definition(); var d = node.definition();
@@ -277,7 +275,7 @@ merge(Compressor.prototype, {
d.fixed = false; d.fixed = false;
} }
} }
if (ie8 && node instanceof AST_SymbolCatch) { if (node instanceof AST_SymbolCatch) {
node.definition().fixed = false; node.definition().fixed = false;
} }
if (node instanceof AST_VarDef) { if (node instanceof AST_VarDef) {
@@ -287,11 +285,12 @@ merge(Compressor.prototype, {
d.fixed = function() { d.fixed = function() {
return node.value; return node.value;
}; };
mark(d, false);
descend(); descend();
} else { } else {
d.fixed = null; d.fixed = null;
} }
mark_as_safe(d); mark(d, true);
return true; return true;
} else if (node.value) { } else if (node.value) {
d.fixed = false; d.fixed = false;
@@ -303,11 +302,10 @@ merge(Compressor.prototype, {
d.fixed = false; d.fixed = false;
} else { } else {
d.fixed = node; d.fixed = node;
mark_as_safe(d); mark(d, true);
} }
var save_ids = safe_ids; var save_ids = safe_ids;
safe_ids = []; safe_ids = Object.create(null);
push();
descend(); descend();
safe_ids = save_ids; safe_ids = save_ids;
return true; return true;
@@ -325,7 +323,7 @@ merge(Compressor.prototype, {
d.fixed = function() { d.fixed = function() {
return iife.args[i] || make_node(AST_Undefined, iife); return iife.args[i] || make_node(AST_Undefined, iife);
}; };
mark_as_safe(d); mark(d, true);
}); });
} }
if (node instanceof AST_If || node instanceof AST_DWLoop) { if (node instanceof AST_If || node instanceof AST_DWLoop) {
@@ -373,13 +371,12 @@ merge(Compressor.prototype, {
}); });
this.walk(tw); this.walk(tw);
function mark_as_safe(def) { function mark(def, safe) {
safe_ids[safe_ids.length - 1][def.id] = true; safe_ids[def.id] = safe;
} }
function is_safe(def) { function is_safe(def) {
for (var i = safe_ids.length, id = def.id; --i >= 0;) { if (safe_ids[def.id]) {
if (safe_ids[i][id]) {
if (def.fixed == null) { if (def.fixed == null) {
var orig = def.orig[0]; var orig = def.orig[0];
if (orig instanceof AST_SymbolFunarg || orig.name == "arguments") return false; if (orig instanceof AST_SymbolFunarg || orig.name == "arguments") return false;
@@ -388,14 +385,13 @@ merge(Compressor.prototype, {
return true; return true;
} }
} }
}
function push() { function push() {
safe_ids.push(Object.create(null)); safe_ids = Object.create(safe_ids);
} }
function pop() { function pop() {
safe_ids.pop(); safe_ids = Object.getPrototypeOf(safe_ids);
} }
function reset_def(def) { function reset_def(def) {

View File

@@ -1917,7 +1917,7 @@ side_effects_assign: {
expect_stdout: "undefined" expect_stdout: "undefined"
} }
pure_getters: { pure_getters_1: {
options = { options = {
pure_getters: true, pure_getters: true,
reduce_vars: true, reduce_vars: true,
@@ -1938,3 +1938,45 @@ pure_getters: {
} }
expect_stdout: "undefined" expect_stdout: "undefined"
} }
pure_getters_2: {
options = {
pure_getters: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a;
var a = a && a.b;
}
expect: {
var a;
var a = a && a.b;
}
}
catch_var: {
options = {
booleans: true,
evaluate: true,
reduce_vars: true,
}
input: {
try {
throw {};
} catch (e) {
var e;
console.log(!!e);
}
}
expect: {
try {
throw {};
} catch (e) {
var e;
console.log(!!e);
}
}
expect_stdout: "true"
}