fix corner case in reduce_vars (#3959)

fixes #3958
This commit is contained in:
Alex Lam S.L
2020-06-06 10:04:37 +08:00
committed by GitHub
parent eb481cee8c
commit 486ce00b8e
2 changed files with 62 additions and 23 deletions

View File

@@ -352,6 +352,23 @@ merge(Compressor.prototype, {
return orig.length == 1 && orig[0] instanceof AST_SymbolFunarg;
}
function is_content_constant(ref, depth) {
var escaped = ref.definition().escaped;
switch (escaped.length) {
case 0:
return true;
case 1:
var found = false;
escaped[0].walk(new TreeWalker(function(node) {
if (found) return true;
if (node === ref) return found = true;
}));
return found;
default:
return depth <= escaped.depth;
}
}
(function(def) {
def(AST_Node, noop);
@@ -496,9 +513,15 @@ merge(Compressor.prototype, {
}
function to_value(def, sym, fixed) {
if (fixed instanceof AST_Node) return fixed;
if (typeof fixed == "function") return fixed();
return make_node(AST_Undefined, sym);
if (fixed == null) {
fixed = make_node(AST_Undefined, sym);
} else if (typeof fixed == "function") {
fixed = fixed();
}
if (fixed instanceof AST_Array || fixed instanceof AST_Object) {
if (!is_content_constant(sym)) return false;
}
return fixed;
}
function ref_once(compressor, def) {
@@ -3515,27 +3538,8 @@ merge(Compressor.prototype, {
};
cached.push(fixed);
}
if (value && typeof value == "object") {
var escaped = this.definition().escaped;
switch (escaped.length) {
case 0:
break;
case 1:
if (contains_ref(escaped[0], this)) break;
default:
if (depth > escaped.depth) return this;
}
}
if (value && typeof value == "object" && !is_content_constant(this, depth)) return this;
return value;
function contains_ref(expr, ref) {
var found = false;
expr.walk(new TreeWalker(function(node) {
if (found) return true;
if (node === ref) return found = true;
}));
return found;
}
});
var global_objs = {
Array: Array,

View File

@@ -7323,3 +7323,38 @@ issue_3957_2: {
"0",
]
}
issue_3958: {
options = {
evaluate: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var a;
(function(b) {
(function(c) {
console.log(c[0] = 1);
})(a = b);
--a;
})([]);
console.log(a);
}
expect: {
var a;
(function(b) {
(function(c) {
console.log(c[0] = 1);
})(a = []);
--a;
})();
console.log(a);
}
expect_stdout: [
"1",
"0",
]
}