extend `join_vars` on object assignments (#3072)
authorAlex Lam S.L <alexlamsl@gmail.com>
Tue, 10 Apr 2018 17:35:42 +0000 (01:35 +0800)
committerGitHub <noreply@github.com>
Tue, 10 Apr 2018 17:35:42 +0000 (01:35 +0800)
lib/compress.js
test/compress/properties.js

index 5323a86..7660e67 100644 (file)
@@ -1882,9 +1882,6 @@ merge(Compressor.prototype, {
         }
 
         function join_object_assignments(defn, body) {
-            if (!(defn instanceof AST_Definitions)) return;
-            var def = defn.definitions[defn.definitions.length - 1];
-            if (!(def.value instanceof AST_Object)) return;
             var exprs;
             if (body instanceof AST_Assign) {
                 exprs = [ body ];
@@ -1892,6 +1889,23 @@ merge(Compressor.prototype, {
                 exprs = body.expressions.slice();
             }
             if (!exprs) return;
+            if (defn instanceof AST_Definitions) {
+                var def = defn.definitions[defn.definitions.length - 1];
+                if (trim_object_assignments(def.name, def.value, exprs)) return exprs;
+            }
+            for (var i = exprs.length - 1; --i >= 0;) {
+                var expr = exprs[i];
+                if (!(expr instanceof AST_Assign)) continue;
+                if (expr.operator != "=") continue;
+                if (!(expr.left instanceof AST_SymbolRef)) continue;
+                var tail = exprs.slice(i + 1);
+                if (!trim_object_assignments(expr.left, expr.right, tail)) continue;
+                return exprs.slice(0, i + 1).concat(tail);
+            }
+        }
+
+        function trim_object_assignments(name, value, exprs) {
+            if (!(value instanceof AST_Object)) return;
             var trimmed = false;
             do {
                 var node = exprs[0];
@@ -1900,7 +1914,7 @@ merge(Compressor.prototype, {
                 if (!(node.left instanceof AST_PropAccess)) break;
                 var sym = node.left.expression;
                 if (!(sym instanceof AST_SymbolRef)) break;
-                if (def.name.name != sym.name) break;
+                if (name.name != sym.name) break;
                 if (!node.right.is_constant_expression(scope)) break;
                 var prop = node.left.property;
                 if (prop instanceof AST_Node) {
@@ -1913,15 +1927,15 @@ merge(Compressor.prototype, {
                 } : function(node) {
                     return node.key.name != prop;
                 };
-                if (!all(def.value.properties, diff)) break;
-                def.value.properties.push(make_node(AST_ObjectKeyVal, node, {
+                if (!all(value.properties, diff)) break;
+                value.properties.push(make_node(AST_ObjectKeyVal, node, {
                     key: prop,
                     value: node.right
                 }));
                 exprs.shift();
                 trimmed = true;
             } while (exprs.length);
-            return trimmed && exprs;
+            return trimmed;
         }
 
         function join_consecutive_vars(statements) {
index ec99c09..efe0d49 100644 (file)
@@ -1208,6 +1208,37 @@ join_object_assignments_3: {
     expect_stdout: "PASS"
 }
 
+join_object_assignments_4: {
+    options = {
+        join_vars: true,
+        sequences: true,
+    }
+    input: {
+        var o;
+        console.log(o);
+        o = {};
+        o.a = "foo";
+        console.log(o.b);
+        o.b = "bar";
+        console.log(o.a);
+    }
+    expect: {
+        var o;
+        console.log(o),
+        o = {
+            a: "foo",
+        },
+        console.log(o.b),
+        o.b = "bar",
+        console.log(o.a);
+    }
+    expect_stdout: [
+        "undefined",
+        "undefined",
+        "foo",
+    ]
+}
+
 join_object_assignments_return_1: {
     options = {
         join_vars: true,