[Pkg-javascript-commits] [uglifyjs] 446/491: improve `unused` on built-in functions (#2817)

Jonas Smedegaard dr at jones.dk
Wed Feb 14 19:52:03 UTC 2018


This is an automated email from the git hooks/post-receive script.

js pushed a commit to annotated tag debian/3.3.10-1
in repository uglifyjs.

commit 3e7873217cad8b6f67839cb06d1e126ca231bc42
Author: Alex Lam S.L <alexlamsl at gmail.com>
Date:   Fri Jan 19 20:41:57 2018 +0800

    improve `unused` on built-in functions (#2817)
---
 lib/compress.js                | 216 ++++++++++++++++++++++++++---------------
 test/compress/collapse_vars.js |  23 +++++
 test/compress/dead-code.js     |  17 ++++
 test/compress/evaluate.js      |  36 +++++--
 4 files changed, 205 insertions(+), 87 deletions(-)

diff --git a/lib/compress.js b/lib/compress.js
index 00593e8..5235a05 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -2113,6 +2113,95 @@ merge(Compressor.prototype, {
         return (first_in_statement(compressor) ? best_of_statement : best_of_expression)(ast1, ast2);
     }
 
+    function convert_to_predicate(obj) {
+        for (var key in obj) {
+            obj[key] = makePredicate(obj[key]);
+        }
+    }
+
+    var object_fns = [
+        "constructor",
+        "toString",
+        "valueOf",
+    ];
+    var native_fns = {
+        Array: [
+            "indexOf",
+            "join",
+            "lastIndexOf",
+            "slice",
+        ].concat(object_fns),
+        Boolean: object_fns,
+        Number: [
+            "toExponential",
+            "toFixed",
+            "toPrecision",
+        ].concat(object_fns),
+        Object: object_fns,
+        RegExp: [
+            "test",
+        ].concat(object_fns),
+        String: [
+            "charAt",
+            "charCodeAt",
+            "concat",
+            "indexOf",
+            "italics",
+            "lastIndexOf",
+            "match",
+            "replace",
+            "search",
+            "slice",
+            "split",
+            "substr",
+            "substring",
+            "trim",
+        ].concat(object_fns),
+    };
+    convert_to_predicate(native_fns);
+    var static_fns = {
+        Array: [
+            "isArray",
+        ],
+        Math: [
+            "abs",
+            "acos",
+            "asin",
+            "atan",
+            "ceil",
+            "cos",
+            "exp",
+            "floor",
+            "log",
+            "round",
+            "sin",
+            "sqrt",
+            "tan",
+            "atan2",
+            "pow",
+            "max",
+            "min",
+        ],
+        Number: [
+            "isFinite",
+            "isNaN",
+        ],
+        Object: [
+            "create",
+            "getOwnPropertyDescriptor",
+            "getOwnPropertyNames",
+            "getPrototypeOf",
+            "isExtensible",
+            "isFrozen",
+            "isSealed",
+            "keys",
+        ],
+        String: [
+            "fromCharCode",
+        ],
+    };
+    convert_to_predicate(static_fns);
+
     // methods to evaluate a constant expression
     (function(def){
         // If the node has been successfully reduced to a constant,
@@ -2278,13 +2367,9 @@ merge(Compressor.prototype, {
             Array: Array,
             Math: Math,
             Number: Number,
+            Object: Object,
             String: String,
         };
-        function convert_to_predicate(obj) {
-            for (var key in obj) {
-                obj[key] = makePredicate(obj[key]);
-            }
-        }
         var static_values = {
             Math: [
                 "E",
@@ -2325,77 +2410,6 @@ merge(Compressor.prototype, {
             }
             return this;
         });
-        var object_fns = [
-            "constructor",
-            "toString",
-            "valueOf",
-        ];
-        var native_fns = {
-            Array: [
-                "indexOf",
-                "join",
-                "lastIndexOf",
-                "slice",
-            ].concat(object_fns),
-            Boolean: object_fns,
-            Number: [
-                "toExponential",
-                "toFixed",
-                "toPrecision",
-            ].concat(object_fns),
-            RegExp: [
-                "test",
-            ].concat(object_fns),
-            String: [
-                "charAt",
-                "charCodeAt",
-                "concat",
-                "indexOf",
-                "italics",
-                "lastIndexOf",
-                "match",
-                "replace",
-                "search",
-                "slice",
-                "split",
-                "substr",
-                "substring",
-                "trim",
-            ].concat(object_fns),
-        };
-        convert_to_predicate(native_fns);
-        var static_fns = {
-            Array: [
-                "isArray",
-            ],
-            Math: [
-                "abs",
-                "acos",
-                "asin",
-                "atan",
-                "ceil",
-                "cos",
-                "exp",
-                "floor",
-                "log",
-                "round",
-                "sin",
-                "sqrt",
-                "tan",
-                "atan2",
-                "pow",
-                "max",
-                "min"
-            ],
-            Number: [
-                "isFinite",
-                "isNaN",
-            ],
-            String: [
-                "fromCharCode",
-            ],
-        };
-        convert_to_predicate(static_fns);
         def(AST_Call, function(compressor, depth) {
             var exp = this.expression;
             if (compressor.option("unsafe") && exp instanceof AST_PropAccess) {
@@ -2420,7 +2434,16 @@ merge(Compressor.prototype, {
                     if (arg === value) return this;
                     args.push(value);
                 }
-                return val[key].apply(val, args);
+                try {
+                    return val[key].apply(val, args);
+                } catch (ex) {
+                    compressor.warn("Error evaluating {code} [{file}:{line},{col}]", {
+                        code: this.print_to_string(),
+                        file: this.start.file,
+                        line: this.start.line,
+                        col: this.start.col
+                    });
+                }
             }
             return this;
         });
@@ -2511,9 +2534,34 @@ merge(Compressor.prototype, {
         if (compressor.option("unsafe")) {
             var expr = this.expression;
             if (is_undeclared_ref(expr) && global_pure_fns(expr.name)) return true;
+            if (expr instanceof AST_Dot
+                && is_undeclared_ref(expr.expression)
+                && (static_fns[expr.expression.name] || return_false)(expr.property)) {
+                return true;
+            }
         }
         return this.pure || !compressor.pure_funcs(this);
     });
+    AST_Node.DEFMETHOD("is_call_pure", return_false);
+    AST_Dot.DEFMETHOD("is_call_pure", function(compressor) {
+        if (!compressor.option("unsafe")) return;
+        var expr = this.expression;
+        var fns = return_false;
+        if (expr instanceof AST_Array) {
+            fns = native_fns.Array;
+        } else if (expr.is_boolean()) {
+            fns = native_fns.Boolean;
+        } else if (expr.is_number(compressor)) {
+            fns = native_fns.Number;
+        } else if (expr instanceof AST_RegExp) {
+            fns = native_fns.RegExp;
+        } else if (expr.is_string(compressor)) {
+            fns = native_fns.String;
+        } else if (!this.may_throw_on_access(compressor)) {
+            fns = native_fns.Object;
+        }
+        return fns(this.property);
+    });
 
     // determine if expression has side effects
     (function(def){
@@ -2534,8 +2582,12 @@ merge(Compressor.prototype, {
             return any(this.body, compressor);
         });
         def(AST_Call, function(compressor){
-            return !this.is_expr_pure(compressor)
-                || any(this.args, compressor);
+            if (!this.is_expr_pure(compressor)
+                && (!this.expression.is_call_pure(compressor)
+                    || this.expression.has_side_effects(compressor))) {
+                return true;
+            }
+            return any(this.args, compressor);
         });
         def(AST_Switch, function(compressor){
             return this.expression.has_side_effects(compressor)
@@ -3365,6 +3417,12 @@ merge(Compressor.prototype, {
         def(AST_This, return_null);
         def(AST_Call, function(compressor, first_in_statement){
             if (!this.is_expr_pure(compressor)) {
+                if (this.expression.is_call_pure(compressor)) {
+                    var exprs = this.args.slice();
+                    exprs.unshift(this.expression.expression);
+                    exprs = trim(exprs, compressor, first_in_statement);
+                    return exprs && make_sequence(this, exprs);
+                }
                 if (this.expression instanceof AST_Function
                     && (!this.expression.name || !this.expression.name.definition().references.length)) {
                     var node = this.clone();
diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js
index 9597b67..970f822 100644
--- a/test/compress/collapse_vars.js
+++ b/test/compress/collapse_vars.js
@@ -4089,3 +4089,26 @@ cascade_forin: {
         "2",
     ]
 }
+
+unsafe_builtin: {
+    options = {
+        collapse_vars: true,
+        pure_getters: "strict",
+        unsafe: true,
+        unused: true,
+    }
+    input: {
+        function f(a) {
+            var b = Math.abs(a);
+            return Math.pow(b, 2);
+        }
+        console.log(f(-1), f(2));
+    }
+    expect: {
+        function f(a) {
+            return Math.pow(Math.abs(a), 2);
+        }
+        console.log(f(-1), f(2));
+    }
+    expect_stdout: "1 4"
+}
diff --git a/test/compress/dead-code.js b/test/compress/dead-code.js
index afc8c56..b66d5ac 100644
--- a/test/compress/dead-code.js
+++ b/test/compress/dead-code.js
@@ -862,3 +862,20 @@ issue_2749: {
     }
     expect_stdout: "PASS"
 }
+
+unsafe_builtin: {
+    options = {
+        side_effects: true,
+        unsafe: true,
+    }
+    input: {
+        (!w).constructor(x);
+        Math.abs(y);
+        [ 1, 2, z ].valueOf();
+    }
+    expect: {
+        w, x;
+        y;
+        z;
+    }
+}
diff --git a/test/compress/evaluate.js b/test/compress/evaluate.js
index 6106fce..d40880f 100644
--- a/test/compress/evaluate.js
+++ b/test/compress/evaluate.js
@@ -1194,6 +1194,9 @@ issue_2231_1: {
         console.log(Object.keys(void 0));
     }
     expect_stdout: true
+    expect_warnings: [
+        "WARN: Error evaluating Object.keys(void 0) [test/compress/evaluate.js:1191,20]",
+    ]
 }
 
 issue_2231_2: {
@@ -1208,6 +1211,23 @@ issue_2231_2: {
         console.log(Object.getOwnPropertyNames(null));
     }
     expect_stdout: true
+    expect_warnings: [
+        "WARN: Error evaluating Object.getOwnPropertyNames(null) [test/compress/evaluate.js:1208,20]",
+    ]
+}
+
+issue_2231_3: {
+    options = {
+        evaluate: true,
+        unsafe: true,
+    }
+    input: {
+        console.log(Object.keys({ foo: "bar" })[0]);
+    }
+    expect: {
+        console.log("foo");
+    }
+    expect_stdout: "foo"
 }
 
 self_comparison_1: {
@@ -1330,13 +1350,13 @@ issue_2535_3: {
     }
     expect_stdout: true
     expect_warnings: [
-        "WARN: Dropping side-effect-free && [test/compress/evaluate.js:1316,20]",
-        "WARN: Dropping side-effect-free && [test/compress/evaluate.js:1317,20]",
-        "WARN: Dropping side-effect-free && [test/compress/evaluate.js:1318,20]",
-        "WARN: Condition left of && always false [test/compress/evaluate.js:1318,20]",
-        "WARN: Dropping side-effect-free || [test/compress/evaluate.js:1319,20]",
-        "WARN: Dropping side-effect-free || [test/compress/evaluate.js:1320,20]",
-        "WARN: Dropping side-effect-free || [test/compress/evaluate.js:1321,20]",
-        "WARN: Condition left of || always true [test/compress/evaluate.js:1321,20]",
+        "WARN: Dropping side-effect-free && [test/compress/evaluate.js:1336,20]",
+        "WARN: Dropping side-effect-free && [test/compress/evaluate.js:1337,20]",
+        "WARN: Dropping side-effect-free && [test/compress/evaluate.js:1338,20]",
+        "WARN: Condition left of && always false [test/compress/evaluate.js:1338,20]",
+        "WARN: Dropping side-effect-free || [test/compress/evaluate.js:1339,20]",
+        "WARN: Dropping side-effect-free || [test/compress/evaluate.js:1340,20]",
+        "WARN: Dropping side-effect-free || [test/compress/evaluate.js:1341,20]",
+        "WARN: Condition left of || always true [test/compress/evaluate.js:1341,20]",
     ]
 }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/uglifyjs.git



More information about the Pkg-javascript-commits mailing list