[Pkg-javascript-commits] [uglifyjs] 223/491: perform `reduce_vars` on safe literals (#2351)

Jonas Smedegaard dr at jones.dk
Wed Feb 14 19:51:38 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 b810e2f8da4bfd42a8876b64d067e83dfd340aa1
Author: Alex Lam S.L <alexlamsl at gmail.com>
Date:   Mon Oct 9 12:25:06 2017 +0800

    perform `reduce_vars` on safe literals (#2351)
    
    - constant expression
    - single reference
    - same scope
    - not across loop body
---
 lib/compress.js                |  63 +++++++++++---
 test/compress/collapse_vars.js |  40 ++++++---
 test/compress/drop-unused.js   |  12 +--
 test/compress/evaluate.js      |  14 ++-
 test/compress/reduce_vars.js   | 193 ++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 286 insertions(+), 36 deletions(-)

diff --git a/lib/compress.js b/lib/compress.js
index 33b4ef0..c3876f9 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -297,6 +297,8 @@ merge(Compressor.prototype, {
             if (node instanceof AST_SymbolRef) d.references.push(node);
             d.fixed = false;
         });
+        var in_loop = null;
+        var loop_ids = Object.create(null);
         var tw = new TreeWalker(function(node, descend) {
             node._squeezed = false;
             node._optimized = false;
@@ -307,7 +309,7 @@ merge(Compressor.prototype, {
                     var d = node.definition();
                     d.references.push(node);
                     if (d.fixed === undefined || !safe_to_read(d)
-                        || is_modified(node, 0, is_immutable(node.fixed_value()))) {
+                        || is_modified(node, 0, is_immutable(node))) {
                         d.fixed = false;
                     } else {
                         var parent = tw.parent();
@@ -329,6 +331,7 @@ merge(Compressor.prototype, {
                             d.fixed = function() {
                                 return node.value;
                             };
+                            loop_ids[d.id] = in_loop;
                             mark(d, false);
                             descend();
                         } else {
@@ -384,6 +387,7 @@ merge(Compressor.prototype, {
                                 d.fixed = function() {
                                     return iife.args[i] || make_node(AST_Undefined, iife);
                                 };
+                                loop_ids[d.id] = in_loop;
                                 mark(d, true);
                             } else {
                                 d.fixed = false;
@@ -431,10 +435,13 @@ merge(Compressor.prototype, {
                     return true;
                 }
                 if (node instanceof AST_DWLoop) {
+                    var saved_loop = in_loop;
+                    in_loop = node;
                     push();
                     node.condition.walk(tw);
                     node.body.walk(tw);
                     pop();
+                    in_loop = saved_loop;
                     return true;
                 }
                 if (node instanceof AST_LabeledStatement) {
@@ -445,6 +452,8 @@ merge(Compressor.prototype, {
                 }
                 if (node instanceof AST_For) {
                     if (node.init) node.init.walk(tw);
+                    var saved_loop = in_loop;
+                    in_loop = node;
                     if (node.condition) {
                         push();
                         node.condition.walk(tw);
@@ -458,14 +467,18 @@ merge(Compressor.prototype, {
                         node.step.walk(tw);
                         pop();
                     }
+                    in_loop = saved_loop;
                     return true;
                 }
                 if (node instanceof AST_ForIn) {
                     node.init.walk(suppressor);
                     node.object.walk(tw);
+                    var saved_loop = in_loop;
+                    in_loop = node;
                     push();
                     node.body.walk(tw);
                     pop();
+                    in_loop = saved_loop;
                     return true;
                 }
                 if (node instanceof AST_Try) {
@@ -535,10 +548,23 @@ merge(Compressor.prototype, {
             }
             def.references = [];
             def.should_replace = undefined;
-        }
-
-        function is_immutable(value) {
-            return value && value.is_constant() || value instanceof AST_Lambda;
+            def.single_use = undefined;
+        }
+
+        function is_immutable(node) {
+            var value = node.fixed_value();
+            if (!value) return false;
+            if (value.is_constant()) return true;
+            if (compressor.option("unused")) {
+                var d = node.definition();
+                if (d.single_use === undefined) {
+                    d.single_use = loop_ids[d.id] === in_loop
+                        && d.scope === node.scope
+                        && value.is_constant_expression();
+                }
+                if (d.references.length == 1 && d.single_use) return true;
+            }
+            return value instanceof AST_Lambda;
         }
 
         function is_modified(node, level, immutable) {
@@ -2115,6 +2141,22 @@ merge(Compressor.prototype, {
         }
         def(AST_Node, return_false);
         def(AST_Constant, return_true);
+        def(AST_Function, function(){
+            var self = this;
+            var result = true;
+            self.walk(new TreeWalker(function(node) {
+                if (!result) return true;
+                if (node instanceof AST_SymbolRef) {
+                    var def = node.definition();
+                    if (self.enclosed.indexOf(def) >= 0
+                        && self.variables.get(def.name) !== def) {
+                        result = false;
+                        return true;
+                    }
+                }
+            }));
+            return result;
+        });
         def(AST_Unary, function(){
             return this.expression.is_constant_expression();
         });
@@ -4078,12 +4120,13 @@ merge(Compressor.prototype, {
                 d.fixed = fixed = make_node(AST_Function, fixed, fixed);
             }
             if (compressor.option("unused")
-                && fixed instanceof AST_Function
                 && d.references.length == 1
-                && !(d.scope.uses_arguments && d.orig[0] instanceof AST_SymbolFunarg)
-                && !d.scope.uses_eval
-                && compressor.find_parent(AST_Scope) === fixed.parent_scope) {
-                return fixed.clone(true);
+                && (d.single_use || fixed instanceof AST_Function
+                    && !(d.scope.uses_arguments && d.orig[0] instanceof AST_SymbolFunarg)
+                    && !d.scope.uses_eval
+                    && compressor.find_parent(AST_Scope) === fixed.parent_scope)) {
+                var value = fixed.optimize(compressor);
+                return value === fixed ? fixed.clone(true) : value;
             }
             if (compressor.option("evaluate") && fixed) {
                 if (d.should_replace === undefined) {
diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js
index 631f5b2..7d66f7c 100644
--- a/test/compress/collapse_vars.js
+++ b/test/compress/collapse_vars.js
@@ -1268,22 +1268,21 @@ collapse_vars_short_circuited_conditions: {
 
 collapse_vars_regexp: {
     options = {
+        booleans:      true,
+        cascade:       true,
         collapse_vars: true,
-        loops:         false,
-        sequences:     true,
-        dead_code:     true,
-        conditionals:  true,
         comparisons:   true,
+        conditionals:  true,
+        dead_code:     true,
         evaluate:      true,
-        booleans:      true,
-        unused:        true,
-        hoist_funs:    true,
-        keep_fargs:    true,
         if_return:     true,
         join_vars:     true,
-        cascade:       true,
-        side_effects:  true,
+        hoist_funs:    true,
+        keep_fargs:    true,
+        loops:         false,
         reduce_vars:   true,
+        side_effects:  true,
+        unused:        true,
     }
     input: {
         function f1() {
@@ -1292,12 +1291,12 @@ collapse_vars_regexp: {
             return [rx, k];
         }
         function f2() {
-            var rx = /[abc123]+/;
+            var rx = /ab*/g;
             return function(s) {
                 return rx.exec(s);
             };
         }
-        (function(){
+        (function() {
             var result;
             var s = 'acdabcdeabbb';
             var rx = /ab*/g;
@@ -1305,22 +1304,35 @@ collapse_vars_regexp: {
                 console.log(result[0]);
             }
         })();
+        (function() {
+            var result;
+            var s = 'acdabcdeabbb';
+            var rx = f2();
+            while (result = rx(s)) {
+                console.log(result[0]);
+            }
+        })();
     }
     expect: {
         function f1() {
             return [/[A-Z]+/, 9];
         }
         function f2() {
-            var rx = /[abc123]+/;
+            var rx = /ab*/g;
             return function(s) {
                 return rx.exec(s);
             };
         }
-        (function(){
+        (function() {
             var result, rx = /ab*/g;
             while (result = rx.exec("acdabcdeabbb"))
                 console.log(result[0]);
         })();
+        (function() {
+            var result, rx = f2();
+            while (result = rx("acdabcdeabbb"))
+                console.log(result[0]);
+        })();
     }
     expect_stdout: true
 }
diff --git a/test/compress/drop-unused.js b/test/compress/drop-unused.js
index c904854..4ce8d2e 100644
--- a/test/compress/drop-unused.js
+++ b/test/compress/drop-unused.js
@@ -751,12 +751,12 @@ issue_1583: {
     expect: {
         function m(t) {
             (function(e) {
-                t = e();
-            })(function() {
-                return (function(a) {
-                    return a;
-                })(function(a) {});
-            });
+                t = function() {
+                    return (function(a) {
+                        return function(a) {};
+                    })();
+                }();
+            })();
         }
     }
 }
diff --git a/test/compress/evaluate.js b/test/compress/evaluate.js
index 1c73706..5f5a4a9 100644
--- a/test/compress/evaluate.js
+++ b/test/compress/evaluate.js
@@ -1021,6 +1021,7 @@ issue_1964_1: {
     input: {
         function f() {
             var long_variable_name = /\s/;
+            console.log(long_variable_name.source);
             return "a b c".split(long_variable_name)[1];
         }
         console.log(f());
@@ -1028,11 +1029,15 @@ issue_1964_1: {
     expect: {
         function f() {
             var long_variable_name = /\s/;
+            console.log(long_variable_name.source);
             return "a b c".split(long_variable_name)[1];
         }
         console.log(f());
     }
-    expect_stdout: "b"
+    expect_stdout: [
+        "\\s",
+        "b",
+    ]
 }
 
 issue_1964_2: {
@@ -1045,17 +1050,22 @@ issue_1964_2: {
     input: {
         function f() {
             var long_variable_name = /\s/;
+            console.log(long_variable_name.source);
             return "a b c".split(long_variable_name)[1];
         }
         console.log(f());
     }
     expect: {
         function f() {
+            console.log(/\s/.source);
             return "a b c".split(/\s/)[1];
         }
         console.log(f());
     }
-    expect_stdout: "b"
+    expect_stdout: [
+        "\\s",
+        "b",
+    ]
 }
 
 array_slice_index: {
diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js
index 4e096d9..c1da299 100644
--- a/test/compress/reduce_vars.js
+++ b/test/compress/reduce_vars.js
@@ -172,6 +172,7 @@ unsafe_evaluate: {
     options = {
         evaluate     : true,
         reduce_vars  : true,
+        side_effects : true,
         unsafe       : true,
         unused       : true
     }
@@ -1898,10 +1899,7 @@ redefine_farg_3: {
         console.log(f([]), g([]), h([]));
     }
     expect: {
-        console.log(function(a) {
-            var a;
-            return typeof a;
-        }([]), "number", "undefined");
+        console.log(typeof [], "number", "undefined");
     }
     expect_stdout: "object number undefined"
 }
@@ -2629,3 +2627,190 @@ for_in_prop: {
     }
     expect_stdout: "1"
 }
+
+obj_var_1: {
+    options = {
+        evaluate: true,
+        passes: 2,
+        reduce_vars: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var C = 1;
+        var obj = {
+            bar: function() {
+                return C + C;
+            }
+        };
+        console.log(obj.bar());
+    }
+    expect: {
+        console.log({
+            bar: function() {
+                return 2;
+            }
+        }.bar());
+    }
+    expect_stdout: "2"
+}
+
+obj_var_2: {
+    options = {
+        evaluate: true,
+        inline: true,
+        passes: 2,
+        reduce_vars: true,
+        side_effects: true,
+        toplevel: true,
+        unsafe: true,
+        unused: true,
+    }
+    input: {
+        var C = 1;
+        var obj = {
+            bar: function() {
+                return C + C;
+            }
+        };
+        console.log(obj.bar());
+    }
+    expect: {
+        console.log(2);
+    }
+    expect_stdout: "2"
+}
+
+obj_arg_1: {
+    options = {
+        evaluate: true,
+        inline: true,
+        passes: 2,
+        reduce_vars: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var C = 1;
+        function f(obj) {
+            return obj.bar();
+        }
+        console.log(f({
+            bar: function() {
+                return C + C;
+            }
+        }));
+    }
+    expect: {
+        console.log({
+            bar: function() {
+                return 2;
+            }
+        }.bar());
+    }
+    expect_stdout: "2"
+}
+
+obj_arg_2: {
+    options = {
+        evaluate: true,
+        inline: true,
+        passes: 2,
+        reduce_vars: true,
+        side_effects: true,
+        toplevel: true,
+        unsafe: true,
+        unused: true,
+    }
+    input: {
+        var C = 1;
+        function f(obj) {
+            return obj.bar();
+        }
+        console.log(f({
+            bar: function() {
+                return C + C;
+            }
+        }));
+    }
+    expect: {
+        console.log(2);
+    }
+    expect_stdout: "2"
+}
+
+func_arg_1: {
+    options = {
+        evaluate: true,
+        inline: true,
+        passes: 2,
+        reduce_vars: true,
+        side_effects: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var a = 42;
+        !function(a) {
+            console.log(a());
+        }(function() {
+            return a;
+        });
+    }
+    expect: {
+        console.log(42);
+    }
+    expect_stdout: "42"
+}
+
+func_arg_2: {
+    options = {
+        evaluate: true,
+        inline: true,
+        passes: 2,
+        reduce_vars: true,
+        side_effects: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var a = 42;
+        !function(a) {
+            console.log(a());
+        }(function(a) {
+            return a;
+        });
+    }
+    expect: {
+        console.log(void 0);
+    }
+    expect_stdout: "undefined"
+}
+
+regex_loop: {
+    options = {
+        reduce_vars: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        function f(x) {
+            for (var r, s = "acdabcdeabbb"; r = x().exec(s);)
+                console.log(r[0]);
+        }
+        var a = /ab*/g;
+        f(function() {
+            return a;
+        });
+    }
+    expect: {
+        var a = /ab*/g;
+        (function(x) {
+            for (var r, s = "acdabcdeabbb"; r = x().exec(s);)
+                console.log(r[0]);
+        })(function() {
+            return a;
+        });
+    }
+    expect_stdout: true
+}

-- 
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