fix deep cloning of labels (#1565)
authorAlex Lam S.L <alexlamsl@gmail.com>
Tue, 7 Mar 2017 10:38:27 +0000 (18:38 +0800)
committerGitHub <noreply@github.com>
Tue, 7 Mar 2017 10:38:27 +0000 (18:38 +0800)
`AST_Label.references` get `.initialize()` to `[]` every time after `.clone()`

So walk down the tree to pick up the cloned `AST_LoopControl` pieces and put it back together.

lib/ast.js
test/compress/reduce_vars.js

index a2125e7..f7ab52e 100644 (file)
@@ -91,7 +91,7 @@ var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos
 }, null);
 
 var AST_Node = DEFNODE("Node", "start end", {
-    clone: function(deep) {
+    _clone: function(deep) {
         if (deep) {
             var self = this.clone();
             return self.transform(new TreeTransformer(function(node) {
@@ -102,6 +102,9 @@ var AST_Node = DEFNODE("Node", "start end", {
         }
         return new this.CTOR(this);
     },
+    clone: function(deep) {
+        return this._clone(deep);
+    },
     $documentation: "Base class of all AST nodes",
     $propdoc: {
         start: "[AST_Token] The first token of this node",
@@ -207,6 +210,20 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
             this.label._walk(visitor);
             this.body._walk(visitor);
         });
+    },
+    clone: function(deep) {
+        var node = this._clone(deep);
+        if (deep) {
+            var refs = node.label.references;
+            var label = this.label;
+            node.walk(new TreeWalker(function(node) {
+                if (node instanceof AST_LoopControl
+                    && node.label && node.label.thedef === label) {
+                    refs.push(node);
+                }
+            }));
+        }
+        return node;
     }
 }, AST_StatementWithBody);
 
index a373de2..53e2815 100644 (file)
@@ -1093,3 +1093,32 @@ func_modified: {
         }
     }
 }
+
+defun_label: {
+    options = {
+        passes: 2,
+        reduce_vars: true,
+        unused: true,
+    }
+    input: {
+        !function() {
+            function f(a) {
+                L: {
+                    if (a) break L;
+                    return 1;
+                }
+            }
+            console.log(f(2));
+        }();
+    }
+    expect: {
+        !function() {
+            console.log(function(a) {
+                L: {
+                    if (a) break L;
+                    return 1;
+                }
+            }(2));
+        }();
+    }
+}