fix corner case in `reduce_vars` (#4563)
authorAlex Lam S.L <alexlamsl@gmail.com>
Sun, 17 Jan 2021 17:47:07 +0000 (17:47 +0000)
committerGitHub <noreply@github.com>
Sun, 17 Jan 2021 17:47:07 +0000 (01:47 +0800)
fixes #4562

lib/compress.js
test/compress/rests.js
test/input/reduce/destructured_catch.reduced.js
test/reduce.js

index 6bbae0f..d5334a9 100644 (file)
@@ -620,7 +620,7 @@ merge(Compressor.prototype, {
                     var save = fixed;
                     if (save) fixed = function() {
                         var value = save();
-                        return is_undefined(value) ? make_sequence(node, [ value, node.value ]) : node.name;
+                        return is_undefined(value) ? make_sequence(node, [ value, node.value ]) : node;
                     };
                     node.name.walk(scanner);
                     fixed = save;
@@ -646,7 +646,7 @@ merge(Compressor.prototype, {
                             var value = save();
                             return value instanceof AST_Array ? make_node(AST_Array, node, {
                                 elements: value.elements.slice(node.elements.length),
-                            }) : node.rest;
+                            }) : node;
                         };
                         node.rest.walk(scanner);
                     }
index 6bc5b75..017f871 100644 (file)
@@ -646,3 +646,20 @@ issue_4544_2: {
     expect_stdout: "PASS"
     node_version: ">=6"
 }
+
+issue_4562: {
+    options = {
+        evaluate: true,
+        reduce_vars: true,
+        rests: true,
+        unsafe: true,
+    }
+    input: {
+        console.log((([ ...[ a ] ]) => a)("foo"));
+    }
+    expect: {
+        console.log((([ a ]) => a)("foo"));
+    }
+    expect_stdout: "f"
+    node_version: ">=6"
+}
index c7a6736..1979b99 100644 (file)
@@ -1,14 +1,12 @@
 // (beautified)
 try {
     1 in 0;
-} catch ({
-    message: message
-}) {
+} catch (message) {
     console.log(message);
 }
-// output: Cannot use 'in' operator to search for '1' in 0
+// output: TypeError: Cannot use 'in' operator to search for '1' in 0
 // 
-// minify: Cannot use 'in' operator to search for '0' in 0
+// minify: TypeError: Cannot use 'in' operator to search for '0' in 0
 // 
 // options: {
 //   "mangle": false
index 3f24b7b..c478da5 100644 (file)
@@ -104,15 +104,14 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
 
             // quick ignores
             if (node instanceof U.AST_Accessor) return;
-            if (node instanceof U.AST_Destructured) return;
             if (node instanceof U.AST_Directive) return;
             if (!in_list && node instanceof U.AST_EmptyStatement) return;
             if (node instanceof U.AST_Label) return;
             if (node instanceof U.AST_LabelRef) return;
-            if (!in_list && node instanceof U.AST_SymbolDeclaration) return;
             if (node instanceof U.AST_Toplevel) return;
             var parent = tt.parent();
             if (node instanceof U.AST_SymbolFunarg && parent instanceof U.AST_Accessor) return;
+            if (!in_list && parent.rest !== node && node instanceof U.AST_SymbolDeclaration) return;
 
             // ensure that the _permute prop is a number.
             // can not use `node.start._permute |= 0;` as it will erase fractional part.
@@ -124,6 +123,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
 
             // ignore lvalues
             if (parent instanceof U.AST_Assign && parent.left === node) return;
+            if (parent instanceof U.AST_DefaultValue && parent.name === node) return;
             if (parent instanceof U.AST_DestructuredKeyVal && parent.value === node) return;
             if (parent instanceof U.AST_Unary && parent.expression === node) switch (parent.operator) {
               case "++":
@@ -229,6 +229,23 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
                 CHANGED = true;
                 return node.name;
             }
+            else if (node instanceof U.AST_DestructuredArray) {
+                var expr = node.elements[0];
+                if (expr && !(expr instanceof U.AST_Hole)) {
+                    node.start._permute++;
+                    CHANGED = true;
+                    return expr;
+                }
+            }
+            else if (node instanceof U.AST_DestructuredObject) {
+                // first property's value
+                var expr = node.properties[0];
+                if (expr) {
+                    node.start._permute++;
+                    CHANGED = true;
+                    return expr.value;
+                }
+            }
             else if (node instanceof U.AST_Defun) {
                 switch (((node.start._permute += step) * steps | 0) % 2) {
                   case 0:
@@ -443,15 +460,6 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
                     CHANGED = true;
                     return List.skip;
                 }
-
-                // skip element/property from (destructured) array/object
-                if (parent instanceof U.AST_Array
-                    || parent instanceof U.AST_Destructured
-                    || parent instanceof U.AST_Object) {
-                    node.start._permute++;
-                    CHANGED = true;
-                    return List.skip;
-                }
             } else if (parent.rest === node) {
                 node.start._permute++;
                 CHANGED = true;