[Pkg-javascript-commits] [uglifyjs] 155/228: handle overlapped variable definitions (#1691)

Jonas Smedegaard dr at jones.dk
Sat Apr 15 14:25:26 UTC 2017


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

js pushed a commit to branch master
in repository uglifyjs.

commit 57ce5bd9e085546a5c1cb8dd4a3ea71ab6c56f26
Author: Alex Lam S.L <alexlamsl at gmail.com>
Date:   Mon Mar 27 01:30:21 2017 +0800

    handle overlapped variable definitions (#1691)
    
    Process variable definitions with or without assigned values against:
    - `arguments`
    - named function arguments
    - multiple definitions within same scope
    
    Essentially demote variable declarations with no value assignments.
    
    Also fixed invalid use of `AST_VarDef` over `arguments` - should use a member of `AST_SymbolDeclaration` instead.
---
 lib/compress.js              |  17 ++-
 lib/scope.js                 |  32 ++---
 test/compress/reduce_vars.js | 289 ++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 314 insertions(+), 24 deletions(-)

diff --git a/lib/compress.js b/lib/compress.js
index 83486b6..590015f 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -260,7 +260,7 @@ merge(Compressor.prototype, {
                 if (node instanceof AST_SymbolRef) {
                     var d = node.definition();
                     d.references.push(node);
-                    if (!d.fixed || !is_safe(d)
+                    if (d.fixed === undefined || !is_safe(d)
                         || is_modified(node, 0, d.fixed instanceof AST_Lambda)) {
                         d.fixed = false;
                     }
@@ -270,10 +270,10 @@ merge(Compressor.prototype, {
                 }
                 if (node instanceof AST_VarDef) {
                     var d = node.name.definition();
-                    if (d.fixed === undefined) {
-                        d.fixed = node.value || make_node(AST_Undefined, node);
+                    if (d.fixed == null) {
+                        d.fixed = node.value;
                         mark_as_safe(d);
-                    } else {
+                    } else if (node.value) {
                         d.fixed = false;
                     }
                 }
@@ -357,7 +357,14 @@ merge(Compressor.prototype, {
 
         function is_safe(def) {
             for (var i = safe_ids.length, id = def.id; --i >= 0;) {
-                if (safe_ids[i][id]) return true;
+                if (safe_ids[i][id]) {
+                    if (def.fixed == null) {
+                        var orig = def.orig[0];
+                        if (orig instanceof AST_SymbolFunarg || orig.name == "arguments") return false;
+                        def.fixed = make_node(AST_Undefined, orig);
+                    }
+                    return true;
+                }
             }
         }
 
diff --git a/lib/scope.js b/lib/scope.js
index 483503e..b255032 100644
--- a/lib/scope.js
+++ b/lib/scope.js
@@ -100,15 +100,14 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
         if (node instanceof AST_Catch) {
             var save_scope = scope;
             scope = new AST_Scope(node);
-            scope.init_scope_vars();
-            scope.parent_scope = save_scope;
+            scope.init_scope_vars(save_scope);
             descend();
             scope = save_scope;
             return true;
         }
         if (node instanceof AST_Scope) {
-            node.init_scope_vars();
-            var save_scope = node.parent_scope = scope;
+            node.init_scope_vars(scope);
+            var save_scope = scope;
             var save_defun = defun;
             var save_labels = labels;
             defun = scope = node;
@@ -243,23 +242,24 @@ AST_Toplevel.DEFMETHOD("def_global", function(node){
     }
 });
 
-AST_Scope.DEFMETHOD("init_scope_vars", function(){
-    this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
-    this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
-    this.uses_with = false;   // will be set to true if this or some nested scope uses the `with` statement
-    this.uses_eval = false;   // will be set to true if this or nested scope uses the global `eval`
-    this.parent_scope = null; // the parent scope
-    this.enclosed = [];       // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
-    this.cname = -1;          // the current index for mangling functions/variables
+AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope){
+    this.variables = new Dictionary();  // map name to AST_SymbolVar (variables defined in this scope; includes functions)
+    this.functions = new Dictionary();  // map name to AST_SymbolDefun (functions defined in this scope)
+    this.uses_with = false;             // will be set to true if this or some nested scope uses the `with` statement
+    this.uses_eval = false;             // will be set to true if this or nested scope uses the global `eval`
+    this.parent_scope = parent_scope;   // the parent scope
+    this.enclosed = [];                 // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
+    this.cname = -1;                    // the current index for mangling functions/variables
 });
 
 AST_Lambda.DEFMETHOD("init_scope_vars", function(){
     AST_Scope.prototype.init_scope_vars.apply(this, arguments);
     this.uses_arguments = false;
-
-    var symbol = new AST_VarDef({ name: "arguments", start: this.start, end: this.end });
-    var def = new SymbolDef(this, this.variables.size(), symbol);
-    this.variables.set(symbol.name, def);
+    this.def_variable(new AST_SymbolVar({
+        name: "arguments",
+        start: this.start,
+        end: this.end
+    }));
 });
 
 AST_SymbolRef.DEFMETHOD("reference", function(options) {
diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js
index f4dd68d..87942ab 100644
--- a/test/compress/reduce_vars.js
+++ b/test/compress/reduce_vars.js
@@ -425,7 +425,7 @@ iife_new: {
     expect_stdout: true
 }
 
-multi_def: {
+multi_def_1: {
     options = {
         evaluate: true,
         reduce_vars: true,
@@ -435,7 +435,7 @@ multi_def: {
             if (a)
                 var b = 1;
             else
-                var b = 2
+                var b = 2;
             console.log(b + 1);
         }
     }
@@ -444,7 +444,7 @@ multi_def: {
             if (a)
                 var b = 1;
             else
-                var b = 2
+                var b = 2;
             console.log(b + 1);
         }
     }
@@ -479,6 +479,33 @@ multi_def_2: {
     }
 }
 
+multi_def_3: {
+    options = {
+        evaluate: true,
+        reduce_vars: true,
+    }
+    input: {
+        function f(a) {
+            var b = 2;
+            if (a)
+                var b;
+            else
+                var b;
+            console.log(b + 1);
+        }
+    }
+    expect: {
+        function f(a) {
+            var b = 2;
+            if (a)
+                var b;
+            else
+                var b;
+            console.log(3);
+        }
+    }
+}
+
 use_before_var: {
     options = {
         evaluate: true,
@@ -1571,3 +1598,259 @@ unary_delete: {
     }
     expect_stdout: true
 }
+
+redefine_arguments_1: {
+    options = {
+        evaluate: true,
+        keep_fargs: false,
+        reduce_vars: true,
+        unused: true,
+    }
+    input: {
+        function f() {
+            var arguments;
+            return typeof arguments;
+        }
+        function g() {
+            var arguments = 42;
+            return typeof arguments;
+        }
+        function h(x) {
+            var arguments = x;
+            return typeof arguments;
+        }
+        console.log(f(), g(), h());
+    }
+    expect: {
+        function f() {
+            var arguments;
+            return typeof arguments;
+        }
+        function g() {
+            return"number";
+        }
+        function h(x) {
+            var arguments = x;
+            return typeof arguments;
+        }
+        console.log(f(), g(), h());
+    }
+    expect_stdout: "object number undefined"
+}
+
+redefine_arguments_2: {
+    options = {
+        evaluate: true,
+        keep_fargs: false,
+        reduce_vars: true,
+        side_effects: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        function f() {
+            var arguments;
+            return typeof arguments;
+        }
+        function g() {
+            var arguments = 42;
+            return typeof arguments;
+        }
+        function h(x) {
+            var arguments = x;
+            return typeof arguments;
+        }
+        console.log(f(), g(), h());
+    }
+    expect: {
+        console.log(function() {
+            var arguments;
+            return typeof arguments;
+        }(), function() {
+            return"number";
+        }(), function(x) {
+            var arguments = x;
+            return typeof arguments;
+        }());
+    }
+    expect_stdout: "object number undefined"
+}
+
+redefine_arguments_3: {
+    options = {
+        evaluate: true,
+        keep_fargs: false,
+        passes: 3,
+        reduce_vars: true,
+        side_effects: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        function f() {
+            var arguments;
+            return typeof arguments;
+        }
+        function g() {
+            var arguments = 42;
+            return typeof arguments;
+        }
+        function h(x) {
+            var arguments = x;
+            return typeof arguments;
+        }
+        console.log(f(), g(), h());
+    }
+    expect: {
+        console.log(function() {
+            var arguments;
+            return typeof arguments;
+        }(), "number", "undefined");
+    }
+    expect_stdout: "object number undefined"
+}
+
+redefine_farg_1: {
+    options = {
+        evaluate: true,
+        keep_fargs: false,
+        reduce_vars: true,
+        unused: true,
+    }
+    input: {
+        function f(a) {
+            var a;
+            return typeof a;
+        }
+        function g(a) {
+            var a = 42;
+            return typeof a;
+        }
+        function h(a, b) {
+            var a = b;
+            return typeof a;
+        }
+        console.log(f([]), g([]), h([]));
+    }
+    expect: {
+        function f(a) {
+            var a;
+            return typeof a;
+        }
+        function g() {
+            return"number";
+        }
+        function h(a, b) {
+            var a = b;
+            return typeof a;
+        }
+        console.log(f([]), g([]), h([]));
+    }
+    expect_stdout: "object number undefined"
+}
+
+redefine_farg_2: {
+    options = {
+        evaluate: true,
+        keep_fargs: false,
+        reduce_vars: true,
+        side_effects: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        function f(a) {
+            var a;
+            return typeof a;
+        }
+        function g(a) {
+            var a = 42;
+            return typeof a;
+        }
+        function h(a, b) {
+            var a = b;
+            return typeof a;
+        }
+        console.log(f([]), g([]), h([]));
+    }
+    expect: {
+        console.log(function(a) {
+            var a;
+            return typeof a;
+        }([]), function() {
+            return "number";
+        }(),function(a, b) {
+            var a = b;
+            return typeof a;
+        }([]));
+    }
+    expect_stdout: "object number undefined"
+}
+
+redefine_farg_3: {
+    options = {
+        evaluate: true,
+        keep_fargs: false,
+        passes: 3,
+        reduce_vars: true,
+        side_effects: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        function f(a) {
+            var a;
+            return typeof a;
+        }
+        function g(a) {
+            var a = 42;
+            return typeof a;
+        }
+        function h(a, b) {
+            var a = b;
+            return typeof a;
+        }
+        console.log(f([]), g([]), h([]));
+    }
+    expect: {
+        console.log(function(a) {
+            var a;
+            return typeof a;
+        }([]), "number", function(a) {
+            var a = void 0;
+            return typeof a;
+        }([]));
+    }
+    expect_stdout: "object number undefined"
+}
+
+delay_def: {
+    options = {
+        evaluate: true,
+        reduce_vars: true,
+        unused: true,
+    }
+    input: {
+        function f() {
+            return a;
+            var a;
+        }
+        function g() {
+            return a;
+            var a = 1;
+        }
+        console.log(f(), g());
+    }
+    expect: {
+        function f() {
+            return a;
+            var a;
+        }
+        function g() {
+            return a;
+            var a = 1;
+        }
+        console.log(f(), g());
+    }
+    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