Repository: mishoo/UglifyJS (JavaScript)

Issue:
ufuzz failure
```js
// original code
// (beautified)
var _calls_ = 10, a = 100, b = 10, c = 0;

function f0(foo_2, await_1, Infinity_1) {
    a++ + ~b;
    if ({}[--b + [].null]) {
        ({
            Infinity: typeof f0 == "function" && --_calls_ >= 0 && f0(),
            "-2": 1 === 1 ? a : b,
            in: (c = c + 1) + foo_2,
            ...Infinity_1
        })[void b];
    } else {
        var foo_2_1 = 0 === 1 ? a : b, [ await_1 = a++ + (b = a), Math_1, async ] = [], bar = --b + ((await_1 = (22 !== "bar") <= (c = c + 1, 
        false)) + (c = c + 1, [ , 0 ].length === 2 ^ Infinity));
    }
}

console.log(null, a, b, c, Infinity, NaN, undefined);
```
```
// !!! uglify failed !!!
Error: left must be assignable: UnaryPrefix
    at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:1377:27)
    at validate_destructured (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:1432:5)
    at validate_destructured (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:1425:67)
    at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:1427:42)
    at Array.forEach (<anonymous>)
    at validate_destructured (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:1426:69)
    at AST_Assign._validate (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:1375:13)
    at AST_Assign.validate (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:387:38)
    at AST_Assign.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:434:22)
    at AST_Assign.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
    at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3818:25)
    at List (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:120:23)
    at do_list (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3817:16)
    at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3913:28)
    at Compressor.before (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:6608:9)
    at AST_Sequence.eval [as transform] (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3964:31)
    at AST_Sequence.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
    at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3938:45)
    at Compressor.before (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:6608:9)
    at AST_Conditional.eval [as transform] (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3964:31)
    at AST_Conditional.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
    at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3828:31)
    at Compressor.before (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:6608:9)
    at AST_SimpleStatement.eval [as transform] (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3964:31)
    at AST_SimpleStatement.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
    at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3818:25)
    at List (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:120:23)
    at do_list (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3817:16)
    at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3831:21)
    at Compressor.before (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:6608:9)
    at AST_BlockStatement.eval [as transform] (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3964:31)
    at AST_BlockStatement.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
    at AST_BlockStatement.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
    at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3818:25)
    at List (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:120:23)
    at do_list (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3817:16)
    at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3898:21)
    at Compressor.before (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:6612:9)
    at AST_Defun.eval [as transform] (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3964:31)
    at AST_Defun.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
    at AST_Defun.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
    at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3818:25)
    at List (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:120:23)
    at do_list (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3817:16)
    at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3831:21)
    at Compressor.before (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:6608:9)
    at AST_Toplevel.eval [as transform] (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3964:31)
    at AST_Toplevel.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
    at AST_Toplevel.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
    at AST_Toplevel.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
    at Compressor.compress (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:6567:25)
    at Object.minify (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:18151:57)
    at /home/runner/work/UglifyJS/UglifyJS/test/ufuzz/index.js:1841:32
    at Array.forEach (<anonymous>)
    at Object.<anonymous> (/home/runner/work/UglifyJS/UglifyJS/test/ufuzz/index.js:1837:20)
    at Module._compile (module.js:653:30)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)
    at Function.Module.runMain (module.js:694:10)
    at startup (bootstrap_node.js:204:16)
    at bootstrap_node.js:625:3
```
```js
// reduced test case (output will differ)

// (beautified)
function f0() {
    if (0..null) {} else {
        var [ await_1 = 0, Math_1, async ] = 0, bar = await_1 = 0;
    }
}
// minify error: Error: left must be assignable: Number
//     at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:1377:27)
//     at validate_destructured (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:1432:5)
//     at validate_destructured (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:1425:67)
//     at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:1427:42)
//     at Array.forEach (<anonymous>)
//     at validate_destructured (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:1426:69)
//     at AST_Assign._validate (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:1375:13)
//     at AST_Assign.validate (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:387:38)
//     at AST_Assign.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:434:22)
//     at AST_Assign.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
//     at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3818:25)
//     at List (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:120:23)
//     at do_list (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3817:16)
//     at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3913:28)
//     at Compressor.before (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:6608:9)
//     at AST_Sequence.eval [as transform] (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3964:31)
//     at AST_Sequence.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
//     at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3933:33)
//     at Compressor.before (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:6608:9)
//     at AST_Binary.eval [as transform] (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3964:31)
//     at AST_Binary.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
//     at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:13565:24)
//     at AST_If.eval [as optimize] (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:16861:19)
//     at Compressor.before (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:6613:24)
//     at AST_If.eval [as transform] (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3964:31)
//     at AST_If.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
//     at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3818:25)
//     at List (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:120:23)
//     at do_list (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3817:16)
//     at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3898:21)
//     at Compressor.before (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:6608:9)
//     at AST_Defun.eval [as transform] (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3964:31)
//     at AST_Defun.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
//     at AST_Defun.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
//     at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3818:25)
//     at List (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:120:23)
//     at do_list (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3817:16)
//     at eval (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3831:21)
//     at Compressor.before (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:6608:9)
//     at AST_Toplevel.eval [as transform] (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:3964:31)
//     at AST_Toplevel.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
//     at AST_Toplevel.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
//     at AST_Toplevel.ctor.transform (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:432:34)
//     at Compressor.compress (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:6567:25)
//     at Object.minify (eval at <anonymous> (/home/runner/work/UglifyJS/UglifyJS/tools/node.js:18:1), <anonymous>:18151:57)
//     at test_minify (/home/runner/work/UglifyJS/UglifyJS/test/reduce.js:742:22)
//     at reduce_test (/home/runner/work/UglifyJS/UglifyJS/test/reduce.js:579:20)
//     at log (/home/runner/work/UglifyJS/UglifyJS/test/ufuzz/index.js:1686:23)
//     at /home/runner/work/UglifyJS/UglifyJS/test/ufuzz/index.js:1880:80
//     at Array.forEach (<anonymous>)
//     at Object.<anonymous> (/home/runner/work/UglifyJS/UglifyJS/test/ufuzz/index.js:1837:20)
//     at Module._compile (module.js:653:30)
//     at Object.Module._extensions..js (module.js:664:10)
//     at Module.load (module.js:566:32)
//     at tryModuleLoad (module.js:506:12)
//     at Function.Module._load (module.js:498:3)
//     at Function.Module.runMain (module.js:694:10)
//     at startup (bootstrap_node.js:204:16)
//     at bootstrap_node.js:625:3
// options: {
//   "mangle": false,
//   "output": {
//     "v8": true
//   },
//   "validate": true
// }
```
```
minify(options):
{
  "mangle": false,
  "output": {
    "v8": true
  }
}

Suspicious compress options:
  booleans
  conditionals
  evaluate
  reduce_vars
```


Discussion:

Patch:
diff --git a/lib/compress.js b/lib/compress.js
index 3ac9e74d924..aea3155a2c8 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -3603,6 +3603,7 @@ merge(Compressor.prototype, {
 
     function is_lhs(node, parent) {
         if (parent instanceof AST_Assign) return parent.left === node && node;
+        if (parent instanceof AST_DefaultValue) return parent.name === node && node;
         if (parent instanceof AST_Destructured) return node;
         if (parent instanceof AST_DestructuredKeyVal) return node;
         if (parent instanceof AST_Unary) return unary_side_effects[parent.operator] && parent.expression;


Test patch:
diff --git a/test/compress/default-values.js b/test/compress/default-values.js
index 39fcddbd612..5b21ae6a761 100644
--- a/test/compress/default-values.js
+++ b/test/compress/default-values.js
@@ -1206,3 +1206,24 @@ issue_4468: {
     expect_stdout: "PASS"
     node_version: ">=6"
 }
+
+issue_4483: {
+    options = {
+        conditionals: true,
+        evaluate: true,
+        reduce_vars: true,
+        toplevel: true,
+    }
+    input: {
+        if (console)
+            var [ a = "FAIL" ] = [], b = a = "PASS";
+        console.log(b);
+    }
+    expect: {
+        var a, b;
+        console && ([ a = "FAIL" ] = [], b = "PASS");
+        console.log(b);
+    }
+    expect_stdout: "PASS"
+    node_version: ">=6"
+}
diff --git a/test/reduce.js b/test/reduce.js
index 48030b0fec2..120868fee08 100644
--- a/test/reduce.js
+++ b/test/reduce.js
@@ -124,7 +124,6 @@ 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_DestructuredArray) return;
             if (parent instanceof U.AST_DestructuredKeyVal && parent.value === node) return;
             if (parent instanceof U.AST_Unary && parent.expression === node) switch (parent.operator) {
               case "++":