enhance `evaluate` (#3649)
authorAlex Lam S.L <alexlamsl@gmail.com>
Sat, 28 Dec 2019 20:26:15 +0000 (20:26 +0000)
committerGitHub <noreply@github.com>
Sat, 28 Dec 2019 20:26:15 +0000 (20:26 +0000)
bin/uglifyjs
lib/ast.js
lib/compress.js
lib/output.js
test/compress/hoist_props.js
test/compress/numbers.js

index ace94e7..dc9baf8 100755 (executable)
@@ -59,7 +59,7 @@ if (program.configFile) {
     if (options.mangle && options.mangle.properties && options.mangle.properties.regex) {
         options.mangle.properties.regex = UglifyJS.parse(options.mangle.properties.regex, {
             expression: true
-        }).getValue();
+        }).value;
     }
 }
 if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
@@ -370,7 +370,7 @@ function parse_js(flag) {
                 if (!(node instanceof UglifyJS.AST_Sequence)) throw node;
 
                 function to_string(value) {
-                    return value instanceof UglifyJS.AST_Constant ? value.getValue() : value.print_to_string({
+                    return value instanceof UglifyJS.AST_Constant ? value.value : value.print_to_string({
                         quote_keys: true
                     });
                 }
index b170491..3088590 100644 (file)
@@ -618,7 +618,7 @@ var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
     getProperty: function() {
         var p = this.property;
         if (p instanceof AST_Constant) {
-            return p.getValue();
+            return p.value;
         }
         if (p instanceof AST_UnaryPrefix
             && p.operator == "void"
@@ -824,9 +824,6 @@ var AST_This = DEFNODE("This", null, {
 
 var AST_Constant = DEFNODE("Constant", null, {
     $documentation: "Base class for all constants",
-    getValue: function() {
-        return this.value;
-    }
 });
 
 var AST_String = DEFNODE("String", "value quote", {
index e277e9a..77f5d47 100644 (file)
@@ -3014,7 +3014,7 @@ merge(Compressor.prototype, {
         def(AST_Lambda, return_this);
         def(AST_Node, return_this);
         def(AST_Constant, function() {
-            return this.getValue();
+            return this.value;
         });
         def(AST_Function, function(compressor) {
             if (compressor.option("unsafe")) {
@@ -4877,7 +4877,7 @@ merge(Compressor.prototype, {
         var sym = condition.right.expression;
         if (!is_undeclared_ref(sym)) return;
         var body;
-        var undef = condition.left.getValue() == "undefined";
+        var undef = condition.left.value == "undefined";
         switch (condition.operator) {
           case "==":
             body = undef ? alternative : consequent;
@@ -5313,7 +5313,7 @@ merge(Compressor.prototype, {
                 if (self.args.length == 1) {
                     var first = self.args[0];
                     if (first instanceof AST_Number) try {
-                        var length = first.getValue();
+                        var length = first.value;
                         if (length > 6) break;
                         var elements = Array(length);
                         for (var i = 0; i < length; i++) elements[i] = make_node(AST_Hole, self);
@@ -6071,7 +6071,7 @@ merge(Compressor.prototype, {
             // "undefined" == typeof x => undefined === x
             else if (compressor.option("typeofs")
                 && self.left instanceof AST_String
-                && self.left.getValue() == "undefined"
+                && self.left.value == "undefined"
                 && self.right instanceof AST_UnaryPrefix
                 && self.right.operator == "typeof") {
                 var expr = self.right.expression;
@@ -6143,7 +6143,7 @@ merge(Compressor.prototype, {
             }
             break;
           case "==":
-            if (self.left instanceof AST_String && self.left.getValue() == "" && self.right.is_string(compressor)) {
+            if (self.left instanceof AST_String && self.left.value == "" && self.right.is_string(compressor)) {
                 return make_node(AST_UnaryPrefix, self, {
                     operator: "!",
                     expression: self.right
@@ -6151,7 +6151,7 @@ merge(Compressor.prototype, {
             }
             break;
           case "!=":
-            if (self.left instanceof AST_String && self.left.getValue() == "" && self.right.is_string(compressor)) {
+            if (self.left instanceof AST_String && self.left.value == "" && self.right.is_string(compressor)) {
                 return self.right.optimize(compressor);
             }
             break;
@@ -6172,19 +6172,19 @@ merge(Compressor.prototype, {
         }
         if (self.operator == "+") {
             if (self.right instanceof AST_String
-                && self.right.getValue() == ""
+                && self.right.value == ""
                 && self.left.is_string(compressor)) {
                 return self.left.optimize(compressor);
             }
             if (self.left instanceof AST_String
-                && self.left.getValue() == ""
+                && self.left.value == ""
                 && self.right.is_string(compressor)) {
                 return self.right.optimize(compressor);
             }
             if (self.left instanceof AST_Binary
                 && self.left.operator == "+"
                 && self.left.left instanceof AST_String
-                && self.left.left.getValue() == ""
+                && self.left.left.value == ""
                 && self.right.is_string(compressor)) {
                 self.left = self.left.right;
                 return self.optimize(compressor);
@@ -6270,7 +6270,7 @@ merge(Compressor.prototype, {
                     self = make_node(AST_Binary, self, {
                         operator: "+",
                         left: make_node(AST_String, self.left, {
-                            value: "" + self.left.getValue() + self.right.left.getValue(),
+                            value: "" + self.left.value + self.right.left.value,
                             start: self.left.start,
                             end: self.right.left.end
                         }),
@@ -6287,7 +6287,7 @@ merge(Compressor.prototype, {
                         operator: "+",
                         left: self.left.left,
                         right: make_node(AST_String, self.right, {
-                            value: "" + self.left.right.getValue() + self.right.getValue(),
+                            value: "" + self.left.right.value + self.right.value,
                             start: self.left.right.start,
                             end: self.right.end
                         })
@@ -6308,7 +6308,7 @@ merge(Compressor.prototype, {
                             operator: "+",
                             left: self.left.left,
                             right: make_node(AST_String, self.left.right, {
-                                value: "" + self.left.right.getValue() + self.right.left.getValue(),
+                                value: "" + self.left.right.value + self.right.left.value,
                                 start: self.left.right.start,
                                 end: self.right.left.end
                             })
@@ -6391,8 +6391,8 @@ merge(Compressor.prototype, {
                 // a + +b => +b + a
                 if (self.operator != "-"
                     && self.operator != "/"
-                    && self.left.is_number(compressor)
-                    && self.right.is_number(compressor)
+                    && (self.left.is_boolean(compressor) || self.left.is_number(compressor))
+                    && (self.right.is_boolean(compressor) || self.right.is_number(compressor))
                     && reversible()
                     && !(self.left instanceof AST_Binary
                         && self.left.operator != self.operator
@@ -6455,6 +6455,43 @@ merge(Compressor.prototype, {
                 }
                 break;
             }
+            if (self.left instanceof AST_Number && !self.right.is_constant()) switch (self.operator) {
+              // 0 + n => n
+              case "+":
+                if (self.left.value == 0) {
+                    if (self.right.is_number(compressor)) return self.right;
+                    if (self.right.is_boolean(compressor)) return make_node(AST_UnaryPrefix, self, {
+                        operator: "+",
+                        expression: self.right
+                    }).optimize(compressor);
+                }
+                break;
+              // 0 - n => -n
+              case "-":
+                if (self.left.value == 0) return make_node(AST_UnaryPrefix, self, {
+                    operator: "-",
+                    expression: self.right
+                }).optimize(compressor);
+                break;
+              // 1 * n => n
+              case "*":
+                if (self.left.value == 1) {
+                    return self.right.is_number(compressor) ? self.right : make_node(AST_UnaryPrefix, self, {
+                        operator: "+",
+                        expression: self.right
+                    }).optimize(compressor);
+                }
+                break;
+            }
+            // n - 0 => n
+            // n / 1 => n
+            if (self.right instanceof AST_Number && !self.left.is_constant() && self.right.value == {
+                "-": 0,
+                "/": 1,
+            }[self.operator]) return self.left.is_number(compressor) ? self.left : make_node(AST_UnaryPrefix, self, {
+                operator: "+",
+                expression: self.left
+            }).optimize(compressor);
         }
         if (compressor.option("typeofs")) switch (self.operator) {
           case "&&":
@@ -6470,7 +6507,7 @@ merge(Compressor.prototype, {
                 && indexRight
                 && (self.operator == "==" || self.operator == "!=")
                 && self.left instanceof AST_Number
-                && self.left.getValue() == 0) {
+                && self.left.value == 0) {
                 return (self.operator == "==" ? make_node(AST_UnaryPrefix, self, {
                     operator: "!",
                     expression: self.right
@@ -6573,19 +6610,19 @@ merge(Compressor.prototype, {
             switch (self.operator) {
               case "<=":
                 // 0 <= array.indexOf(string) => !!~array.indexOf(string)
-                return indexRight && self.left instanceof AST_Number && self.left.getValue() == 0;
+                return indexRight && self.left instanceof AST_Number && self.left.value == 0;
               case "<":
                 // array.indexOf(string) < 0 => !~array.indexOf(string)
-                if (indexLeft && self.right instanceof AST_Number && self.right.getValue() == 0) return true;
+                if (indexLeft && self.right instanceof AST_Number && self.right.value == 0) return true;
                 // -1 < array.indexOf(string) => !!~array.indexOf(string)
               case "==":
               case "!=":
                 // -1 == array.indexOf(string) => !~array.indexOf(string)
                 // -1 != array.indexOf(string) => !!~array.indexOf(string)
                 if (!indexRight) return false;
-                return self.left instanceof AST_Number && self.left.getValue() == -1
+                return self.left instanceof AST_Number && self.left.value == -1
                     || self.left instanceof AST_UnaryPrefix && self.left.operator == "-"
-                        && self.left.expression instanceof AST_Number && self.left.expression.getValue() == 1;
+                        && self.left.expression instanceof AST_Number && self.left.expression.value == 1;
             }
         }
     });
@@ -6906,7 +6943,7 @@ merge(Compressor.prototype, {
         if ((self.operator == "-=" || self.operator == "+="
                 && (self.left.is_boolean(compressor) || self.left.is_number(compressor)))
             && self.right instanceof AST_Number
-            && self.right.getValue() === 1) {
+            && self.right.value == 1) {
             var op = self.operator.slice(0, -1);
             return make_node(AST_UnaryPrefix, self, {
                 operator: op + op,
@@ -7149,22 +7186,22 @@ merge(Compressor.prototype, {
             return node instanceof AST_True
                 || in_bool
                     && node instanceof AST_Constant
-                    && node.getValue()
+                    && node.value
                 || (node instanceof AST_UnaryPrefix
                     && node.operator == "!"
                     && node.expression instanceof AST_Constant
-                    && !node.expression.getValue());
+                    && !node.expression.value);
         }
         // AST_False or !1
         function is_false(node) {
             return node instanceof AST_False
                 || in_bool
                     && node instanceof AST_Constant
-                    && !node.getValue()
+                    && !node.value
                 || (node instanceof AST_UnaryPrefix
                     && node.operator == "!"
                     && node.expression instanceof AST_Constant
-                    && node.expression.getValue());
+                    && node.expression.value);
         }
 
         function arg_diff() {
@@ -7272,7 +7309,7 @@ merge(Compressor.prototype, {
             && is_arguments(def = expr.definition())
             && prop instanceof AST_Number
             && (fn = expr.scope) === find_lambda()) {
-            var index = prop.getValue();
+            var index = prop.value;
             if (parent instanceof AST_UnaryPrefix && parent.operator == "delete") {
                 if (!def.deleted) def.deleted = [];
                 def.deleted[index] = true;
@@ -7318,7 +7355,7 @@ merge(Compressor.prototype, {
         }
         if (compressor.option("properties") && compressor.option("side_effects")
             && prop instanceof AST_Number && expr instanceof AST_Array) {
-            var index = prop.getValue();
+            var index = prop.value;
             var elements = expr.elements;
             var retValue = elements[index];
             if (safe_to_flatten(retValue, compressor)) {
index 38b4f8b..a63671c 100644 (file)
@@ -782,7 +782,7 @@ function OutputStream(options) {
     PARENS(AST_Number, function(output) {
         var p = output.parent();
         if (p instanceof AST_PropAccess && p.expression === this) {
-            var value = this.getValue();
+            var value = this.value;
             if (value < 0 || /^0/.test(make_num(value))) {
                 return true;
             }
@@ -1212,7 +1212,7 @@ function OutputStream(options) {
             output.print_string(prop);
             output.print("]");
         } else {
-            if (expr instanceof AST_Number && expr.getValue() >= 0) {
+            if (expr instanceof AST_Number && expr.value >= 0) {
                 if (!/[xa-f.)]/i.test(output.last())) {
                     output.print(".");
                 }
@@ -1336,21 +1336,21 @@ function OutputStream(options) {
         output.print("this");
     });
     DEFPRINT(AST_Constant, function(self, output) {
-        output.print(self.getValue());
+        output.print(self.value);
     });
     DEFPRINT(AST_String, function(self, output) {
-        output.print_string(self.getValue(), self.quote);
+        output.print_string(self.value, self.quote);
     });
     DEFPRINT(AST_Number, function(self, output) {
         if (use_asm && self.start && self.start.raw != null) {
             output.print(self.start.raw);
         } else {
-            output.print(make_num(self.getValue()));
+            output.print(make_num(self.value));
         }
     });
 
     DEFPRINT(AST_RegExp, function(self, output) {
-        var regexp = self.getValue();
+        var regexp = self.value;
         var str = regexp.toString();
         if (regexp.raw_source) {
             str = "/" + regexp.raw_source + str.slice(str.lastIndexOf("/"));
index 0d8e771..c647ccc 100644 (file)
@@ -664,7 +664,7 @@ issue_2519: {
     }
     expect: {
         function testFunc() {
-            return 1 * ((6 + 5) / 2);
+            return +((6 + 5) / 2);
         }
         console.log(testFunc());
     }
index 673ce23..c432a43 100644 (file)
@@ -91,7 +91,7 @@ evaluate_1: {
     expect: {
         console.log(
             x + 1 + 2,
-            1 * x * 2,
+            2 * x,
             +x + 1 + 2,
             1 + x + 2 + 3,
             3 | x,
@@ -173,7 +173,7 @@ evaluate_2: {
         var x = "42", y = null;
         [
             x + 1 + 2,
-            1 * x * 2,
+            2 * x,
             +x + 1 + 2,
             1 + x + 2 + 3,
             3 | x,
@@ -979,3 +979,81 @@ unsafe_math_swap_constant: {
     }
     expect_stdout: "6 6 7 6 6 8 9 10"
 }
+
+identity_1: {
+    options = {
+        evaluate: true,
+    }
+    input: {
+        0 + a;
+        a + 0;
+        0 - a;
+        a - 0;
+        1 * a;
+        a * 1;
+        1 / a;
+        a / 1;
+    }
+    expect: {
+        0 + a;
+        a + 0;
+        -a;
+        +a;
+        +a;
+        +a;
+        1 / a;
+        +a;
+    }
+}
+
+identity_2: {
+    options = {
+        evaluate: true,
+    }
+    input: {
+        0 + !a;
+        !a + 0;
+        0 - !a;
+        !a - 0;
+        1 * !a;
+        !a * 1;
+        1 / !a;
+        !a / 1;
+    }
+    expect: {
+        +!a;
+        +!a;
+        -!a;
+        +!a;
+        +!a;
+        +!a;
+        1 / !a;
+        +!a;
+    }
+}
+
+identity_3: {
+    options = {
+        evaluate: true,
+    }
+    input: {
+        0 + --a;
+        --a + 0;
+        0 - --a;
+        --a - 0;
+        1 * --a;
+        --a * 1;
+        1 / --a;
+        --a / 1;
+    }
+    expect: {
+        --a;
+        --a;
+        - --a;
+        --a;
+        --a;
+        --a;
+        1 / --a;
+        --a;
+    }
+}