fix unsafe on evaluate of reduce_vars (#1870)

Determine if variables with non-constant values can escape and be modified.

fixes #1865
This commit is contained in:
Alex Lam S.L
2017-05-06 23:18:55 +08:00
committed by GitHub
parent ecf3563c45
commit 2c7ee956fd
2 changed files with 85 additions and 35 deletions

View File

@@ -283,6 +283,14 @@ merge(Compressor.prototype, {
if (d.fixed === undefined || !safe_to_read(d)
|| is_modified(node, 0, is_immutable(node.fixed_value()))) {
d.fixed = false;
} else {
var parent = tw.parent();
if (parent instanceof AST_Assign && parent.operator == "=" && node === parent.right
|| parent instanceof AST_Call && node !== parent.expression
|| parent instanceof AST_Return && node === parent.value && node.scope !== d.scope
|| parent instanceof AST_VarDef && node === parent.value) {
d.escaped = true;
}
}
}
if (node instanceof AST_SymbolCatch) {
@@ -482,6 +490,7 @@ merge(Compressor.prototype, {
}
function reset_def(def) {
def.escaped = false;
if (!def.global || def.orig[0] instanceof AST_SymbolConst || compressor.toplevel(def)) {
def.fixed = undefined;
} else {
@@ -1595,23 +1604,20 @@ merge(Compressor.prototype, {
: ev(this.alternative, compressor);
});
def(AST_SymbolRef, function(compressor){
if (this._evaluating) throw def;
if (!compressor.option("reduce_vars") || this._evaluating) throw def;
this._evaluating = true;
try {
var fixed = this.fixed_value();
if (compressor.option("reduce_vars") && fixed) {
if (compressor.option("unsafe")) {
if (!HOP(fixed, "_evaluated")) {
fixed._evaluated = ev(fixed, compressor);
}
return fixed._evaluated;
}
return ev(fixed, compressor);
}
if (!fixed) throw def;
var value = ev(fixed, compressor);
if (!HOP(fixed, "_eval")) fixed._eval = function() {
return value;
};
if (value && typeof value == "object" && this.definition().escaped) throw def;
return value;
} finally {
this._evaluating = false;
}
throw def;
});
def(AST_PropAccess, function(compressor){
if (compressor.option("unsafe")) {