aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2020-05-10 11:38:32 +0100
committerGitHub <noreply@github.com>2020-05-10 18:38:32 +0800
commitf9806b43c33400b73e19d5bd216a2b5653dfcfbd (patch)
tree3ff6eadb6f82c43cf49a025f8688c71248b60966
parentc4c9c6d37de8074bba3e433621bc70f88d7631ae (diff)
downloadtracifyjs-f9806b43c33400b73e19d5bd216a2b5653dfcfbd.tar.gz
tracifyjs-f9806b43c33400b73e19d5bd216a2b5653dfcfbd.zip
enhance `evaluate` & `reduce_vars` (#3870)
-rw-r--r--lib/compress.js24
-rw-r--r--test/compress/join_vars.js22
-rw-r--r--test/compress/reduce_vars.js21
3 files changed, 48 insertions, 19 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 904295ee..4f5e9253 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -3302,19 +3302,23 @@ merge(Compressor.prototype, {
var non_converting_unary = makePredicate("! typeof void");
def(AST_UnaryPrefix, function(compressor, ignore_side_effects, cached, depth) {
var e = this.expression;
+ var op = this.operator;
// Function would be evaluated to an array and so typeof would
// incorrectly return 'object'. Hence making is a special case.
if (compressor.option("typeofs")
- && this.operator == "typeof"
+ && op == "typeof"
&& (e instanceof AST_Lambda
|| e instanceof AST_SymbolRef
&& e.fixed_value() instanceof AST_Lambda)) {
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);
- if (v === this.expression) return this;
- switch (this.operator) {
+ if (v === e) {
+ if (ignore_side_effects && op == "void") return void 0;
+ return this;
+ }
+ switch (op) {
case "!": return !v;
case "typeof":
// typeof <RegExp> returns "object" or "function" on different platforms
@@ -3330,7 +3334,7 @@ merge(Compressor.prototype, {
if (!(e instanceof AST_SymbolRef)) return this;
var refs = e.definition().references;
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;
});
@@ -7500,9 +7504,13 @@ merge(Compressor.prototype, {
init = fixed;
}
} else {
- var ev = fixed.evaluate(compressor);
- if (ev !== fixed && (!(ev instanceof RegExp)
- || compressor.option("unsafe_regexp") && !def.cross_loop && same_scope(def))) {
+ var ev = fixed.evaluate(compressor, true);
+ if (ev !== fixed
+ && 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);
}
}
diff --git a/test/compress/join_vars.js b/test/compress/join_vars.js
index 3e4334cf..67d7fd05 100644
--- a/test/compress/join_vars.js
+++ b/test/compress/join_vars.js
@@ -785,11 +785,12 @@ issue_3791_2: {
issue_3795: {
options = {
+ booleans: true,
collapse_vars: true,
- conditionals: true,
dead_code: true,
evaluate: true,
join_vars: true,
+ keep_fargs: "strict",
loops: true,
passes: 2,
reduce_vars: true,
@@ -798,22 +799,21 @@ issue_3795: {
}
input: {
var a = "FAIL";
- function f(b) {
- for (var i = 1; b && i; --i) return 0;
+ function f(b, c) {
+ for (var i = 5; c && i; --i) return -1;
a = "PASS";
}
- var c = f(a = "");
- console.log(a);
+ var d = f(a = 42, d);
+ console.log(a, d);
}
expect: {
- var a = "FAIL";
- (function(b) {
- a = "";
+ var a = "FAIL", d = function() {
+ if (a = 42, d) return -1;
a = "PASS";
- })();
- console.log(a);
+ }();
+ console.log(a, d);
}
- expect_stdout: "PASS"
+ expect_stdout: "PASS undefined"
}
if_body: {
diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js
index ec75e911..ee1e4711 100644
--- a/test/compress/reduce_vars.js
+++ b/test/compress/reduce_vars.js
@@ -7054,3 +7054,24 @@ issue_3866: {
}
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",
+ ]
+}