Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug triggered by keep_fargs=false #2114

Closed
alexlamsl opened this issue Jun 16, 2017 · 27 comments · Fixed by #2116
Closed

Bug triggered by keep_fargs=false #2114

alexlamsl opened this issue Jun 16, 2017 · 27 comments · Fixed by #2116
Labels

Comments

@alexlamsl
Copy link
Collaborator

Similar to #2107 - ouch indeed.

// original code
// (beautified)
var a = 100, b = 10, c = 0;

{
    var b_2 = function f0(a_2, a_2, b) {
        +("" / -2 % ~3 > (a_2 = 0 % "") % ([] * Infinity));
        {
            return;
            (c = c + 1) + {
                c: a++ + typeof parseInt,
                1.5: a++ + a--
            }[a++ + [ b <<= a, --b + [].length, (c = c + 1) + [ --b + (b >>>= a), (c = c + 1) + --b, , a++ + [ (c = 1 + c, 
            (NaN % 23..toString() | 38..toString() % Infinity) + ((a_2 |= 1 !== []) - (a_2 && (a_2[(c = 1 + c, 
            ([] ^ -1) << (a_2 && (a_2.c /= null === /[a2][^e]+$/)) > (/[a2][^e]+$/, -5) >> (Infinity >> "number"))] += 25 | -5)))) ][(([ , 0 ].length === 2) >> "object" ^ null << 25) - (null & "undefined" || -2 >> "bar")], b + 1 - .1 - .1 - .1 ].c, a++ + (b = a) ].var];
        }
    }([ b++, ((c = c + 1) + (b = a) || 2).toString()[a++ + a++], typeof foo_2 != "symbol", --b + {
        "": [ [ , {
            Infinity: (c = 1 + c, b_2 && (b_2.undefined ^= ({} === "bar") * (5 < ([ , 0 ].length === 2))) && 4 > -0 & 1 !== -0),
            0: (c = 1 + c, c = c + 1, NaN + -2 + [ , 0 ][1] % [ , 0 ][1]),
            length: (c = 1 + c, (-0 % -5 !== (b_2 && (b_2.var = [] !== 3))) < /[a2][^e]+$/ % -3 * (null || 1))
        }.in ][/[abc4]/.test(((c = c + 1) + (b += a) || b || 5).toString())], a++ + /[abc4]/.test(((b += a) || b || 5).toString()), typeof bar_1 !== "symbol", ,  ].Infinity
    }[(a++ + "" || 6).toString()[--b + function() {
        {
            {
            }
            {
                var brake6 = 5;
                do {
                    c = 1 + c, (5 >> 3, -4 <= [ , 0 ][1]) - (b_2 && (b_2.undefined = 2 < -1 || "foo" === undefined));
                } while ((c = 1 + c, (0 >>> [ , 0 ][1]) - 23..toString() % 1 >= ((-2, "number") != {} * "function")) && --brake6 > 0);
            }
            {
                var expr8 = (c = 1 + c, (undefined <= "object") >> 0 / 3 <= (1 != "bar", "bar" ^ 3));
                L127602: for (var key8 in expr8) {
                    c = 1 + c;
                    var bar_2 = expr8[key8];
                    c = 1 + c, b_2 && (b_2.a = ([] === 4 !== "number" <= -5) >= (void -0, c = c + 1, 
                    []));
                }
            }
            return;
        }
        {
            var brake12 = 5;
            do {
                {}
            } while ((b += a) && --brake12 > 0);
        }
    }()]], typeof void function a_1() {
        {
            var NaN_1 = function f1(a_1) {
                var undefined = (c = 1 + c, void (-3 || "bar") * (c = c + 1, true * 25)), parseInt = (c = 1 + c, 
                (-5 ^ -5 && -3 >> ([ , 0 ].length === 2)) + (24..toString() < 5 ^ (1 | "object")));
            }((b_2 && (b_2.foo += -2 ^ 23..toString())) >>> ("function" >= 1) === (NaN_1 && (NaN_1.b += ([] >= -0) % (c = c + 1, 
            24..toString()))));
        }
        {
            var brake17 = 5;
            L127603: do {
                [ (c = 1 + c, (delete -3 ^ "number" >>> NaN) / ((b_2 = -1 * "object") >= (Infinity ^ 25))), (c = 1 + c, 
                ((/[a2][^e]+$/ ^ 3) !== 22 >> 38..toString()) <= (1 <= "function") % (/[a2][^e]+$/ === Infinity)), (c = 1 + c, 
                ("undefined" - []) * ("undefined" && 23..toString()) - ~(22 > "object")), (c = 1 + c, 
                b_2 && (b_2.in |= (1 <= null, "bar", -4) << (c = c + 1, []) * ~4)) ].null;
            } while (a++ && --brake17 > 0);
        }
    }() ]);
}

{
    var brake20 = 5;
    while ([ (c = c + 1) + new function() {
        this[3] = (((b_2 += -0 << 2 <= 23..toString() % -1) >>> (b_2 && (b_2.a = Infinity >> 3 > Infinity * "number")) !== ((b_2 && (b_2.foo /= ([ , 0 ].length === 2) > -0), 
        22 != -2) == ("number" == false) + (5 && -0))) >= ((b_2 && (b_2[-5 > "undefined" < 5 * {} < ("function" ^ "" | 0 >>> [ , 0 ][1])] += (([ , 0 ].length === 2) - -2 + (4 <= 38..toString())) * (([ , 0 ].length === 2) % 38..toString() >>> (/[a2][^e]+$/ & 23..toString())))) <= ((-0 >> null !== [ , 0 ][1] >>> undefined) >= (b_2 && (b_2.null = 4 == "" !== -1 >= {})))) | (((undefined & "undefined") >>> (/[a2][^e]+$/ != -5)) - ((c = c + 1, 
        24..toString()) + ("function" + "foo")) & (true ^ null) >>> ({} >= false) >> ((5, 
        38..toString()) !== (NaN | "foo"))) / (((23..toString() * -2 ^ ("" | "number")) >>> (3 <= "number", 
        23..toString() + "foo")) % ((null < 5) * (true != -4) | (b_2 |= 0 * NaN) >>> (0, 
        0)))) / (((c = c + 1, (Infinity | "foo") === (b_2 *= 24..toString() ^ -2) | (23..toString() ^ -0 && NaN <= "")) === ((b_2 && (b_2[(c = c + 1) + /[abc4]/.test((a++ + (b = a) || b || 5).toString())] = ({} == false, 
        true != undefined) % (/[a2][^e]+$/ + undefined >> ("bar" > ([ , 0 ].length === 2))))) & !((0 && 24..toString()) < ([ , 0 ].length === 2 ^ {})))) >= (((b_2 ^= ("object", 
        null) != 23..toString() + null) === (b_2 && (b_2.undefined += 5 === "undefined" === ([ , 0 ].length === 2) >= -2))) <= ((b_2 && (b_2.NaN = "number" || NaN)) + 38..toString() / ([ , 0 ].length === 2) ^ (undefined ^ true) !== (NaN == false))) << (((+"undefined" && false % Infinity) < (/[a2][^e]+$/ - false || 38..toString() ^ 1)) >> (("undefined" != 38..toString()) << 2 % {} >= (b_2 && (b_2.NaN += -3 >> 4 >> (23..toString() ^ 5)))))) < ((b_2 && (b_2[[]] += (((false != []) + (Infinity === -3) !== ("" != 25 | NaN <= "bar")) << (("undefined" > "object") >> (-0 ^ -2) || (b_2 += 1 - 5, 
        23..toString() && 38..toString())), (c = c + 1, true) % (b_2 && (b_2.null += (1, 
        -5))) + (b_2 && (b_2.null ^= ("number" > -5) * ("function" !== ([ , 0 ].length === 2)))) ^ ((5, 
        "function") << -1 * 24..toString()) + (22 >>> "" || -3 + [])) || +((c = c + 1, 24..toString() > NaN) == (3 ^ 0) % (-2 >> true)) == (("object" ^ 2 ^ (-2 | [ , 0 ].length === 2), 
        (24..toString() >> Infinity) * (b_2 && (b_2.foo = {} >>> 24..toString()))) === ("function" < ([ , 0 ].length === 2) ^ [ , 0 ][1] + 3) >= (("object" == "number") > 5 - "object")))) !== (c = c + 1, 
        b_2 && (b_2[{
            b: a++ + -((5 > NaN >= 23..toString() + "foo") / ((1 > false) % (NaN & 24..toString()))),
            length: (c = c + 1) + /[abc4]/.test(((c = 1 + c, (5 < 5 | (3 | "foo")) - (("function" === 0) >> (null == NaN))) || b || 5).toString()),
            undefined: b = a,
            a: (c = c + 1) + [ (c = 1 + c, b_2 && (b_2[a++ + b--] /= ((0 | "") > "number" >>> "number") / ([ , 0 ][1] !== 3 & (b_2 && (b_2.var = -5 <= Infinity))))), ,  ]
        }] += (-1 % "undefined" <= {} - [ , 0 ][1]) << (-3, -4) - (c = c + 1, true) << ((b_2 && (b_2[a++ + ((c = 1 + c, 
        c = c + 1, b_2 && (b_2.Infinity /= 0 < -3 ^ true % 3)) || a || 3).toString()] = (Infinity <= NaN) / (false && "object"))) | (5 ^ "foo") != {} + 25))) << ((b_2 && (b_2[(c = c + 1) + a--] = (b_2 -= 1 == /[a2][^e]+$/) > (false || [ , 0 ].length === 2) & (-3 != 25) >> (3 && "number") & ({} === [] | (b_2 && (b_2[(c = 1 + c, 
        (4 << 1) / (c = c + 1, NaN) >= ((23..toString() ^ 4) === [ , 0 ][1] * null))] /= -0 != 5)) || (5 | 24..toString()) + "undefined" * -1))) === ((24..toString() + -1 | 22 < false) >= (b_2 && (b_2.c = (Infinity <= -3) >>> ([ , 0 ][1] >>> undefined))) && (3 > "bar") % ("function" > 22) / ("" > "foo" > ("bar" !== 5)))));
        this[[ 0 === 1 ? a : b, a++ + {
            undefined: void (b_2 && (b_2[[ , 0 ].length === 2] = 23..toString() >>> false >> ([] !== "function") & ([ , 0 ][1] !== Infinity && "foo" == 1)))
        }.in, (c = c + 1) + ((a++ + a++ || 9).toString()[--b + ~(((-4 ^ "bar") <= -0 + 24..toString()) - ((24..toString() == 1) + (38..toString() + Infinity)))] || a || 3).toString(), --b + (1 === 1 ? a : b), b_2 && b_2[!b ? {
            NaN: typeof bar_2 != "special",
            "\t": --b + ((b_2 <<= true ^ null) % (24..toString(), 25) || (NaN > "number") / (b_2 && (b_2.Infinity = 1 || -2))),
            "-2": --b
        }.NaN : [].c] ]] = (((b_2 && (b_2.null = -2 >= 2 < 1 - 38..toString() == (null << "bar" || -5))) + (((b_2 && (b_2[(c = 1 + c, 
        ([ , 0 ][1] ^ Infinity || -0 != 2) < ((2, "foo") | -3 - 1))] *= false | 2)) >= ([ , 0 ].length === 2 & [ , 0 ][1])) - (-4 >> -1 == "" >> 5))) % (("function" % -4 - (false | Infinity)) * ((c = c + 1, 
        38..toString()) ^ 2 - undefined) ^ (c = c + 1, 25 % true) != (b_2 && (b_2.in = 24..toString() == ([ , 0 ].length === 2))) >>> undefined % true) / (((-5 & 24..toString()) % ("number" << "object") & (-0 && 4) !== (NaN & [ , 0 ][1]) || delete {} === (5 && 3) !== ("foo" || "undefined") << -0 - 25) != (b_2 = ((b_2 && (b_2.in += null - "undefined")) ^ (-2, 
        {})) == !(38..toString() | 23..toString())) * (([ , 0 ][1] * 4 < -2 << -3) >>> (("number" ^ 22) < 0 >> "bar"))) > (b_2 && (b_2[!function b() {
            {
                var brake21 = 5;
                while ((c = c + 1) + ((c = 1 + c, (b_2 && (b_2.Infinity += 5 !== 23..toString() === ("object" && 1))) === 0 >> ([ , 0 ].length === 2) <= ([] ^ "object")) || 8).toString()[(c = 1 + c, 
                ~((-1 || -2) >>> (25 ^ -0)))] && --brake21 > 0) {
                }
            }
            try {
                {
                    var brake24 = 5;
                    do {
                        c = 1 + c, ([ , 0 ][1] >= -0 & "object" / {}) / (-0 - 5 > (c = c + 1, /[a2][^e]+$/));
                    } while ((c = 1 + c, (c = c + 1, /[a2][^e]+$/ % /[a2][^e]+$/) <= ("function" > 24..toString() >= (b_2 && (b_2.undefined += undefined <= 3)))) && --brake24 > 0);
                }
            } catch (b) {
                c = 1 + c, (3 >= -2 && {} >>> 38..toString()) % ((b_2 && (b_2.null = -1 < 24..toString())) / (-5 ^ 22));
                c = 1 + c, ({} + Infinity || 24..toString() * 0) | void -2 != (-1 | "undefined");
            }
            {
                return b += a;
            }
        }()] += ((4 | "function") === (-3 === -3)) % ("bar" / 5 >>> (-0 ^ 25)) + ((3 << null || "" != null) + (c = c + 1, 
        b_2 >>>= -3 == 3)) | delete (b_2 && (b_2.in += "function" < 2)) >>> (("number" != "number") >= ("", 
        23..toString())) !== ((b_2 && (b_2[(c = 1 + c, (undefined >> 24..toString() !== (-5 & "foo")) << -(38..toString() >> 3))] += -5 << -2)) - ({} == 0) & (c = c + 1, 
        Infinity == "foo")))) % ((b_2 && (b_2[function parseInt_1() {
            L127604: for (var brake29 = 5; (c = 1 + c, ((/[a2][^e]+$/, 2) <= (-0, /[a2][^e]+$/)) >> (-0 === 24..toString()) - ("function" > {})) && brake29 > 0; --brake29) {
                c = 1 + c, (23..toString() & 2 | /[a2][^e]+$/ ^ "foo") !== 3 > -1 <= (-3 <= "undefined");
            }
        }] += (c = c + 1, (-1 & -3) !== true <= 23..toString()) % ((-2 <= "function" == -2 >= -4) <= (b_2 += [] || true) >>> (-3 != -0)))) ^ ("undefined" >= "number" < (3 ^ -2) ^ (c = c + 1, 
        24..toString()) >>> (undefined | [ , 0 ].length === 2)) >= (0 + 4 ^ true != 25 | (b_2 && (b_2.NaN >>>= "bar" <= -0) || "function" >>> "foo")))) / (((3 << 4 << (b_2 && (b_2[(c = 1 + c, 
        (c = c + 1, 4 === "number") <= (c = c + 1, 22 >= "foo"))] += true >= "number")), 
        b_2 && (b_2.undefined >>= null + 23..toString() >> (-5 == Infinity))) >> (("foo" >= false & {} << ([ , 0 ].length === 2)) >>> (-0 != "undefined", 
        undefined !== "foo")) ^ ((b_2 && (b_2.foo = (b_2 && (b_2[(c = 1 + c, void (/[a2][^e]+$/ !== []) >>> ("undefined" / 3 ^ [ , 0 ].length === 2 == "number"))] = [ , 0 ][1] || "object")) | 4 << -3)) - (b_2 && (b_2.undefined >>>= (38..toString() || "object") ^ 5 & 24..toString())) | (2 ^ 2) + (24..toString() >>> "number") === ~(b_2 && (b_2.c <<= NaN & -3))) && (([ , 0 ][1] & 1) >= (23..toString() == 0) <= (/[a2][^e]+$/ > "function") - (b_2 && (b_2[(c = 1 + c, 
        (("number" || []) ^ (b_2 = 3 !== {})) - (false * [ , 0 ][1] == /[a2][^e]+$/ / 38..toString()))] -= ([ , 0 ].length === 2) + "")), 
        void 3 >> 3 % -5 <= (3 != NaN && 1 >> "")) >> ((null != /[a2][^e]+$/) - ("number" << 23..toString()) + ("bar" - "number" <= -2 / "")) % ((1 ^ 24..toString()) >> (-0 == NaN) & (c = c + 1, 
        [] % 5))) | (b_2 = ((2 ^ NaN && [] >= []) >>> (Infinity === "" !== 0 % NaN) && (1 & -3 || b_2 && (b_2[(c = 1 + c, 
        (c = c + 1, undefined) > (-2 >= ([ , 0 ].length === 2)) && ([] != undefined && (b_2 && (b_2[(c = 1 + c, 
        b_2 += (c = c + 1, true ^ 38..toString()) * (void "undefined" !== "" <= 38..toString()))] = NaN === "bar"))))] = NaN <= 3)) / (NaN >= 5 || [ , 0 ][1] | false) && true % {} % (0 & -5) + ((25 & 23..toString()) >> delete "function") >= (("undefined" % null || "object" * [ , 0 ][1]) <= (NaN > undefined) << (b_2 = 0 + null)), 
        -((c = c + 1, c = c + 1, NaN >> undefined) !== !(b_2 && (b_2.Infinity |= Infinity - /[a2][^e]+$/), 
        38..toString() > "object")))));
        this[(c = c + 1) + b++] += (b_2 += ((-2 == [ , 0 ][1] & /[a2][^e]+$/ != true, -0 <= 3 > (null || "function")) == (-(-2 < []) | (-"object", 
        -5 - null))) / (c = c + 1, +("number" | 38..toString()) >= ([], -0) % (false * 0)) >= (c = c + 1, 
        (c = c + 1, (38..toString() | "undefined") >= (5 & 5)) === ([] - -0 === (-3 !== -1) !== !4 <= undefined / [ , 0 ][1]))) << ((c = c + 1, 
        -{} ^ 4 >> "foo") > ((23..toString(), true) & -0 + 25 || 38..toString() % undefined ^ 22 != -4) == (b_2 && (b_2[--b + +(delete (b_2 && (b_2.undefined >>>= "number" > "number")) % (0 !== 23..toString() === !38..toString()))] /= (("bar" | 24..toString()) >>> (-5 ^ 24..toString()) && (b_2 && (b_2.a = "foo" == 2)) === (b_2 && (b_2.foo >>>= {} >= -5))) != ((b_2 && (b_2.null += -2 * /[a2][^e]+$/) || 24..toString() === -2) & (5 >> [ , 0 ][1] && "function" | null)))) & (((b_2 && (b_2[(c = 1 + c, 
        ("foo" < "number" || "bar" >= null) ^ (null <= "object") >> (true << [ , 0 ][1]))] = (-5, 
        ""))) != (0 ^ 2)) >= ((-2 || [ , 0 ][1]) | (b_2 && (b_2[(c = 1 + c, delete (b_2 += -4 === {} || -[]))] = "function" >> -0))), 
        2 * -1 === "foo" >= -2, 5 * NaN >= void 38..toString()) >> (((b_2 && (b_2[b_2 && b_2.Infinity] = delete 0 >= ("function" != 3))) ^ "number" % -5 << (-1 ^ -3)) >= ((c = c + 1, 
        2) == (b_2 = false || NaN)) % (c = c + 1, "foo" & -1))) != -((((c = c + 1, -2) * ("function" ^ -3), 
        -3 ^ -5 ^ "number" >>> -3) < (-1 / 0 == (c = c + 1, /[a2][^e]+$/)) / ((3 >= /[a2][^e]+$/) - (2 + "foo")), 
        (((b_2 = 24..toString() ^ -1) && (b_2 += "function" || 38..toString())) > (!"function" > (NaN | "function"))) - ((4 ^ 0) / (true, 
        undefined) ^ (([ , 0 ].length === 2) >>> 1 ^ undefined & 0))) < ((b_2 && (b_2.a = (0 < undefined === -2 >> 23..toString()) + (("object" ^ Infinity) == null >= 23..toString()))) < (c = c + 1, 
        "foo" << -0 ^ !true) < ((-4 ^ 1) < (b_2 && (b_2.var = 1 + "function")) > Infinity / "number" + (3 << "bar") & (c = c + 1, 
        b_2 && (b_2[--b] = [ , 0 ].length === 2 | "object" && "function" ^ 1)))));
    }() ][--b + {
        b: --b + (b_2 && b_2[a++ + (b_2 && b_2.NaN)]),
        0: 1 === 1 ? a : b,
        NaN: b--
    }.b] && --brake20 > 0) {
        L127605: {
            if ((c = c + 1) + [ a++ + (b_2 && b_2[a++ + [ delete b ].in]), ,  ][--b + +function() {
                {
                    var parseInt_1 = function f2() {
                        for (var brake34 = 5; (c = 1 + c, (true >= 22) - ([ , 0 ].length === 2 ^ "number") === (24..toString() | 3) >= (25 ^ 4)) && brake34 > 0; --brake34) {
                            c = 1 + c, b_2 && (b_2[(c = c + 1) + -0] = b_2 && (b_2.Infinity -= -0 + Infinity << (1 && 24..toString())) || (-3 >> {}) % ("object" > 1));
                        }
                    }(a++ + (0 === 1 ? a : b));
                }
                {
                    var brake37 = 5;
                    while ((-4 - -4) % (-5 ^ -0) < (-5 - -3 & (1 && 3)) && --brake37 > 0) {}
                }
                b--;
            }()]) {
                a++ + 23..toString();
            } else {
                var brake41 = 5;
                L127606: while (--b + (typeof Math_1 == "boolean") && --brake41 > 0) {}
            }
        }
    }
}

console.log(null, a, b, c);
// uglified code
// (beautified)
for (var a = 100, b = 10, c = 0, b_2 = (b++, ((c += 1) + (b = a) || 2).toString()[a++ + a++], 
--b, c = 1 + c, b_2 && (b_2.undefined ^= ("bar" === {}) * (5 < (2 === [ , 0 ].length))), 
c = 1 + c, c += 1, c = 1 + (c += 1), b_2 && (b_2.var = 3 !== []), /[abc4]/.test(((c += 1) + (b += a) || b || 5).toString()), 
a++, /[abc4]/.test(((b += a) || b || 5).toString()), (a++ + "" || 6).toString()[--b + function() {
    var t = 5;
    do {
        c = 1 + c, b_2 && (b_2.undefined = !1);
    } while (c = 1 + c, (0 >>> [ , 0 ][1]) - 23..toString() % 1 >= ("number" != "function" * {}) && --t > 0);
    var n = (c = 1 + c, !0);
    for (var b in n) {
        c = 1 + (c = 1 + c), b_2 && (b_2.a = (4 === [] != 0) >= (c += 1, []));
    }
}()], void function() {
    var t = (b_2 && (b_2.foo += -2 ^ 23..toString()), t && (t.b += ([] >= -0) % (c += 1, 
    24..toString())), c = 1 + c, c += 1, c = 1 + c, void 24..toString()), n = 5;
    do {
        b_2 = NaN, c = 1 + (c = 1 + c), 38..toString(), c = 1 + c, 23..toString(), c = 1 + c, 
        b_2 && (b_2.in |= -4 << -5 * (c += 1, []));
    } while (a++ && --n > 0);
}()), brake20 = 5; [ (c += 1) + new function() {
    this[3] = (((b_2 += 0 <= 23..toString() % -1) >>> (b_2 && (b_2.a = !1)) !== (0 == (b_2 && (b_2.foo /= (2 === [ , 0 ].length) > -0), 
    !0))) >= ((b_2 && (b_2[!1 < 5 * {} < (0 | 0 >>> [ , 0 ][1])] += ((2 === [ , 0 ].length) - -2 + (4 <= 38..toString())) * ((2 === [ , 0 ].length) % 38..toString() >>> (/[a2][^e]+$/ & 23..toString())))) <= ((0 != [ , 0 ][1] >>> void 0) >= (b_2 && (b_2.null = 0 != -1 >= {})))) | (0 - (c += 1, 
    24..toString() + "functionfoo") & 1 >>> ({} >= !1) >> (0 !== 38..toString())) / (((-2 * 23..toString() ^ 0) >>> 23..toString() + "foo") % (1 | (b_2 |= NaN) >>> 0))) / (c += 1, 
    ((0 == (b_2 *= -2 ^ 24..toString()) | (-0 ^ 23..toString() && !1)) == ((b_2 && (b_2[(c += 1) + /[abc4]/.test((a++ + (b = a) || b || 5).toString())] = !0 % (/[a2][^e]+$/ + void 0 >> ("bar" > (2 === [ , 0 ].length))))) & !(0 < (2 === [ , 0 ].length ^ {})))) >= (((b_2 ^= null != 23..toString() + null) === (b_2 && (b_2.undefined += 0 == (2 === [ , 0 ].length) >= -2))) <= ((b_2 && (b_2.NaN = "number")) + 38..toString() / (2 === [ , 0 ].length) ^ !0)) << ((NaN < (1 ^ 38..toString())) >> (("undefined" != 38..toString()) << 2 % {} >= (b_2 && (b_2.NaN += -1 >> (5 ^ 23..toString())))))) < ((b_2 && (b_2[[]] += (b_2 += -4, 
    23..toString() && 38..toString(), c += 1, !0 % (b_2 && (b_2.null += -5)) + (b_2 && (b_2.null ^= !1 * ("function" !== (2 === [ , 0 ].length)))) ^ 22 + ("function" << -1 * 24..toString()) || +(0 == (c += 1, 
    24..toString() > NaN)) == ((24..toString() >> 1 / 0) * (b_2 && (b_2.foo = {} >>> 24..toString())) === ("function" < (2 === [ , 0 ].length) ^ [ , 0 ][1] + 3) >= !1)))) !== (c += 1, 
    (b_2 && (b_2[{
        b: a++ + -(!1 >= 23..toString() + "foo") / (!0 % (NaN & 24..toString())),
        length: (c += 1) + /[abc4]/.test((c = 1 + c, 3).toString()),
        undefined: b = a,
        a: (c += 1) + [ (c = 1 + c, b_2 && (b_2[a++ + b--] /= !1 / (3 !== [ , 0 ][1] & (b_2 && (b_2.var = !0))))), ,  ]
    }] += (NaN <= {} - [ , 0 ][1]) << -4 - (c += 1, !0) << ((b_2 && (b_2[a++ + (c = 1 + c, 
    c += 1, b_2 && (b_2.Infinity /= 1) || a || 3).toString()] = NaN)) | 5 != {} + 25))) << ((b_2 && (b_2[(c += 1) + a--] = (b_2 -= !1) > (2 === [ , 0 ].length) & 1 & ({} === [] | (b_2 && (b_2[(c = 1 + c, 
    8 / (c += 1, NaN) >= ((4 ^ 23..toString()) == null * [ , 0 ][1]))] /= !0)) || (5 | 24..toString()) + NaN))) === ((24..toString() + -1 | !1) >= (b_2 && (b_2.c = !1 >>> ([ , 0 ][1] >>> void 0))) && NaN)))), 
    this[[ b, a++ + {
        undefined: void (b_2 && (b_2[2 === [ , 0 ].length] = 23..toString() >>> !1 >> ("function" !== []) & ([ , 0 ][1] !== 1 / 0 && !1)))
    }.in, (c += 1) + ((a++ + a++ || 9).toString()[--b + ~((-4 <= -0 + 24..toString()) - ((1 == 24..toString()) + (38..toString() + 1 / 0)))] || a || 3).toString(), --b + a, b_2 && b_2[b ? [].c : {
        NaN: "special" != typeof bar_2,
        "\t": --b + ((b_2 <<= 1) % (24..toString(), 25) || !1 / (b_2 && (b_2.Infinity = 1))),
        "-2": --b
    }.NaN] ]] = (((b_2 && (b_2.null = !1 < 1 - 38..toString() == -5)) + (((b_2 && (b_2[(c = 1 + c, 
    ([ , 0 ][1] ^ 1 / 0 || !0) < -4)] *= 2)) >= (2 === [ , 0 ].length & [ , 0 ][1])) - !1)) % (NaN * (NaN ^ (c += 1, 
    38..toString())) ^ (c += 1, 0 != (b_2 && (b_2.in = 24..toString() == (2 === [ , 0 ].length))) >>> NaN)) / (((-5 & 24..toString()) % 0 & -0 != (NaN & [ , 0 ][1]) || !0) != (b_2 = ((b_2 && (b_2.in += NaN)) ^ {}) == !(38..toString() | 23..toString())) * ((4 * [ , 0 ][1] < -2 << -3) >>> !1)) > (b_2 && (b_2[!function t() {
        for (var n = 5; (c += 1) + (c = 1 + c, (b_2 && (b_2.Infinity += 5 !== 23..toString() === 1)) === 0 >> (2 === [ , 0 ].length) <= ("object" ^ []) || 8).toString()[(c = 1 + c, 
        -128)] && --n > 0; ) {}
        try {
            var b = 5;
            do {
                c = 1 + c, c += 1;
            } while (c = 1 + c, c += 1, NaN <= ("function" > 24..toString() >= (b_2 && (b_2.undefined += !1))) && --b > 0);
        } catch (t) {
            c = 1 + c, 38..toString(), b_2 && (b_2.null = -1 < 24..toString()), c = 1 + c, {} + 1 / 0 || 24..toString();
        }
        return t += a;
    }()] += NaN + (3 + (c += 1, b_2 >>>= !1)) | (b_2 && (b_2.in += !1), !0 >>> (!1 >= 23..toString()) != ((b_2 && (b_2[(c = 1 + c, 
    (void 0 >> 24..toString() != 0) << -(38..toString() >> 3))] += -5 << -2)) - (0 == {}) & (c += 1, 
    !1))))) % ((b_2 && (b_2[function() {
        for (var t = 5; c = 1 + c, !1 >> (-0 === 24..toString()) - ("function" > {}) && t > 0; --t) {
            c = 1 + c, 23..toString();
        }
    }] += (c += 1, (-3 !== !0 <= 23..toString()) % (!1 <= (b_2 += [] || !0) >>> !0)))) ^ (!1 ^ (c += 1, 
    24..toString() >>> (void 0 | 2 === [ , 0 ].length))) >= (5 | (b_2 && (b_2.NaN >>>= !1) || 0)))) / (b_2 && (b_2[(c = 1 + c, 
    c += 1, !1 <= (c += 1, !1))] += !1), ((b_2 && (b_2.undefined >>= null + 23..toString() >> !1)) >> ((!1 & {} << (2 === [ , 0 ].length)) >>> !0) ^ ((b_2 && (b_2.foo = (b_2 && (b_2[(c = 1 + c, 
    void 0 >>> (NaN ^ 2 === [ , 0 ].length == "number"))] = [ , 0 ][1] || "object")) | 4 << -3)) - (b_2 && (b_2.undefined >>>= (38..toString() || "object") ^ 5 & 24..toString())) | 0 + (24..toString() >>> "number") == ~(b_2 && (b_2.c <<= 0))) && (23..toString(), 
    b_2 && (b_2[(c = 1 + c, ("number" ^ (b_2 = 3 !== {})) - (!1 * [ , 0 ][1] == /[a2][^e]+$/ / 38..toString()))] -= (2 === [ , 0 ].length) + ""), 
    !0 >> (!0 - ("number" << 23..toString()) + !1) % ((1 ^ 24..toString()) >> !1 & (c += 1, 
    [] % 5)))) | (([] >= []) >>> !0 && 1 / (!1 | [ , 0 ][1]) && (23..toString(), b_2 = 0), 
    c += 1, c += 1, b_2 = -(0 !== (b_2 && (b_2.Infinity |= NaN), !(38..toString() > "object"))))), 
    this[(c += 1) + b++] += (b_2 += (0 == (-5 | -(-2 < []))) / (c += 1, +("number" | 38..toString()) >= NaN) >= (c += 1, 
    c += 1, ("undefined" | 38..toString()) >= 5 == ([] - -0 === !0 != !1 <= void 0 / [ , 0 ][1]))) << (c += 1, 
    (4 ^ -{}) > (25 & (23..toString(), !0) || 38..toString() % void 0 ^ !0) == (b_2 && (b_2[--b + (b_2 && (b_2.undefined >>>= !1), 
    1 % (0 !== 23..toString() == !38..toString()))] /= (("bar" | 24..toString()) >>> (-5 ^ 24..toString()) && (b_2 && (b_2.a = !1)) === (b_2 && (b_2.foo >>>= {} >= -5))) != ((b_2 && (b_2.null += NaN) || -2 === 24..toString()) & (5 >> [ , 0 ][1] && 0)))) & (b_2 && (b_2[(c = 1 + c, 
    !0 ^ !1 >> (!0 << [ , 0 ][1]))] = ""), b_2 && (b_2[(c = 1 + c, b_2 += -4 === {} || -[], 
    !0)] = 0), (NaN >= void 38..toString()) >> ((0 ^ (b_2 && (b_2[b_2 && b_2.Infinity] = !0))) >= (c += 1, 
    (2 == (b_2 = NaN)) % (c += 1, 0))))) != (c += 1, c += 1, -((((b_2 = -1 ^ 24..toString()) && (b_2 += "function")) > !1) - (0 ^ (2 === [ , 0 ].length) >>> 1) < ((b_2 && (b_2.a = (!1 === -2 >> 23..toString()) + (0 == null >= 23..toString()))) < (c += 1, 
    0) < (-3 < (b_2 && (b_2.var = "1function")) > NaN & (c += 1, b_2 && (b_2[--b] = 2 === [ , 0 ].length | "object" && 1))))));
}() ][--b + {
    b: --b + (b_2 && b_2[a++ + (b_2 && b_2.NaN)]),
    0: a,
    NaN: b--
}.b] && --brake20 > 0; ) {
    if ((c += 1) + [ a++ + (b_2 && b_2[a++ + [ delete b ].in]), ,  ][--b + +function() {
        !function() {
            for (var t = 5; c = 1 + c, !1 - (2 === [ , 0 ].length ^ "number") === (3 | 24..toString()) >= 29 && t > 0; --t) {
                c = 1 + c, b_2 && (b_2[(c += 1) + -0] = b_2 && (b_2.Infinity -= 1 / 0 << 24..toString()) || (-3 >> {}) % !1);
            }
        }(a++);
        for (var t = 5; --t > 0; ) {}
        b--;
    }()]) {
        a++, 23..toString();
    } else {
        for (var brake41 = 5; --b + ("boolean" == typeof Math_1) && --brake41 > 0; ) {}
    }
}

console.log(null, a, b, c);
original result:
null 115 103 84

uglified result:
null 115 103 85

minify(options):
{
  "compress": {
    "keep_fargs": false,
    "passes": 3
  }
}

Suspicious compress options:
  collapse_vars
  dead_code
  if_return
  inline
  pure_getters
  side_effects
  unused
@alexlamsl alexlamsl added the bug label Jun 16, 2017
@alexlamsl alexlamsl changed the title Bug in possibly collapse_vars Bug triggered by keep_fargs=false Jun 16, 2017
@alexlamsl
Copy link
Collaborator Author

Reduced test case:

$ type test.js
var c = 0;

!function(a_2) {
    a_2 = 0;
}([ {
    0: c = c + 1,
    length: c = 1 + c
}, typeof void function a_1() {
    var NaN_1 = function f1(a_1) {
    }(NaN_1 && (NaN_1.b += (c = c + 1, 0)));
}() ]);

console.log(c);

$ type test.js | node
2

$ uglifyjs test.js -c | node
2

$ uglifyjs test.js -c keep_fargs=0 | node
3

alexlamsl added a commit to alexlamsl/UglifyJS that referenced this issue Jun 17, 2017
alexlamsl added a commit to alexlamsl/UglifyJS that referenced this issue Jun 17, 2017
alexlamsl added a commit that referenced this issue Jun 17, 2017
@kzc
Copy link
Contributor

kzc commented Jun 17, 2017

With #2116 applied:

$ cat 2114.js 
var c = 0;

!function(a_2) {
    a_2 = 0;
}([ {
    0: c = c + 1,
    length: c = 1 + c
}, typeof void function a_1() {
    var NaN_1 = function f1(a_1) {
    }(NaN_1 && (NaN_1.b += (c = c + 1, 0)));
}() ]);

console.log(c);
$ bin/uglifyjs 2114.js -c passes=3 -b
var c = 0;

c = 1 + (c += 1), function() {
    var NaN_1 = void (NaN_1 && (NaN_1.b += (c += 1, 0)));
}(), console.log(c);

Notice that reduce_vars did not eliminate the statement
var NaN_1 = void (NaN_1 && (NaN_1.b += (c += 1, 0)));

I recognize it's nonsensical to have a declaration initialization to refer to itself before it has a value, but reduce_vars does know that NaN_1 is undefined at that point - does it not?

@alexlamsl
Copy link
Collaborator Author

reduce_vars hasn't become self-aware... I mean, it registers NaN_1 as having void (NaN_1 && (NaN_1.b += (c += 1, 0))) without discerning between where those NaN_1 are placed.

But you raised a good point - adding it to my TODO list 😉

@kzc
Copy link
Contributor

kzc commented Jun 17, 2017

reduce_vars hasn't become self-aware

It hasn't?!!

I'm waiting for reduce_vars to create bug reports on itself - and resolve them.

@alexlamsl
Copy link
Collaborator Author

alexlamsl commented Jun 17, 2017

Correction - NaN_1 will get marked as unsafe for substitution right after being assigned the value node from above, as it will immediately descend() into its value and run into its own AST_SymbolRef:
https://github.com/mishoo/UglifyJS2/blob/0a0f4f55912fed32b09c93a2a1efa19edce24e28/lib/compress.js#L320-L321

@alexlamsl
Copy link
Collaborator Author

and resolve them.

This is the vital part of the equation.

@alexlamsl
Copy link
Collaborator Author

I feel like I should be a responsible netizen and figure out the culprit in this, but I also feel rather lazy...

$ node test.js
null NaN NaN 190

$ cat test.js | node
null NaN NaN 132
// original code
// (beautified)
var a = 100, b = 10, c = 0;

try {
    switch (3) {
      case b += a:
        {
            var undefined_1 = function f0() {
                if (--b + /[abc4]/.test(((c = c + 1) + function() {
                    if (c = 1 + c, -4 % "foo" >>> 2 + "object" & [] * false <= (-4 > "foo")) {
                        c = 1 + c, (-2 & "undefined") / (23..toString() >= "") - (false << -4 >> (38..toString() > {}));
                    }
                }() || b || 5).toString())) {
                    for (var brake7 = 5; a++ + (+b ? a++ + +function() {
                        c = 1 + c, ((NaN && "foo") - (c = c + 1, [])) * (/[a2][^e]+$/ ^ 22 ^ (c = c + 1, 
                        [ , 0 ][1]));
                        c = 1 + c, (3 * {} === ("object" ^ "number")) <= ((1 & -0) === false >> -3);
                        c = 1 + c, (a = undefined > -0 && (a && (a[(c = 1 + c, {} * "bar" == (-0 && "foo") ^ (3 == 25 && (-5 || [ , 0 ][1])))] += ([ , 0 ].length === 2) / false))) != ([ , 0 ].length === 2 ^ true) + (c = c + 1, 
                        24..toString());
                    }() : --b + /[abc4]/.test((a++ + [ (c = 1 + c, 38..toString() + -0 - (25 >> -3) <= (5 >>> -1 >= 22 / null)), (c = 1 + c, 
                    (a.NaN = 0 << 22 >>> (-4 >= 3)) ^ (a && (a.a = true < [] > -2 + "undefined"))), (c = 1 + c, 
                    (c = c + 1, -2 <= -0) == (a && (a[(c = c + 1) + ++b] |= NaN / 2 >= (5 > "undefined")))) ][(c = 1 + c, 
                    (-5 >= -4 === (23..toString() !== true)) < (-0 || 3) + (Infinity, "bar"))] || b || 5).toString())) && brake7 > 0; --brake7) {
                        if (a++ + a--) {
                            var expr12 = NaN_1 && NaN_1.c;
                            for (var key12 in expr12) {
                                c = 1 + c;
                                var NaN_1 = expr12[key12];
                                try {
                                    c = 1 + c, (-5 >> 24..toString() << ("number" & {})) - ((-1 > 24..toString()) << (c = c + 1, 
                                    []));
                                } catch (a) {
                                } finally {
                                }
                            }
                        } else {
                            switch ((c = c + 1) + (NaN_1 && NaN_1.var)) {
                              case --b + --b:
                                c = c + 1;
                                {
                                    var a_2 = function f1(b_1, c, a_1) {
                                    }((c = 1 + c, (+"bar" ^ true >>> -0) != (c = c + 1, null) - (a_2 && (a_2.a = 5 >> 5))));
                                }
                                break;

                              default:
                              case --b + {
                                    length: a_2 && a_2.Infinity
                                }.NaN:
                                {
                                    var b = function f2(b_2, NaN, a) {
                                    }((c = 1 + c, ("object" + -2 == -2 < /[a2][^e]+$/) >> (null < "function") / (c = c + 1, 
                                    0)));
                                }
                                {
                                    return;
                                    a++ + +(!(-4 % 22) >> (("" === -1) >= (-3 !== -0)));
                                }
                                break;

                              case a++ + !a:
                                {
                                    var brake20 = 5;
                                    L89960: while ((b += a) && --brake20 > 0) {
                                        var brake21 = 5;
                                        L89961: do {
                                            c = 1 + c, (Infinity && -1) < (-2 ^ undefined), false % "bar" + (a_2 <<= -0 - 0);
                                        } while ((c = 1 + c, (22, 5) % (2 + -0) * (undefined % 5 % ("", false))) && --brake21 > 0);
                                    }
                                }
                                break;
                            }
                        }
                    }
                }
                switch (1 === 1 ? a : b) {
                  case --b + !function() {
                        c = c + 1;
                        var a_2_1 = !((Infinity && Infinity) === (-0 !== "") ^ (NaN_1 && (NaN_1[(c = 1 + c, 
                        ((NaN_1 += -5 || false) && ("foo", -1)) >> ((true ^ 2) != (true ^ undefined)))] = "" & NaN)) === -0 >= "foo");
                        {
                            var Infinity_2 = function f3(a_2_1) {
                            }((c = 1 + c, (("" ^ -5) < (a_2_1 && (a_2_1[(c = 1 + c, (true * "number" ^ (22, 
                            -2)) / (NaN_1 = 4 > true !== (1 ^ 5)))] = "undefined" >> "undefined"))) >>> ((5 || 22) < (Infinity_2 = (3, 
                            -0)))));
                        }
                        var Infinity_2_2 = a++ + {
                            Infinity: (c = 1 + c, Infinity_2_2 && (Infinity_2_2[(c = c + 1) + [ (c = 1 + c, 
                            ([ , 0 ].length === 2 !== null && 3 !== 24..toString()) < (NaN_2 && (NaN_2.NaN >>= (-2 >>> 2) / (a_2_1 = "undefined" >= null)))), (c = 1 + c, 
                            (38..toString() !== 1 ^ -4 & "number") > (void "" ^ + -0)) ][(c = 1 + c, Infinity_2 && (Infinity_2.null %= (-0 >>> []) % (Infinity * 38..toString()) - (-0 !== "bar") % +38..toString()))]] = (NaN_2 && (NaN_2.Infinity += 4 ^ false)) != -0 >= {}) && 22 - null === (NaN_2 = 22 - -1)),
                            length: (c = 1 + c, ([ , 0 ][1] < -2 ^ ([ , 0 ].length === 2) > []) >>> (-5 % "object" < (NaN_1 && (NaN_1.null = -0 >= {}))))
                        }, NaN_2 = (([ , 0 ][1] | 24..toString()) - (-2 ^ undefined)) * ((-2 & 22) > -1 + "undefined");
                    }():
                    var a_1 = "foo";

                  case a++ + [].length:
                    if ((c = c + 1) + {}[a++ + (1 === 1 ? a : b)]) {
                        L89962: for (var brake30 = 5; a++ + [ (c = 1 + c, a_2 && (a_2[--b + (("foo" >= true) * (3 || -2) < void (([ , 0 ].length === 2) > -4))] += (-2 >= 23..toString()) >> (24..toString() != -2) >>> ((NaN_1 && (NaN_1[(c = 1 + c, 
                        (a_2 && (a_2.b <<= (22 | -0) ^ ([ , 0 ].length === 2 ^ -2))) >= (a_1 += (NaN_1 && (NaN_1[(c = 1 + c, 
                        2 - -1 < (0 | 3), -4 % ([ , 0 ].length === 2) + -5 * null)] = ([ , 0 ].length === 2) * "undefined")) != 2 < 5))] += /[a2][^e]+$/ >= 0)) ^ -5 << -0))), (c = 1 + c, 
                        (NaN_1 && (NaN_1[a++ + --a] ^= (24..toString() == undefined) >> (([ , 0 ].length === 2) >= 2))) === (-5 | Infinity) >= (([ , 0 ].length === 2) >= 25)), (c = 1 + c, 
                        (NaN && -0, null < -5) & (a_2 = 4 >> -0 ^ "number" !== "undefined")), (c = 1 + c, 
                        ~(23..toString() + "foo" === false >= -1)), (c = 1 + c, (("foo" != true) > (24..toString() == 4)) / (24..toString() > -0 | "object" / -2)) ][(c = 1 + c, 
                        (/[a2][^e]+$/ + 3 ^ -5 % -1) >> (false | -5) - (25 > 38..toString()))] && brake30 > 0; --brake30) {
                            c = c + 1;
                        }
                    }
                    (c = c + 1) + ((true / -2 || NaN ^ true) && (NaN_1 && (NaN_1[(c = 1 + c, ((23..toString() >= ([ , 0 ].length === 2)) >> (undefined !== undefined)) - ((38..toString() || 38..toString()) < (a_1 && (a_1[(c = 1 + c, 
                    ("number" * 0 >= ([ , 0 ].length === 2 ^ 25)) % ([ , 0 ][1] >>> ([ , 0 ].length === 2) ^ ~23..toString()))] = 2 - 3))))] <<= "foo" << "number")) == (24..toString() ^ 2));
                    break;

                  default:
                  case !((NaN_1 = (0 ^ 5) >>> (24..toString() >> 5)) % (-2 >= [ , 0 ][1] > (1 || -0))):
                    switch (a++ + typeof c_1) {
                      case a_2 && (a_2.null = ("undefined" << "undefined" === (a_1 = 0 >>> /[a2][^e]+$/)) - (/[a2][^e]+$/ != undefined != (a_2[(c = 1 + c, 
                        3 * "" != 38..toString() > 24..toString(), (5 === {}) < (24..toString() !== {}))] = 25 * 25))):
                        break;

                      case [].var:
                        c = 1 + c, [ , 0 ][1] < 0 !== {} + "" !== (-2 / Infinity === true + 4);
                        break;

                      case 1 === 1 ? a : b:
                        for (var brake35 = 5; (c = 1 + c, ("object" | 0) === "undefined" * 24..toString(), 
                        -4 >= "bar" ^ (c = c + 1, [ , 0 ].length === 2)) && brake35 > 0; --brake35) {
                            c = 1 + c, -(NaN_1 && (NaN_1.foo += null ^ 24..toString()) && (NaN_1 && (NaN_1.NaN = -3 <= [])));
                        }
                        return;
                        break;

                      case 0 === 1 ? a : b:
                        var b_2 = (c = 1 + c, (-2 ^ "") > "bar" + 4 != (NaN_1 && (NaN_1[a_2 ^= (void "number" > (-2 !== {}), 
                        (5 != "number") << ("undefined" !== -0))] = -4 >> [] & (c = c + 1, -1))));
                        break;
                    }
                    return;
                    break;
                }
            }(a++ + ((-1 + -1 ^ (-3 | 24..toString())) !== (0 || Infinity) * (-5 * 4)));
        }
        break;

      default:
        (c = c + 1) + {
            0: --b + {
                in: (c = c + 1) + (0 === 1 ? a : b),
                null: --b + ((4 || []) | 1 ^ 38..toString()) % (undefined_1 = (undefined_1 && (undefined_1[(c = 1 + c, 
                (-2 || "function") >= false * 0 || (undefined_1 && (undefined_1.in = 2 != /[a2][^e]+$/)) ^ (0 ^ -5))] = false < 24..toString())) !== (-0 ^ 22))
            }.a,
            in: typeof parseInt_1 === "boolean"
        };
        {
            var NaN = function f4(bar_2, b, b) {
                {
                    var brake42 = 5;
                    L89963: do {
                        switch (0 === 1 ? a : b) {
                          case c = c + 1, ([ , 0 ].length === 2 & NaN) == "undefined" % 1:
                            switch (a++ + (bar_2 && bar_2[(c = 1 + c, (24..toString() / 23..toString() & (0 && {})) !== (undefined_1 && (undefined_1[a++] += (-1 != -4) <= ("number" != -0))))])) {
                              default:
                              case a++ + (1 === 1 ? a : b):
                                c = 1 + c, bar_2 = (2 >= 3 | -4 & Infinity) % (-5 > 38..toString() !== (bar_2 += /[a2][^e]+$/ >>> "undefined"));
                                break;

                              case +function undefined_1_2() {
                                }():
                                c = 1 + c, (undefined_1 && (undefined_1[(c = 1 + c, +"undefined" >= ([ , 0 ][1] == 1) >= (!1 === Infinity / 24..toString()))] += 2 ^ 0)) >>> (/[a2][^e]+$/ && "") | ([ , 0 ][1] & 2) === "number" * NaN;
                                break;

                              case b += a:
                                c = 1 + c, (/[a2][^e]+$/ == ([ , 0 ].length === 2)) > (5 && 38..toString()) ^ (null << 25, 
                                ([ , 0 ].length === 2) % [ , 0 ][1]);
                                break;
                            }
                            var b_2 = (c = c + 1) + function() {
                            }();

                          case a++ + (--b + 5 || a || 3).toString():
                            break;

                          case {
                                in: (c = c + 1) + {
                                    length: (c = 1 + c, (23..toString(), 5) <= ("object" <= 3) < (c = c + 1, -2) << (5 ^ Infinity)),
                                    0: (c = 1 + c, ~(c = c + 1, "number") << (-2 >= -5 !== (-0, /[a2][^e]+$/))),
                                    0: (c = 1 + c, (bar_2 && (bar_2.c = 25 / 38..toString())) == -3 && ([ , 0 ][1] / 38..toString(), 
                                    3 << 22)),
                                    null: (c = 1 + c, (25 === 25) >>> "function" / Infinity && (-0 > null) << (([ , 0 ].length === 2) >= 38..toString())),
                                    in: (c = 1 + c, -3 / -5 - (undefined_1 && (undefined_1.c %= null * 25)) >> (/[a2][^e]+$/ / -5 != (5 && "")))
                                }[(c = 1 + c, 24..toString() * Infinity / (25 << 22) != 38..toString() >> 0 > (b_2 && (b_2[(c = 1 + c, 
                                (Infinity > "function" != (-4 ^ true)) <= ((bar_2 += "function" ^ "object") && 5 & undefined))] = 25 < Infinity)))],
                                3: (c = c + 1) + delete a,
                                c: --b + (c = 1 + c, ([ , 0 ].length === 2 || {}) >>> (38..toString() === "undefined") | 38..toString() <= "foo" ^ 22 > "foo"),
                                Infinity: typeof NaN_1 == "symbol"
                            }:
                            {
                                return;
                                (c = c + 1) + (bar_2 && (bar_2.b = (/[a2][^e]+$/ !== true) - 2 / Infinity) || ((c = c + 1, 
                                4) || /[a2][^e]+$/ % [ , 0 ][1]));
                            }

                          default:
                            c = c + 1;
                        }
                    } while (--b + --b && --brake42 > 0);
                }
                {
                    var a_2 = function f5(undefined_1, b_2) {
                        function f6(NaN, parseInt_2, a_2) {
                            c = 1 + c, (parseInt_2[/[abc4]/.test(((c = 1 + c, undefined + "object" < (NaN & "object") | (c = c + 1, 
                            "number" !== 0)) || b || 5).toString())] -= (b_2 && (b_2.in = null >> "undefined")) | (bar_2 && (bar_2[(c = 1 + c, 
                            "bar" > -3 >= (-4 | "number") != ((a_2 = 5 ^ {}) & 1 >>> Infinity))] = null >>> undefined))) - (bar_2 && (bar_2.Infinity += 5 >> -0 >= (bar_2 && (bar_2.in = 2 === 22))));
                            c = 1 + c, delete (-3 << -2 || -5 ^ -0);
                        }
                        var b_2 = f6(null, NaN);
                        function f7(bar_2_1) {
                            c = 1 + c, bar_2_1 = 24..toString() + undefined > (-5 ^ undefined) == (38..toString() >= 2 === (undefined_1 && (undefined_1.b = 4 >= NaN)));
                            c = 1 + c, 38..toString() >= /[a2][^e]+$/ > (bar_2_1 >>>= null * 4) ^ "" >> "object" & 0 < true;
                        }
                        var Math = f7("object");
                        function f8(Math, undefined_2) {
                            c = 1 + c, (undefined_1.null = [ , 0 ][1] !== "bar") << (5 ^ -0) && ("undefined" & Infinity) % (c = c + 1, 
                            23..toString());
                            c = 1 + c, (bar_2 && (bar_2[--b + new function a_1() {
                                this.a = -3 && -2;
                                this[(c = 1 + c, -3 == -1 || Infinity & "bar" || (undefined_1 = -3 >>> 23..toString()) % ("number" > ([ , 0 ].length === 2)))] >>>= 0 === [ , 0 ][1];
                                this[(c = 1 + c, ((b_2 && (b_2[(c = 1 + c, -0 === -5 ^ (b_2 && (b_2[(c = 1 + c, 
                                ((Infinity == 0) >>> (3 >= 25)) - (null % 23..toString() <= (a_1 && (a_1[(c = 1 + c, 
                                ("object" <= "number" >= (-1 > -0)) >>> (4 % "bar" ^ [] > ([ , 0 ].length === 2)))] += -4 & "undefined"))))] = 5 >= 0)) | ("foo" !== {}) - (([ , 0 ].length === 2) >>> null))] <<= -1 - -2)) - (c = c + 1, 
                                "object")) % (NaN <= {} != (undefined !== false)))] = Infinity * -3;
                            }()] = (bar_2 && (bar_2.NaN *= 4 != 25)) * ([] + 38..toString()))) / (undefined_1 && (undefined_1[(c = c + 1) + (b <<= a)] += (undefined_1 = -2 * -5) ^ (undefined_1 && (undefined_1.foo += 22 / -0))));
                        }
                        var bar = f8(2);
                        function f9() {
                        }
                        var b = f9("object");
                    }((c = c + 1) + (1 === 1 ? a : b));
                }
            }(--b + -b);
        }

      case a++ + !a:
      case typeof (1 === 1 ? a : b):
    }
} catch (b_1) {
    {
        {
            var brake59 = 5;
            do {
                {
                    var Math = function f10() {
                        function f11(parseInt_1, undefined_2, c_2) {
                        }
                        var bar_2 = f11("bar", [ , 0 ][1], {});
                        function f12() {
                            c = 1 + c, ((bar_2 = 38..toString() < 24..toString()) && true >>> 0) ^ NaN / [ , 0 ][1] < 22 >> -0;
                            c = 1 + c, ((25 == Infinity) >> (2 <= false)) * (-5 | 1 || "object" / -3);
                        }
                        var b_2 = f12();
                        function f13(b_1, arguments_2, b) {
                            c = 1 + c, ("" * [], "function" >> {}) != (-4 >= -5) - ({} + 5);
                            c = 1 + c, (-1, null) !== "number" * 23..toString() ^ (false >= "bar" || 22 > 5);
                        }
                        var a_1 = f13("foo", 23..toString());
                        function f14() {
                            c = 1 + c, (38..toString() && null && "" % -1) == (b_1 && (b_1[(c = 1 + c, delete "undefined" >> (-4 && [ , 0 ].length === 2) == (c = c + 1, 
                            NaN ^ false))] = "foo" - "bar")) % (NaN <= "foo");
                            c = 1 + c, (-5 & 23..toString()) >>> ("function" !== /[a2][^e]+$/) | (bar_2 && (bar_2.null %= (bar_2 && (bar_2[(c = 1 + c, 
                            (25 === false) % (24..toString() ^ -4) ^ (0 ^ 25) !== -0 < "bar")] += 22 <= [])) == (-5 ^ "number")));
                        }
                        var a_1 = f14("function");
                    }(new function() {
                        this.b >>= ((true < 23..toString()) - (22 < 22) ^ (38..toString() & "object") + (2 > -0)) != ((undefined_1 = (22 | true) >>> 23..toString() - true) || (c = c + 1, 
                        4) == (5 == 1));
                        L89964: {}
                        c = c + 1;
                        -(4 << false << (NaN | "undefined") === (-1 === NaN) <= -4 >> 23..toString());
                        {
                            var brake70 = 5;
                            do {
                                var b_2 = (c = 1 + c, ([] ^ 25 ^ -3 != false) <= (c = c + 1, "bar" < 23..toString())), b = (c = 1 + c, 
                                (b_1 |= void 22 == 5 <= [ , 0 ][1]) / (b_1 && (b_1[(([] | undefined) << (false !== [ , 0 ][1]), 
                                ("" != -0) > ("object" == false))] = false & -0 | -4 > "object")));
                            } while (+function b() {
                            }() && --brake70 > 0);
                        }
                    }());
                }
            } while ({} && --brake59 > 0);
        }
    }
    if (--b) {
        var brake73 = 5;
        do {
            (c = c + 1) + !((null >> 23..toString() || undefined_1 && (undefined_1.Infinity = 22 >> 0)) - ((undefined_1 = Infinity >> Infinity) + (-4 || Infinity)));
        } while ((c = c + 1) + (b = a) && --brake73 > 0);
    }
} finally {
    {
        var brake75 = 5;
        do {
            {
                var brake76 = 5;
                do {
                    {
                        var a = function f15(bar_2, foo_2) {
                            ({
                                length: b++,
                                a: b += a,
                                c: --b + !b,
                                foo: --b + (b += a),
                                "": b--
                            }).foo;
                            --b + [].NaN;
                        }((c = c + 1) + (typeof foo != "crap"));
                    }
                } while ((undefined_1 && (undefined_1.c = 4 ^ "foo")) - (NaN != 1) != "number" << ([ , 0 ].length === 2) >> (1 > -4) && --brake76 > 0);
            }
        } while (a++ && --brake75 > 0);
    }
    {
        var expr80 = --b + typeof ((c = c + 1) + ((3 & 25) << (NaN !== -2) <= (-4 <= Infinity) / (false, 
        NaN)));
        L89965: for (var key80 in expr80) {
            c = 1 + c;
            var a_2 = expr80[key80];
            if (a++ + void a) {
                var c = function f16(a_1, b_1, parseInt_2) {
                    L89966: for (var brake83 = 5; --b && brake83 > 0; --brake83) {
                        return --b + (2 || 8).toString()[{
                            Infinity: (c = 1 + c, ("function" ^ 5) >>> ("undefined" << 23..toString()) & ([] && "undefined") == "foo" <= -2),
                            a: (c = 1 + c, (a_2 += 1 << -5 >>> ([ , 0 ].length === 2) * "object") !== (undefined | 2) >>> (false << 38..toString())),
                            a: (c = 1 + c, b_1 && (b_1[[ (c = 1 + c, (/[a2][^e]+$/, []) % (1 >>> "function") == (2 < /[a2][^e]+$/) << (5 <= [])), (c = 1 + c, 
                            [ , 0 ][1] - "object" > 5 / 1 ^ ("object" >> "function") / (-0 == /[a2][^e]+$/)), (c = 1 + c, 
                            a_1 |= ("function" === "foo", "object" ^ /[a2][^e]+$/) % (c = c + 1, 23..toString() % -1)) ]] = ("foo" ^ -5 || 1 + 2) >>> (b_1 += "" >> "number" << ([ , 0 ][1] || Infinity))))
                        }.NaN];
                    }
                    try {
                        {
                            var bar_1 = function f17() {
                                c = 1 + c, c = c + 1, (a_2 && (a_2.c %= Infinity << "bar")) != {} > "function";
                                c = 1 + c, delete ("object" < "object", "function", true);
                            }((-5 * 25 == (Infinity == null)) <= 2 >>> [ , 0 ][1] >>> ~-0);
                        }
                    } finally {
                        for (var brake89 = 5; (0 === 1 ? a : b) && brake89 > 0; --brake89) {
                            L89967: {
                            }
                        }
                        {
                            c = 1 + c, 23..toString() * 1 / (4, "object") << (b_1 && (b_1.b = (undefined_1 += -2 !== "") || [ , 0 ].length === 2 & {}));
                            c = 1 + c, (-5 >= "undefined") << ("function" !== 25) < (2 ^ 1) % -2;
                            c = 1 + c, !((24..toString(), 5) <= "bar" - 25);
                        }
                    }
                }((a_2 ^= 3 << 38..toString()) % (25 * "number") > (23..toString() - []) % ([ , 0 ].length === 2 !== ([ , 0 ].length === 2)));
            } else {
                var Infinity = function f18(Math_1, b) {
                    {
                        var expr96 = (c = c + 1) + (a_1 && a_1.a);
                        L89968: for (var key96 in expr96) {
                            c = 1 + c;
                            var a_1 = expr96[key96];
                            {
                                var brake97 = 5;
                                L89969: while (typeof foo_1 == "boolean" && --brake97 > 0) {
                                    var b = function f19(b_1, a_1) {
                                    }((c = 1 + c, ((/[a2][^e]+$/ ^ 38..toString()) << -4 * undefined) * ({} % undefined ^ ("undefined" | false))));
                                }
                            }
                        }
                    }
                }((c = c + 1) + [ --b + function arguments_1() {
                    {
                        var expr100 = (c = 1 + c, ((c = c + 1, "number") != (false && [ , 0 ][1])) >>> (1 >= 2 >= (24..toString() >= 0)));
                        for (var key100 in expr100) {
                            c = 1 + c, -(([ , 0 ].length === 2) < -3 === (a_2 && (a_2[(c = 1 + c, (/[a2][^e]+$/ < ([ , 0 ].length === 2)) / (24..toString() - null) << "object" % 4 % (23..toString() || [ , 0 ][1]))] -= undefined % {})));
                        }
                    }
                }(), --b + b--, (c = c + 1) + ((2 ^ "function") >>> ("foo" ^ undefined)) * ("" << 38..toString() < 38..toString() >> 22), (c = c + 1) + !function b_2() {
                    {
                    }
                    var a_2 = (c = 1 + c, ("" & "undefined") << (25 & 3) <= ("bar" << "number") - (-4 === 0)), undefined_1 = (c = 1 + c, 
                    (0 << 3) / ("bar" * "foo") >= (NaN <= 38..toString() && [] & 22));
                    {
                        var brake104 = 5;
                        while ((c = 1 + c, c = c + 1, (5 < "function") >>> [ , 0 ][1] * null) && --brake104 > 0) {
                            c = 1 + c, ((c = c + 1, -2) || "foo" / "bar") ^ (c = c + 1, 3) % (Infinity >= false);
                        }
                    }
                }() ]);
            }
        }
    }
}

--b + typeof ((c = c + 1) + +b);

console.log(null, a, b, c);
// uglified code
// (beautified)
var a = 100, b = 10, c = 0;

try {
    switch (3) {
      case b += a:
        var undefined_1 = function() {
            if (--e + /[abc4]/.test(((c += 1) + (c = 1 + c, void (0 & !1 * [] <= !1 && (c = 1 + c, 
            23..toString(), 38..toString()))) || e || 5).toString())) {
                for (var t = 5; a++ + (+e ? a++ + (c = 1 + c, c += 1, c = 1 + (c = 1 + (c += 1)), 
                a = !1, c += 1, +void 24..toString()) : --e + /[abc4]/.test((a++ + [ (c = 1 + c, 
                38..toString() + -0 - 0 <= !1), (c = 1 + c, (a.NaN = 0) ^ (a && (a.a = !0 < [] > "-2undefined"))), (c = 1 + c, 
                c += 1, 1 == (a && (a[(c += 1) + ++e] |= NaN / 2 >= !1))) ][(c = 1 + c, (0 == (!0 !== 23..toString())) < "3bar")] || e || 5).toString())) && t > 0; --t) {
                    if (a++ + a--) {
                        var n = r && r.c;
                        for (var i in n) {
                            c = 1 + c;
                            var r = n[i];
                            try {
                                c = 1 + c, 24..toString(), 24..toString(), c += 1;
                            } catch (c) {}
                        }
                    } else {
                        switch ((c += 1) + (r && r.var)) {
                          case --e + --e:
                            var o = (c = 1 + (c += 1), c += 1, void (o && (o.a = 0)));
                            break;

                          default:
                          case --e + {
                                length: o && o.Infinity
                            }.NaN:
                            var e = (c = 1 + c, void (c += 1));
                            return;

                          case a++ + !a:
                            for (var g = 5; (e += a) && --g > 0; ) {
                                do {
                                    c = 1 + c, o <<= -0;
                                } while (c = 1 + c, 0 / 0);
                            }
                        }
                    }
                }
            }
            switch (a) {
              case --e + !function() {
                    c += 1;
                    var t = !(!0 === (Infinity && Infinity) ^ !1 === (r && (r[(c = 1 + c, ((r += -5) && -1) >> !0)] = "" & NaN))), n = (c = 1 + c, 
                    t && (t[(c = 1 + c, -2 / (r = !0))] = 0), void (n = -0)), i = a++ + {
                        Infinity: (c = 1 + c, i && (i[(c += 1) + [ (c = 1 + c, (2 === [ , 0 ].length !== null && 3 !== 24..toString()) < (o && (o.NaN >>= (-2 >>> 2) / (t = !1)))), (c = 1 + c, 
                        (1 !== 38..toString() ^ 0) > 0) ][(c = 1 + c, n && (n.null %= (-0 >>> []) % (Infinity * 38..toString()) - !0 % +38..toString()))]] = (o && (o.Infinity += 4)) != -0 >= {}) && 22 == (o = 23)),
                        length: (c = 1 + c, ([ , 0 ][1] < -2 ^ (2 === [ , 0 ].length) > []) >>> (0 / 0 < (r && (r.null = -0 >= {}))))
                    }, o = !1 * (([ , 0 ][1] | 24..toString()) - -2);
                }():
                var f = "foo";

              case a++ + [].length:
                if ((c += 1) + {}[a++ + a]) {
                    for (var S = 5; a++ + [ (c = 1 + c, o && (o[--e + !1] += (-2 >= 23..toString()) >> (-2 != 24..toString()) >>> (-5 ^ (r && (r[(c = 1 + c, 
                    (o && (o.b <<= 2 === [ , 0 ].length ^ -2 ^ 22)) >= (f += 1 != (r && (r[(c = 1 + c, 
                    -4 % (2 === [ , 0 ].length) - 0)] = "undefined" * (2 === [ , 0 ].length)))))] += !1))))), (c = 1 + c, 
                    (r && (r[a++ + --a] ^= (void 0 == 24..toString()) >> ((2 === [ , 0 ].length) >= 2))) === (-5 | Infinity) >= ((2 === [ , 0 ].length) >= 25)), (c = 1 + c, 
                    !1 & (o = 5)), (c = 1 + c, ~(23..toString() + "foo" === !0)), (c = 1 + c, (!0 > (4 == 24..toString())) / (24..toString() > -0 | 0 / 0)) ][(c = 1 + c, 
                    0 >> -5 - (25 > 38..toString()))] && S > 0; --S) {
                        c += 1;
                    }
                }
                c += 1, r && (r[(c = 1 + c, ((23..toString() >= (2 === [ , 0 ].length)) >> !1) - ((38..toString() || 38..toString()) < (f && (f[(c = 1 + c, 
                (0 / 0 >= (2 === [ , 0 ].length ^ 25)) % ([ , 0 ][1] >>> (2 === [ , 0 ].length) ^ ~23..toString()))] = -1))))] <<= 0), 
                24..toString();
                break;

              default:
              case !((r = 5 >>> (24..toString() >> 5)) % (-2 >= [ , 0 ][1] > 1)):
                switch (a++ + typeof c_1) {
                  case o && (o.null = (0 == (f = 0)) - (1 != (o[(c = 1 + c, 38..toString(), 24..toString(), 
                    (5 === {}) < (24..toString() !== {}))] = 625))):
                    break;

                  case [].var:
                    c = 1 + c;
                    break;

                  case a:
                    for (var l = 5; c = 1 + c, 24..toString(), !1 ^ (c += 1, 2 === [ , 0 ].length) && l > 0; --l) {
                        c = 1 + c, r && (r.foo += null ^ 24..toString()) && r && (r.NaN = -3 <= []);
                    }
                    return;

                  case e:
                    c = 1 + c, r && (r[o ^= 2] = -4 >> [] & (c += 1, -1));
                }
                return;
            }
        }((a++, 24..toString()));
        break;

      default:
        c += 1, --b, c += 1, --b, 38..toString(), undefined_1 = 22 !== (undefined_1 && (undefined_1[(c = 1 + c, 
        -5 ^ (undefined_1 && (undefined_1.in = !0)))] = !1 < 24..toString()));
        var NaN = function(t, n, n) {
            var i = 5;
            do {
                switch (n) {
                  case c += 1, (2 === [ , 0 ].length & NaN) == 0 / 0:
                    switch (a++ + (t && t[(c = 1 + c, (24..toString() / 23..toString() & 0) !== (undefined_1 && (undefined_1[a++] += !0)))])) {
                      default:
                      case a++ + a:
                        c = 1 + c, t = (!1 | -4 & Infinity) % (-5 > 38..toString() !== (t += 0));
                        break;

                      case 0 / 0:
                        c = 1 + c, undefined_1 && (undefined_1[(c = 1 + c, 0 / 0 >= (1 == [ , 0 ][1]) >= (!1 === Infinity / 24..toString()))] += 2);
                        break;

                      case n += a:
                        c = 1 + c, 38..toString();
                    }
                    var r = (c += 1) + void 0;

                  case a++ + (5 + --n || a || 3).toString():
                    break;

                  case {
                        in: (c += 1) + {
                            length: (c = 1 + c, 23..toString(), !1 < (c += 1, -2 << (5 ^ Infinity))),
                            0: (c = 1 + c, c += 1, -2),
                            0: (c = 1 + c, -3 == (t && (t.c = 25 / 38..toString())) && (38..toString(), 3 << 22)),
                            null: (c = 1 + c, !0 >>> "function" / Infinity && !1 << ((2 === [ , 0 ].length) >= 38..toString())),
                            in: (c = 1 + c, .6 - (undefined_1 && (undefined_1.c %= 0)) >> !0)
                        }[(c = 1 + c, 24..toString() * Infinity / (25 << 22) != 38..toString() >> 0 > (r && (r[(c = 1 + c, 
                        (Infinity > "function" != -3) <= ((t += 0) && 0))] = 25 < Infinity)))],
                        3: (c += 1) + delete a,
                        c: --n + (c = 1 + c, (2 === [ , 0 ].length || {}) >>> ("undefined" === 38..toString()) | 38..toString() <= "foo" ^ !1),
                        Infinity: "symbol" == typeof NaN_1
                    }:
                    return;

                  default:
                    c += 1;
                }
            } while (--n + --n && --i > 0);
            !function(n, i) {
                var i = (c = 1 + c, (0)[/[abc4]/.test((c = 1 + c, !1 | (c += 1, !0) || r || 5).toString())] -= (i && (i.in = 0)) | (t && (t[(c = 1 + c, 
                1 != ((5 ^ {}) & 1 >>> Infinity))] = 0)), t && (t.Infinity += 5 >= (t && (t.in = !1))), 
                void (c = 1 + c)), r = (function(t) {
                    c = 1 + c, t = 24..toString() + void 0 > -5 == (38..toString() >= 2 === (n && (n.b = 4 >= NaN))), 
                    c = 1 + c, 38..toString(), t >>>= 0;
                }("object"), c = 1 + c, (n.null = "bar" !== [ , 0 ][1]) << 5 && (c += 1, 23..toString()), 
                c = 1 + c, t && (t[--r + new function t() {
                    this.a = -2, this[(c = 1 + c, "bar" & Infinity || (n = -3 >>> 23..toString()) % ("number" > (2 === [ , 0 ].length)))] >>>= 0 === [ , 0 ][1], 
                    this[(c = 1 + c, ((i && (i[(c = 1 + c, !1 ^ (i && (i[(c = 1 + c, ((0 == Infinity) >>> !1) - (null % 23..toString() <= (t && (t[(c = 1 + c, 
                    !0 >>> (0 / 0 ^ [] > (2 === [ , 0 ].length)))] += 0))))] = !0)) | ("foo" !== {}) - ((2 === [ , 0 ].length) >>> null))] <<= 1)) - (c += 1, 
                    "object")) % (NaN <= {} != 1))] = -3 * Infinity;
                }()] = (t && (t.NaN *= !0)) * ([] + 38..toString())), void (n && (n[(c += 1) + (r <<= a)] += (n = 10) ^ (n && (n.foo += -1 / 0)))));
            }((c += 1) + a);
        }(--b - b);

      case a++ + !a:
      case typeof a:
    }
} catch (t) {
    var brake59 = 5;
    do {
        var Math = function() {
            var n = void 0;
            c = 1 + c, n = 38..toString() < 24..toString(), c = 1 + c, 23..toString(), c = 1 + (c = 1 + c), 
            23..toString(), c = 1 + c, 38..toString(), t && (t[(c = 1 + c, !0 >> (2 === [ , 0 ].length) == (c += 1, 
            !1 ^ NaN))] = 0 / 0), c = 1 + c, 23..toString(), n && (n.null %= -5 == (n && (n[(c = 1 + c, 
            !1 % (-4 ^ 24..toString()) ^ !0)] += 22 <= [])));
        }(new function() {
            this.b >>= ((!0 < 23..toString()) - !1 ^ ("object" & 38..toString()) + !0) != ((undefined_1 = 23 >>> 23..toString() - !0) || 0 == (c += 1, 
            4)), c += 1, 23..toString(), c = 1 + c, c += 1, 23..toString(), c = 1 + c, (t |= void 0 == 5 <= [ , 0 ][1]) && (t[!1] = 0);
        }());
    } while ({} && --brake59 > 0);
    if (--b) {
        var brake73 = 5;
        do {
            c += 1, null >> 23..toString() || undefined_1 && (undefined_1.Infinity = 22), undefined_1 = Infinity >> Infinity;
        } while ((c += 1) + (b = a) && --brake73 > 0);
    }
} finally {
    var brake75 = 5;
    do {
        var brake76 = 5;
        do {
            var a = (c += 1, b++, b += a, --b, --b, b += a, b--, void --b);
        } while ((undefined_1 && (undefined_1.c = 4)) - (1 != NaN) != "number" << (2 === [ , 0 ].length) >> !0 && --brake76 > 0);
    } while (a++ && --brake75 > 0);
    var expr80 = --b + typeof ((c += 1) + (1 << (-2 !== NaN) <= (-4 <= Infinity) / NaN));
    for (var key80 in expr80) {
        c = 1 + c;
        var a_2 = expr80[key80];
        if (a++ + void 0) {
            var c = function(t, n) {
                for (var i = 5; --b && i > 0; --i) {
                    return --b + 2..toString()[{
                        Infinity: (c = 1 + c, 5 >>> ("undefined" << 23..toString()) & 0 == ([] && "undefined")),
                        a: (c = 1 + c, (a_2 += 1 << -5 >>> "object" * (2 === [ , 0 ].length)) !== 2 >>> (!1 << 38..toString())),
                        a: (c = 1 + c, n && (n[[ (c = 1 + c, [] % 1 == !1 << (5 <= [])), (c = 1 + c, [ , 0 ][1] - "object" > 5 ^ 0 / 0), (c = 1 + c, 
                        t |= 0 % (c += 1, 23..toString() % -1)) ]] = -5 >>> (n += 0 << ([ , 0 ][1] || Infinity))))
                    }.NaN];
                }
                try {
                    c = 1 + c, c += 1, a_2 && (a_2.c %= Infinity << "bar"), c = 1 + c;
                } finally {
                    for (var r = 5; b && r > 0; --r) {}
                    c = 1 + c, 23..toString(), n && (n.b = (undefined_1 += !0) || 2 === [ , 0 ].length & {}), 
                    c = 1 + (c = 1 + c), 24..toString();
                }
            }((a_2 ^= 3 << 38..toString()) % (0 / 0) > (23..toString() - []) % (2 === [ , 0 ].length != (2 === [ , 0 ].length)));
        } else {
            var Infinity = function() {
                var t = (c += 1) + (i && i.a);
                for (var n in t) {
                    c = 1 + c;
                    for (var i = t[n], r = 5; "boolean" == typeof foo_1 && --r > 0; ) {
                        c = 1 + c, 38..toString();
                    }
                }
            }((c += 1, --b, function() {
                var t = (c = 1 + c, (0 != (c += 1, "number")) >>> (!1 >= (24..toString() >= 0)));
                for (var n in t) {
                    c = 1 + c, a_2 && (a_2[(c = 1 + c, (/[a2][^e]+$/ < (2 === [ , 0 ].length)) / (24..toString() - null) << 0 / 0 % (23..toString() || [ , 0 ][1]))] -= void 0 % {});
                }
            }(), --b, b--, c += 1, 38..toString(), 38..toString(), c += 1, function() {
                c = 1 + (c = 1 + c), 38..toString();
                for (var t = 5; c = 1 + c, c += 1, !1 >>> null * [ , 0 ][1] && --t > 0; ) {
                    c = 1 + c, c += 1, c += 1;
                }
            }()));
        }
    }
}

--b, c += 1, console.log(null, a, b, c);
original result:
null NaN NaN 190

uglified result:
null NaN NaN 132

minify(options):
{
  "compress": {
    "keep_fargs": false,
    "passes": 3
  }
}

Suspicious compress options:
  collapse_vars
  evaluate
  inline
  passes
  reduce_vars
  sequences
  unused

@alexlamsl
Copy link
Collaborator Author

alexlamsl commented Jun 17, 2017

OT: as I was collecting these failed test cases and found this one, one of the false positives was blowing up node itself with an exception thrown from Stream.cork() about Math.floor() being absent.

And then I look at the test case and it's like:

var a = ..., b = ..., c = ...;

function f0() { ... }
var Math = f0();

console.log(...);

... yeah, that would blow that up 😅

@kzc
Copy link
Contributor

kzc commented Jun 17, 2017

Regarding the last fuzz test case discovered: #2114 (comment)

Suspicious compress options:
collapse_vars
...
inline

It would appear to be shallow copy related based on those suspicious compress options.

As we know, collapse_vars has an assumption that it's the owner of the single-use variable's value. If it were to be changed to deep copy that variable value AST rather than steal and null it, it might avoid this class of errors. But then again, the deep copy probably would likely introduce another class of errors.

@alexlamsl
Copy link
Collaborator Author

Regarding the last fuzz test case discovered: #2114 (comment)

I'm fairly sure it's a false positive:

$ node test.js
null NaN NaN 190

$ cat test.js | node
null NaN NaN 132

Note that uglify-js isn't involved at all to produce the same difference of results above.

@kzc
Copy link
Contributor

kzc commented Jun 17, 2017

Note that uglify-js isn't involved at all to produce the same difference of results above.

You beat me to it - just discovered the same thing.

$ cat bug2.js 
var a = 100, b = 10, c = 0;

try {
    c = c + 1;
    var NaN = function n(e, t, t) {
        var i = function n(i, a) {
            function b(n, i, b) {
                c = 1 + c, (i[/[abc4]/.test(((c = 1 + c, undefined + "object" < (n & "object") | (c = c + 1, 
                "number" !== 0)) || t || 5).toString())] -= (a && (a.in = null >> "undefined")) | (e && (e[(c = 1 + c, 
                "bar" > -3 >= (-4 | "number") != ((b = 5 ^ {}) & 1 >>> Infinity))] = null >>> undefined))) - (e && (e.Infinity += 5 >> -0 >= (e && (e.in = 2 === 22))));
                c = 1 + c, delete (-3 << -2 || -5 ^ -0);
            }
            var a = b(null, NaN);
        }((c = c + 1) + (1 === 1 ? a : t));
    }(--b + -b);
} catch (c) {}

--b + typeof ((c = c + 1) + +b);

console.log(null, a, b, c);
$ node bug2.js 
null 100 8 6

$ cat bug2.js | node
null 100 8 7

@kzc
Copy link
Contributor

kzc commented Jun 17, 2017

That node FUZZ.js vs cat FUZZ.js | node test ought to be the very first test we perform.

@alexlamsl
Copy link
Collaborator Author

That node FUZZ.js vs cat FUZZ.js | node test ought to be the very first test we perform.

If by "we" you mean you and I, yes - that's the first thing I run through to filter out false positives.

Back when I was younger, though, I had the energy and curiosity to work out why Node.js would be affected. 😞

... jokes aside, this is quite a bit more rare than those [Function: 1000001] vs [Function: 1000002] stuff, and it's not exactly difficult to discover and discard.

@alexlamsl
Copy link
Collaborator Author

You beat me to it - just discovered the same thing.

Sorry for burying that at the very top of #2114 (comment) 👻

@kzc
Copy link
Contributor

kzc commented Jun 17, 2017

Just by coincidence... similar to #2114 (comment)

    var NaN = function n(e, t, t) {
          ... init uses NaN ...
    }();

@alexlamsl If you ever implement this new reduce_vars feature, emitting a warning for this obvious coding error would be nice.

Edit: "obvious coding error" in this case refers to "have a declaration initialization to refer to itself before it has a value", not overriding NaN - which is also terrible.

@kzc
Copy link
Contributor

kzc commented Jun 17, 2017

If by "we" you mean you and I, yes - that's the first thing I run through to filter out false positives.

Sorry for burying that at the very top of #2114 (comment)

Groan - how did I miss that?

@alexlamsl
Copy link
Collaborator Author

If you ever implement this new reduce_vars feature, emitting a warning for this obvious coding error would be nice.

I think this falls under the TODO of multi-segment reduce_vars:

if (a) {
    var key = 1;
    x(key);
} else {
    var key = 2;
    y(key);
}

I've encountered this coding pattern, many of them as switch-cases, in the wild presumbly because it's more human readable.

@kzc
Copy link
Contributor

kzc commented Jun 17, 2017

I think this falls under the TODO of multi-segment reduce_vars:

There's a step in between that I'm failing to see. It's a different situation in my view - it's not in the var decl init. key in both branches is defined by the time it calls x(key) or y(key).

@kzc
Copy link
Contributor

kzc commented Jun 17, 2017

That node FUZZ.js vs cat FUZZ.js | node test ought to be the very first test we perform.

Could that test on the original code be automated as part of test/ufuzz.js so no time is wasted analyzing it?

Edit: after the uglify vs. original test run fails of course - to not waste CPU.

@alexlamsl
Copy link
Collaborator Author

There's a step in between that I'm failing to see.

reduce_vars already treats uninitialised var as being assigned undefined:
https://github.com/mishoo/UglifyJS2/blob/0a0f4f55912fed32b09c93a2a1efa19edce24e28/lib/compress.js#L491

So as we dwell into the initialisation value in the multi-segment case, it should Just Work ™️

@alexlamsl
Copy link
Collaborator Author

Could that test on the original code be automated as part of test/ufuzz.js so no time is wasted analyzing it?

Sure, it's just a couple of child_process.execSync() with the slight complication of having to write out to a file first.

@kzc
Copy link
Contributor

kzc commented Jun 17, 2017

There's a step in between that I'm failing to see.

reduce_vars already treats uninitialised var as being assigned undefined:

That part I assumed, but I still can't bridge the gap between a case with a var assigned something and later used in another statement versus a case with a var referencing itself in its own init.

@kzc
Copy link
Contributor

kzc commented Jun 17, 2017

What the ufuzz iteration count now, by the way?

@alexlamsl
Copy link
Collaborator Author

I still can't bridge the gap between a case with a var assigned something and later used in another statement versus a case with a var referencing itself in its own init.

When we walk() to an instance of AST_VarDef, the AST_SymbolVar is marked, then the init value is processed - much the same way as if the init value is on the next line as a separate AST_Statement.

So these two cases have same transversal order:

var a = x();

versus

var a;
x();

(Obviously the resulting assigned value to a would be different in those two cases.)

@alexlamsl
Copy link
Collaborator Author

What the ufuzz iteration count now, by the way?

1.14MFuzz

@kzc
Copy link
Contributor

kzc commented Jun 17, 2017

When we walk() to an instance of AST_VarDef, the AST_SymbolVar is marked, then the init value is processed - much the same way as if the init value is on the next line as a separate AST_Statement.

That's the missing piece.

If that's the case, why not separate all var declarations from their inits prior to reduce_vars?

$ echo 'function bar(){ var a = a && foo(); }' | bin/uglifyjs -c
function bar(){var a=a&&foo()}

$ echo 'function bar(){ var a; a && foo(); }' | bin/uglifyjs -c
function bar(){}

@kzc
Copy link
Contributor

kzc commented Jun 17, 2017

Correction: last command was not equivalent. Should have been:

$ echo 'function bar(){ var a; a = a && foo(); }' | bin/uglifyjs -c
function bar(){var a;a=a&&foo()}

which doesn't help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants