enhance evaluate & reduce_vars (#3870)

This commit is contained in:
Alex Lam S.L
2020-05-10 11:38:32 +01:00
committed by GitHub
parent c4c9c6d37d
commit f9806b43c3
3 changed files with 48 additions and 19 deletions

View File

@@ -3302,19 +3302,23 @@ merge(Compressor.prototype, {
var non_converting_unary = makePredicate("! typeof void"); var non_converting_unary = makePredicate("! typeof void");
def(AST_UnaryPrefix, function(compressor, ignore_side_effects, cached, depth) { def(AST_UnaryPrefix, function(compressor, ignore_side_effects, cached, depth) {
var e = this.expression; var e = this.expression;
var op = this.operator;
// Function would be evaluated to an array and so typeof would // Function would be evaluated to an array and so typeof would
// incorrectly return 'object'. Hence making is a special case. // incorrectly return 'object'. Hence making is a special case.
if (compressor.option("typeofs") if (compressor.option("typeofs")
&& this.operator == "typeof" && op == "typeof"
&& (e instanceof AST_Lambda && (e instanceof AST_Lambda
|| e instanceof AST_SymbolRef || e instanceof AST_SymbolRef
&& e.fixed_value() instanceof AST_Lambda)) { && e.fixed_value() instanceof AST_Lambda)) {
return typeof function(){}; return typeof function(){};
} }
if (!non_converting_unary[this.operator]) 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 === this.expression) return this; if (v === e) {
switch (this.operator) { if (ignore_side_effects && op == "void") return void 0;
return this;
}
switch (op) {
case "!": return !v; case "!": return !v;
case "typeof": case "typeof":
// typeof <RegExp> returns "object" or "function" on different platforms // typeof <RegExp> returns "object" or "function" on different platforms
@@ -3330,7 +3334,7 @@ merge(Compressor.prototype, {
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 (refs[refs.length - 1] !== e) return this;
return HOP(e, "_eval") ? +(this.operator[0] + 1) + +v : v; return HOP(e, "_eval") ? +(op[0] + 1) + +v : v;
} }
return this; return this;
}); });
@@ -7500,9 +7504,13 @@ merge(Compressor.prototype, {
init = fixed; init = fixed;
} }
} else { } else {
var ev = fixed.evaluate(compressor); var ev = fixed.evaluate(compressor, true);
if (ev !== fixed && (!(ev instanceof RegExp) if (ev !== fixed
|| compressor.option("unsafe_regexp") && !def.cross_loop && same_scope(def))) { && typeof ev != "function"
&& (typeof ev != "object"
|| ev instanceof RegExp
&& compressor.option("unsafe_regexp")
&& !def.cross_loop && same_scope(def))) {
init = make_node_from_constant(ev, fixed); init = make_node_from_constant(ev, fixed);
} }
} }

View File

@@ -785,11 +785,12 @@ issue_3791_2: {
issue_3795: { issue_3795: {
options = { options = {
booleans: true,
collapse_vars: true, collapse_vars: true,
conditionals: true,
dead_code: true, dead_code: true,
evaluate: true, evaluate: true,
join_vars: true, join_vars: true,
keep_fargs: "strict",
loops: true, loops: true,
passes: 2, passes: 2,
reduce_vars: true, reduce_vars: true,
@@ -798,22 +799,21 @@ issue_3795: {
} }
input: { input: {
var a = "FAIL"; var a = "FAIL";
function f(b) { function f(b, c) {
for (var i = 1; b && i; --i) return 0; for (var i = 5; c && i; --i) return -1;
a = "PASS"; a = "PASS";
} }
var c = f(a = ""); var d = f(a = 42, d);
console.log(a); console.log(a, d);
} }
expect: { expect: {
var a = "FAIL"; var a = "FAIL", d = function() {
(function(b) { if (a = 42, d) return -1;
a = "";
a = "PASS"; a = "PASS";
})(); }();
console.log(a); console.log(a, d);
} }
expect_stdout: "PASS" expect_stdout: "PASS undefined"
} }
if_body: { if_body: {

View File

@@ -7054,3 +7054,24 @@ issue_3866: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
void_side_effects: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = void console.log("PASS");
console.log(a);
}
expect: {
console.log("PASS");
console.log(void 0);
}
expect_stdout: [
"PASS",
"undefined",
]
}