@@ -858,7 +858,7 @@ merge(Compressor.prototype, {
|
|||||||
d.assignments++;
|
d.assignments++;
|
||||||
var fixed = d.fixed;
|
var fixed = d.fixed;
|
||||||
if (!fixed) return;
|
if (!fixed) return;
|
||||||
exp.fixed = d.fixed = function() {
|
d.fixed = function() {
|
||||||
var value = fixed instanceof AST_Node ? fixed : fixed();
|
var value = fixed instanceof AST_Node ? fixed : fixed();
|
||||||
return value && make_node(AST_Binary, node, {
|
return value && make_node(AST_Binary, node, {
|
||||||
operator: node.operator.slice(0, -1),
|
operator: node.operator.slice(0, -1),
|
||||||
@@ -871,6 +871,13 @@ merge(Compressor.prototype, {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
exp.fixed = node instanceof AST_UnaryPrefix ? d.fixed : function() {
|
||||||
|
var value = fixed instanceof AST_Node ? fixed : fixed();
|
||||||
|
return value && make_node(AST_UnaryPrefix, node, {
|
||||||
|
operator: "+",
|
||||||
|
expression: value
|
||||||
|
});
|
||||||
|
};
|
||||||
if (!safe) return;
|
if (!safe) return;
|
||||||
d.references.push(exp);
|
d.references.push(exp);
|
||||||
mark(tw, d, true);
|
mark(tw, d, true);
|
||||||
@@ -3233,6 +3240,12 @@ merge(Compressor.prototype, {
|
|||||||
&& unaryPrefix[this.operator];
|
&& unaryPrefix[this.operator];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
function modified(sym) {
|
||||||
|
if (!(sym instanceof AST_SymbolRef)) return;
|
||||||
|
sym.definition().references.forEach(function(node) {
|
||||||
|
delete node._eval;
|
||||||
|
});
|
||||||
|
}
|
||||||
def(AST_Statement, function() {
|
def(AST_Statement, function() {
|
||||||
throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
|
throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
|
||||||
});
|
});
|
||||||
@@ -3246,6 +3259,7 @@ merge(Compressor.prototype, {
|
|||||||
if (this.operator != "=") return this;
|
if (this.operator != "=") return this;
|
||||||
var node = this.right;
|
var node = this.right;
|
||||||
var value = node._eval(compressor, ignore_side_effects, cached, depth);
|
var value = node._eval(compressor, ignore_side_effects, cached, depth);
|
||||||
|
modified(this.left);
|
||||||
return value === node ? this : value;
|
return value === node ? this : value;
|
||||||
});
|
});
|
||||||
def(AST_Sequence, function(compressor, ignore_side_effects, cached, depth) {
|
def(AST_Sequence, function(compressor, ignore_side_effects, cached, depth) {
|
||||||
@@ -3317,7 +3331,7 @@ merge(Compressor.prototype, {
|
|||||||
if (!non_converting_unary[op]) depth++;
|
if (!non_converting_unary[op]) depth++;
|
||||||
var v = e._eval(compressor, ignore_side_effects, cached, depth);
|
var v = e._eval(compressor, ignore_side_effects, cached, depth);
|
||||||
if (v === e) {
|
if (v === e) {
|
||||||
if (ignore_side_effects && op == "void") return void 0;
|
if (ignore_side_effects && op == "void") return;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
switch (op) {
|
switch (op) {
|
||||||
@@ -3327,7 +3341,7 @@ merge(Compressor.prototype, {
|
|||||||
// so cannot evaluate reliably
|
// so cannot evaluate reliably
|
||||||
if (v instanceof RegExp) return this;
|
if (v instanceof RegExp) return this;
|
||||||
return typeof v;
|
return typeof v;
|
||||||
case "void": return void v;
|
case "void": return;
|
||||||
case "~": return ~v;
|
case "~": return ~v;
|
||||||
case "-": return -v;
|
case "-": return -v;
|
||||||
case "+": return +v;
|
case "+": return +v;
|
||||||
@@ -3335,11 +3349,22 @@ merge(Compressor.prototype, {
|
|||||||
case "--":
|
case "--":
|
||||||
if (!(e instanceof AST_SymbolRef)) return this;
|
if (!(e instanceof AST_SymbolRef)) return this;
|
||||||
var refs = e.definition().references;
|
var refs = e.definition().references;
|
||||||
if (refs[refs.length - 1] !== e) return this;
|
if (!ignore_side_effects && refs[refs.length - 1] !== e) return this;
|
||||||
return HOP(e, "_eval") ? +(op[0] + 1) + +v : v;
|
if (HOP(e, "_eval")) v = +(op[0] + 1) + +v;
|
||||||
|
modified(e);
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
});
|
});
|
||||||
|
def(AST_UnaryPostfix, function(compressor, ignore_side_effects, cached, depth) {
|
||||||
|
var e = this.expression;
|
||||||
|
if (!(e instanceof AST_SymbolRef)) return this;
|
||||||
|
var refs = e.definition().references;
|
||||||
|
if (!ignore_side_effects && refs[refs.length - 1] !== e) return this;
|
||||||
|
var v = e._eval(compressor, ignore_side_effects, cached, depth + 1);
|
||||||
|
modified(e);
|
||||||
|
return v === e ? this : +v;
|
||||||
|
});
|
||||||
var non_converting_binary = makePredicate("&& || === !==");
|
var non_converting_binary = makePredicate("&& || === !==");
|
||||||
def(AST_Binary, function(compressor, ignore_side_effects, cached, depth) {
|
def(AST_Binary, function(compressor, ignore_side_effects, cached, depth) {
|
||||||
if (!non_converting_binary[this.operator]) depth++;
|
if (!non_converting_binary[this.operator]) depth++;
|
||||||
@@ -3514,14 +3539,14 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
if (node instanceof AST_Scope && node !== fn) return true;
|
if (node instanceof AST_Scope && node !== fn) return true;
|
||||||
}));
|
}));
|
||||||
if (!found) return void 0;
|
if (!found) return;
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
var args = eval_args(this.args);
|
var args = eval_args(this.args);
|
||||||
if (!args) return this;
|
if (!args && !ignore_side_effects) return this;
|
||||||
if (!stat.value) return undefined;
|
if (!stat.value) return;
|
||||||
if (!all(fn.argnames, function(sym, i) {
|
if (args && !all(fn.argnames, function(sym, i) {
|
||||||
var value = args[i];
|
var value = args[i];
|
||||||
var def = sym.definition();
|
var def = sym.definition();
|
||||||
if (def.orig[def.orig.length - 1] !== sym) return false;
|
if (def.orig[def.orig.length - 1] !== sym) return false;
|
||||||
@@ -3532,7 +3557,7 @@ merge(Compressor.prototype, {
|
|||||||
cached.push(node);
|
cached.push(node);
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
})) return this;
|
}) && !ignore_side_effects) return this;
|
||||||
fn.evaluating = true;
|
fn.evaluating = true;
|
||||||
var val = stat.value._eval(compressor, ignore_side_effects, cached, depth);
|
var val = stat.value._eval(compressor, ignore_side_effects, cached, depth);
|
||||||
delete fn.evaluating;
|
delete fn.evaluating;
|
||||||
|
|||||||
@@ -2326,3 +2326,46 @@ void_returns_recursive: {
|
|||||||
"undefined",
|
"undefined",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3878_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = function(a) {
|
||||||
|
return (a = 0) == (a && this > (a += 0));
|
||||||
|
}();
|
||||||
|
console.log(b ? "PASS" : "FAIL");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = function(a) {
|
||||||
|
return (a = 0) == (a && this > (a += 0));
|
||||||
|
}();
|
||||||
|
console.log(b ? "PASS" : "FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3878_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "foo";
|
||||||
|
a++ + a;
|
||||||
|
a && a;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "foo";
|
||||||
|
a++ + a;
|
||||||
|
a;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user