aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2021-07-07 17:29:23 +0100
committerGitHub <noreply@github.com>2021-07-08 00:29:23 +0800
commit6577d641ac82419d462f11fee73a7b067e793003 (patch)
tree9e57daf56b31eb61a3a47d3b2fd8417a22d3fe1f
parent2340feff875eb4b32e95abfe7526dede72ba2253 (diff)
downloadtracifyjs-6577d641ac82419d462f11fee73a7b067e793003.tar.gz
tracifyjs-6577d641ac82419d462f11fee73a7b067e793003.zip
enhance `evaluate` & `reduce_vars` (#5060)
-rw-r--r--lib/compress.js65
-rw-r--r--test/compress/default-values.js55
-rw-r--r--test/compress/hoist_vars.js4
-rw-r--r--test/compress/reduce_vars.js1
4 files changed, 78 insertions, 47 deletions
diff --git a/lib/compress.js b/lib/compress.js
index de74f56c..90261d0a 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -734,7 +734,12 @@ merge(Compressor.prototype, {
var save = fixed;
if (save) fixed = function() {
var value = save();
- return is_undefined(value) ? make_sequence(node, [ value, node.value ]) : node;
+ var ev;
+ if (is_undefined(value, compressor)
+ || (ev = fuzzy_eval(compressor, value, true)) === undefined) {
+ return make_sequence(node, [ value, node.value ]);
+ }
+ return ev instanceof AST_Node ? node : value;
};
node.name.walk(scanner);
fixed = save;
@@ -7293,7 +7298,7 @@ merge(Compressor.prototype, {
node.in_bool = true;
var value = node.value;
if (value) {
- var ev = value.is_truthy() || value.evaluate(compressor, true);
+ var ev = fuzzy_eval(compressor, value);
if (!ev) {
value = value.drop_side_effect_free(compressor);
node.value = value ? make_sequence(node.value, [
@@ -8006,7 +8011,7 @@ merge(Compressor.prototype, {
OPT(AST_Do, function(self, compressor) {
if (!compressor.option("loops")) return self;
- var cond = self.condition.is_truthy() || self.condition.evaluate(compressor, true);
+ var cond = fuzzy_eval(compressor, self.condition);
if (!(cond instanceof AST_Node)) {
if (cond && !has_loop_control(self, compressor.parent(), AST_Continue)) return make_node(AST_For, self, {
body: make_node(AST_BlockStatement, self.body, {
@@ -8174,36 +8179,25 @@ merge(Compressor.prototype, {
if (self.step) self.step = self.step.drop_side_effect_free(compressor);
}
if (self.condition) {
- var cond = self.condition.evaluate(compressor);
- if (cond instanceof AST_Node) {
- cond = self.condition.is_truthy() || self.condition.evaluate(compressor, true);
- } else if (cond) {
- self.condition = null;
- }
+ var cond = fuzzy_eval(compressor, self.condition);
if (!cond) {
if (compressor.option("dead_code")) {
var body = [];
if (is_statement(self.init)) {
body.push(self.init);
} else if (self.init) {
- body.push(make_node(AST_SimpleStatement, self.init, {
- body: self.init
- }));
+ body.push(make_node(AST_SimpleStatement, self.init, { body: self.init }));
}
- body.push(make_node(AST_SimpleStatement, self.condition, {
- body: self.condition
- }));
+ body.push(make_node(AST_SimpleStatement, self.condition, { body: self.condition }));
extract_declarations_from_unreachable_code(compressor, self.body, body);
return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
}
- } else if (self.condition && !(cond instanceof AST_Node)) {
+ } else if (!(cond instanceof AST_Node)) {
self.body = make_node(AST_BlockStatement, self.body, {
body: [
- make_node(AST_SimpleStatement, self.condition, {
- body: self.condition
- }),
- self.body
- ]
+ make_node(AST_SimpleStatement, self.condition, { body: self.condition }),
+ self.body,
+ ],
});
self.condition = null;
}
@@ -8894,7 +8888,7 @@ merge(Compressor.prototype, {
if (!compressor.option("optional_chains")) return;
if (!self.optional) return;
var expr = self.expression;
- var ev = expr.evaluate(compressor, true);
+ var ev = fuzzy_eval(compressor, expr, true);
if (ev == null) return make_node(AST_UnaryPrefix, self, {
operator: "void",
expression: expr,
@@ -10492,7 +10486,7 @@ merge(Compressor.prototype, {
}
// (x || false) && y ---> x ? y : false
if (self.left.operator == "||") {
- var lr = self.left.right.evaluate(compressor, true);
+ var lr = fuzzy_eval(compressor, self.left.right);
if (!lr) return make_node(AST_Conditional, self, {
condition: self.left.left,
consequent: self.right,
@@ -10545,7 +10539,7 @@ merge(Compressor.prototype, {
}
// x && true || y ---> x ? true : y
if (!nullish && self.left.operator == "&&") {
- var lr = self.left.right.is_truthy() || self.left.right.evaluate(compressor, true);
+ var lr = fuzzy_eval(compressor, self.left.right);
if (lr && !(lr instanceof AST_Node)) return make_node(AST_Conditional, self, {
condition: self.left.left,
consequent: self.left.right,
@@ -11070,21 +11064,16 @@ merge(Compressor.prototype, {
}
var local = self.fixed !== def.fixed;
if (fixed && (local || def.should_replace !== false)) {
- var init;
+ var ev, init;
if (fixed instanceof AST_This) {
- if (!is_funarg(def) && same_scope(def)) {
- init = fixed;
- }
- } else {
- 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);
- }
+ if (!is_funarg(def) && same_scope(def)) init = fixed;
+ } else if ((ev = fixed.evaluate(compressor, true)) !== fixed
+ && typeof ev != "function"
+ && (ev === null
+ || typeof ev != "object"
+ || compressor.option("unsafe_regexp")
+ && ev instanceof RegExp && !def.cross_loop && same_scope(def))) {
+ init = make_node_from_constant(ev, fixed);
}
if (init) {
if (!local && def.should_replace === undefined) {
diff --git a/test/compress/default-values.js b/test/compress/default-values.js
index b3662715..de5374fa 100644
--- a/test/compress/default-values.js
+++ b/test/compress/default-values.js
@@ -149,7 +149,7 @@ process_boolean_returns: {
}
expect: {
console.log(function(a = console.log("FAIL 1")) {
- return a() ? "PASS" : "FAIL 2";
+ return 42 ? "PASS" : "FAIL 2";
}(function() {
return 1;
}));
@@ -245,21 +245,64 @@ maintain_if: {
node_version: ">=6"
}
-reduce_value: {
+reduce_funarg: {
options = {
evaluate: true,
+ keep_fargs: false,
reduce_vars: true,
unused: true,
}
input: {
- console.log(function(a = "PASS") {
- return a;
+ console.log(...function(a = "foo", b = "bar", c = "baz") {
+ return [ a, b, c ];
+ }(void 0, null));
+ }
+ expect: {
+ console.log(...function() {
+ return [ "foo", null, "baz" ];
}());
}
+ expect_stdout: "foo null baz"
+ node_version: ">=6"
+}
+
+reduce_array: {
+ options = {
+ evaluate: true,
+ reduce_vars: true,
+ toplevel: true,
+ unsafe: true,
+ unused: true,
+ }
+ input: {
+ var [ a = "foo", b = "bar", c = "baz" ] = [ void 0, null ];
+ console.log(a, b, c);
+ }
expect: {
- console.log("PASS");
+ var [ , , c = "baz" ] = [ void 0, null ];
+ console.log("foo", null, c);
}
- expect_stdout: "PASS"
+ expect_stdout: "foo null baz"
+ node_version: ">=6"
+}
+
+reduce_object: {
+ options = {
+ evaluate: true,
+ reduce_vars: true,
+ toplevel: true,
+ unsafe: true,
+ unused: true,
+ }
+ input: {
+ var { a = "foo", b = "bar", c = "baz" } = { a: void 0, b: null };
+ console.log(a, b, c);
+ }
+ expect: {
+ var { c = "baz" } = { a: void 0, b: null };
+ console.log("foo", null, c);
+ }
+ expect_stdout: "foo null baz"
node_version: ">=6"
}
diff --git a/test/compress/hoist_vars.js b/test/compress/hoist_vars.js
index 97987fd9..39a27275 100644
--- a/test/compress/hoist_vars.js
+++ b/test/compress/hoist_vars.js
@@ -323,9 +323,7 @@ issue_4893_1: {
expect: {
try{
(function f() {
- var b;
- b = null;
- b.p += 42;
+ null.p += 42;
f;
})();
} catch (e) {
diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js
index 66c70d5a..ebb6229a 100644
--- a/test/compress/reduce_vars.js
+++ b/test/compress/reduce_vars.js
@@ -1292,6 +1292,7 @@ toplevel_on_loops_3: {
loops: true,
reduce_funcs: true,
reduce_vars: true,
+ side_effects: true,
toplevel: true,
unused: true,
}