Repository: mishoo/UglifyJS (JavaScript)

Issue:
ufuzz failure
```js
// original code
// (beautified)
var _calls_ = 10, a = 100, b = 10, c = 0;

{
    var a = function f0(undefined, async_2, foo_2) {
        function f1(foo_1, foo) {
            {
                {
                    var brake3 = 5;
                    while ("foo" && --brake3 > 0) {
                        var arguments_1 = (c = 1 + c, Infinity && (Infinity.in = ("function" || -3 || (foo = {} != "number")) * (("foo" === undefined) >= (NaN | -0)))), Infinity = (c = 1 + c, 
                        ([ , 0 ][1] >= -4) << (c = c + 1, "object") >= (this <= -2 ^ "number" <= 25));
                    }
                }
                c = c + 1;
                L20030: for (var brake6 = 5; arguments_1 && typeof arguments_1.Infinity == "function" && --_calls_ >= 0 && arguments_1.Infinity(4, -0) && brake6 > 0; --brake6) {
                    for (var brake7 = 5; (c = 1 + c, ((-2 >>> "undefined") + (-1 >>> 23..toString())) * ((c = c + 1, 
                    4) % (false && /[a2][^e]+$/))) && brake7 > 0; --brake7) {
                        c = 1 + c, (c = c + 1, c = c + 1, 2) ^ ("foo" >= ([ , 0 ].length === 2)) << (-4 == 25);
                    }
                }
            }
            {
                var brake9 = 5;
                while (function a_2() {} && --brake9 > 0) {
                    return;
                    ({
                        length: (c = 1 + c, ((-0, 38..toString()) || "number" ^ "c") % ([] - -5 - (38..toString(), 
                        0))),
                        in: (c = 1 + c, void (/[a2][^e]+$/ - "b") - ((2 & "object") <= ("number" | "b"))),
                        b: (c = 1 + c, (25 | "function") << (38..toString() == -5) || +(foo_2 && ({
                            in: foo_2.a
                        } = {
                            in: this | -2
                        }))),
                        foo_1: foo_1
                    }).NaN;
                }
            }
        }
        var await_2 = f1();
        function f2({
            var: async_2,
            [a++ + (undefined ^ 2 ^ ([ , 0 ].length === 2) + []) * (this + 25 || await_2 && (await_2.a += true & true))]: bar = [ a++ + ((c = c + 1) + (await_2 && await_2[c = 1 + c, 
            ({} >> 0 || 3 % -4) >>> ("foo" < ([ , 0 ].length === 2) !== {} << 24..toString())]) ? a++ + /[abc4]/.test(((c = 1 + c, 
            (undefined && ([ undefined.NaN ] = [ ("b" && undefined, {} ^ "number") ])) != (("c", 
            /[a2][^e]+$/) ^ 23..toString() << "c")) || b || 5).toString()) : a++ + (typeof c_2 == "function")), --b + (((c = c + 1, 
            5) != (4 != 38..toString())) > ("a" || 3) % ("undefined" ^ true)), --b + ((-3 != "") + (undefined <= true) == ("object" > 24..toString()) >> (async_2 && ([ async_2[c = 1 + c, 
            ("foo" || NaN) % (NaN || -3) + ((foo_2 && (foo_2[c = 1 + c, c = c + 1, -2 >>> /[a2][^e]+$/ <= (24..toString() | this)] = [ , 0 ][1] / 5)) >> (24..toString() ^ "object"))] ] = [ undefined < [] ]))) ].foo
        }, async_2_2) {
            function f3(async_2 = "undefined") {
                function f4(async_2, foo, bar) {
                }
                var undefined_1 = f4("", []);
            }
            var await_2_1 = f3([ , 0 ][1]);
        }
        var Math_1 = f2({});
        function f5(NaN_2) {
            c = c + 1;
        }
        var a_2 = f5(38..toString(), a++ + (b = a));
    }(a && a[--b + +function() {
        {
            for (var brake14 = 5; delete (NaN <= [ , 0 ][1] != (c = c + 1, [ , 0 ][1]) !== ((a && (a.Infinity = (true, 
            [ , 0 ].length === 2))) != (-5 || 38..toString()))) && brake14 > 0; --brake14) {
                if ((c = c + 1) + /[abc4]/.test(((c = 1 + c, (c = c + 1, Infinity == null) < NaN / /[a2][^e]+$/ + (a = {} % true)) || b || 5).toString())) {} else {
                    for (var brake17 = 5; (c = 1 + c, (1 || 1) >>> ([] ^ -2), (undefined & true) >= (23..toString() && "bar")) && brake17 > 0; --brake17) {
                        c = 1 + c, ((c = c + 1, 1) ^ (null ^ -0)) / ((a && (a[c = 1 + c, a && (a[(c = c + 1) + (a && typeof a.b == "function" && --_calls_ >= 0 && a.b(1, (c = 1 + c, 
                        (25 >>> 4) - ([] || 38..toString()) <= (a && ([ a.undefined ] = [ "undefined" === "bar" ])) % (a && ([ a[c = 1 + c, 
                        -("c" | "foo") % (1 !== 1 ^ 22 & 4)] ] = [ "b" >= undefined ]))), (c = 1 + c, void {} !== (true !== 22) && (null || "undefined") ^ ("foo" ^ 2))))] = ("foo" + -1 ^ true * "undefined") % (Infinity >> this <= ~([ , 0 ].length === 2)))] <<= "number" != "object")) ^ "a" > NaN);
                    }
                }
            }
        }
        {
            var brake19 = 5;
            do {
                c = c + 1;
            } while (a++ + a && --brake19 > 0);
        }
        {
            var brake21 = 5;
            while (--b + (a++ + 2 || 9).toString()[a++ + (typeof a == "function" && --_calls_ >= 0 && a())] && --brake21 > 0) {
                var b_2 = a && a.foo, b_2 = --b;
            }
        }
    }()], [], NaN);
}

if (~((3 != [ , 0 ][1], 1 >= -2) - (22 >>> 3 < !"function"))) {
    for (var brake24 = 5; (c = c + 1) + void ((24..toString() > "") >> ("c" >>> true), 
    (a && (a.foo -= "" % -2)) << (38..toString() & false)) && brake24 > 0; --brake24) {
        var bar_2 = function f6(b_2, parseInt_2, Math_1) {
            {
                var expr26 = "a";
                for (var key26 in expr26) {
                    c = 1 + c;
                    var parseInt_2 = expr26[key26];
                    var b_2 = --b + (Math_1 && Math_1[(22 >>> -1 ^ null != "c") + (a_1 = (22 & [ , 0 ][1]) + (38..toString() - undefined))] ? --b + /[abc4]/g.exec(((a++ + ((c = 1 + c, 
                    (b_2 && (b_2.NaN &= (/[a2][^e]+$/ | 38..toString()) + (a_1 && (a_1.undefined = 38..toString() ^ "")))) != ("undefined" <= /[a2][^e]+$/) % ("a" == "a")) ? (c = 1 + c, 
                    (parseInt_2 = (3 ^ [ , 0 ].length === 2) <= 25 << 24..toString()) >= (-2 < "bar") >>> (parseInt_2 && ({
                        3: parseInt_2.a
                    } = {
                        3: [ , 0 ][1] !== []
                    }))) : (c = 1 + c, 3 != -1 === "foo" <= 25 != (Math_1 && (Math_1[a++ + ("" in [ (c = 1 + c, 
                    a && ([ a.a ] = [ (3 | [] && -0 + "a") + (-"foo" || "bar" && "foo") ])), (c = 1 + c, 
                    void ((parseInt_2 ^= "c" > /[a2][^e]+$/) === ![])), (c = 1 + c, (-3 - -2 !== Infinity >= 0) < (undefined / "object" != (undefined, 
                    "a"))) ])] += ([ , 0 ].length === 2 ^ -5) <= (parseInt_2 && (parseInt_2.var = (null, 
                    23..toString()))))))) ? --a : --b + /[abc4]/.test(((c = 1 + c, 5 + "c" == /[a2][^e]+$/ / [] === ((23..toString() ^ -0) == ("undefined" && true))) || b || 5).toString())) || b || 5).toString()) : (c = c + 1) + typeof undefined), a_1 = (c = c + 1) + b--;
                }
            }
            {
                return;
                switch ((c = c + 1) + (b + 1 - .1 - .1 - .1)) {
                  case b_2 && b_2[b_2 && typeof b_2.length == "function" && --_calls_ >= 0 && b_2.length((c = 1 + c, 
                    (23..toString() & 1) <= (a && (a.Infinity = 4 ^ 2)) != "bar" + 22 <= (22 | "")), (c = 1 + c, 
                    (-4 - "b" ^ 25 !== -3) <= ("function" === 1 !== NaN + {})))]:
                    break;

                  case [ (c = c + 1) + (0 === 1 ? a : b), --b + (1 === 1 ? a : b), false / "undefined" >> (-1 !== 0) > ((1 !== 24..toString()) >= ("" ^ 1)), (c = c + 1) + (-0 in {
                        length: (c = 1 + c, (undefined + 24..toString() ^ ("" ^ 23..toString())) >> (-5 - "a" <= (c = c + 1, 
                        "undefined"))),
                        "-2": (c = 1 + c, a >>>= (-1 / "a" != ("function" ^ undefined)) << (("foo" & "c") == "" < "b")),
                        3: (c = 1 + c, ([] < 3) / ("b" && "number") || "bar" % true >> (-5 <= "number")),
                        undefined: (c = 1 + c, ((null ^ null) <= (0 > "b")) / ((23..toString() | "undefined") ^ -0 == -3)),
                        3: (c = 1 + c, (b_2 &= (4 - NaN) % (-3 == false)) < (false + "a" && void 1))
                    }) ].c:
                    break;

                  case b + 1 - .1 - .1 - .1:
                    break;

                  case typeof a_1 == "function" && --_calls_ >= 0 && a_1("b", -5):
                    break;
                }
                if ((c = c + 1) + (b -= a)) {
                    var foo_2 = a++ + (typeof a === "number");
                }
            }
        }(bar_2 && typeof bar_2.NaN == "function" && --_calls_ >= 0 && bar_2.NaN(--b + [ , 0 ][1], -0, -2), a++ + /[abc4]/g.exec((a++ + a || b || 5).toString()) ? 1 === 1 ? a : b : (c = c + 1) + (1 === 1 ? a : b));
    }
}

console.log(null, a, b, c, Infinity, NaN, undefined);
```
```js
// uglified code
// (beautified)
for (var _calls_ = 10, b = 10, c = 0, a = function(undefined, foo_2) {
    var await_2 = function() {
        for (var brake3 = 5; 0 < --brake3; ) {
            var arguments_1 = (c = 1 + c, Infinity && (Infinity.in = "function" * (0 <= ("foo" === undefined)))), Infinity = (c = 1 + c, 
            !0 << (c += 1, "object") >= (this <= -2 ^ !1));
        }
        c += 1;
        for (var brake6 = 5; arguments_1 && "function" == typeof arguments_1.Infinity && 0 <= --_calls_ && arguments_1.Infinity(4, -0) && 0 < brake6; --brake6) {
            for (var brake7 = 5; c = 1 + c, (4294967294 + (-1 >>> 23..toString())) * (c += 1, 
            NaN) && 0 < brake7; --brake7) {
                c = 1 + c, c += 1, c += 1;
            }
        }
    }();
    ([ {
        [a++ + (2 ^ undefined ^ (2 === [ , 0 ].length) + []) * (this + 25 || await_2 && (await_2.a += 1))]: 0[0] = [ a++ + ((c += 1) + (await_2 && await_2[c = 1 + c, 
        ({} >> 0 || 3) >>> ("foo" < (2 === [ , 0 ].length) !== {} << 24..toString())]) ? a++ + /[abc4]/.test((c = 1 + c, 
        ((undefined && ([ undefined.NaN ] = [ "number" ^ {} ])) != (/[a2][^e]+$/ ^ 23..toString() << "c") || b || 5).toString())) : a++ + ("function" == typeof c_2)), --b + (c += 1, 
        NaN < (5 != (4 != 38..toString()))), --b + (!0 + (undefined <= !0) == (24..toString() < "object") >> (async_2 && ([ async_2[c = 1 + c, 
        NaN + ((foo_2 && (foo_2[c = 1 + c, c += 1, 4294967294 <= (24..toString() | this)] = 0)) >> ("object" ^ 24..toString()))] ] = [ undefined < [] ]))) ].foo
    } ] = [ {} ]);
    38..toString(), b = ++a, c += 1;
}((a = 100) && a[--b + +function() {
    for (var brake14 = 5; c += 1, a && (a.Infinity = 2 === [ , 0 ].length), 0 < brake14; --brake14) {
        if (!((c += 1) + /[abc4]/.test((c = 1 + c, c += 1, (!1 < NaN + (a = {} % !0) || b || 5).toString())))) {
            for (var brake17 = 5; c = 1 + c, (23..toString() && "bar") <= 0 && 0 < brake17; --brake17) {
                c = 1 + c, c += 1, a && (a[c = 1 + c, a && (a[(c += 1) + (a && "function" == typeof a.b && 0 <= --_calls_ && a.b(1, (c = 1 + c, 
                1 - [] <= (a && ([ a.undefined ] = [ !1 ])) % (a && ([ a[c = 1 + c, -0] ] = [ !1 ]))), (c = 1 + c, 
                2)))] = 0 % (1 / 0 >> this <= ~(2 === [ , 0 ].length)))] <<= !0);
            }
        }
    }
    for (var brake19 = 5; c += 1, a++ + a && 0 < --brake19; ) {}
    for (var brake21 = 5; --b + (2 + a++ || 9).toString()[a++ + ("function" == typeof a && 0 <= --_calls_ && a())] && 0 < --brake21; ) {
        a && a.foo, --b;
    }
}()], NaN), brake24 = 5; (c += 1) + (24..toString(), void (a && (a.foo -= 0), 38..toString())) && 0 < brake24; --brake24) {
    var bar_2 = function(b_2, parseInt_2, Math_1) {
        for (var key26 in "a") {
            c = 1 + c;
            var parseInt_2 = "a"[key26], b_2 = --b + (Math_1 && Math_1[1 + (a_1 = 38..toString() - void 0 + 0)] ? --b + /[abc4]/g.exec(((a++ + (c = 1 + c, 
            0 != (b_2 && (b_2.NaN &= (/[a2][^e]+$/ | 38..toString()) + (a_1 && (a_1.undefined = "" ^ 38..toString())))) ? (c = 1 + c, 
            (parseInt_2 = (3 ^ 2 === [ , 0 ].length) <= 25 << 24..toString()) >= !1 >>> (parseInt_2 && ({
                3: parseInt_2.a
            } = {
                3: 0 !== []
            }))) : (c = 1 + c, 0 != (Math_1 && (Math_1[a++ + ("" in [ (c = 1 + c, a && ([ a.a ] = [ (3 | [] && "0a") + "foo" ])), void (parseInt_2 ^= !0), (c = 1 + (c = 1 + c), 
            !1) ])] += (2 === [ , 0 ].length ^ -5) <= (parseInt_2 && (parseInt_2.var = 23..toString())))))) ? --a : --b + /[abc4]/.test((c = 1 + c, 
            ("5c" == /[a2][^e]+$/ / [] == (!0 == (-0 ^ 23..toString())) || b || 5).toString()))) || b || 5).toString()) : (c += 1) + "undefined"), a_1 = (c += 1) + b--;
        }
    }(bar_2 && "function" == typeof bar_2.NaN && 0 <= --_calls_ && bar_2.NaN(--b, -0, -2), a++ + /[abc4]/g.exec((a++ + a || b || 5).toString()) ? a : (c += 1) + a);
}

console.log(null, a, b, c, 1 / 0, NaN, void 0);
```
```
original result:
null undefined NaN 39 Infinity NaN undefined

uglified result:
evalmachine.<anonymous>:1
for(var _calls_=10,b=10,c=0,a=function(undefined,foo_2){var await_2=function(){for(var brake3=5;0<--brake3;)var arguments_1=(c=1+c,Infinity&&(Infinity.in="function"*(0<=("foo"===undefined)))),Infinity=(c=1+c,!0<<(c+=1,"object")>=(this<=-2^!1));c+=1;for(var brake6=5;arguments_1&&"function"==typeof arguments_1.Infinity&&0<=--_calls_&&arguments_1.Infinity(4,-0)&&0<brake6;--brake6)for(var brake7=5;c=1+c,(4294967294+(-1>>>23..toString()))*(c+=1,NaN)&&0<brake7;--brake7)c=1+c,c+=1,c+=1}();([{[a+++(2^undefined^(2===[,0].length)+[])*(this+25||await_2&&(await_2.a+=1))]:0[0]=[a+++((c+=1)+(await_2&&await_2[c=1+c,({}>>0||3)>>>("foo"<(2===[,0].length)!=={}<<24..toString())])?a+++/[abc4]/.test((c=1+c,((undefined&&([undefined.NaN]=["number"^{}]))!=(/[a2][^e]+$/^23..toString()<<"c")||b||5).toString())):a+++("function"==typeof c_2)),--b+(c+=1,NaN<(5!=(4!=38..toString()))),--b+(!0+(undefined<=!0)==(24..toString()<"object")>>(async_2&&([async_2[c=1+c,NaN+((foo_2&&(foo_2[c=1+c,c+=1,4294967294<=(24..toS

ReferenceError: async_2 is not defined
    at a (evalmachine.<anonymous>:1:921)
    at evalmachine.<anonymous>:1:1103
    at ContextifyScript.Script.runInContext (vm.js:59:29)
    at Object.runInContext (vm.js:120:6)
    at Object.run_code (D:\a\UglifyJS\UglifyJS\test\sandbox.js:75:12)
    at D:\a\UglifyJS\UglifyJS\test\ufuzz\index.js:1847:37
    at Array.forEach (<anonymous>)
    at Object.<anonymous> (D:\a\UglifyJS\UglifyJS\test\ufuzz\index.js:1839:20)
    at Module._compile (module.js:653:30)
    at Object.Module._extensions..js (module.js:664:10)
```
```js
// reduced test case (output will differ)

// (beautified)
(function f0() {
    function f2({
        var: async_2,
        [0]: bar = async_2 && foo_2[this]
    }) {}
    f2({});
})();
// output: 
// minify: ReferenceError: async_2 is not defined
// options: {
//   "mangle": false,
//   "output": {
//     "v8": true
//   },
//   "validate": true
// }
```
```
minify(options):
{
  "mangle": false,
  "output": {
    "v8": true
  }
}

Suspicious compress options:
  keep_fargs
  reduce_vars
  side_effects
  unused
```


Discussion:

Patch:
diff --git a/lib/compress.js b/lib/compress.js
index 1714306e58a..5ba240e2e11 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -8072,15 +8072,7 @@ merge(Compressor.prototype, {
             }
             if (argname instanceof AST_Destructured) {
                 has_destructured = true;
-                var abort = false;
-                argname.walk(new TreeWalker(function(node) {
-                    if (abort) return true;
-                    if (node instanceof AST_DestructuredKeyVal) {
-                        var key = node.key;
-                        if (key instanceof AST_Node && has_arg_refs(key)) return abort = true;
-                    }
-                }));
-                if (abort) return false;
+                if (has_arg_refs(argname)) return false;
             }
             return true;
         });


Test patch:
diff --git a/test/compress/destructured.js b/test/compress/destructured.js
index a476705da33..4f6a9f2fc72 100644
--- a/test/compress/destructured.js
+++ b/test/compress/destructured.js
@@ -2384,3 +2384,17 @@ issue_4508: {
     ]
     node_version: ">=6"
 }
+
+issue_4512: {
+    options = {
+        side_effects: true,
+    }
+    input: {
+        console.log(function([ a, b = a ]) {}([]));
+    }
+    expect: {
+        console.log(function([ a, b = a ]) {}([]));
+    }
+    expect_stdout: "undefined"
+    node_version: ">=6"
+}