Repository: mishoo/UglifyJS (JavaScript)

Issue:
ufuzz failure
```js
// original code
// (beautified)
var _calls_ = 10, a = 100, b = 10, c = 0;

function f0(b_1) {
    function f1() {
        b++;
        if (a++ + [][("object" >>> /[a2][^e]+$/) / ({} !== NaN) ^ "" % [ , 0 ][1] + (this ^ null)]) {
            var expr3 = {
                [(c = 1 + c, 1 * 22 >= (b_1 && (b_1.then &= "object" | 5)) <= ((24..toString() || -5) === (4 && 25)))]: (c = 1 + c, 
                b_1 += (null < true | "bar" >> 5) & (24..toString() % -2 | NaN + 25)),
                ...b_1,
                [(c = 1 + c, (b_1 && (b_1[b_1 && b_1[c = 1 + c, (b_1 && (b_1[--b + (b_1 && typeof b_1.get == "function" && --_calls_ >= 0 && (c = 1 + c, 
                b_1 && (b_1["b" in {
                    foo: (c = 1 + c, (25 >>> []) * (23..toString() + -0) || (5, "object") === 1 >> ([ , 0 ].length === 2))
                }] >>>= (-2 << NaN) * (true % 3) ^ (b_1 = {} == "object") & "undefined" / null), 
                b_1.get)(this, 4))] += 25 !== "number" & delete 0)) <= ((b_1 && (b_1.set += this !== this)) > -2 / "undefined")]] = (b_1 && (b_1[c = 1 + c, 
                1 - 38..toString() ^ (38..toString(), true), "function" << ([ , 0 ].length === 2) >>> (NaN <= null)] >>= "b" - {})) <= /[a2][^e]+$/ / {})) >> (b_1 && ({
                    next: b_1[((c = 1 + c, (2 ^ null) >= ("bar" <= null) != ("b" || 22) / - -3) || 2).toString()[c = 1 + c, 
                    ([] % 0 & (b_1 && ({
                        Infinity: b_1.value
                    } = {
                        Infinity: [] || 38..toString()
                    }))) > (3 | Infinity) >>> (b_1 && (b_1[c = 1 + c, ((b_1 && ([ b_1.done ] = [ 38..toString() == 5 ])) ^ 5 - 24..toString()) === void (23..toString() <= "object")] += "number" || -1))]]
                } = {
                    next: "" * "b" ^ (b_1 /= "b" === "object")
                })))]: (c = 1 + c, (b_1 && (b_1[c = 1 + c, (("number" !== -2) >> ("c" > "number")) % ("foo" > -5 && (b_1 && (b_1[c = 1 + c, 
                25 === /[a2][^e]+$/ == (4 & "bar") === (("b" | true) == /[a2][^e]+$/ + Infinity)] += "b" > -5)))] += 3 || Infinity)) <= ("a" !== "c") || this - 5 === "object" << 38..toString()),
                get: (c = 1 + c, (b_1 && (b_1.set += [] && "function") || "bar" | undefined) | "a" > "number" > ([ , 0 ].length === 2 ^ "object")),
                3: (c = 1 + c, (-0 ^ 23..toString() | "a" + 38..toString()) != "foo" >= 25 < (0 | [ , 0 ].length === 2))
            }.foo;
            for (var key3 in expr3) {
                c = 1 + c;
                var a_2 = expr3[key3];
                c = c + 1;
            }
        } else {
            var expr5 = (22 in [ (c = 1 + c, ((23..toString(), 2) && "foo" <= "c") << (this || 3) % (5 <= "a")), (c = 1 + c, 
            ((b_1 = false << "c") ^ "" & true) & ("foo" >= Infinity ^ false << ([ , 0 ].length === 2))), (c = 1 + c, 
            ((5 >= -3) << ("foo" | 2)) % (b_1 && (b_1.in >>= 5 >> "number" || 0 && [ , 0 ].length === 2))), (c = 1 + c, 
            ([] ^ "number") * (([ , 0 ].length === 2) >= true) / (-3 >= Infinity !== true - -4)), (c = 1 + c, 
            (4 !== null) - (22 | -0) >> (22 ^ {}) / (-2 < "c")) ] || a || 3).toString();
            L31160: for (var key5 in expr5) {
            }
        }
    }
    var arguments = f1(-1, "", []);
    function f2(yield) {
        try {
            {
                if (c = 1 + c, (arguments && (arguments[{
                    b: (c = 1 + c, (yield && (yield[{}] += !([ , 0 ].length === 2) == "undefined" + [])) & (24..toString() === 23..toString() && 22 - 1)),
                    value(yield_2, a_2, b) {
                        arguments = super.b;
                    },
                    undefined: (c = 1 + c, void (22 >= [ , 0 ][1] || (c = c + 1, 23..toString()))),
                    [(c = 1 + c, c = c + 1, yield -= (c = c + 1, -5) != "bar" >>> "function")]: (c = 1 + c, 
                    (22, "undefined", -2 ^ -5) >= (undefined ^ "" ^ (arguments && (arguments[c = 1 + c, 
                    !("c" == /[a2][^e]+$/) << (25 <= 0) + (c = c + 1, true)] = true === 5))))
                }.foo] = "undefined" >> -5 != (arguments && (arguments[c = 1 + c, 22 - "a" - (true >= -3) ^ -5 - /[a2][^e]+$/ >>> 25 / Infinity] = Infinity << ([ , 0 ].length === 2))))) != (24..toString(), 
                -3, arguments && (arguments.NaN |= Infinity !== 4))) {
                    c = 1 + c, (!this & 1 == "undefined") + (("a" === null) >> ("b" === false));
                } else {
                    c = 1 + c, (0 >= "bar" || 5 ^ -3) > ({} >>> 24..toString() || false - 4);
                }
            }
        } catch (Infinity) {
            {
                var arguments_2 = function f3() {
                }((c = 1 + c, -4 ^ -2 && 4 ^ /[a2][^e]+$/ && ([ , 0 ].length === 2 ^ 25) - ("" <= Infinity)));
            }
            return;
        } finally {
            var foo_1;
            {
                var expr15 = --b + (typeof f3 == "function" && --_calls_ >= 0 && f3(false, false, ..."" + arguments));
                for (const key15 in expr15) {
                    c = 1 + c;
                    var bar = expr15[key15];
                    {
                    }
                }
            }
        }
        switch (--b + (arguments && arguments[([ , 0 ].length === 2) << [ , 0 ][1] !== (4 || this), 
        true == "bar" ^ -2 / -1])) {
          default:
          case --b + ++b:
            switch (0 === 1 ? a : b) {
              case a++ + (typeof f0 == "function" && --_calls_ >= 0 && f0((c = 1 + c, Infinity << "number" > true - this || (-2 >= 38..toString()) * (5 || 5)))):
                c = 1 + c, (b_1 = "foo" <= -5) <= (yield && (yield.a -= 1 > {})) ^ (b_1 && (b_1.done = 4 != {})) == (4 != 0);
                c = 1 + c, (b_1 && (b_1[c = 1 + c, (yield && (yield.in |= 3 & NaN ^ (-4 ^ 2))) ^ ("function" << 1 | {} > ([ , 0 ].length === 2))] -= this * 1)) > undefined >> "object" !== ({} + 23..toString() && "number" & true);
                break;

              case --b + "a":
                c = 1 + c, ("undefined" << 25) * (2 + /[a2][^e]+$/) <= "number" / this % (b_1 && (b_1.set = 22 >= [ , 0 ][1]));
                break;

              case a++ + (yield && yield[c = 1 + c, (24..toString() ^ undefined) >>> (3 >= Infinity) == (b_1 && ([ b_1.value ] = [ (-3 !== 24..toString()) > (-4 != "a") ]))]):
                c = 1 + c, (0 == 0) >= (1 === "b") | 3 ** 3 > ("a" ^ "b");
                c = 1 + c, ((b_1 && (b_1[c = 1 + c, (-4 && undefined) <= -3 + Infinity == ((b_1 && ([ b_1[c = 1 + c, 
                ((b_1 = 0 || /[a2][^e]+$/) !== (4 !== false)) < (yield && (yield.async = (/[a2][^e]+$/ || "number") * (this < 23..toString())))] ] = [ 24..toString() >= undefined ])) === (-2 || -4))] += 38..toString() || "number")) == ([ , 0 ][1] ^ -2)) * (b_1 = (-4 !== "") >> (24..toString() && Infinity));
                break;

              case typeof f2 == "function" && --_calls_ >= 0 && f2(38..toString()):
                c = 1 + c, (yield && (yield.foo **= "c" >> "undefined" === 0 * -0)) ^ 1 <= -4 == ("b" != 22);
                c = 1 + c, (("foo" & 4) >= NaN >> 5) / ((yield && ([ yield.var ] = [ 1 % -1 ])) % ("a" >> "function"));
                break;
            }
            break;

          case arguments && (arguments[(c = c + 1) + ((c = c + 1, 22 >>> {}) == ("foo" % -0 && "b" < 2))] += ("foo" % 5 === (2 | 25)) > (24..toString() | 25 && -0 + "bar")):
            {
                var c_1 = function f4(foo, a_2) {
                }();
            }
            {
                var bar_1 = function f5(yield_2) {
                }((c = 1 + c, ((yield **= "function" & 5) < "number" % "undefined") >>> (24..toString() !== 23..toString() !== (arguments && (arguments[c = 1 + c, 
                (c_1 && (c_1.done = -3 << 5), undefined > 22) | (0, 3) - (0 || 3)] = this < 1)))), ..."" + arguments);
            }
            break;

          case 0 === 1 ? a : b:
            if (/[abc4]/.test(((c = 1 + c, ("b" !== 1) >> (([ , 0 ].length === 2) >> -1) <= (("a" !== "") <= (c = c + 1, 
            {}))) || b || 5).toString())) {
                var bar_2;
            }
            break;
        }
    }
    var undefined_2 = f2(b_1 && b_1.get);
    function f6(b_1) {
        function f7() {
            try {
                c = 1 + c, (("number" && 38..toString()) == ("bar", -0)) % ((/[a2][^e]+$/ >> -5) - "undefined" * /[a2][^e]+$/);
            } finally {
            }
        }
        var b_1_1 = f7("b");
        function f8(b_2, b_1, c_1) {
            c = 1 + c, ("foo" || -3) < ("a" | -2) || ("a" ^ "") == (false != true);
            L31161: for (var brake34 = 5; (c = 1 + c, b_1 && (b_1[b_1 && typeof b_1.done == "function" && --_calls_ >= 0 && b_1.done((c = 1 + c, 
            (false ^ "a") == (false & -1) & "object" <= ([ , 0 ].length === 2) !== ("" ^ 3)), (c = 1 + c, 
            b_1 && (b_1.get = (c_1 && (c_1[c = 1 + c, (-3 << 22 && false != "b") == +!0] = 1 || [ , 0 ].length === 2)) ^ 24..toString() << "number" | (([ , 0 ][1] || 23..toString()) | false & 22))), (c = 1 + c, 
            ((b_1_1 = 0 === -2) || 23..toString() >>> undefined) >> ("a" >>> /[a2][^e]+$/ && (b_1 && (b_1[c = 1 + c, 
            (22 >> 22, "function" > "undefined") == (undefined_2 && (undefined_2.in = {} % this)) / ("bar" ^ -5)] = -1 | 0)))))] = (c = c + 1, 
            -4 >> "object") || 5 / [ , 0 ][1] / (false == 38..toString()))) && brake34 > 0; --brake34) {
                c = 1 + c, false == "b" & (-3 || 0) | -1 % 38..toString() << undefined * Infinity;
            }
        }
        var yield_1 = f8(--b + ++a, 3);
        function f9(a, bar_2) {
            function f10(yield_1, NaN_2, b_1) {
            }
            var b_1_2 = f10(23..toString(), (c = 1 + c, (b_1 = "number" > false == ([] === "number")) - (c = c + 1, 
            [] > undefined)), false);
            function f11(bar_1, bar_2, async) {
            }
            var bar_2_1 = f11();
            function f12() {
            }
            var bar = f12([ , 0 ].length === 2, (c = 1 + c, c = c + 1, ~("b" <= 23..toString())), 2);
        }
        var b = f9(4, "a");
        function f13(c_2, undefined_2_1) {
            function f14(b_1, foo) {
            }
            var b = f14();
            function f15(a_2 = "undefined", c_2_2) {
            }
            var async_2 = f15(Infinity, 4);
            function f16(b_2, foo) {
            }
            var yield_1 = f16(1, (c = 1 + c, + -5 * (yield_1 && (yield_1[c = 1 + c, ("c" ^ -0) / ("b" >>> 23..toString()) * !("object" === -4)] = 3 > 2)) ^ (b += false >= "undefined" && (c = c + 1, 
            "bar"))), 0);
        }
        var yield_1 = f13((c = c + 1) + --b, 0);
        function f17(a_1, bar_1, b_1 = true) {
            function f18(a_1_2) {
            }
            var a_2 = f18((c = 1 + c, ("a" === 25) + !"number" - ("bar" >>> -1) * (1 || -1)), -3);
        }
        var b_2 = f17("a");
    }
    var undefined_2_2 = f6();
}

var a_1 = f0(24..toString(), -0);

console.log(null, a, b, c, Infinity, NaN, undefined);
```
```js
// uglified code
// (beautified)
var _calls_ = 10, a = 100, b = 10, c = 0;

function f0(b_1) {
    !function() {
        if (b++, a++ + [][0 / (NaN !== {}) ^ NaN + (null ^ this)]) {
            var key3, expr3 = {
                [(c = 1 + c, (b_1 && (b_1.then &= 5)) <= 22 <= (25 === (24..toString() || -5)))]: (c = 1 + c, 
                b_1 += 1 & (24..toString() % -2 | NaN)),
                ...b_1,
                [(c = 1 + c, (b_1 && (b_1[b_1 && b_1[c = 1 + c, (b_1 && (b_1[--b + (b_1 && "function" == typeof b_1.get && 0 <= --_calls_ && (c = 1 + c, 
                b_1 && (b_1["b" in {
                    foo: (c = 1 + c, (25 >>> []) * (23..toString() + -0) || "object" === 1 >> (2 === [ , 0 ].length))
                }] >>>= -2 ^ NaN & (b_1 = "object" == {})), b_1.get)(this, 4))] += 1)) <= (NaN < (b_1 && (b_1.set += this != this)))]] = (b_1 && (b_1[c = 1 + c, 
                38..toString(), 38..toString(), "function" << (2 === [ , 0 ].length) >>> !1] >>= "b" - {})) <= /[a2][^e]+$/ / {})) >> (b_1 && ({
                    next: b_1[c = 1 + c, (!0).toString()[c = 1 + c, ([] % 0 & (b_1 && ({
                        Infinity: b_1.value
                    } = {
                        Infinity: []
                    }))) > 3 >>> (b_1 && (b_1[c = 1 + c, ((b_1 && ([ b_1.done ] = [ 5 == 38..toString() ])) ^ 5 - 24..toString()) === void 23..toString()] += "number"))]]
                } = {
                    next: NaN ^ (b_1 /= !1)
                })))]: (c = 1 + c, (b_1 && (b_1[c = 1 + c, NaN] += 3)) <= !0 || this - 5 == "object" << 38..toString()),
                get: (c = 1 + c, (b_1 && (b_1.set += "function") || 0) | (2 === [ , 0 ].length ^ "object") < !1),
                3: (c = 1 + c, (-0 ^ 23..toString() | "a" + 38..toString()) != !1 < (0 | 2 === [ , 0 ].length))
            }.foo;
            for (key3 in expr3) {
                c = 1 + c;
                expr3[key3];
                c += 1;
            }
        } else {
            (22 in [ (c = 1 + c, 23..toString(), !1 << (this || 3) % !1), (0 ^ (b_1 = 0)) & (!1 ^ !1 << (2 === [ , 0 ].length)), (c = 1 + (c = 1 + c), 
            4 % (b_1 && (b_1.in >>= 5))), ("number" ^ []) * (!0 <= (2 === [ , 0 ].length)) / !0, (c = 1 + (c = 1 + c), 
            -21 >> (22 ^ {}) / !1) ] || a || 3).toString();
        }
    }();
    (function f2(yield, argument_1, argument_2) {
        try {
            c = 1 + c, (arguments && (arguments[{
                b: (c = 1 + c, (yield && (yield[{}] += !(2 === [ , 0 ].length) == "undefined" + [])) & (24..toString() === 23..toString() && 21)),
                value(yield_2, a_2, b) {
                    super.b;
                },
                undefined: void (c = 1 + c),
                [(c = 1 + c, c += 1, yield -= !0)]: (c = 1 + (c += 1), (0 ^ (arguments && (arguments[c = 1 + c, 
                !0 << !1 + (c += 1, !0)] = !1))) <= 5)
            }.foo] = 0 != (arguments && (arguments[c = 1 + c, 0] = 1 / 0 << (2 === [ , 0 ].length))))) != (24..toString(), 
            arguments && (arguments.NaN |= !0)) ? c = 1 + c : (c = 1 + c, 24..toString());
        } catch (Infinity) {
            return void (c = 1 + c);
        } finally {
            var expr15 = --b + ("function" == typeof f3 && 0 <= --_calls_ && f3(!1, !1, ..."" + arguments));
            for (const key15 in expr15) {
                c = 1 + c, key15;
            }
        }
        switch (--b + (arguments && argument_2)) {
          default:
          case --b + ++b:
            switch (b) {
              case a++ + ("function" == typeof f0 && 0 <= --_calls_ && f0((c = 1 + c, !0 - this < 0 || 5 * (38..toString() <= -2)))):
                c = 1 + c, b_1 = !1, yield && (yield.a -= {} < 1), b_1 && (b_1.done = 4 != {}), 
                c = 1 + c, b_1 && (b_1[c = 1 + c, (yield && (yield.in |= -2)) ^ (0 | (2 === [ , 0 ].length) < {})] -= +this), 
                23..toString();
                break;

              case --b + "a":
                c = 1 + c, b_1 && (b_1.set = !0);
                break;

              case a++ + (yield && yield[c = 1 + c, (void 0 ^ 24..toString()) >>> !1 == (b_1 && ([ b_1.value ] = [ !0 < (-3 !== 24..toString()) ]))]):
                c = 1 + (1 + c), b_1 && (b_1[c = 1 + c, 0 == (-2 === (b_1 && ([ b_1[c = 1 + c, (!0 !== (b_1 = /[a2][^e]+$/)) < (yield && (yield.async = /[a2][^e]+$/ * (this < 23..toString())))] ] = [ void 0 <= 24..toString() ])))] += 38..toString() || "number"), 
                b_1 = !0 >> (24..toString() && 1 / 0);
                break;

              case 0 <= --_calls_ && f2(38..toString()):
                c = 1 + c, yield && (yield.foo **= !0), c = 1 + c, yield && ([ yield.var ] = [ 0 ]);
            }
            break;

          case arguments && (arguments[(c += 1) + (NaN == (c += 1, 22 >>> {}))] += (25 | 24..toString() && "0bar") < !1):
            var c_1 = void 0;
            c = 1 + c, yield **= 0, 24..toString(), 23..toString(), arguments && (arguments[c = 1 + c, 
            0 | (c_1 && (c_1.done = -96), !1)] = this < 1);
            break;

          case b:
            /[abc4]/.test((c = 1 + c, (!0 >> ((2 === [ , 0 ].length) >> -1) <= (!0 <= (c += 1, 
            {})) || b || 5).toString()));
        }
    })(b_1 && b_1.get);
    c = 1 + c, 38..toString(), function(b_1, c_1) {
        c = 1 + c;
        for (var brake34 = 5; c = 1 + c, b_1 && (b_1[b_1 && "function" == typeof b_1.done && 0 <= --_calls_ && b_1.done(!0 & "object" <= (2 === [ , 0 ].length) !== 3, (c = 1 + (c = 1 + c), 
        b_1 && (b_1.get = (c_1 && (c_1[c = 1 + c, !0] = 1)) ^ 24..toString() << "number" | 0 | 23..toString())), (c = 1 + c, 
        23..toString() >>> void 0 >> 0))] = (c += 1, -4)) && 0 < brake34; --brake34) {
            c = 1 + c, 38..toString();
        }
    }((++a, 3)), 23..toString(), c = 1 + c, c = 1 + (c += 1), c += 1, 23..toString(), 
    function() {
        var yield_1 = (c = 1 + c, void (yield_1 && (yield_1[c = 1 + c, 0 / ("b" >>> 23..toString()) * !0] = !0)));
    }(c += 1), c = 1 + c;
}

var a_1 = f0(24..toString(), -0);

console.log(null, a, b, c, 1 / 0, NaN, void 0);
```
```
original result:
null 102 9 46 Infinity NaN undefined

uglified result:
null 144 -12 494 Infinity NaN undefined
```
```js
// reduced test case (output will differ)

// (beautified)
function f0() {
    function f2() {
        arguments[!console.log() << 1] = 0;
        switch (arguments[-2 / -1]) {
          case 0:
            0();
        }
    }
    f2();
}

f0();
// output: TypeError: 0 is not a function
// minify: 
// 
// options: {
//   "mangle": false,
//   "output": {
//     "v8": true
//   },
//   "validate": true
// }
```
```
minify(options):
{
  "mangle": false,
  "output": {
    "v8": true
  }
}

Suspicious compress options:
  arguments
  evaluate
  keep_fargs
  pure_getters
  reduce_vars
  side_effects
```


Discussion:

Patch:
diff --git a/lib/compress.js b/lib/compress.js
index 63c1164bd15..ce12da2def6 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -463,6 +463,7 @@ merge(Compressor.prototype, {
             })) {
                 tw.defun_ids[def.id] = false;
             }
+            def.reassigned = 0;
             def.recursive_refs = 0;
             def.references = [];
             def.should_replace = undefined;
@@ -662,7 +663,7 @@ merge(Compressor.prototype, {
             var key = node.property;
             if (key.is_constant()) key = key.value;
             if (!(key instanceof AST_Node) && !RE_POSITIVE_INTEGER.test(key)) return;
-            def.reassigned = true;
+            def.reassigned++;
             (key instanceof AST_Node ? def.scope.argnames : [ def.scope.argnames[key] ]).forEach(function(argname) {
                 if (argname instanceof AST_SymbolFunarg) argname.definition().fixed = false;
             });
@@ -11235,14 +11236,12 @@ merge(Compressor.prototype, {
                     || !all(fn.argnames, function(argname) {
                         return argname instanceof AST_SymbolFunarg;
                     })) {
-                    if (!compressor.option("reduce_vars")
-                        || def.reassigned
-                        || arg_def.assignments
-                        || arg_def.orig.length > 1) {
-                        argname = null;
-                    }
+                    if (has_reassigned() || arg_def.assignments || arg_def.orig.length > 1) argname = null;
                 }
-            } else if (index < fn.argnames.length + 5 && compressor.drop_fargs(fn, fn_parent) && !fn.rest) {
+            } else if ((assigned || !has_reassigned())
+                && index < fn.argnames.length + 5
+                && compressor.drop_fargs(fn, fn_parent)
+                && !fn.rest) {
                 while (index >= fn.argnames.length) {
                     argname = fn.make_var(AST_SymbolFunarg, fn, "argument_" + fn.argnames.length);
                     fn.argnames.push(argname);
@@ -11251,7 +11250,7 @@ merge(Compressor.prototype, {
             if (argname && find_if(function(node) {
                 return node.name === argname.name;
             }, fn.argnames) === argname) {
-                def.reassigned = false;
+                if (assigned) def.reassigned--;
                 var sym = make_node(AST_SymbolRef, self, argname);
                 sym.reference();
                 delete argname.__unused;
@@ -11330,6 +11329,10 @@ merge(Compressor.prototype, {
                 }
             }
         }
+
+        function has_reassigned() {
+            return !compressor.option("reduce_vars") || def.reassigned;
+        }
     });
 
     AST_Arrow.DEFMETHOD("contains_super", return_false);


Test patch:
diff --git a/test/compress/arguments.js b/test/compress/arguments.js
index 4c602a685d8..5d773172190 100644
--- a/test/compress/arguments.js
+++ b/test/compress/arguments.js
@@ -84,6 +84,7 @@ replace_index_drop_fargs_1: {
         evaluate: true,
         keep_fargs: false,
         properties: true,
+        reduce_vars: true,
     }
     input: {
         var arguments = [];
@@ -119,7 +120,7 @@ replace_index_drop_fargs_1: {
             console.log(b, b, arguments.foo);
         })("bar", 42);
         (function(arguments) {
-            console.log(arguments[1], arguments[1], arguments.foo);
+            console.log("bar"[1], "bar"[1], "bar".foo);
         })("bar", 42);
         (function(argument_0, argument_1) {
             var arguments;
@@ -649,6 +650,7 @@ issue_3420_1: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         console.log(function() {
@@ -671,6 +673,7 @@ issue_3420_2: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         var foo = function() {
@@ -691,6 +694,7 @@ issue_3420_3: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         "use strict";
@@ -713,6 +717,7 @@ issue_3420_4: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         !function() {
@@ -738,6 +743,7 @@ issue_3420_5: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         "use strict";
@@ -765,6 +771,7 @@ issue_3420_6: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         console.log(function() {
@@ -783,6 +790,7 @@ issue_3420_7: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         "use strict";
@@ -827,6 +835,7 @@ issue_4291_1: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         console.log(function() {
@@ -847,6 +856,7 @@ issue_4291_2: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         var a = function() {
@@ -857,8 +867,8 @@ issue_4291_2: {
         console.log(a[1], a[0], a.length);
     }
     expect: {
-        var a = function(argument_0) {
-            if (argument_0)
+        var a = function() {
+            if (arguments[0])
                 arguments[1] = "PASS";
             return arguments;
         }(42);
@@ -871,6 +881,7 @@ issue_4397: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         console.log(typeof function() {
@@ -999,3 +1010,26 @@ issue_4696: {
     }
     expect_stdout: "PASS"
 }
+
+issue_4809: {
+    options = {
+        arguments: true,
+        keep_fargs: false,
+        reduce_vars: true,
+    }
+    input: {
+        A = 0;
+        (function() {
+            arguments[A] = "PASS";
+            console.log(arguments[0]);
+        })();
+    }
+    expect: {
+        A = 0;
+        (function() {
+            arguments[A] = "PASS";
+            console.log(arguments[0]);
+        })();
+    }
+    expect_stdout: "PASS"
+}
diff --git a/test/compress/arrows.js b/test/compress/arrows.js
index c906aa4cb49..56355edb2f9 100644
--- a/test/compress/arrows.js
+++ b/test/compress/arrows.js
@@ -276,6 +276,7 @@ drop_arguments: {
     options = {
         arguments: true,
         keep_fargs: false,
+        reduce_vars: true,
     }
     input: {
         console.log(function() {