Repository: mishoo/UglifyJS (JavaScript)

Issue:
ufuzz failure
```js
// original code
// (beautified)
var _calls_ = 10, a = 100, b = 10, c = 0;

function f0(foo_1) {
    function f1(a_2, foo_2, b_1) {
        var arguments_2 = /[abc4]/g.exec((a++ + -a || b || 5).toString());
        try {
            c = c + 1;
        } catch (NaN_2) {
            {
                var brake4 = 5;
                L26114: while ((c = 1 + c, undefined / 5 & 1 >>> 4 ^ -4 >>> 25 == (-3 ^ "a")) && --brake4 > 0) {}
            }
            {
                c = 1 + c, (true !== -5 ^ "foo" + 1) !== (2 <= 5 || 1 % 38..toString());
                c = 1 + c, (a_2 && (a_2[(c = c + 1) + ((-5 !== "c") / ("c" | NaN) < (arguments_2 && (arguments_2[+((c = c + 1, 
                22) / (/[a2][^e]+$/ % this) && (4 || [ , 0 ][1]) == (-0 != undefined))] += -4 / true >= ([ , 0 ].length === 2) - 1)))] = false >>> -1 << (0 == ""))) !== (-5, 
                "undefined") % (-0 < 38..toString());
                c = 1 + c, (0 !== 24..toString() ^ "a" & [ , 0 ][1]) + (24..toString() << -2 >> ("undefined" << -3));
                c = 1 + c, (false >>> [ , 0 ][1], "bar" === 4) >> (arguments_2 && (arguments_2[/[abc4]/.test(((c = 1 + c, 
                b_1 && (b_1.foo = ("function" ^ null) >= (-3 ^ -4) ^ (2 == undefined) / (/[a2][^e]+$/ && ""))) || b || 5).toString())] /= -1 - "c" || + -4));
            }
        }
    }
    var bar_2 = f1((c = c + 1) + (foo_1 && typeof foo_1.a == "function" && --_calls_ >= 0 && foo_1.a("a")));
    function f2() {
        switch (a++ + [ --b + (0 === 1 ? a : b), /[abc4]/.test(((c = 1 + c, +((/[a2][^e]+$/ === []) * (38..toString() * true))) || b || 5).toString()), b += a, (c = c + 1) + (([ , 0 ].length === 2) in [ (c = 1 + c, 
        (c = c + 1, "foo") & (-1 ^ this) ^ "function" / "function" + (-1 >> 25)) ]), --b + "function" ]) {
          case a++ + (typeof foo_1 == "function" && --_calls_ >= 0 && foo_1("", a++ + (bar_2 && typeof bar_2.c == "function" && --_calls_ >= 0 && bar_2.c()), (c = c + 1) + (c = 1 + c, 
            {} & false ^ (c = c + 1, "bar") ^ (c = c + 1, -0 % false)))):
            for (var brake12 = 5; (c = 1 + c, ("object" === 2) >>> (3 & null) << (c = c + 1, 
            []) / (-4 != -2)) && brake12 > 0; --brake12) {
            }
            break;

          case -((0 > 2 == ("b" !== 24..toString())) > (-5 > false && (38..toString() || /[a2][^e]+$/))):
            var async_2 = typeof f0 == "function" && --_calls_ >= 0 && f0((c = 1 + c, foo_1 && (foo_1.foo += (true >> -1 || "c" * Infinity) >= (23..toString() >= Infinity) >>> (38..toString() >> []))), ...[], 23..toString());
            break;

          case --b + (--b || 0).toString()[foo_1 && typeof foo_1.var == "function" && --_calls_ >= 0 && foo_1.var(-4, ..."" + bar_2)]:
            break;
            break;

          case 1 === 1 ? a : b:
            {
                var brake16 = 5;
                while ((c = c + 1) + Infinity && --brake16 > 0) {
                    for (var brake17 = 5; (c = 1 + c, this > 1 != (async_2 && (async_2[c = 1 + c, (4 >>> 25 !== "a" + "undefined") >>> ((c = c + 1, 
                    []) ^ 5 >= 24..toString())] = 3 >>> /[a2][^e]+$/)), c = c + 1, -2 == "function") && brake17 > 0; --brake17) {
                        c = 1 + c, ("undefined" && 22) == 0 % "c", c = c + 1, 5 << -0;
                    }
                }
            }
            var await_2 = a++ + foo_1, b = 0 === 1 ? a : b;
            break;
        }
        {
            return foo_1 && foo_1.c;
        }
    }
    var c = f2((c = c + 1) + true);
    function f3() {
        function f4(a_2, foo_1_1, ...foo_1) {
            if (c = 1 + c, ("number" == 38..toString()) >> (1 << true) ^ (1, -1) >= Infinity % "number") {
                c = 1 + c, "undefined" & 3 | Infinity ^ [] || 0 === "c" === null % -2;
            }
        }
        var NaN = f4("");
        function f5(async_1, bar_2, a) {
            return c = 1 + c, (("function" || 4) != "foo" >> "object") + ((bar_2 && (bar_2[c = 1 + c, 
            1 - "bar" <= "foo" >>> 24..toString() === 38..toString() >> [ , 0 ][1] > (undefined, 
            24..toString())] = true && /[a2][^e]+$/)) - (c = c + 1, -5));
            for (var brake25 = 5; (c = 1 + c, bar_2 = ~("c" >> "c") | /[a2][^e]+$/ <= false ^ -5 >> true) && brake25 > 0; --brake25) {
                c = 1 + c, c = c + 1, (/[a2][^e]+$/ != 23..toString()) >= ([ , 0 ].length === 2 & 1);
            }
        }
        var a = f5(-0);
        function f6(foo_1 = undefined, async = NaN) {
            function f7() {
            }
            var foo = f7((c = 1 + c, (NaN = 2 !== ([ , 0 ].length === 2) != this > 2) + (foo_1 && ({
                length: foo_1[(c = c + 1) + NaN]
            } = {
                length: true + false !== ("b" !== -0)
            }))));
        }
        var c_2 = f6(24..toString(), -1, -1);
        function f8(a_1, arguments_2) {
            c = 1 + c, c = c + 1, (bar_2 = "bar" % "number") >>> (-0 || "c");
            switch (c = 1 + c, ~(null != 22) << (-1 <= "foo", [ , 0 ].length === 2 !== 2)) {
              case c = 1 + c, (a && (a[c = 1 + c, (24..toString() << -0) % (arguments_2 && (arguments_2[c = 1 + c, 
                "c" / [] < ("" >= -2) & ("object", "a") === (c = c + 1, -4)] >>= -4 > "number")) >> (-2 << this) / (38..toString() & 0)] /= null ^ 2)) / (38..toString() ^ "bar") === ("undefined" > true && 23..toString() > -3):
                ;
                break;

              case c = 1 + c, -(c_2 && (c_2[c = 1 + c, c = c + 1, 25 >> "bar" === ~"c"] = "c" >>> 38..toString())) << (2 * 1 & 1 * 5):
                ;
                break;

              default:
                ;

              case c = 1 + c, "bar" << /[a2][^e]+$/ <= true * "function" < ((25 ^ 4) !== "foo" >>> null):
                ;
                break;
            }
        }
        var a_1 = f8((c = c + 1) + -b, foo_1);
    }
    var b_2 = f3("foo", bar_2);
    function f9(async_2, foo, {
        Infinity: {
            [a++ + [ delete ((("function" || this) != (-4 ^ 22)) - (1 > "bar" > 38..toString() - 0)), a++ + !function() {
            }(), ..."" + c, c && c[c = 1 + c, ("bar" < "bar") % (22 ^ {}) || ("a" !== NaN) - (24..toString() ^ -3)] ][(c = c + 1) + new function undefined_1(await_2, undefined) {
                this[undefined && undefined[c = 1 + c, (25 / 4 ^ "c" - []) >> (c && ({
                    a: c.undefined
                } = {
                    a: "b" > 3 === (undefined_1 = 25 == "function")
                }))]] += "" >> 3 << (22 != "function");
            }((c = 1 + c, (c && (c.foo &= -2 - "function" < ("object" !== {}))) >> (b_2 = ("b" ^ undefined) & "undefined" + null)))]]: bar_2,
            var: arguments,
            undefined: bar
        },
        var: {
            [(c = c + 1) + (b += a)]: foo_2,
            a: b_2 = -0,
            foo: foo_1
        },
        null: foo_1_1
    }) {
        function f10(await, foo) {
            return c = 1 + c, (0 - 5 & "b" !== "function") >= (-1 == /[a2][^e]+$/ == undefined * Infinity);
            switch (c = 1 + c, "bar" * this >= "" << "function", (NaN >= -4) << "undefined" / -1) {
              case c = 1 + c, ("b" && -1) !== (arguments && (arguments[c = 1 + c, (c = c + 1, foo_2 && (foo_2[c = 1 + c, 
                delete 3 >= ("function" >= 0) >= ((true && false) >= void this)] += "" | false)) % (24..toString() % 23..toString() * ("b" % "c"))] &= "object" + [ , 0 ][1])) ^ (await = (0 | false) <= (0 || false)):
                ;
                break;

              case c = 1 + c, ((true ^ [ , 0 ][1]) < (true ^ "foo")) >> ([] / "foo" || (38..toString() || "number")):
                ;
                break;

              case c = 1 + c, (0 & "c") >>> ({} & 25) > (this ^ -4 ^ false - 22):
                ;
                break;

              case c = 1 + c, bar && (bar[typeof foo_1 == "function" && --_calls_ >= 0 && foo_1(22, (c = 1 + c, 
                c = c + 1, (false + 23..toString()) / ([] + 1)), ..."" + c)] += -0 - -4 | 2 >>> -4) && ([ , 0 ].length === 2) << -2 < 23..toString() >> []:
                ;
                break;
            }
        }
        var async_2 = f10(Infinity, {}, b + 1 - .1 - .1 - .1);
        function f11(b_2_2, bar_1) {
            {
                var brake32 = 5;
                while ((c = 1 + c, delete (!"a" + ("bar" << 3))) && --brake32 > 0) {
                    c = 1 + c, ("object" === 22) < (2 && false) >= ((38..toString() ^ true) & Infinity >>> "foo");
                }
            }
        }
        var arguments = f11("foo");
        function f12(a_2, arguments, a_1) {
            let bar_1 = --b + !async function() {
                c = 1 + c, 23..toString() > 22 < 38..toString() % null || 5 / 2 | (NaN, this);
                c = 1 + c, arguments = (c && (c[a++ + [ (c = 1 + c, ([ , 0 ].length === 2 === "c") + ("c" - -4) >> (a_1 && (a_1.NaN += ("a" <= -0) >> (23..toString() << -5)))), (c = 1 + c, 
                (2 % "" || 4 == false) === ((c = c + 1, -0) ^ {} * -3)), ..."" + bar_2, (c = 1 + c, 
                ({} > "undefined") >>> ("bar" ^ 0) >= 4 >>> "b" >> ("b" >>> -4)), (c = 1 + c, (22 == 23..toString()) / ("foo" <= "") > (-0 / 22 != ({} === -1))) ][c = 1 + c, 
                (undefined != [ , 0 ][1] || -3 * -5) < (1 + 22 || "number" & 0)]] = (false >= Infinity) % ("a" & 5))) == -1 / "a" < ([ , 0 ].length === 2, 
                23..toString());
                c = 1 + c, (a_1 && (a_1.foo = 24..toString() < null != (c = c + 1, -2))) / ((undefined && {}) < null >>> "object");
                c = 1 + c, ((arguments && (arguments[c = 1 + c, ((-1 || "") >>> ("a" << "a")) - (NaN ^ {} || "" < "")] -= /[a2][^e]+$/ / Infinity)) ^ 5 <= "") % (22 % [ , 0 ][1] ^ (arguments && (arguments[c = 1 + c, 
                (-3 / false ^ {} - 24..toString()) != 0 / {} <= (2 < "number")] -= 23..toString() != /[a2][^e]+$/)));
            }();
            c = c + 1;
        }
        var async_2_2 = f12(typeof (bar = (c = 1 + c, (-5, "undefined") * ("" == false) + (void /[a2][^e]+$/ || -5 ^ -0))), "foo", a++ + ~a);
        function f13(arguments_1) {
            {
            }
            try {
                c = 1 + c, -4 >>> 2 >>> (this ^ "b"), void (23..toString() >= 0);
            } catch (b) {
            }
        }
        var c = f13("undefined", -0);
        function f14(bar_2, foo, async_2) {
            function f15() {
            }
            var async_2_1 = f15(25, "function");
            function f16(a_1, async_2_2) {
            }
            var b_2 = f16("object", -3, "undefined");
            function f17(foo_1_1, async_2_2_1) {
            }
            var await = f17();
            function f18(a, async_2_2, await_1) {
            }
            var async_2_1 = f18("number", (c = 1 + c, (("c" || 38..toString()) && (23..toString() || 3)) / ((-0 && "foo") < ("" < []))), [ , 0 ][1]);
            function f19() {
            }
            var async_2_1 = f19((c = 1 + c, c = c + 1, (c = c + 1, [ , 0 ].length === 2) << "number" + "c"), ..."" + async_2, (c = 1 + c, 
            (-4 & 24..toString()) / (-4 == ([ , 0 ].length === 2)) * (-5 >>> 1 | -3 - 23..toString())));
        }
        var arguments_2 = f14(++b, --b + new function() {
            this[c = 1 + c, ({} ^ 0 ^ "c" < 3) + ({} << "bar" > ("undefined" | 38..toString()))] *= undefined != -5;
            this[c = 1 + c, this / -4 + /[a2][^e]+$/ / "object" || (c = c + 1, "undefined") + ([ , 0 ][1] <= "a")] >>>= /[a2][^e]+$/ << -0;
        }(0, [ , 0 ][1]), (c = c + 1) + (c && typeof c.var == "function" && --_calls_ >= 0 && c.var(-1)));
    }
    var b = f9("undefined", --b + a++, {
        var: {},
        Infinity: {
            undefined: undefined,
            var: --b + ({
                c: c
            } = a-- || {})
        },
        0: 0
    });
    function f20([ {
        "": await,
        length: foo = (c = c + 1) + (typeof f3 == "function" && --_calls_ >= 0 && f3(--b + (bar_2 && bar_2.foo))),
        Infinity: bar
    }, , foo_1, c_2 ], await_1, b_2) {
        return;
        {
            L26115: {
                c = 1 + c, foo && (foo.a = ((23..toString() | 23..toString()) != ([ , 0 ].length === 2 && NaN), 
                ("function" <= 0) >> (-5 != "c")));
                c = 1 + c, b_2 && (b_2[(c = c + 1) + (b_2 && b_2[{}[c = 1 + c, ("bar" / "a" || -4 != -2) & (-1 <= 22 ^ 3 === "number")]])] += "foo" * 1 + ([ , 0 ][1], 
                NaN) <= (b_2 && (b_2.a ^= "" | "undefined")) << (22 ^ undefined));
            }
        }
    }
    var bar_1 = f20([ {}, , -1 ], -5);
}

var b_2 = f0(-4, "", "undefined");

console.log(null, a, b, c, Infinity, NaN, undefined);
```
```js
// uglified code
// (beautified)
var _calls_ = 10, a = 100, b = 10, c = 0;

function f0(foo_1) {
    var bar_2 = function(a_2, b_1) {
        var arguments_2 = /[abc4]/g.exec((a++ - a || b || 5).toString());
        try {
            c += 1;
        } catch (NaN_2) {
            0, c = 1 + (c = 1 + (c = 1 + c)), a_2 && (a_2[(c += 1) + (1 / 0 < (arguments_2 && (arguments_2[c += 1, 
            +(22 / (/[a2][^e]+$/ % this) && !1)] += (2 === [ , 0 ].length) - 1 <= -4)))] = 0), 
            38..toString(), c = 1 + c, 24..toString(), 24..toString(), c = 1 + c, arguments_2 && (arguments_2[/[abc4]/.test((c = 1 + c, 
            (b_1 && (b_1.foo = 0) || b || 5).toString()))] /= -4);
        }
    }((c += 1) + (foo_1 && "function" == typeof foo_1.a && 0 <= --_calls_ && foo_1.a("a")));
    var c = function() {
        switch (a++ + [ --b + b, /[abc4]/.test((c = 1 + c, (+((/[a2][^e]+$/ === []) * (!0 * 38..toString())) || b || 5).toString())), b += a, (c += 1) + ((2 === [ , 0 ].length) in [ (c = 1 + c, 
        NaN ^ (c += 1, "foo" & (-1 ^ this))) ]), --b + "function" ]) {
          case a++ + ("function" == typeof foo_1 && 0 <= --_calls_ && foo_1("", a++ + (bar_2 && "function" == typeof bar_2.c && 0 <= --_calls_ && bar_2.c()), (c += 1) + (c = 1 + c, 
            !1 & {} ^ (c += 1, "bar") ^ (c += 1, NaN)))):
            for (var brake12 = 5; c = 1 + c, 0 << (c += 1, [] / !0) && 0 < brake12; --brake12) {}
            break;

          case -(!1 < (0 == ("b" !== 24..toString()))):
            var async_2 = "function" == typeof f0 && 0 <= --_calls_ && f0((c = 1 + c, foo_1 && (foo_1.foo += (23..toString() >= 1 / 0) >>> (38..toString() >> []) <= NaN)), 23..toString());
            break;

          case --b + (--b || 0).toString()[foo_1 && "function" == typeof foo_1.var && 0 <= --_calls_ && foo_1.var(-4, ..."" + bar_2)]:
            break;

          case a:
            for (var brake16 = 5; (c += 1) + 1 / 0 && 0 < --brake16; ) {
                c = 1 + c, async_2 && (async_2[c = 1 + c, !0 >>> (c += 1, [] ^ 24..toString() <= 5)] = 3), 
                c += 1;
            }
            a++;
            var b = b;
        }
        return foo_1 && foo_1.c;
    }(c += 1);
    function f3() {
        var NaN = (c = 1 + c, void (("number" == 38..toString()) >> 2 ^ !1 && (c = 1 + c)));
        var a = function(bar_2) {
            return c = 1 + c, (bar_2 && (bar_2[c = 1 + c, 0 / 0 <= "foo" >>> 24..toString() == 38..toString() >> 0 > 24..toString()] = /[a2][^e]+$/)) - (c += 1, 
            -5) + !0;
        }();
        var c_2 = function(foo_1 = void 0) {
            c = 1 + c, NaN = 2 !== (2 === [ , 0 ].length) != 2 < this, foo_1 && ({
                length: foo_1[(c += 1) + NaN]
            } = {
                length: !0
            });
        }(24..toString());
        !function(arguments_2) {
            switch (c = 1 + c, bar_2 = 0 / 0, -2 << (2 === [ , 0 ].length !== 2)) {
              case c = 1 + (c = 1 + (c += 1)), (a && (a[c = 1 + c, (24..toString() << -0) % (arguments_2 && (arguments_2[c = 1 + c, 
                "c" / [] < !0 & "a" === (c += 1, -4)] >>= !1)) >> (-2 << this) / (0 & 38..toString())] /= 2)) / ("bar" ^ 38..toString()) === !1:
              case c = 1 + c, -(c_2 && (c_2[c = 1 + c, c += 1, !1] = "c" >>> 38..toString())) << 0:
                break;

              default:
              case c = 1 + c, !0:
            }
        }((c += 1, foo_1));
    }
    f3();
    var b = function({
        Infinity: {
            [a++ + [ (38..toString(), !0), a++ + !0, ..."" + c, c && c[c = 1 + c, !1 % (22 ^ {}) || !0 - (-3 ^ 24..toString())] ][(c += 1) + new function(await_2, undefined) {
                this[undefined && undefined[(6.25 ^ "c" - []) >> ((c = 1 + c) && ({
                    a: c.undefined
                } = {
                    a: !0
                }))]] += 0;
            }((c = 1 + c, c && (c.foo &= NaN < ("object" !== {}))))]]: bar_2
        },
        var: {
            [(c += 1) + (b += a)]: foo_2
        }
    }) {
        var a_1;
        !function(await, foo) {
            c = 1 + c;
        }(1 / 0, {}, b + 1 - .1 - .1 - .1), function() {
            for (var brake32 = 5; c = 1 + c, 0 < --brake32; ) {
                c = 1 + c, 38..toString();
            }
        }(), c = 1 + c, a_1 = a++ + ~a, --b, async function() {
            c = 1 + c, 23..toString(), 38..toString(), c = 1 + c, arguments = (c && (c[a++ + [ (c = 1 + c, 
            (2 === [ , 0 ].length === "c") + NaN >> (a_1 && (a_1.NaN += !1 >> (23..toString() << -5)))), (c = 1 + c, 
            !1 === (c += 1, -0 ^ -3 * {})), ..."" + bar_2, 4 <= ("undefined" < {}) >>> 0, (c = 1 + (c = 1 + c), 
            (22 == 23..toString()) / !1 > (-0 != (-1 === {}))) ][c = 1 + c, !0]] = NaN)) == NaN < 23..toString(), 
            c = 1 + c, a_1 && (a_1.foo = 24..toString() < null != (c += 1, -2)), c = 1 + c, 
            arguments && (arguments[c = 1 + c, (-1 >>> 0) - (NaN ^ {} || !1)] -= NaN), arguments && (arguments[c = 1 + c, 
            (-1 / 0 ^ {} - 24..toString()) != 0 / {} <= !1] -= 23..toString() != /[a2][^e]+$/);
        }(), c += 1;
        var c = function() {
            try {
                c = 1 + c, 23..toString();
            } catch (b) {}
        }();
        ++b, --b, new function() {
            this[c = 1 + c, (0 ^ {} ^ !1) + ({} << "bar" > ("undefined" | 38..toString()))] *= !0, 
            this[c = 1 + c, this / -4 + NaN || (c += 1, "undefined" + !1)] >>>= 0;
        }(), (c += 1) && "function" == typeof c.var && 0 <= --_calls_ && c.var(-1), c = 1 + c, 
        23..toString(), c = 1 + c, c += 1, c = 1 + (c += 1), 24..toString(), 23..toString();
    }((--b, a++, {
        var: {},
        Infinity: {
            undefined: void 0,
            var: --b + ({
                c: c
            } = a-- || {})
        },
        0: 0
    }));
    var foo;
    ([ [ {
        length: foo = (c += 1, 0 <= --_calls_ && f3((--b, bar_2 && bar_2.foo)))
    } ] ] = [ [ {}, , -1 ] ]);
}

var b_2 = f0(-4, "", "undefined");

console.log(null, a, b, c, 1 / 0, NaN, void 0);
```
```
original result:
ReferenceError: b_2 is not defined
    at f9 ([stdin]:313:77)
    at f0 ([stdin]:448:9)
    at [stdin]:471:11
    at ContextifyScript.Script.runInThisContext (vm.js:50:33)
    at Object.runInThisContext (vm.js:139:38)
    at Object.<anonymous> ([stdin]-wrapper:6:22)
    at Module._compile (module.js:653:30)
    at evalScript (bootstrap_node.js:479:27)
    at Socket.<anonymous> (bootstrap_node.js:250:15)
    at emitNone (events.js:111:20)
uglified result:
null 106 10 0 Infinity NaN undefined
```
```js
// reduced test case (output will differ)

// (beautified)
var a = 0;

function f9(async_2, foo, {
    Infinity: {
        [0(b_2 = 0)]: bar_2
    },
    var: {
        a: b_2 = 0
    }
}) {}

f9("undefined", a, {
    Infinity: 0
});
// output: ReferenceError: b_2 is not defined
// minify: TypeError: 0 is not a function
// options: {
//   "mangle": false,
//   "output": {
//     "v8": true
//   },
//   "validate": true
// }
```
```
minify(options):
{
  "mangle": false,
  "output": {
    "v8": true
  }
}

Suspicious compress options:
  evaluate
  reduce_vars
```


Discussion:

Patch:
diff --git a/lib/compress.js b/lib/compress.js
index 547ef57403e..c6ebb34caf5 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -786,7 +786,10 @@ merge(Compressor.prototype, {
                     }
                     var d = sym.definition();
                     d.assignments++;
-                    if (fixed && !is_modified(compressor, tw, node, node.right, 0) && safe_to_assign(tw, d)) {
+                    if (fixed
+                        && !is_modified(compressor, tw, node, node.right, 0)
+                        && !sym.in_arg
+                        && safe_to_assign(tw, d)) {
                         push_ref(d, sym);
                         mark(tw, d);
                         if (d.single_use && left instanceof AST_Destructured) d.single_use = false;
@@ -809,7 +812,7 @@ merge(Compressor.prototype, {
                 }
                 var safe = safe_to_read(tw, d);
                 node.right.walk(tw);
-                if (safe && safe_to_assign(tw, d)) {
+                if (safe && !left.in_arg && safe_to_assign(tw, d)) {
                     push_ref(d, left);
                     mark(tw, d);
                     if (d.single_use) d.single_use = false;
@@ -1117,7 +1120,7 @@ merge(Compressor.prototype, {
             var d = exp.definition();
             d.assignments++;
             var fixed = d.fixed;
-            if (safe_to_read(tw, d) && safe_to_assign(tw, d)) {
+            if (safe_to_read(tw, d) && !exp.in_arg && safe_to_assign(tw, d)) {
                 push_ref(d, exp);
                 mark(tw, d);
                 if (d.single_use) d.single_use = false;


Test patch:
diff --git a/test/compress/destructured.js b/test/compress/destructured.js
index 7cc6f46d722..58fec606491 100644
--- a/test/compress/destructured.js
+++ b/test/compress/destructured.js
@@ -2487,3 +2487,30 @@ issue_4554: {
     expect_stdout: "PASS"
     node_version: ">=6"
 }
+
+issue_4584: {
+    options = {
+        evaluate: true,
+        reduce_vars: true,
+    }
+    input: {
+        try {
+            (function f({
+                [console.log(a = "FAIL")]: a,
+            }) {})(0);
+        } catch (e) {
+            console.log("PASS");
+        }
+    }
+    expect: {
+        try {
+            (function f({
+                [console.log(a = "FAIL")]: a,
+            }) {})(0);
+        } catch (e) {
+            console.log("PASS");
+        }
+    }
+    expect_stdout: "PASS"
+    node_version: ">=6"
+}
diff --git a/test/ufuzz/index.js b/test/ufuzz/index.js
index a6784ee7e9d..0a6de2a3018 100644
--- a/test/ufuzz/index.js
+++ b/test/ufuzz/index.js
@@ -431,12 +431,18 @@ function createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, was
     unique_vars.length = len;
     return pairs;
 
-    function mapShuffled(array, fn) {
-        var result = [];
-        for (var i = array.length; --i >= 0;) {
-            result.splice(rng(result.length + 1), 0, fn(array[i], i));
-        }
-        return result;
+    function mapShuffled(values, fn) {
+        var ordered = [];
+        var shuffled = [];
+        values.forEach(function(value, index) {
+            value = fn(value, index);
+            if (/]:/.test(value) ? canThrow && rng(10) == 0 : rng(5)) {
+                shuffled.splice(rng(shuffled.length + 1), 0, value);
+            } else {
+                ordered.push(value);
+            }
+        });
+        return shuffled.concat(ordered);
     }
 
     function convertToRest(names) {